/* jshint ignore:start */

window.EmberENV = {"FEATURES":{}};
var runningTests = false;



/* jshint ignore:end */

;var loader, define, requireModule, require, requirejs;

(function (global) {
  'use strict';

  var heimdall = global.heimdall;

  function dict() {
    var obj = Object.create(null);
    obj['__'] = undefined;
    delete obj['__'];
    return obj;
  }

  // Save off the original values of these globals, so we can restore them if someone asks us to
  var oldGlobals = {
    loader: loader,
    define: define,
    requireModule: requireModule,
    require: require,
    requirejs: requirejs
  };

  requirejs = require = requireModule = function (name) {
    var pending = [];
    var mod = findModule(name, '(require)', pending);

    for (var i = pending.length - 1; i >= 0; i--) {
      pending[i].exports();
    }

    return mod.module.exports;
  };

  loader = {
    noConflict: function (aliases) {
      var oldName, newName;

      for (oldName in aliases) {
        if (aliases.hasOwnProperty(oldName)) {
          if (oldGlobals.hasOwnProperty(oldName)) {
            newName = aliases[oldName];

            global[newName] = global[oldName];
            global[oldName] = oldGlobals[oldName];
          }
        }
      }
    }
  };

  var _isArray;
  if (!Array.isArray) {
    _isArray = function (x) {
      return Object.prototype.toString.call(x) === '[object Array]';
    };
  } else {
    _isArray = Array.isArray;
  }

  var registry = dict();
  var seen = dict();

  var uuid = 0;

  function unsupportedModule(length) {
    throw new Error('an unsupported module was defined, expected `define(name, deps, module)` instead got: `' + length + '` arguments to define`');
  }

  var defaultDeps = ['require', 'exports', 'module'];

  function Module(name, deps, callback, alias) {
    this.id = uuid++;
    this.name = name;
    this.deps = !deps.length && callback.length ? defaultDeps : deps;
    this.module = { exports: {} };
    this.callback = callback;
    this.hasExportsAsDep = false;
    this.isAlias = alias;
    this.reified = new Array(deps.length);

    /*
       Each module normally passes through these states, in order:
         new       : initial state
         pending   : this module is scheduled to be executed
         reifying  : this module's dependencies are being executed
         reified   : this module's dependencies finished executing successfully
         errored   : this module's dependencies failed to execute
         finalized : this module executed successfully
     */
    this.state = 'new';
  }

  Module.prototype.makeDefaultExport = function () {
    var exports = this.module.exports;
    if (exports !== null && (typeof exports === 'object' || typeof exports === 'function') && exports['default'] === undefined && Object.isExtensible(exports)) {
      exports['default'] = exports;
    }
  };

  Module.prototype.exports = function () {
    // if finalized, there is no work to do. If reifying, there is a
    // circular dependency so we must return our (partial) exports.
    if (this.state === 'finalized' || this.state === 'reifying') {
      return this.module.exports;
    }

    if (loader.wrapModules) {
      this.callback = loader.wrapModules(this.name, this.callback);
    }

    this.reify();

    var result = this.callback.apply(this, this.reified);
    this.state = 'finalized';

    if (!(this.hasExportsAsDep && result === undefined)) {
      this.module.exports = result;
    }
    this.makeDefaultExport();
    return this.module.exports;
  };

  Module.prototype.unsee = function () {
    this.state = 'new';
    this.module = { exports: {} };
  };

  Module.prototype.reify = function () {
    if (this.state === 'reified') {
      return;
    }
    this.state = 'reifying';
    try {
      this.reified = this._reify();
      this.state = 'reified';
    } finally {
      if (this.state === 'reifying') {
        this.state = 'errored';
      }
    }
  };

  Module.prototype._reify = function () {
    var reified = this.reified.slice();
    for (var i = 0; i < reified.length; i++) {
      var mod = reified[i];
      reified[i] = mod.exports ? mod.exports : mod.module.exports();
    }
    return reified;
  };

  Module.prototype.findDeps = function (pending) {
    if (this.state !== 'new') {
      return;
    }

    this.state = 'pending';

    var deps = this.deps;

    for (var i = 0; i < deps.length; i++) {
      var dep = deps[i];
      var entry = this.reified[i] = { exports: undefined, module: undefined };
      if (dep === 'exports') {
        this.hasExportsAsDep = true;
        entry.exports = this.module.exports;
      } else if (dep === 'require') {
        entry.exports = this.makeRequire();
      } else if (dep === 'module') {
        entry.exports = this.module;
      } else {
        entry.module = findModule(resolve(dep, this.name), this.name, pending);
      }
    }
  };

  Module.prototype.makeRequire = function () {
    var name = this.name;
    var r = function (dep) {
      return require(resolve(dep, name));
    };
    r['default'] = r;
    r.has = function (dep) {
      return has(resolve(dep, name));
    };
    return r;
  };

  define = function (name, deps, callback) {
    var module = registry[name];

    // If a module for this name has already been defined and is in any state
    // other than `new` (meaning it has been or is currently being required),
    // then we return early to avoid redefinition.
    if (module && module.state !== 'new') {
      return;
    }

    if (arguments.length < 2) {
      unsupportedModule(arguments.length);
    }

    if (!_isArray(deps)) {
      callback = deps;
      deps = [];
    }

    if (callback instanceof Alias) {
      registry[name] = new Module(callback.name, deps, callback, true);
    } else {
      registry[name] = new Module(name, deps, callback, false);
    }
  };

  // we don't support all of AMD
  // define.amd = {};

  function Alias(path) {
    this.name = path;
  }

  define.alias = function (path, target) {
    if (arguments.length === 2) {
      return define(target, new Alias(path));
    }

    return new Alias(path);
  };

  function missingModule(name, referrer) {
    throw new Error('Could not find module `' + name + '` imported from `' + referrer + '`');
  }

  function findModule(name, referrer, pending) {
    var mod = registry[name] || registry[name + '/index'];

    while (mod && mod.isAlias) {
      mod = registry[mod.name];
    }

    if (!mod) {
      missingModule(name, referrer);
    }

    if (pending && mod.state !== 'pending' && mod.state !== 'finalized') {
      mod.findDeps(pending);
      pending.push(mod);
    }
    return mod;
  }

  function resolve(child, name) {
    if (child.charAt(0) !== '.') {
      return child;
    }

    var parts = child.split('/');
    var nameParts = name.split('/');
    var parentBase = nameParts.slice(0, -1);

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

      if (part === '..') {
        if (parentBase.length === 0) {
          throw new Error('Cannot access parent module of root');
        }
        parentBase.pop();
      } else if (part === '.') {
        continue;
      } else {
        parentBase.push(part);
      }
    }

    return parentBase.join('/');
  }

  function has(name) {
    return !!(registry[name] || registry[name + '/index']);
  }

  requirejs.entries = requirejs._eak_seen = registry;
  requirejs.has = has;
  requirejs.unsee = function (moduleName) {
    findModule(moduleName, '(unsee)', false).unsee();
  };

  requirejs.clear = function () {
    requirejs.entries = requirejs._eak_seen = registry = dict();
    seen = dict();
  };

  // This code primes the JS engine for good performance by warming the
  // JIT compiler for these functions.
  define('foo', function () {});
  define('foo/bar', [], function () {});
  define('foo/asdf', ['module', 'exports', 'require'], function (module, exports, require) {
    if (require.has('foo/bar')) {
      require('foo/bar');
    }
  });
  define('foo/baz', [], define.alias('foo'));
  define('foo/quz', define.alias('foo'));
  define.alias('foo', 'foo/qux');
  define('foo/bar', ['foo', './quz', './baz', './asdf', './bar', '../foo'], function () {});
  define('foo/main', ['foo/bar'], function () {});

  require('foo/main');
  require.unsee('foo/bar');

  requirejs.clear();

  if (typeof exports === 'object' && typeof module === 'object' && module.exports) {
    module.exports = { require: require, define: define };
  }
})(this);
;/*!
 * jQuery JavaScript Library v2.2.4
 * http://jquery.com/
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2016-05-20T17:23Z
 */

(function( global, factory ) {

    if ( typeof module === "object" && typeof module.exports === "object" ) {
        // For CommonJS and CommonJS-like environments where a proper `window`
        // is present, execute the factory and get jQuery.
        // For environments that do not have a `window` with a `document`
        // (such as Node.js), expose a factory as module.exports.
        // This accentuates the need for the creation of a real `window`.
        // e.g. var jQuery = require("jquery")(window);
        // See ticket #14549 for more info.
        module.exports = global.document ?
            factory( global, true ) :
            function( w ) {
                if ( !w.document ) {
                    throw new Error( "jQuery requires a window with a document" );
                }
                return factory( w );
            };
    } else {
        factory( global );
    }

// Pass this if window is not defined yet
}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

// Support: Firefox 18+
// Can't be in strict mode, several libs including ASP.NET trace
// the stack via arguments.caller.callee and Firefox dies if
// you try to trace through "use strict" call chains. (#13335)
//"use strict";
var arr = [];

var document = window.document;

var slice = arr.slice;

var concat = arr.concat;

var push = arr.push;

var indexOf = arr.indexOf;

var class2type = {};

var toString = class2type.toString;

var hasOwn = class2type.hasOwnProperty;

var support = {};



var
    version = "2.2.4",

    // Define a local copy of jQuery
    jQuery = function( selector, context ) {

        // The jQuery object is actually just the init constructor 'enhanced'
        // Need init if jQuery is called (just allow error to be thrown if not included)
        return new jQuery.fn.init( selector, context );
    },

    // Support: Android<4.1
    // Make sure we trim BOM and NBSP
    rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,

    // Matches dashed string for camelizing
    rmsPrefix = /^-ms-/,
    rdashAlpha = /-([\da-z])/gi,

    // Used by jQuery.camelCase as callback to replace()
    fcamelCase = function( all, letter ) {
        return letter.toUpperCase();
    };

jQuery.fn = jQuery.prototype = {

    // The current version of jQuery being used
    jquery: version,

    constructor: jQuery,

    // Start with an empty selector
    selector: "",

    // The default length of a jQuery object is 0
    length: 0,

    toArray: function() {
        return slice.call( this );
    },

    // Get the Nth element in the matched element set OR
    // Get the whole matched element set as a clean array
    get: function( num ) {
        return num != null ?

            // Return just the one element from the set
            ( num < 0 ? this[ num + this.length ] : this[ num ] ) :

            // Return all the elements in a clean array
            slice.call( this );
    },

    // Take an array of elements and push it onto the stack
    // (returning the new matched element set)
    pushStack: function( elems ) {

        // Build a new jQuery matched element set
        var ret = jQuery.merge( this.constructor(), elems );

        // Add the old object onto the stack (as a reference)
        ret.prevObject = this;
        ret.context = this.context;

        // Return the newly-formed element set
        return ret;
    },

    // Execute a callback for every element in the matched set.
    each: function( callback ) {
        return jQuery.each( this, callback );
    },

    map: function( callback ) {
        return this.pushStack( jQuery.map( this, function( elem, i ) {
            return callback.call( elem, i, elem );
        } ) );
    },

    slice: function() {
        return this.pushStack( slice.apply( this, arguments ) );
    },

    first: function() {
        return this.eq( 0 );
    },

    last: function() {
        return this.eq( -1 );
    },

    eq: function( i ) {
        var len = this.length,
            j = +i + ( i < 0 ? len : 0 );
        return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
    },

    end: function() {
        return this.prevObject || this.constructor();
    },

    // For internal use only.
    // Behaves like an Array's method, not like a jQuery method.
    push: push,
    sort: arr.sort,
    splice: arr.splice
};

jQuery.extend = jQuery.fn.extend = function() {
    var options, name, src, copy, copyIsArray, clone,
        target = arguments[ 0 ] || {},
        i = 1,
        length = arguments.length,
        deep = false;

    // Handle a deep copy situation
    if ( typeof target === "boolean" ) {
        deep = target;

        // Skip the boolean and the target
        target = arguments[ i ] || {};
        i++;
    }

    // Handle case when target is a string or something (possible in deep copy)
    if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
        target = {};
    }

    // Extend jQuery itself if only one argument is passed
    if ( i === length ) {
        target = this;
        i--;
    }

    for ( ; i < length; i++ ) {

        // Only deal with non-null/undefined values
        if ( ( options = arguments[ i ] ) != null ) {

            // Extend the base object
            for ( name in options ) {
                src = target[ name ];
                copy = options[ name ];

                // Prevent never-ending loop
                if ( target === copy ) {
                    continue;
                }

                // Recurse if we're merging plain objects or arrays
                if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
                    ( copyIsArray = jQuery.isArray( copy ) ) ) ) {

                    if ( copyIsArray ) {
                        copyIsArray = false;
                        clone = src && jQuery.isArray( src ) ? src : [];

                    } else {
                        clone = src && jQuery.isPlainObject( src ) ? src : {};
                    }

                    // Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );

                // Don't bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }

    // Return the modified object
    return target;
};

jQuery.extend( {

    // Unique for each copy of jQuery on the page
    expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),

    // Assume jQuery is ready without the ready module
    isReady: true,

    error: function( msg ) {
        throw new Error( msg );
    },

    noop: function() {},

    isFunction: function( obj ) {
        return jQuery.type( obj ) === "function";
    },

    isArray: Array.isArray,

    isWindow: function( obj ) {
        return obj != null && obj === obj.window;
    },

    isNumeric: function( obj ) {

        // parseFloat NaNs numeric-cast false positives (null|true|false|"")
        // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
        // subtraction forces infinities to NaN
        // adding 1 corrects loss of precision from parseFloat (#15100)
        var realStringObj = obj && obj.toString();
        return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
    },

    isPlainObject: function( obj ) {
        var key;

        // Not plain objects:
        // - Any object or value whose internal [[Class]] property is not "[object Object]"
        // - DOM nodes
        // - window
        if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
            return false;
        }

        // Not own constructor property must be Object
        if ( obj.constructor &&
                !hasOwn.call( obj, "constructor" ) &&
                !hasOwn.call( obj.constructor.prototype || {}, "isPrototypeOf" ) ) {
            return false;
        }

        // Own properties are enumerated firstly, so to speed up,
        // if last one is own, then all properties are own
        for ( key in obj ) {}

        return key === undefined || hasOwn.call( obj, key );
    },

    isEmptyObject: function( obj ) {
        var name;
        for ( name in obj ) {
            return false;
        }
        return true;
    },

    type: function( obj ) {
        if ( obj == null ) {
            return obj + "";
        }

        // Support: Android<4.0, iOS<6 (functionish RegExp)
        return typeof obj === "object" || typeof obj === "function" ?
            class2type[ toString.call( obj ) ] || "object" :
            typeof obj;
    },

    // Evaluates a script in a global context
    globalEval: function( code ) {
        var script,
            indirect = eval;

        code = jQuery.trim( code );

        if ( code ) {

            // If the code includes a valid, prologue position
            // strict mode pragma, execute code by injecting a
            // script tag into the document.
            if ( code.indexOf( "use strict" ) === 1 ) {
                script = document.createElement( "script" );
                script.text = code;
                document.head.appendChild( script ).parentNode.removeChild( script );
            } else {

                // Otherwise, avoid the DOM node creation, insertion
                // and removal by using an indirect global eval

                indirect( code );
            }
        }
    },

    // Convert dashed to camelCase; used by the css and data modules
    // Support: IE9-11+
    // Microsoft forgot to hump their vendor prefix (#9572)
    camelCase: function( string ) {
        return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
    },

    nodeName: function( elem, name ) {
        return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
    },

    each: function( obj, callback ) {
        var length, i = 0;

        if ( isArrayLike( obj ) ) {
            length = obj.length;
            for ( ; i < length; i++ ) {
                if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                    break;
                }
            }
        } else {
            for ( i in obj ) {
                if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                    break;
                }
            }
        }

        return obj;
    },

    // Support: Android<4.1
    trim: function( text ) {
        return text == null ?
            "" :
            ( text + "" ).replace( rtrim, "" );
    },

    // results is for internal usage only
    makeArray: function( arr, results ) {
        var ret = results || [];

        if ( arr != null ) {
            if ( isArrayLike( Object( arr ) ) ) {
                jQuery.merge( ret,
                    typeof arr === "string" ?
                    [ arr ] : arr
                );
            } else {
                push.call( ret, arr );
            }
        }

        return ret;
    },

    inArray: function( elem, arr, i ) {
        return arr == null ? -1 : indexOf.call( arr, elem, i );
    },

    merge: function( first, second ) {
        var len = +second.length,
            j = 0,
            i = first.length;

        for ( ; j < len; j++ ) {
            first[ i++ ] = second[ j ];
        }

        first.length = i;

        return first;
    },

    grep: function( elems, callback, invert ) {
        var callbackInverse,
            matches = [],
            i = 0,
            length = elems.length,
            callbackExpect = !invert;

        // Go through the array, only saving the items
        // that pass the validator function
        for ( ; i < length; i++ ) {
            callbackInverse = !callback( elems[ i ], i );
            if ( callbackInverse !== callbackExpect ) {
                matches.push( elems[ i ] );
            }
        }

        return matches;
    },

    // arg is for internal usage only
    map: function( elems, callback, arg ) {
        var length, value,
            i = 0,
            ret = [];

        // Go through the array, translating each of the items to their new values
        if ( isArrayLike( elems ) ) {
            length = elems.length;
            for ( ; i < length; i++ ) {
                value = callback( elems[ i ], i, arg );

                if ( value != null ) {
                    ret.push( value );
                }
            }

        // Go through every key on the object,
        } else {
            for ( i in elems ) {
                value = callback( elems[ i ], i, arg );

                if ( value != null ) {
                    ret.push( value );
                }
            }
        }

        // Flatten any nested arrays
        return concat.apply( [], ret );
    },

    // A global GUID counter for objects
    guid: 1,

    // Bind a function to a context, optionally partially applying any
    // arguments.
    proxy: function( fn, context ) {
        var tmp, args, proxy;

        if ( typeof context === "string" ) {
            tmp = fn[ context ];
            context = fn;
            fn = tmp;
        }

        // Quick check to determine if target is callable, in the spec
        // this throws a TypeError, but we will just return undefined.
        if ( !jQuery.isFunction( fn ) ) {
            return undefined;
        }

        // Simulated bind
        args = slice.call( arguments, 2 );
        proxy = function() {
            return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
        };

        // Set the guid of unique handler to the same of original handler, so it can be removed
        proxy.guid = fn.guid = fn.guid || jQuery.guid++;

        return proxy;
    },

    now: Date.now,

    // jQuery.support is not used in Core but other projects attach their
    // properties to it so it needs to exist.
    support: support
} );

// JSHint would error on this code due to the Symbol not being defined in ES5.
// Defining this global in .jshintrc would create a danger of using the global
// unguarded in another place, it seems safer to just disable JSHint for these
// three lines.
/* jshint ignore: start */
if ( typeof Symbol === "function" ) {
    jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
}
/* jshint ignore: end */

// Populate the class2type map
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
function( i, name ) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
} );

function isArrayLike( obj ) {

    // Support: iOS 8.2 (not reproducible in simulator)
    // `in` check used to prevent JIT error (gh-2145)
    // hasOwn isn't used here due to false negatives
    // regarding Nodelist length in IE
    var length = !!obj && "length" in obj && obj.length,
        type = jQuery.type( obj );

    if ( type === "function" || jQuery.isWindow( obj ) ) {
        return false;
    }

    return type === "array" || length === 0 ||
        typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
var Sizzle =
/*!
 * Sizzle CSS Selector Engine v2.2.1
 * http://sizzlejs.com/
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2015-10-17
 */
(function( window ) {

var i,
    support,
    Expr,
    getText,
    isXML,
    tokenize,
    compile,
    select,
    outermostContext,
    sortInput,
    hasDuplicate,

    // Local document vars
    setDocument,
    document,
    docElem,
    documentIsHTML,
    rbuggyQSA,
    rbuggyMatches,
    matches,
    contains,

    // Instance-specific data
    expando = "sizzle" + 1 * new Date(),
    preferredDoc = window.document,
    dirruns = 0,
    done = 0,
    classCache = createCache(),
    tokenCache = createCache(),
    compilerCache = createCache(),
    sortOrder = function( a, b ) {
        if ( a === b ) {
            hasDuplicate = true;
        }
        return 0;
    },

    // General-purpose constants
    MAX_NEGATIVE = 1 << 31,

    // Instance methods
    hasOwn = ({}).hasOwnProperty,
    arr = [],
    pop = arr.pop,
    push_native = arr.push,
    push = arr.push,
    slice = arr.slice,
    // Use a stripped-down indexOf as it's faster than native
    // http://jsperf.com/thor-indexof-vs-for/5
    indexOf = function( list, elem ) {
        var i = 0,
            len = list.length;
        for ( ; i < len; i++ ) {
            if ( list[i] === elem ) {
                return i;
            }
        }
        return -1;
    },

    booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",

    // Regular expressions

    // http://www.w3.org/TR/css3-selectors/#whitespace
    whitespace = "[\\x20\\t\\r\\n\\f]",

    // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
    identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",

    // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
    attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
        // Operator (capture 2)
        "*([*^$|!~]?=)" + whitespace +
        // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
        "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
        "*\\]",

    pseudos = ":(" + identifier + ")(?:\\((" +
        // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
        // 1. quoted (capture 3; capture 4 or capture 5)
        "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
        // 2. simple (capture 6)
        "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
        // 3. anything else (capture 2)
        ".*" +
        ")\\)|)",

    // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
    rwhitespace = new RegExp( whitespace + "+", "g" ),
    rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),

    rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
    rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),

    rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),

    rpseudo = new RegExp( pseudos ),
    ridentifier = new RegExp( "^" + identifier + "$" ),

    matchExpr = {
        "ID": new RegExp( "^#(" + identifier + ")" ),
        "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
        "TAG": new RegExp( "^(" + identifier + "|[*])" ),
        "ATTR": new RegExp( "^" + attributes ),
        "PSEUDO": new RegExp( "^" + pseudos ),
        "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
            "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
            "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
        "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
        // For use in libraries implementing .is()
        // We use this for POS matching in `select`
        "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
            whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
    },

    rinputs = /^(?:input|select|textarea|button)$/i,
    rheader = /^h\d$/i,

    rnative = /^[^{]+\{\s*\[native \w/,

    // Easily-parseable/retrievable ID or TAG or CLASS selectors
    rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

    rsibling = /[+~]/,
    rescape = /'|\\/g,

    // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
    runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
    funescape = function( _, escaped, escapedWhitespace ) {
        var high = "0x" + escaped - 0x10000;
        // NaN means non-codepoint
        // Support: Firefox<24
        // Workaround erroneous numeric interpretation of +"0x"
        return high !== high || escapedWhitespace ?
            escaped :
            high < 0 ?
                // BMP codepoint
                String.fromCharCode( high + 0x10000 ) :
                // Supplemental Plane codepoint (surrogate pair)
                String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
    },

    // Used for iframes
    // See setDocument()
    // Removing the function wrapper causes a "Permission Denied"
    // error in IE
    unloadHandler = function() {
        setDocument();
    };

// Optimize for push.apply( _, NodeList )
try {
    push.apply(
        (arr = slice.call( preferredDoc.childNodes )),
        preferredDoc.childNodes
    );
    // Support: Android<4.0
    // Detect silently failing push.apply
    arr[ preferredDoc.childNodes.length ].nodeType;
} catch ( e ) {
    push = { apply: arr.length ?

        // Leverage slice if possible
        function( target, els ) {
            push_native.apply( target, slice.call(els) );
        } :

        // Support: IE<9
        // Otherwise append directly
        function( target, els ) {
            var j = target.length,
                i = 0;
            // Can't trust NodeList.length
            while ( (target[j++] = els[i++]) ) {}
            target.length = j - 1;
        }
    };
}

function Sizzle( selector, context, results, seed ) {
    var m, i, elem, nid, nidselect, match, groups, newSelector,
        newContext = context && context.ownerDocument,

        // nodeType defaults to 9, since context defaults to document
        nodeType = context ? context.nodeType : 9;

    results = results || [];

    // Return early from calls with invalid selector or context
    if ( typeof selector !== "string" || !selector ||
        nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {

        return results;
    }

    // Try to shortcut find operations (as opposed to filters) in HTML documents
    if ( !seed ) {

        if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
            setDocument( context );
        }
        context = context || document;

        if ( documentIsHTML ) {

            // If the selector is sufficiently simple, try using a "get*By*" DOM method
            // (excepting DocumentFragment context, where the methods don't exist)
            if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {

                // ID selector
                if ( (m = match[1]) ) {

                    // Document context
                    if ( nodeType === 9 ) {
                        if ( (elem = context.getElementById( m )) ) {

                            // Support: IE, Opera, Webkit
                            // TODO: identify versions
                            // getElementById can match elements by name instead of ID
                            if ( elem.id === m ) {
                                results.push( elem );
                                return results;
                            }
                        } else {
                            return results;
                        }

                    // Element context
                    } else {

                        // Support: IE, Opera, Webkit
                        // TODO: identify versions
                        // getElementById can match elements by name instead of ID
                        if ( newContext && (elem = newContext.getElementById( m )) &&
                            contains( context, elem ) &&
                            elem.id === m ) {

                            results.push( elem );
                            return results;
                        }
                    }

                // Type selector
                } else if ( match[2] ) {
                    push.apply( results, context.getElementsByTagName( selector ) );
                    return results;

                // Class selector
                } else if ( (m = match[3]) && support.getElementsByClassName &&
                    context.getElementsByClassName ) {

                    push.apply( results, context.getElementsByClassName( m ) );
                    return results;
                }
            }

            // Take advantage of querySelectorAll
            if ( support.qsa &&
                !compilerCache[ selector + " " ] &&
                (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {

                if ( nodeType !== 1 ) {
                    newContext = context;
                    newSelector = selector;

                // qSA looks outside Element context, which is not what we want
                // Thanks to Andrew Dupont for this workaround technique
                // Support: IE <=8
                // Exclude object elements
                } else if ( context.nodeName.toLowerCase() !== "object" ) {

                    // Capture the context ID, setting it first if necessary
                    if ( (nid = context.getAttribute( "id" )) ) {
                        nid = nid.replace( rescape, "\\$&" );
                    } else {
                        context.setAttribute( "id", (nid = expando) );
                    }

                    // Prefix every selector in the list
                    groups = tokenize( selector );
                    i = groups.length;
                    nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']";
                    while ( i-- ) {
                        groups[i] = nidselect + " " + toSelector( groups[i] );
                    }
                    newSelector = groups.join( "," );

                    // Expand context for sibling selectors
                    newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
                        context;
                }

                if ( newSelector ) {
                    try {
                        push.apply( results,
                            newContext.querySelectorAll( newSelector )
                        );
                        return results;
                    } catch ( qsaError ) {
                    } finally {
                        if ( nid === expando ) {
                            context.removeAttribute( "id" );
                        }
                    }
                }
            }
        }
    }

    // All others
    return select( selector.replace( rtrim, "$1" ), context, results, seed );
}

/**
 * Create key-value caches of limited size
 * @returns {function(string, object)} Returns the Object data after storing it on itself with
 *  property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
 *  deleting the oldest entry
 */
function createCache() {
    var keys = [];

    function cache( key, value ) {
        // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
        if ( keys.push( key + " " ) > Expr.cacheLength ) {
            // Only keep the most recent entries
            delete cache[ keys.shift() ];
        }
        return (cache[ key + " " ] = value);
    }
    return cache;
}

/**
 * Mark a function for special use by Sizzle
 * @param {Function} fn The function to mark
 */
function markFunction( fn ) {
    fn[ expando ] = true;
    return fn;
}

/**
 * Support testing using an element
 * @param {Function} fn Passed the created div and expects a boolean result
 */
function assert( fn ) {
    var div = document.createElement("div");

    try {
        return !!fn( div );
    } catch (e) {
        return false;
    } finally {
        // Remove from its parent by default
        if ( div.parentNode ) {
            div.parentNode.removeChild( div );
        }
        // release memory in IE
        div = null;
    }
}

/**
 * Adds the same handler for all of the specified attrs
 * @param {String} attrs Pipe-separated list of attributes
 * @param {Function} handler The method that will be applied
 */
function addHandle( attrs, handler ) {
    var arr = attrs.split("|"),
        i = arr.length;

    while ( i-- ) {
        Expr.attrHandle[ arr[i] ] = handler;
    }
}

/**
 * Checks document order of two siblings
 * @param {Element} a
 * @param {Element} b
 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
 */
function siblingCheck( a, b ) {
    var cur = b && a,
        diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
            ( ~b.sourceIndex || MAX_NEGATIVE ) -
            ( ~a.sourceIndex || MAX_NEGATIVE );

    // Use IE sourceIndex if available on both nodes
    if ( diff ) {
        return diff;
    }

    // Check if b follows a
    if ( cur ) {
        while ( (cur = cur.nextSibling) ) {
            if ( cur === b ) {
                return -1;
            }
        }
    }

    return a ? 1 : -1;
}

/**
 * Returns a function to use in pseudos for input types
 * @param {String} type
 */
function createInputPseudo( type ) {
    return function( elem ) {
        var name = elem.nodeName.toLowerCase();
        return name === "input" && elem.type === type;
    };
}

/**
 * Returns a function to use in pseudos for buttons
 * @param {String} type
 */
function createButtonPseudo( type ) {
    return function( elem ) {
        var name = elem.nodeName.toLowerCase();
        return (name === "input" || name === "button") && elem.type === type;
    };
}

/**
 * Returns a function to use in pseudos for positionals
 * @param {Function} fn
 */
function createPositionalPseudo( fn ) {
    return markFunction(function( argument ) {
        argument = +argument;
        return markFunction(function( seed, matches ) {
            var j,
                matchIndexes = fn( [], seed.length, argument ),
                i = matchIndexes.length;

            // Match elements found at the specified indexes
            while ( i-- ) {
                if ( seed[ (j = matchIndexes[i]) ] ) {
                    seed[j] = !(matches[j] = seed[j]);
                }
            }
        });
    });
}

/**
 * Checks a node for validity as a Sizzle context
 * @param {Element|Object=} context
 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
 */
function testContext( context ) {
    return context && typeof context.getElementsByTagName !== "undefined" && context;
}

// Expose support vars for convenience
support = Sizzle.support = {};

/**
 * Detects XML nodes
 * @param {Element|Object} elem An element or a document
 * @returns {Boolean} True iff elem is a non-HTML XML node
 */
isXML = Sizzle.isXML = function( elem ) {
    // documentElement is verified for cases where it doesn't yet exist
    // (such as loading iframes in IE - #4833)
    var documentElement = elem && (elem.ownerDocument || elem).documentElement;
    return documentElement ? documentElement.nodeName !== "HTML" : false;
};

/**
 * Sets document-related variables once based on the current document
 * @param {Element|Object} [doc] An element or document object to use to set the document
 * @returns {Object} Returns the current document
 */
setDocument = Sizzle.setDocument = function( node ) {
    var hasCompare, parent,
        doc = node ? node.ownerDocument || node : preferredDoc;

    // Return early if doc is invalid or already selected
    if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
        return document;
    }

    // Update global variables
    document = doc;
    docElem = document.documentElement;
    documentIsHTML = !isXML( document );

    // Support: IE 9-11, Edge
    // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
    if ( (parent = document.defaultView) && parent.top !== parent ) {
        // Support: IE 11
        if ( parent.addEventListener ) {
            parent.addEventListener( "unload", unloadHandler, false );

        // Support: IE 9 - 10 only
        } else if ( parent.attachEvent ) {
            parent.attachEvent( "onunload", unloadHandler );
        }
    }

    /* Attributes
    ---------------------------------------------------------------------- */

    // Support: IE<8
    // Verify that getAttribute really returns attributes and not properties
    // (excepting IE8 booleans)
    support.attributes = assert(function( div ) {
        div.className = "i";
        return !div.getAttribute("className");
    });

    /* getElement(s)By*
    ---------------------------------------------------------------------- */

    // Check if getElementsByTagName("*") returns only elements
    support.getElementsByTagName = assert(function( div ) {
        div.appendChild( document.createComment("") );
        return !div.getElementsByTagName("*").length;
    });

    // Support: IE<9
    support.getElementsByClassName = rnative.test( document.getElementsByClassName );

    // Support: IE<10
    // Check if getElementById returns elements by name
    // The broken getElementById methods don't pick up programatically-set names,
    // so use a roundabout getElementsByName test
    support.getById = assert(function( div ) {
        docElem.appendChild( div ).id = expando;
        return !document.getElementsByName || !document.getElementsByName( expando ).length;
    });

    // ID find and filter
    if ( support.getById ) {
        Expr.find["ID"] = function( id, context ) {
            if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
                var m = context.getElementById( id );
                return m ? [ m ] : [];
            }
        };
        Expr.filter["ID"] = function( id ) {
            var attrId = id.replace( runescape, funescape );
            return function( elem ) {
                return elem.getAttribute("id") === attrId;
            };
        };
    } else {
        // Support: IE6/7
        // getElementById is not reliable as a find shortcut
        delete Expr.find["ID"];

        Expr.filter["ID"] =  function( id ) {
            var attrId = id.replace( runescape, funescape );
            return function( elem ) {
                var node = typeof elem.getAttributeNode !== "undefined" &&
                    elem.getAttributeNode("id");
                return node && node.value === attrId;
            };
        };
    }

    // Tag
    Expr.find["TAG"] = support.getElementsByTagName ?
        function( tag, context ) {
            if ( typeof context.getElementsByTagName !== "undefined" ) {
                return context.getElementsByTagName( tag );

            // DocumentFragment nodes don't have gEBTN
            } else if ( support.qsa ) {
                return context.querySelectorAll( tag );
            }
        } :

        function( tag, context ) {
            var elem,
                tmp = [],
                i = 0,
                // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
                results = context.getElementsByTagName( tag );

            // Filter out possible comments
            if ( tag === "*" ) {
                while ( (elem = results[i++]) ) {
                    if ( elem.nodeType === 1 ) {
                        tmp.push( elem );
                    }
                }

                return tmp;
            }
            return results;
        };

    // Class
    Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
        if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
            return context.getElementsByClassName( className );
        }
    };

    /* QSA/matchesSelector
    ---------------------------------------------------------------------- */

    // QSA and matchesSelector support

    // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
    rbuggyMatches = [];

    // qSa(:focus) reports false when true (Chrome 21)
    // We allow this because of a bug in IE8/9 that throws an error
    // whenever `document.activeElement` is accessed on an iframe
    // So, we allow :focus to pass through QSA all the time to avoid the IE error
    // See http://bugs.jquery.com/ticket/13378
    rbuggyQSA = [];

    if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
        // Build QSA regex
        // Regex strategy adopted from Diego Perini
        assert(function( div ) {
            // Select is set to empty string on purpose
            // This is to test IE's treatment of not explicitly
            // setting a boolean content attribute,
            // since its presence should be enough
            // http://bugs.jquery.com/ticket/12359
            docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
                "<select id='" + expando + "-\r\\' msallowcapture=''>" +
                "<option selected=''></option></select>";

            // Support: IE8, Opera 11-12.16
            // Nothing should be selected when empty strings follow ^= or $= or *=
            // The test attribute must be unknown in Opera but "safe" for WinRT
            // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
            if ( div.querySelectorAll("[msallowcapture^='']").length ) {
                rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
            }

            // Support: IE8
            // Boolean attributes and "value" are not treated correctly
            if ( !div.querySelectorAll("[selected]").length ) {
                rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
            }

            // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
            if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
                rbuggyQSA.push("~=");
            }

            // Webkit/Opera - :checked should return selected option elements
            // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
            // IE8 throws error here and will not see later tests
            if ( !div.querySelectorAll(":checked").length ) {
                rbuggyQSA.push(":checked");
            }

            // Support: Safari 8+, iOS 8+
            // https://bugs.webkit.org/show_bug.cgi?id=136851
            // In-page `selector#id sibing-combinator selector` fails
            if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
                rbuggyQSA.push(".#.+[+~]");
            }
        });

        assert(function( div ) {
            // Support: Windows 8 Native Apps
            // The type and name attributes are restricted during .innerHTML assignment
            var input = document.createElement("input");
            input.setAttribute( "type", "hidden" );
            div.appendChild( input ).setAttribute( "name", "D" );

            // Support: IE8
            // Enforce case-sensitivity of name attribute
            if ( div.querySelectorAll("[name=d]").length ) {
                rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
            }

            // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
            // IE8 throws error here and will not see later tests
            if ( !div.querySelectorAll(":enabled").length ) {
                rbuggyQSA.push( ":enabled", ":disabled" );
            }

            // Opera 10-11 does not throw on post-comma invalid pseudos
            div.querySelectorAll("*,:x");
            rbuggyQSA.push(",.*:");
        });
    }

    if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
        docElem.webkitMatchesSelector ||
        docElem.mozMatchesSelector ||
        docElem.oMatchesSelector ||
        docElem.msMatchesSelector) )) ) {

        assert(function( div ) {
            // Check to see if it's possible to do matchesSelector
            // on a disconnected node (IE 9)
            support.disconnectedMatch = matches.call( div, "div" );

            // This should fail with an exception
            // Gecko does not error, returns false instead
            matches.call( div, "[s!='']:x" );
            rbuggyMatches.push( "!=", pseudos );
        });
    }

    rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
    rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );

    /* Contains
    ---------------------------------------------------------------------- */
    hasCompare = rnative.test( docElem.compareDocumentPosition );

    // Element contains another
    // Purposefully self-exclusive
    // As in, an element does not contain itself
    contains = hasCompare || rnative.test( docElem.contains ) ?
        function( a, b ) {
            var adown = a.nodeType === 9 ? a.documentElement : a,
                bup = b && b.parentNode;
            return a === bup || !!( bup && bup.nodeType === 1 && (
                adown.contains ?
                    adown.contains( bup ) :
                    a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
            ));
        } :
        function( a, b ) {
            if ( b ) {
                while ( (b = b.parentNode) ) {
                    if ( b === a ) {
                        return true;
                    }
                }
            }
            return false;
        };

    /* Sorting
    ---------------------------------------------------------------------- */

    // Document order sorting
    sortOrder = hasCompare ?
    function( a, b ) {

        // Flag for duplicate removal
        if ( a === b ) {
            hasDuplicate = true;
            return 0;
        }

        // Sort on method existence if only one input has compareDocumentPosition
        var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
        if ( compare ) {
            return compare;
        }

        // Calculate position if both inputs belong to the same document
        compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
            a.compareDocumentPosition( b ) :

            // Otherwise we know they are disconnected
            1;

        // Disconnected nodes
        if ( compare & 1 ||
            (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {

            // Choose the first element that is related to our preferred document
            if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
                return -1;
            }
            if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
                return 1;
            }

            // Maintain original order
            return sortInput ?
                ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
                0;
        }

        return compare & 4 ? -1 : 1;
    } :
    function( a, b ) {
        // Exit early if the nodes are identical
        if ( a === b ) {
            hasDuplicate = true;
            return 0;
        }

        var cur,
            i = 0,
            aup = a.parentNode,
            bup = b.parentNode,
            ap = [ a ],
            bp = [ b ];

        // Parentless nodes are either documents or disconnected
        if ( !aup || !bup ) {
            return a === document ? -1 :
                b === document ? 1 :
                aup ? -1 :
                bup ? 1 :
                sortInput ?
                ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
                0;

        // If the nodes are siblings, we can do a quick check
        } else if ( aup === bup ) {
            return siblingCheck( a, b );
        }

        // Otherwise we need full lists of their ancestors for comparison
        cur = a;
        while ( (cur = cur.parentNode) ) {
            ap.unshift( cur );
        }
        cur = b;
        while ( (cur = cur.parentNode) ) {
            bp.unshift( cur );
        }

        // Walk down the tree looking for a discrepancy
        while ( ap[i] === bp[i] ) {
            i++;
        }

        return i ?
            // Do a sibling check if the nodes have a common ancestor
            siblingCheck( ap[i], bp[i] ) :

            // Otherwise nodes in our document sort first
            ap[i] === preferredDoc ? -1 :
            bp[i] === preferredDoc ? 1 :
            0;
    };

    return document;
};

Sizzle.matches = function( expr, elements ) {
    return Sizzle( expr, null, null, elements );
};

Sizzle.matchesSelector = function( elem, expr ) {
    // Set document vars if needed
    if ( ( elem.ownerDocument || elem ) !== document ) {
        setDocument( elem );
    }

    // Make sure that attribute selectors are quoted
    expr = expr.replace( rattributeQuotes, "='$1']" );

    if ( support.matchesSelector && documentIsHTML &&
        !compilerCache[ expr + " " ] &&
        ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
        ( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {

        try {
            var ret = matches.call( elem, expr );

            // IE 9's matchesSelector returns false on disconnected nodes
            if ( ret || support.disconnectedMatch ||
                    // As well, disconnected nodes are said to be in a document
                    // fragment in IE 9
                    elem.document && elem.document.nodeType !== 11 ) {
                return ret;
            }
        } catch (e) {}
    }

    return Sizzle( expr, document, null, [ elem ] ).length > 0;
};

Sizzle.contains = function( context, elem ) {
    // Set document vars if needed
    if ( ( context.ownerDocument || context ) !== document ) {
        setDocument( context );
    }
    return contains( context, elem );
};

Sizzle.attr = function( elem, name ) {
    // Set document vars if needed
    if ( ( elem.ownerDocument || elem ) !== document ) {
        setDocument( elem );
    }

    var fn = Expr.attrHandle[ name.toLowerCase() ],
        // Don't get fooled by Object.prototype properties (jQuery #13807)
        val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
            fn( elem, name, !documentIsHTML ) :
            undefined;

    return val !== undefined ?
        val :
        support.attributes || !documentIsHTML ?
            elem.getAttribute( name ) :
            (val = elem.getAttributeNode(name)) && val.specified ?
                val.value :
                null;
};

Sizzle.error = function( msg ) {
    throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Document sorting and removing duplicates
 * @param {ArrayLike} results
 */
Sizzle.uniqueSort = function( results ) {
    var elem,
        duplicates = [],
        j = 0,
        i = 0;

    // Unless we *know* we can detect duplicates, assume their presence
    hasDuplicate = !support.detectDuplicates;
    sortInput = !support.sortStable && results.slice( 0 );
    results.sort( sortOrder );

    if ( hasDuplicate ) {
        while ( (elem = results[i++]) ) {
            if ( elem === results[ i ] ) {
                j = duplicates.push( i );
            }
        }
        while ( j-- ) {
            results.splice( duplicates[ j ], 1 );
        }
    }

    // Clear input after sorting to release objects
    // See https://github.com/jquery/sizzle/pull/225
    sortInput = null;

    return results;
};

/**
 * Utility function for retrieving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
getText = Sizzle.getText = function( elem ) {
    var node,
        ret = "",
        i = 0,
        nodeType = elem.nodeType;

    if ( !nodeType ) {
        // If no nodeType, this is expected to be an array
        while ( (node = elem[i++]) ) {
            // Do not traverse comment nodes
            ret += getText( node );
        }
    } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
        // Use textContent for elements
        // innerText usage removed for consistency of new lines (jQuery #11153)
        if ( typeof elem.textContent === "string" ) {
            return elem.textContent;
        } else {
            // Traverse its children
            for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
                ret += getText( elem );
            }
        }
    } else if ( nodeType === 3 || nodeType === 4 ) {
        return elem.nodeValue;
    }
    // Do not include comment or processing instruction nodes

    return ret;
};

Expr = Sizzle.selectors = {

    // Can be adjusted by the user
    cacheLength: 50,

    createPseudo: markFunction,

    match: matchExpr,

    attrHandle: {},

    find: {},

    relative: {
        ">": { dir: "parentNode", first: true },
        " ": { dir: "parentNode" },
        "+": { dir: "previousSibling", first: true },
        "~": { dir: "previousSibling" }
    },

    preFilter: {
        "ATTR": function( match ) {
            match[1] = match[1].replace( runescape, funescape );

            // Move the given value to match[3] whether quoted or unquoted
            match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );

            if ( match[2] === "~=" ) {
                match[3] = " " + match[3] + " ";
            }

            return match.slice( 0, 4 );
        },

        "CHILD": function( match ) {
            /* matches from matchExpr["CHILD"]
                1 type (only|nth|...)
                2 what (child|of-type)
                3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
                4 xn-component of xn+y argument ([+-]?\d*n|)
                5 sign of xn-component
                6 x of xn-component
                7 sign of y-component
                8 y of y-component
            */
            match[1] = match[1].toLowerCase();

            if ( match[1].slice( 0, 3 ) === "nth" ) {
                // nth-* requires argument
                if ( !match[3] ) {
                    Sizzle.error( match[0] );
                }

                // numeric x and y parameters for Expr.filter.CHILD
                // remember that false/true cast respectively to 0/1
                match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
                match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );

            // other types prohibit arguments
            } else if ( match[3] ) {
                Sizzle.error( match[0] );
            }

            return match;
        },

        "PSEUDO": function( match ) {
            var excess,
                unquoted = !match[6] && match[2];

            if ( matchExpr["CHILD"].test( match[0] ) ) {
                return null;
            }

            // Accept quoted arguments as-is
            if ( match[3] ) {
                match[2] = match[4] || match[5] || "";

            // Strip excess characters from unquoted arguments
            } else if ( unquoted && rpseudo.test( unquoted ) &&
                // Get excess from tokenize (recursively)
                (excess = tokenize( unquoted, true )) &&
                // advance to the next closing parenthesis
                (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {

                // excess is a negative index
                match[0] = match[0].slice( 0, excess );
                match[2] = unquoted.slice( 0, excess );
            }

            // Return only captures needed by the pseudo filter method (type and argument)
            return match.slice( 0, 3 );
        }
    },

    filter: {

        "TAG": function( nodeNameSelector ) {
            var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
            return nodeNameSelector === "*" ?
                function() { return true; } :
                function( elem ) {
                    return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
                };
        },

        "CLASS": function( className ) {
            var pattern = classCache[ className + " " ];

            return pattern ||
                (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
                classCache( className, function( elem ) {
                    return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
                });
        },

        "ATTR": function( name, operator, check ) {
            return function( elem ) {
                var result = Sizzle.attr( elem, name );

                if ( result == null ) {
                    return operator === "!=";
                }
                if ( !operator ) {
                    return true;
                }

                result += "";

                return operator === "=" ? result === check :
                    operator === "!=" ? result !== check :
                    operator === "^=" ? check && result.indexOf( check ) === 0 :
                    operator === "*=" ? check && result.indexOf( check ) > -1 :
                    operator === "$=" ? check && result.slice( -check.length ) === check :
                    operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
                    operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
                    false;
            };
        },

        "CHILD": function( type, what, argument, first, last ) {
            var simple = type.slice( 0, 3 ) !== "nth",
                forward = type.slice( -4 ) !== "last",
                ofType = what === "of-type";

            return first === 1 && last === 0 ?

                // Shortcut for :nth-*(n)
                function( elem ) {
                    return !!elem.parentNode;
                } :

                function( elem, context, xml ) {
                    var cache, uniqueCache, outerCache, node, nodeIndex, start,
                        dir = simple !== forward ? "nextSibling" : "previousSibling",
                        parent = elem.parentNode,
                        name = ofType && elem.nodeName.toLowerCase(),
                        useCache = !xml && !ofType,
                        diff = false;

                    if ( parent ) {

                        // :(first|last|only)-(child|of-type)
                        if ( simple ) {
                            while ( dir ) {
                                node = elem;
                                while ( (node = node[ dir ]) ) {
                                    if ( ofType ?
                                        node.nodeName.toLowerCase() === name :
                                        node.nodeType === 1 ) {

                                        return false;
                                    }
                                }
                                // Reverse direction for :only-* (if we haven't yet done so)
                                start = dir = type === "only" && !start && "nextSibling";
                            }
                            return true;
                        }

                        start = [ forward ? parent.firstChild : parent.lastChild ];

                        // non-xml :nth-child(...) stores cache data on `parent`
                        if ( forward && useCache ) {

                            // Seek `elem` from a previously-cached index

                            // ...in a gzip-friendly way
                            node = parent;
                            outerCache = node[ expando ] || (node[ expando ] = {});

                            // Support: IE <9 only
                            // Defend against cloned attroperties (jQuery gh-1709)
                            uniqueCache = outerCache[ node.uniqueID ] ||
                                (outerCache[ node.uniqueID ] = {});

                            cache = uniqueCache[ type ] || [];
                            nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
                            diff = nodeIndex && cache[ 2 ];
                            node = nodeIndex && parent.childNodes[ nodeIndex ];

                            while ( (node = ++nodeIndex && node && node[ dir ] ||

                                // Fallback to seeking `elem` from the start
                                (diff = nodeIndex = 0) || start.pop()) ) {

                                // When found, cache indexes on `parent` and break
                                if ( node.nodeType === 1 && ++diff && node === elem ) {
                                    uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
                                    break;
                                }
                            }

                        } else {
                            // Use previously-cached element index if available
                            if ( useCache ) {
                                // ...in a gzip-friendly way
                                node = elem;
                                outerCache = node[ expando ] || (node[ expando ] = {});

                                // Support: IE <9 only
                                // Defend against cloned attroperties (jQuery gh-1709)
                                uniqueCache = outerCache[ node.uniqueID ] ||
                                    (outerCache[ node.uniqueID ] = {});

                                cache = uniqueCache[ type ] || [];
                                nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
                                diff = nodeIndex;
                            }

                            // xml :nth-child(...)
                            // or :nth-last-child(...) or :nth(-last)?-of-type(...)
                            if ( diff === false ) {
                                // Use the same loop as above to seek `elem` from the start
                                while ( (node = ++nodeIndex && node && node[ dir ] ||
                                    (diff = nodeIndex = 0) || start.pop()) ) {

                                    if ( ( ofType ?
                                        node.nodeName.toLowerCase() === name :
                                        node.nodeType === 1 ) &&
                                        ++diff ) {

                                        // Cache the index of each encountered element
                                        if ( useCache ) {
                                            outerCache = node[ expando ] || (node[ expando ] = {});

                                            // Support: IE <9 only
                                            // Defend against cloned attroperties (jQuery gh-1709)
                                            uniqueCache = outerCache[ node.uniqueID ] ||
                                                (outerCache[ node.uniqueID ] = {});

                                            uniqueCache[ type ] = [ dirruns, diff ];
                                        }

                                        if ( node === elem ) {
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        // Incorporate the offset, then check against cycle size
                        diff -= last;
                        return diff === first || ( diff % first === 0 && diff / first >= 0 );
                    }
                };
        },

        "PSEUDO": function( pseudo, argument ) {
            // pseudo-class names are case-insensitive
            // http://www.w3.org/TR/selectors/#pseudo-classes
            // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
            // Remember that setFilters inherits from pseudos
            var args,
                fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
                    Sizzle.error( "unsupported pseudo: " + pseudo );

            // The user may use createPseudo to indicate that
            // arguments are needed to create the filter function
            // just as Sizzle does
            if ( fn[ expando ] ) {
                return fn( argument );
            }

            // But maintain support for old signatures
            if ( fn.length > 1 ) {
                args = [ pseudo, pseudo, "", argument ];
                return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
                    markFunction(function( seed, matches ) {
                        var idx,
                            matched = fn( seed, argument ),
                            i = matched.length;
                        while ( i-- ) {
                            idx = indexOf( seed, matched[i] );
                            seed[ idx ] = !( matches[ idx ] = matched[i] );
                        }
                    }) :
                    function( elem ) {
                        return fn( elem, 0, args );
                    };
            }

            return fn;
        }
    },

    pseudos: {
        // Potentially complex pseudos
        "not": markFunction(function( selector ) {
            // Trim the selector passed to compile
            // to avoid treating leading and trailing
            // spaces as combinators
            var input = [],
                results = [],
                matcher = compile( selector.replace( rtrim, "$1" ) );

            return matcher[ expando ] ?
                markFunction(function( seed, matches, context, xml ) {
                    var elem,
                        unmatched = matcher( seed, null, xml, [] ),
                        i = seed.length;

                    // Match elements unmatched by `matcher`
                    while ( i-- ) {
                        if ( (elem = unmatched[i]) ) {
                            seed[i] = !(matches[i] = elem);
                        }
                    }
                }) :
                function( elem, context, xml ) {
                    input[0] = elem;
                    matcher( input, null, xml, results );
                    // Don't keep the element (issue #299)
                    input[0] = null;
                    return !results.pop();
                };
        }),

        "has": markFunction(function( selector ) {
            return function( elem ) {
                return Sizzle( selector, elem ).length > 0;
            };
        }),

        "contains": markFunction(function( text ) {
            text = text.replace( runescape, funescape );
            return function( elem ) {
                return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
            };
        }),

        // "Whether an element is represented by a :lang() selector
        // is based solely on the element's language value
        // being equal to the identifier C,
        // or beginning with the identifier C immediately followed by "-".
        // The matching of C against the element's language value is performed case-insensitively.
        // The identifier C does not have to be a valid language name."
        // http://www.w3.org/TR/selectors/#lang-pseudo
        "lang": markFunction( function( lang ) {
            // lang value must be a valid identifier
            if ( !ridentifier.test(lang || "") ) {
                Sizzle.error( "unsupported lang: " + lang );
            }
            lang = lang.replace( runescape, funescape ).toLowerCase();
            return function( elem ) {
                var elemLang;
                do {
                    if ( (elemLang = documentIsHTML ?
                        elem.lang :
                        elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {

                        elemLang = elemLang.toLowerCase();
                        return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
                    }
                } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
                return false;
            };
        }),

        // Miscellaneous
        "target": function( elem ) {
            var hash = window.location && window.location.hash;
            return hash && hash.slice( 1 ) === elem.id;
        },

        "root": function( elem ) {
            return elem === docElem;
        },

        "focus": function( elem ) {
            return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
        },

        // Boolean properties
        "enabled": function( elem ) {
            return elem.disabled === false;
        },

        "disabled": function( elem ) {
            return elem.disabled === true;
        },

        "checked": function( elem ) {
            // In CSS3, :checked should return both checked and selected elements
            // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
            var nodeName = elem.nodeName.toLowerCase();
            return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
        },

        "selected": function( elem ) {
            // Accessing this property makes selected-by-default
            // options in Safari work properly
            if ( elem.parentNode ) {
                elem.parentNode.selectedIndex;
            }

            return elem.selected === true;
        },

        // Contents
        "empty": function( elem ) {
            // http://www.w3.org/TR/selectors/#empty-pseudo
            // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
            //   but not by others (comment: 8; processing instruction: 7; etc.)
            // nodeType < 6 works because attributes (2) do not appear as children
            for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
                if ( elem.nodeType < 6 ) {
                    return false;
                }
            }
            return true;
        },

        "parent": function( elem ) {
            return !Expr.pseudos["empty"]( elem );
        },

        // Element/input types
        "header": function( elem ) {
            return rheader.test( elem.nodeName );
        },

        "input": function( elem ) {
            return rinputs.test( elem.nodeName );
        },

        "button": function( elem ) {
            var name = elem.nodeName.toLowerCase();
            return name === "input" && elem.type === "button" || name === "button";
        },

        "text": function( elem ) {
            var attr;
            return elem.nodeName.toLowerCase() === "input" &&
                elem.type === "text" &&

                // Support: IE<8
                // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
                ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
        },

        // Position-in-collection
        "first": createPositionalPseudo(function() {
            return [ 0 ];
        }),

        "last": createPositionalPseudo(function( matchIndexes, length ) {
            return [ length - 1 ];
        }),

        "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
            return [ argument < 0 ? argument + length : argument ];
        }),

        "even": createPositionalPseudo(function( matchIndexes, length ) {
            var i = 0;
            for ( ; i < length; i += 2 ) {
                matchIndexes.push( i );
            }
            return matchIndexes;
        }),

        "odd": createPositionalPseudo(function( matchIndexes, length ) {
            var i = 1;
            for ( ; i < length; i += 2 ) {
                matchIndexes.push( i );
            }
            return matchIndexes;
        }),

        "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
            var i = argument < 0 ? argument + length : argument;
            for ( ; --i >= 0; ) {
                matchIndexes.push( i );
            }
            return matchIndexes;
        }),

        "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
            var i = argument < 0 ? argument + length : argument;
            for ( ; ++i < length; ) {
                matchIndexes.push( i );
            }
            return matchIndexes;
        })
    }
};

Expr.pseudos["nth"] = Expr.pseudos["eq"];

// Add button/input type pseudos
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
    Expr.pseudos[ i ] = createInputPseudo( i );
}
for ( i in { submit: true, reset: true } ) {
    Expr.pseudos[ i ] = createButtonPseudo( i );
}

// Easy API for creating new setFilters
function setFilters() {}
setFilters.prototype = Expr.filters = Expr.pseudos;
Expr.setFilters = new setFilters();

tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
    var matched, match, tokens, type,
        soFar, groups, preFilters,
        cached = tokenCache[ selector + " " ];

    if ( cached ) {
        return parseOnly ? 0 : cached.slice( 0 );
    }

    soFar = selector;
    groups = [];
    preFilters = Expr.preFilter;

    while ( soFar ) {

        // Comma and first run
        if ( !matched || (match = rcomma.exec( soFar )) ) {
            if ( match ) {
                // Don't consume trailing commas as valid
                soFar = soFar.slice( match[0].length ) || soFar;
            }
            groups.push( (tokens = []) );
        }

        matched = false;

        // Combinators
        if ( (match = rcombinators.exec( soFar )) ) {
            matched = match.shift();
            tokens.push({
                value: matched,
                // Cast descendant combinators to space
                type: match[0].replace( rtrim, " " )
            });
            soFar = soFar.slice( matched.length );
        }

        // Filters
        for ( type in Expr.filter ) {
            if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
                (match = preFilters[ type ]( match ))) ) {
                matched = match.shift();
                tokens.push({
                    value: matched,
                    type: type,
                    matches: match
                });
                soFar = soFar.slice( matched.length );
            }
        }

        if ( !matched ) {
            break;
        }
    }

    // Return the length of the invalid excess
    // if we're just parsing
    // Otherwise, throw an error or return tokens
    return parseOnly ?
        soFar.length :
        soFar ?
            Sizzle.error( selector ) :
            // Cache the tokens
            tokenCache( selector, groups ).slice( 0 );
};

function toSelector( tokens ) {
    var i = 0,
        len = tokens.length,
        selector = "";
    for ( ; i < len; i++ ) {
        selector += tokens[i].value;
    }
    return selector;
}

function addCombinator( matcher, combinator, base ) {
    var dir = combinator.dir,
        checkNonElements = base && dir === "parentNode",
        doneName = done++;

    return combinator.first ?
        // Check against closest ancestor/preceding element
        function( elem, context, xml ) {
            while ( (elem = elem[ dir ]) ) {
                if ( elem.nodeType === 1 || checkNonElements ) {
                    return matcher( elem, context, xml );
                }
            }
        } :

        // Check against all ancestor/preceding elements
        function( elem, context, xml ) {
            var oldCache, uniqueCache, outerCache,
                newCache = [ dirruns, doneName ];

            // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
            if ( xml ) {
                while ( (elem = elem[ dir ]) ) {
                    if ( elem.nodeType === 1 || checkNonElements ) {
                        if ( matcher( elem, context, xml ) ) {
                            return true;
                        }
                    }
                }
            } else {
                while ( (elem = elem[ dir ]) ) {
                    if ( elem.nodeType === 1 || checkNonElements ) {
                        outerCache = elem[ expando ] || (elem[ expando ] = {});

                        // Support: IE <9 only
                        // Defend against cloned attroperties (jQuery gh-1709)
                        uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});

                        if ( (oldCache = uniqueCache[ dir ]) &&
                            oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {

                            // Assign to newCache so results back-propagate to previous elements
                            return (newCache[ 2 ] = oldCache[ 2 ]);
                        } else {
                            // Reuse newcache so results back-propagate to previous elements
                            uniqueCache[ dir ] = newCache;

                            // A match means we're done; a fail means we have to keep checking
                            if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
                                return true;
                            }
                        }
                    }
                }
            }
        };
}

function elementMatcher( matchers ) {
    return matchers.length > 1 ?
        function( elem, context, xml ) {
            var i = matchers.length;
            while ( i-- ) {
                if ( !matchers[i]( elem, context, xml ) ) {
                    return false;
                }
            }
            return true;
        } :
        matchers[0];
}

function multipleContexts( selector, contexts, results ) {
    var i = 0,
        len = contexts.length;
    for ( ; i < len; i++ ) {
        Sizzle( selector, contexts[i], results );
    }
    return results;
}

function condense( unmatched, map, filter, context, xml ) {
    var elem,
        newUnmatched = [],
        i = 0,
        len = unmatched.length,
        mapped = map != null;

    for ( ; i < len; i++ ) {
        if ( (elem = unmatched[i]) ) {
            if ( !filter || filter( elem, context, xml ) ) {
                newUnmatched.push( elem );
                if ( mapped ) {
                    map.push( i );
                }
            }
        }
    }

    return newUnmatched;
}

function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
    if ( postFilter && !postFilter[ expando ] ) {
        postFilter = setMatcher( postFilter );
    }
    if ( postFinder && !postFinder[ expando ] ) {
        postFinder = setMatcher( postFinder, postSelector );
    }
    return markFunction(function( seed, results, context, xml ) {
        var temp, i, elem,
            preMap = [],
            postMap = [],
            preexisting = results.length,

            // Get initial elements from seed or context
            elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),

            // Prefilter to get matcher input, preserving a map for seed-results synchronization
            matcherIn = preFilter && ( seed || !selector ) ?
                condense( elems, preMap, preFilter, context, xml ) :
                elems,

            matcherOut = matcher ?
                // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
                postFinder || ( seed ? preFilter : preexisting || postFilter ) ?

                    // ...intermediate processing is necessary
                    [] :

                    // ...otherwise use results directly
                    results :
                matcherIn;

        // Find primary matches
        if ( matcher ) {
            matcher( matcherIn, matcherOut, context, xml );
        }

        // Apply postFilter
        if ( postFilter ) {
            temp = condense( matcherOut, postMap );
            postFilter( temp, [], context, xml );

            // Un-match failing elements by moving them back to matcherIn
            i = temp.length;
            while ( i-- ) {
                if ( (elem = temp[i]) ) {
                    matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
                }
            }
        }

        if ( seed ) {
            if ( postFinder || preFilter ) {
                if ( postFinder ) {
                    // Get the final matcherOut by condensing this intermediate into postFinder contexts
                    temp = [];
                    i = matcherOut.length;
                    while ( i-- ) {
                        if ( (elem = matcherOut[i]) ) {
                            // Restore matcherIn since elem is not yet a final match
                            temp.push( (matcherIn[i] = elem) );
                        }
                    }
                    postFinder( null, (matcherOut = []), temp, xml );
                }

                // Move matched elements from seed to results to keep them synchronized
                i = matcherOut.length;
                while ( i-- ) {
                    if ( (elem = matcherOut[i]) &&
                        (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {

                        seed[temp] = !(results[temp] = elem);
                    }
                }
            }

        // Add elements to results, through postFinder if defined
        } else {
            matcherOut = condense(
                matcherOut === results ?
                    matcherOut.splice( preexisting, matcherOut.length ) :
                    matcherOut
            );
            if ( postFinder ) {
                postFinder( null, results, matcherOut, xml );
            } else {
                push.apply( results, matcherOut );
            }
        }
    });
}

function matcherFromTokens( tokens ) {
    var checkContext, matcher, j,
        len = tokens.length,
        leadingRelative = Expr.relative[ tokens[0].type ],
        implicitRelative = leadingRelative || Expr.relative[" "],
        i = leadingRelative ? 1 : 0,

        // The foundational matcher ensures that elements are reachable from top-level context(s)
        matchContext = addCombinator( function( elem ) {
            return elem === checkContext;
        }, implicitRelative, true ),
        matchAnyContext = addCombinator( function( elem ) {
            return indexOf( checkContext, elem ) > -1;
        }, implicitRelative, true ),
        matchers = [ function( elem, context, xml ) {
            var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
                (checkContext = context).nodeType ?
                    matchContext( elem, context, xml ) :
                    matchAnyContext( elem, context, xml ) );
            // Avoid hanging onto element (issue #299)
            checkContext = null;
            return ret;
        } ];

    for ( ; i < len; i++ ) {
        if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
            matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
        } else {
            matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );

            // Return special upon seeing a positional matcher
            if ( matcher[ expando ] ) {
                // Find the next relative operator (if any) for proper handling
                j = ++i;
                for ( ; j < len; j++ ) {
                    if ( Expr.relative[ tokens[j].type ] ) {
                        break;
                    }
                }
                return setMatcher(
                    i > 1 && elementMatcher( matchers ),
                    i > 1 && toSelector(
                        // If the preceding token was a descendant combinator, insert an implicit any-element `*`
                        tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
                    ).replace( rtrim, "$1" ),
                    matcher,
                    i < j && matcherFromTokens( tokens.slice( i, j ) ),
                    j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
                    j < len && toSelector( tokens )
                );
            }
            matchers.push( matcher );
        }
    }

    return elementMatcher( matchers );
}

function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
    var bySet = setMatchers.length > 0,
        byElement = elementMatchers.length > 0,
        superMatcher = function( seed, context, xml, results, outermost ) {
            var elem, j, matcher,
                matchedCount = 0,
                i = "0",
                unmatched = seed && [],
                setMatched = [],
                contextBackup = outermostContext,
                // We must always have either seed elements or outermost context
                elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
                // Use integer dirruns iff this is the outermost matcher
                dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
                len = elems.length;

            if ( outermost ) {
                outermostContext = context === document || context || outermost;
            }

            // Add elements passing elementMatchers directly to results
            // Support: IE<9, Safari
            // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
            for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
                if ( byElement && elem ) {
                    j = 0;
                    if ( !context && elem.ownerDocument !== document ) {
                        setDocument( elem );
                        xml = !documentIsHTML;
                    }
                    while ( (matcher = elementMatchers[j++]) ) {
                        if ( matcher( elem, context || document, xml) ) {
                            results.push( elem );
                            break;
                        }
                    }
                    if ( outermost ) {
                        dirruns = dirrunsUnique;
                    }
                }

                // Track unmatched elements for set filters
                if ( bySet ) {
                    // They will have gone through all possible matchers
                    if ( (elem = !matcher && elem) ) {
                        matchedCount--;
                    }

                    // Lengthen the array for every element, matched or not
                    if ( seed ) {
                        unmatched.push( elem );
                    }
                }
            }

            // `i` is now the count of elements visited above, and adding it to `matchedCount`
            // makes the latter nonnegative.
            matchedCount += i;

            // Apply set filters to unmatched elements
            // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
            // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
            // no element matchers and no seed.
            // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
            // case, which will result in a "00" `matchedCount` that differs from `i` but is also
            // numerically zero.
            if ( bySet && i !== matchedCount ) {
                j = 0;
                while ( (matcher = setMatchers[j++]) ) {
                    matcher( unmatched, setMatched, context, xml );
                }

                if ( seed ) {
                    // Reintegrate element matches to eliminate the need for sorting
                    if ( matchedCount > 0 ) {
                        while ( i-- ) {
                            if ( !(unmatched[i] || setMatched[i]) ) {
                                setMatched[i] = pop.call( results );
                            }
                        }
                    }

                    // Discard index placeholder values to get only actual matches
                    setMatched = condense( setMatched );
                }

                // Add matches to results
                push.apply( results, setMatched );

                // Seedless set matches succeeding multiple successful matchers stipulate sorting
                if ( outermost && !seed && setMatched.length > 0 &&
                    ( matchedCount + setMatchers.length ) > 1 ) {

                    Sizzle.uniqueSort( results );
                }
            }

            // Override manipulation of globals by nested matchers
            if ( outermost ) {
                dirruns = dirrunsUnique;
                outermostContext = contextBackup;
            }

            return unmatched;
        };

    return bySet ?
        markFunction( superMatcher ) :
        superMatcher;
}

compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
    var i,
        setMatchers = [],
        elementMatchers = [],
        cached = compilerCache[ selector + " " ];

    if ( !cached ) {
        // Generate a function of recursive functions that can be used to check each element
        if ( !match ) {
            match = tokenize( selector );
        }
        i = match.length;
        while ( i-- ) {
            cached = matcherFromTokens( match[i] );
            if ( cached[ expando ] ) {
                setMatchers.push( cached );
            } else {
                elementMatchers.push( cached );
            }
        }

        // Cache the compiled function
        cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );

        // Save selector and tokenization
        cached.selector = selector;
    }
    return cached;
};

/**
 * A low-level selection function that works with Sizzle's compiled
 *  selector functions
 * @param {String|Function} selector A selector or a pre-compiled
 *  selector function built with Sizzle.compile
 * @param {Element} context
 * @param {Array} [results]
 * @param {Array} [seed] A set of elements to match against
 */
select = Sizzle.select = function( selector, context, results, seed ) {
    var i, tokens, token, type, find,
        compiled = typeof selector === "function" && selector,
        match = !seed && tokenize( (selector = compiled.selector || selector) );

    results = results || [];

    // Try to minimize operations if there is only one selector in the list and no seed
    // (the latter of which guarantees us context)
    if ( match.length === 1 ) {

        // Reduce context if the leading compound selector is an ID
        tokens = match[0] = match[0].slice( 0 );
        if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
                support.getById && context.nodeType === 9 && documentIsHTML &&
                Expr.relative[ tokens[1].type ] ) {

            context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
            if ( !context ) {
                return results;

            // Precompiled matchers will still verify ancestry, so step up a level
            } else if ( compiled ) {
                context = context.parentNode;
            }

            selector = selector.slice( tokens.shift().value.length );
        }

        // Fetch a seed set for right-to-left matching
        i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
        while ( i-- ) {
            token = tokens[i];

            // Abort if we hit a combinator
            if ( Expr.relative[ (type = token.type) ] ) {
                break;
            }
            if ( (find = Expr.find[ type ]) ) {
                // Search, expanding context for leading sibling combinators
                if ( (seed = find(
                    token.matches[0].replace( runescape, funescape ),
                    rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
                )) ) {

                    // If seed is empty or no tokens remain, we can return early
                    tokens.splice( i, 1 );
                    selector = seed.length && toSelector( tokens );
                    if ( !selector ) {
                        push.apply( results, seed );
                        return results;
                    }

                    break;
                }
            }
        }
    }

    // Compile and execute a filtering function if one is not provided
    // Provide `match` to avoid retokenization if we modified the selector above
    ( compiled || compile( selector, match ) )(
        seed,
        context,
        !documentIsHTML,
        results,
        !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
    );
    return results;
};

// One-time assignments

// Sort stability
support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;

// Support: Chrome 14-35+
// Always assume duplicates if they aren't passed to the comparison function
support.detectDuplicates = !!hasDuplicate;

// Initialize against the default document
setDocument();

// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
support.sortDetached = assert(function( div1 ) {
    // Should return 1, but returns 4 (following)
    return div1.compareDocumentPosition( document.createElement("div") ) & 1;
});

// Support: IE<8
// Prevent attribute/property "interpolation"
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
if ( !assert(function( div ) {
    div.innerHTML = "<a href='#'></a>";
    return div.firstChild.getAttribute("href") === "#" ;
}) ) {
    addHandle( "type|href|height|width", function( elem, name, isXML ) {
        if ( !isXML ) {
            return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
        }
    });
}

// Support: IE<9
// Use defaultValue in place of getAttribute("value")
if ( !support.attributes || !assert(function( div ) {
    div.innerHTML = "<input/>";
    div.firstChild.setAttribute( "value", "" );
    return div.firstChild.getAttribute( "value" ) === "";
}) ) {
    addHandle( "value", function( elem, name, isXML ) {
        if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
            return elem.defaultValue;
        }
    });
}

// Support: IE<9
// Use getAttributeNode to fetch booleans when getAttribute lies
if ( !assert(function( div ) {
    return div.getAttribute("disabled") == null;
}) ) {
    addHandle( booleans, function( elem, name, isXML ) {
        var val;
        if ( !isXML ) {
            return elem[ name ] === true ? name.toLowerCase() :
                    (val = elem.getAttributeNode( name )) && val.specified ?
                    val.value :
                null;
        }
    });
}

return Sizzle;

})( window );



jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[ ":" ] = jQuery.expr.pseudos;
jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;



var dir = function( elem, dir, until ) {
    var matched = [],
        truncate = until !== undefined;

    while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
        if ( elem.nodeType === 1 ) {
            if ( truncate && jQuery( elem ).is( until ) ) {
                break;
            }
            matched.push( elem );
        }
    }
    return matched;
};


var siblings = function( n, elem ) {
    var matched = [];

    for ( ; n; n = n.nextSibling ) {
        if ( n.nodeType === 1 && n !== elem ) {
            matched.push( n );
        }
    }

    return matched;
};


var rneedsContext = jQuery.expr.match.needsContext;

var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );



var risSimple = /^.[^:#\[\.,]*$/;

// Implement the identical functionality for filter and not
function winnow( elements, qualifier, not ) {
    if ( jQuery.isFunction( qualifier ) ) {
        return jQuery.grep( elements, function( elem, i ) {
            /* jshint -W018 */
            return !!qualifier.call( elem, i, elem ) !== not;
        } );

    }

    if ( qualifier.nodeType ) {
        return jQuery.grep( elements, function( elem ) {
            return ( elem === qualifier ) !== not;
        } );

    }

    if ( typeof qualifier === "string" ) {
        if ( risSimple.test( qualifier ) ) {
            return jQuery.filter( qualifier, elements, not );
        }

        qualifier = jQuery.filter( qualifier, elements );
    }

    return jQuery.grep( elements, function( elem ) {
        return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
    } );
}

jQuery.filter = function( expr, elems, not ) {
    var elem = elems[ 0 ];

    if ( not ) {
        expr = ":not(" + expr + ")";
    }

    return elems.length === 1 && elem.nodeType === 1 ?
        jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
        jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
            return elem.nodeType === 1;
        } ) );
};

jQuery.fn.extend( {
    find: function( selector ) {
        var i,
            len = this.length,
            ret = [],
            self = this;

        if ( typeof selector !== "string" ) {
            return this.pushStack( jQuery( selector ).filter( function() {
                for ( i = 0; i < len; i++ ) {
                    if ( jQuery.contains( self[ i ], this ) ) {
                        return true;
                    }
                }
            } ) );
        }

        for ( i = 0; i < len; i++ ) {
            jQuery.find( selector, self[ i ], ret );
        }

        // Needed because $( selector, context ) becomes $( context ).find( selector )
        ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
        ret.selector = this.selector ? this.selector + " " + selector : selector;
        return ret;
    },
    filter: function( selector ) {
        return this.pushStack( winnow( this, selector || [], false ) );
    },
    not: function( selector ) {
        return this.pushStack( winnow( this, selector || [], true ) );
    },
    is: function( selector ) {
        return !!winnow(
            this,

            // If this is a positional/relative selector, check membership in the returned set
            // so $("p:first").is("p:last") won't return true for a doc with two "p".
            typeof selector === "string" && rneedsContext.test( selector ) ?
                jQuery( selector ) :
                selector || [],
            false
        ).length;
    }
} );


// Initialize a jQuery object


// A central reference to the root jQuery(document)
var rootjQuery,

    // A simple way to check for HTML strings
    // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
    // Strict HTML recognition (#11290: must start with <)
    rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,

    init = jQuery.fn.init = function( selector, context, root ) {
        var match, elem;

        // HANDLE: $(""), $(null), $(undefined), $(false)
        if ( !selector ) {
            return this;
        }

        // Method init() accepts an alternate rootjQuery
        // so migrate can support jQuery.sub (gh-2101)
        root = root || rootjQuery;

        // Handle HTML strings
        if ( typeof selector === "string" ) {
            if ( selector[ 0 ] === "<" &&
                selector[ selector.length - 1 ] === ">" &&
                selector.length >= 3 ) {

                // Assume that strings that start and end with <> are HTML and skip the regex check
                match = [ null, selector, null ];

            } else {
                match = rquickExpr.exec( selector );
            }

            // Match html or make sure no context is specified for #id
            if ( match && ( match[ 1 ] || !context ) ) {

                // HANDLE: $(html) -> $(array)
                if ( match[ 1 ] ) {
                    context = context instanceof jQuery ? context[ 0 ] : context;

                    // Option to run scripts is true for back-compat
                    // Intentionally let the error be thrown if parseHTML is not present
                    jQuery.merge( this, jQuery.parseHTML(
                        match[ 1 ],
                        context && context.nodeType ? context.ownerDocument || context : document,
                        true
                    ) );

                    // HANDLE: $(html, props)
                    if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
                        for ( match in context ) {

                            // Properties of context are called as methods if possible
                            if ( jQuery.isFunction( this[ match ] ) ) {
                                this[ match ]( context[ match ] );

                            // ...and otherwise set as attributes
                            } else {
                                this.attr( match, context[ match ] );
                            }
                        }
                    }

                    return this;

                // HANDLE: $(#id)
                } else {
                    elem = document.getElementById( match[ 2 ] );

                    // Support: Blackberry 4.6
                    // gEBID returns nodes no longer in the document (#6963)
                    if ( elem && elem.parentNode ) {

                        // Inject the element directly into the jQuery object
                        this.length = 1;
                        this[ 0 ] = elem;
                    }

                    this.context = document;
                    this.selector = selector;
                    return this;
                }

            // HANDLE: $(expr, $(...))
            } else if ( !context || context.jquery ) {
                return ( context || root ).find( selector );

            // HANDLE: $(expr, context)
            // (which is just equivalent to: $(context).find(expr)
            } else {
                return this.constructor( context ).find( selector );
            }

        // HANDLE: $(DOMElement)
        } else if ( selector.nodeType ) {
            this.context = this[ 0 ] = selector;
            this.length = 1;
            return this;

        // HANDLE: $(function)
        // Shortcut for document ready
        } else if ( jQuery.isFunction( selector ) ) {
            return root.ready !== undefined ?
                root.ready( selector ) :

                // Execute immediately if ready is not present
                selector( jQuery );
        }

        if ( selector.selector !== undefined ) {
            this.selector = selector.selector;
            this.context = selector.context;
        }

        return jQuery.makeArray( selector, this );
    };

// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

// Initialize central reference
rootjQuery = jQuery( document );


var rparentsprev = /^(?:parents|prev(?:Until|All))/,

    // Methods guaranteed to produce a unique set when starting from a unique set
    guaranteedUnique = {
        children: true,
        contents: true,
        next: true,
        prev: true
    };

jQuery.fn.extend( {
    has: function( target ) {
        var targets = jQuery( target, this ),
            l = targets.length;

        return this.filter( function() {
            var i = 0;
            for ( ; i < l; i++ ) {
                if ( jQuery.contains( this, targets[ i ] ) ) {
                    return true;
                }
            }
        } );
    },

    closest: function( selectors, context ) {
        var cur,
            i = 0,
            l = this.length,
            matched = [],
            pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
                jQuery( selectors, context || this.context ) :
                0;

        for ( ; i < l; i++ ) {
            for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {

                // Always skip document fragments
                if ( cur.nodeType < 11 && ( pos ?
                    pos.index( cur ) > -1 :

                    // Don't pass non-elements to Sizzle
                    cur.nodeType === 1 &&
                        jQuery.find.matchesSelector( cur, selectors ) ) ) {

                    matched.push( cur );
                    break;
                }
            }
        }

        return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
    },

    // Determine the position of an element within the set
    index: function( elem ) {

        // No argument, return index in parent
        if ( !elem ) {
            return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
        }

        // Index in selector
        if ( typeof elem === "string" ) {
            return indexOf.call( jQuery( elem ), this[ 0 ] );
        }

        // Locate the position of the desired element
        return indexOf.call( this,

            // If it receives a jQuery object, the first element is used
            elem.jquery ? elem[ 0 ] : elem
        );
    },

    add: function( selector, context ) {
        return this.pushStack(
            jQuery.uniqueSort(
                jQuery.merge( this.get(), jQuery( selector, context ) )
            )
        );
    },

    addBack: function( selector ) {
        return this.add( selector == null ?
            this.prevObject : this.prevObject.filter( selector )
        );
    }
} );

function sibling( cur, dir ) {
    while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
    return cur;
}

jQuery.each( {
    parent: function( elem ) {
        var parent = elem.parentNode;
        return parent && parent.nodeType !== 11 ? parent : null;
    },
    parents: function( elem ) {
        return dir( elem, "parentNode" );
    },
    parentsUntil: function( elem, i, until ) {
        return dir( elem, "parentNode", until );
    },
    next: function( elem ) {
        return sibling( elem, "nextSibling" );
    },
    prev: function( elem ) {
        return sibling( elem, "previousSibling" );
    },
    nextAll: function( elem ) {
        return dir( elem, "nextSibling" );
    },
    prevAll: function( elem ) {
        return dir( elem, "previousSibling" );
    },
    nextUntil: function( elem, i, until ) {
        return dir( elem, "nextSibling", until );
    },
    prevUntil: function( elem, i, until ) {
        return dir( elem, "previousSibling", until );
    },
    siblings: function( elem ) {
        return siblings( ( elem.parentNode || {} ).firstChild, elem );
    },
    children: function( elem ) {
        return siblings( elem.firstChild );
    },
    contents: function( elem ) {
        return elem.contentDocument || jQuery.merge( [], elem.childNodes );
    }
}, function( name, fn ) {
    jQuery.fn[ name ] = function( until, selector ) {
        var matched = jQuery.map( this, fn, until );

        if ( name.slice( -5 ) !== "Until" ) {
            selector = until;
        }

        if ( selector && typeof selector === "string" ) {
            matched = jQuery.filter( selector, matched );
        }

        if ( this.length > 1 ) {

            // Remove duplicates
            if ( !guaranteedUnique[ name ] ) {
                jQuery.uniqueSort( matched );
            }

            // Reverse order for parents* and prev-derivatives
            if ( rparentsprev.test( name ) ) {
                matched.reverse();
            }
        }

        return this.pushStack( matched );
    };
} );
var rnotwhite = ( /\S+/g );



// Convert String-formatted options into Object-formatted ones
function createOptions( options ) {
    var object = {};
    jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
        object[ flag ] = true;
    } );
    return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *  options: an optional list of space-separated options that will change how
 *          the callback list behaves or a more traditional option object
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible options:
 *
 *  once:           will ensure the callback list can only be fired once (like a Deferred)
 *
 *  memory:         will keep track of previous values and will call any callback added
 *                  after the list has been fired right away with the latest "memorized"
 *                  values (like a Deferred)
 *
 *  unique:         will ensure a callback can only be added once (no duplicate in the list)
 *
 *  stopOnFalse:    interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( options ) {

    // Convert options from String-formatted to Object-formatted if needed
    // (we check in cache first)
    options = typeof options === "string" ?
        createOptions( options ) :
        jQuery.extend( {}, options );

    var // Flag to know if list is currently firing
        firing,

        // Last fire value for non-forgettable lists
        memory,

        // Flag to know if list was already fired
        fired,

        // Flag to prevent firing
        locked,

        // Actual callback list
        list = [],

        // Queue of execution data for repeatable lists
        queue = [],

        // Index of currently firing callback (modified by add/remove as needed)
        firingIndex = -1,

        // Fire callbacks
        fire = function() {

            // Enforce single-firing
            locked = options.once;

            // Execute callbacks for all pending executions,
            // respecting firingIndex overrides and runtime changes
            fired = firing = true;
            for ( ; queue.length; firingIndex = -1 ) {
                memory = queue.shift();
                while ( ++firingIndex < list.length ) {

                    // Run callback and check for early termination
                    if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
                        options.stopOnFalse ) {

                        // Jump to end and forget the data so .add doesn't re-fire
                        firingIndex = list.length;
                        memory = false;
                    }
                }
            }

            // Forget the data if we're done with it
            if ( !options.memory ) {
                memory = false;
            }

            firing = false;

            // Clean up if we're done firing for good
            if ( locked ) {

                // Keep an empty list if we have data for future add calls
                if ( memory ) {
                    list = [];

                // Otherwise, this object is spent
                } else {
                    list = "";
                }
            }
        },

        // Actual Callbacks object
        self = {

            // Add a callback or a collection of callbacks to the list
            add: function() {
                if ( list ) {

                    // If we have memory from a past run, we should fire after adding
                    if ( memory && !firing ) {
                        firingIndex = list.length - 1;
                        queue.push( memory );
                    }

                    ( function add( args ) {
                        jQuery.each( args, function( _, arg ) {
                            if ( jQuery.isFunction( arg ) ) {
                                if ( !options.unique || !self.has( arg ) ) {
                                    list.push( arg );
                                }
                            } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {

                                // Inspect recursively
                                add( arg );
                            }
                        } );
                    } )( arguments );

                    if ( memory && !firing ) {
                        fire();
                    }
                }
                return this;
            },

            // Remove a callback from the list
            remove: function() {
                jQuery.each( arguments, function( _, arg ) {
                    var index;
                    while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
                        list.splice( index, 1 );

                        // Handle firing indexes
                        if ( index <= firingIndex ) {
                            firingIndex--;
                        }
                    }
                } );
                return this;
            },

            // Check if a given callback is in the list.
            // If no argument is given, return whether or not list has callbacks attached.
            has: function( fn ) {
                return fn ?
                    jQuery.inArray( fn, list ) > -1 :
                    list.length > 0;
            },

            // Remove all callbacks from the list
            empty: function() {
                if ( list ) {
                    list = [];
                }
                return this;
            },

            // Disable .fire and .add
            // Abort any current/pending executions
            // Clear all callbacks and values
            disable: function() {
                locked = queue = [];
                list = memory = "";
                return this;
            },
            disabled: function() {
                return !list;
            },

            // Disable .fire
            // Also disable .add unless we have memory (since it would have no effect)
            // Abort any pending executions
            lock: function() {
                locked = queue = [];
                if ( !memory ) {
                    list = memory = "";
                }
                return this;
            },
            locked: function() {
                return !!locked;
            },

            // Call all callbacks with the given context and arguments
            fireWith: function( context, args ) {
                if ( !locked ) {
                    args = args || [];
                    args = [ context, args.slice ? args.slice() : args ];
                    queue.push( args );
                    if ( !firing ) {
                        fire();
                    }
                }
                return this;
            },

            // Call all the callbacks with the given arguments
            fire: function() {
                self.fireWith( this, arguments );
                return this;
            },

            // To know if the callbacks have already been called at least once
            fired: function() {
                return !!fired;
            }
        };

    return self;
};


jQuery.extend( {

    Deferred: function( func ) {
        var tuples = [

                // action, add listener, listener list, final state
                [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ],
                [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ],
                [ "notify", "progress", jQuery.Callbacks( "memory" ) ]
            ],
            state = "pending",
            promise = {
                state: function() {
                    return state;
                },
                always: function() {
                    deferred.done( arguments ).fail( arguments );
                    return this;
                },
                then: function( /* fnDone, fnFail, fnProgress */ ) {
                    var fns = arguments;
                    return jQuery.Deferred( function( newDefer ) {
                        jQuery.each( tuples, function( i, tuple ) {
                            var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];

                            // deferred[ done | fail | progress ] for forwarding actions to newDefer
                            deferred[ tuple[ 1 ] ]( function() {
                                var returned = fn && fn.apply( this, arguments );
                                if ( returned && jQuery.isFunction( returned.promise ) ) {
                                    returned.promise()
                                        .progress( newDefer.notify )
                                        .done( newDefer.resolve )
                                        .fail( newDefer.reject );
                                } else {
                                    newDefer[ tuple[ 0 ] + "With" ](
                                        this === promise ? newDefer.promise() : this,
                                        fn ? [ returned ] : arguments
                                    );
                                }
                            } );
                        } );
                        fns = null;
                    } ).promise();
                },

                // Get a promise for this deferred
                // If obj is provided, the promise aspect is added to the object
                promise: function( obj ) {
                    return obj != null ? jQuery.extend( obj, promise ) : promise;
                }
            },
            deferred = {};

        // Keep pipe for back-compat
        promise.pipe = promise.then;

        // Add list-specific methods
        jQuery.each( tuples, function( i, tuple ) {
            var list = tuple[ 2 ],
                stateString = tuple[ 3 ];

            // promise[ done | fail | progress ] = list.add
            promise[ tuple[ 1 ] ] = list.add;

            // Handle state
            if ( stateString ) {
                list.add( function() {

                    // state = [ resolved | rejected ]
                    state = stateString;

                // [ reject_list | resolve_list ].disable; progress_list.lock
                }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
            }

            // deferred[ resolve | reject | notify ]
            deferred[ tuple[ 0 ] ] = function() {
                deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments );
                return this;
            };
            deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
        } );

        // Make the deferred a promise
        promise.promise( deferred );

        // Call given func if any
        if ( func ) {
            func.call( deferred, deferred );
        }

        // All done!
        return deferred;
    },

    // Deferred helper
    when: function( subordinate /* , ..., subordinateN */ ) {
        var i = 0,
            resolveValues = slice.call( arguments ),
            length = resolveValues.length,

            // the count of uncompleted subordinates
            remaining = length !== 1 ||
                ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,

            // the master Deferred.
            // If resolveValues consist of only a single Deferred, just use that.
            deferred = remaining === 1 ? subordinate : jQuery.Deferred(),

            // Update function for both resolve and progress values
            updateFunc = function( i, contexts, values ) {
                return function( value ) {
                    contexts[ i ] = this;
                    values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
                    if ( values === progressValues ) {
                        deferred.notifyWith( contexts, values );
                    } else if ( !( --remaining ) ) {
                        deferred.resolveWith( contexts, values );
                    }
                };
            },

            progressValues, progressContexts, resolveContexts;

        // Add listeners to Deferred subordinates; treat others as resolved
        if ( length > 1 ) {
            progressValues = new Array( length );
            progressContexts = new Array( length );
            resolveContexts = new Array( length );
            for ( ; i < length; i++ ) {
                if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
                    resolveValues[ i ].promise()
                        .progress( updateFunc( i, progressContexts, progressValues ) )
                        .done( updateFunc( i, resolveContexts, resolveValues ) )
                        .fail( deferred.reject );
                } else {
                    --remaining;
                }
            }
        }

        // If we're not waiting on anything, resolve the master
        if ( !remaining ) {
            deferred.resolveWith( resolveContexts, resolveValues );
        }

        return deferred.promise();
    }
} );


// The deferred used on DOM ready
var readyList;

jQuery.fn.ready = function( fn ) {

    // Add the callback
    jQuery.ready.promise().done( fn );

    return this;
};

jQuery.extend( {

    // Is the DOM ready to be used? Set to true once it occurs.
    isReady: false,

    // A counter to track how many items to wait for before
    // the ready event fires. See #6781
    readyWait: 1,

    // Hold (or release) the ready event
    holdReady: function( hold ) {
        if ( hold ) {
            jQuery.readyWait++;
        } else {
            jQuery.ready( true );
        }
    },

    // Handle when the DOM is ready
    ready: function( wait ) {

        // Abort if there are pending holds or we're already ready
        if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
            return;
        }

        // Remember that the DOM is ready
        jQuery.isReady = true;

        // If a normal DOM Ready event fired, decrement, and wait if need be
        if ( wait !== true && --jQuery.readyWait > 0 ) {
            return;
        }

        // If there are functions bound, to execute
        readyList.resolveWith( document, [ jQuery ] );

        // Trigger any bound ready events
        if ( jQuery.fn.triggerHandler ) {
            jQuery( document ).triggerHandler( "ready" );
            jQuery( document ).off( "ready" );
        }
    }
} );

/**
 * The ready event handler and self cleanup method
 */
function completed() {
    document.removeEventListener( "DOMContentLoaded", completed );
    window.removeEventListener( "load", completed );
    jQuery.ready();
}

jQuery.ready.promise = function( obj ) {
    if ( !readyList ) {

        readyList = jQuery.Deferred();

        // Catch cases where $(document).ready() is called
        // after the browser event has already occurred.
        // Support: IE9-10 only
        // Older IE sometimes signals "interactive" too soon
        if ( document.readyState === "complete" ||
            ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {

            // Handle it asynchronously to allow scripts the opportunity to delay ready
            window.setTimeout( jQuery.ready );

        } else {

            // Use the handy event callback
            document.addEventListener( "DOMContentLoaded", completed );

            // A fallback to window.onload, that will always work
            window.addEventListener( "load", completed );
        }
    }
    return readyList.promise( obj );
};

// Kick off the DOM ready check even if the user does not
jQuery.ready.promise();




// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
    var i = 0,
        len = elems.length,
        bulk = key == null;

    // Sets many values
    if ( jQuery.type( key ) === "object" ) {
        chainable = true;
        for ( i in key ) {
            access( elems, fn, i, key[ i ], true, emptyGet, raw );
        }

    // Sets one value
    } else if ( value !== undefined ) {
        chainable = true;

        if ( !jQuery.isFunction( value ) ) {
            raw = true;
        }

        if ( bulk ) {

            // Bulk operations run against the entire set
            if ( raw ) {
                fn.call( elems, value );
                fn = null;

            // ...except when executing function values
            } else {
                bulk = fn;
                fn = function( elem, key, value ) {
                    return bulk.call( jQuery( elem ), value );
                };
            }
        }

        if ( fn ) {
            for ( ; i < len; i++ ) {
                fn(
                    elems[ i ], key, raw ?
                    value :
                    value.call( elems[ i ], i, fn( elems[ i ], key ) )
                );
            }
        }
    }

    return chainable ?
        elems :

        // Gets
        bulk ?
            fn.call( elems ) :
            len ? fn( elems[ 0 ], key ) : emptyGet;
};
var acceptData = function( owner ) {

    // Accepts only:
    //  - Node
    //    - Node.ELEMENT_NODE
    //    - Node.DOCUMENT_NODE
    //  - Object
    //    - Any
    /* jshint -W018 */
    return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
};




function Data() {
    this.expando = jQuery.expando + Data.uid++;
}

Data.uid = 1;

Data.prototype = {

    register: function( owner, initial ) {
        var value = initial || {};

        // If it is a node unlikely to be stringify-ed or looped over
        // use plain assignment
        if ( owner.nodeType ) {
            owner[ this.expando ] = value;

        // Otherwise secure it in a non-enumerable, non-writable property
        // configurability must be true to allow the property to be
        // deleted with the delete operator
        } else {
            Object.defineProperty( owner, this.expando, {
                value: value,
                writable: true,
                configurable: true
            } );
        }
        return owner[ this.expando ];
    },
    cache: function( owner ) {

        // We can accept data for non-element nodes in modern browsers,
        // but we should not, see #8335.
        // Always return an empty object.
        if ( !acceptData( owner ) ) {
            return {};
        }

        // Check if the owner object already has a cache
        var value = owner[ this.expando ];

        // If not, create one
        if ( !value ) {
            value = {};

            // We can accept data for non-element nodes in modern browsers,
            // but we should not, see #8335.
            // Always return an empty object.
            if ( acceptData( owner ) ) {

                // If it is a node unlikely to be stringify-ed or looped over
                // use plain assignment
                if ( owner.nodeType ) {
                    owner[ this.expando ] = value;

                // Otherwise secure it in a non-enumerable property
                // configurable must be true to allow the property to be
                // deleted when data is removed
                } else {
                    Object.defineProperty( owner, this.expando, {
                        value: value,
                        configurable: true
                    } );
                }
            }
        }

        return value;
    },
    set: function( owner, data, value ) {
        var prop,
            cache = this.cache( owner );

        // Handle: [ owner, key, value ] args
        if ( typeof data === "string" ) {
            cache[ data ] = value;

        // Handle: [ owner, { properties } ] args
        } else {

            // Copy the properties one-by-one to the cache object
            for ( prop in data ) {
                cache[ prop ] = data[ prop ];
            }
        }
        return cache;
    },
    get: function( owner, key ) {
        return key === undefined ?
            this.cache( owner ) :
            owner[ this.expando ] && owner[ this.expando ][ key ];
    },
    access: function( owner, key, value ) {
        var stored;

        // In cases where either:
        //
        //   1. No key was specified
        //   2. A string key was specified, but no value provided
        //
        // Take the "read" path and allow the get method to determine
        // which value to return, respectively either:
        //
        //   1. The entire cache object
        //   2. The data stored at the key
        //
        if ( key === undefined ||
                ( ( key && typeof key === "string" ) && value === undefined ) ) {

            stored = this.get( owner, key );

            return stored !== undefined ?
                stored : this.get( owner, jQuery.camelCase( key ) );
        }

        // When the key is not a string, or both a key and value
        // are specified, set or extend (existing objects) with either:
        //
        //   1. An object of properties
        //   2. A key and value
        //
        this.set( owner, key, value );

        // Since the "set" path can have two possible entry points
        // return the expected data based on which path was taken[*]
        return value !== undefined ? value : key;
    },
    remove: function( owner, key ) {
        var i, name, camel,
            cache = owner[ this.expando ];

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

        if ( key === undefined ) {
            this.register( owner );

        } else {

            // Support array or space separated string of keys
            if ( jQuery.isArray( key ) ) {

                // If "name" is an array of keys...
                // When data is initially created, via ("key", "val") signature,
                // keys will be converted to camelCase.
                // Since there is no way to tell _how_ a key was added, remove
                // both plain key and camelCase key. #12786
                // This will only penalize the array argument path.
                name = key.concat( key.map( jQuery.camelCase ) );
            } else {
                camel = jQuery.camelCase( key );

                // Try the string as a key before any manipulation
                if ( key in cache ) {
                    name = [ key, camel ];
                } else {

                    // If a key with the spaces exists, use it.
                    // Otherwise, create an array by matching non-whitespace
                    name = camel;
                    name = name in cache ?
                        [ name ] : ( name.match( rnotwhite ) || [] );
                }
            }

            i = name.length;

            while ( i-- ) {
                delete cache[ name[ i ] ];
            }
        }

        // Remove the expando if there's no more data
        if ( key === undefined || jQuery.isEmptyObject( cache ) ) {

            // Support: Chrome <= 35-45+
            // Webkit & Blink performance suffers when deleting properties
            // from DOM nodes, so set to undefined instead
            // https://code.google.com/p/chromium/issues/detail?id=378607
            if ( owner.nodeType ) {
                owner[ this.expando ] = undefined;
            } else {
                delete owner[ this.expando ];
            }
        }
    },
    hasData: function( owner ) {
        var cache = owner[ this.expando ];
        return cache !== undefined && !jQuery.isEmptyObject( cache );
    }
};
var dataPriv = new Data();

var dataUser = new Data();



//  Implementation Summary
//
//  1. Enforce API surface and semantic compatibility with 1.9.x branch
//  2. Improve the module's maintainability by reducing the storage
//      paths to a single mechanism.
//  3. Use the same single mechanism to support "private" and "user" data.
//  4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
//  5. Avoid exposing implementation details on user objects (eg. expando properties)
//  6. Provide a clear path for implementation upgrade to WeakMap in 2014

var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
    rmultiDash = /[A-Z]/g;

function dataAttr( elem, key, data ) {
    var name;

    // If nothing was found internally, try to fetch any
    // data from the HTML5 data-* attribute
    if ( data === undefined && elem.nodeType === 1 ) {
        name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
        data = elem.getAttribute( name );

        if ( typeof data === "string" ) {
            try {
                data = data === "true" ? true :
                    data === "false" ? false :
                    data === "null" ? null :

                    // Only convert to a number if it doesn't change the string
                    +data + "" === data ? +data :
                    rbrace.test( data ) ? jQuery.parseJSON( data ) :
                    data;
            } catch ( e ) {}

            // Make sure we set the data so it isn't changed later
            dataUser.set( elem, key, data );
        } else {
            data = undefined;
        }
    }
    return data;
}

jQuery.extend( {
    hasData: function( elem ) {
        return dataUser.hasData( elem ) || dataPriv.hasData( elem );
    },

    data: function( elem, name, data ) {
        return dataUser.access( elem, name, data );
    },

    removeData: function( elem, name ) {
        dataUser.remove( elem, name );
    },

    // TODO: Now that all calls to _data and _removeData have been replaced
    // with direct calls to dataPriv methods, these can be deprecated.
    _data: function( elem, name, data ) {
        return dataPriv.access( elem, name, data );
    },

    _removeData: function( elem, name ) {
        dataPriv.remove( elem, name );
    }
} );

jQuery.fn.extend( {
    data: function( key, value ) {
        var i, name, data,
            elem = this[ 0 ],
            attrs = elem && elem.attributes;

        // Gets all values
        if ( key === undefined ) {
            if ( this.length ) {
                data = dataUser.get( elem );

                if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
                    i = attrs.length;
                    while ( i-- ) {

                        // Support: IE11+
                        // The attrs elements can be null (#14894)
                        if ( attrs[ i ] ) {
                            name = attrs[ i ].name;
                            if ( name.indexOf( "data-" ) === 0 ) {
                                name = jQuery.camelCase( name.slice( 5 ) );
                                dataAttr( elem, name, data[ name ] );
                            }
                        }
                    }
                    dataPriv.set( elem, "hasDataAttrs", true );
                }
            }

            return data;
        }

        // Sets multiple values
        if ( typeof key === "object" ) {
            return this.each( function() {
                dataUser.set( this, key );
            } );
        }

        return access( this, function( value ) {
            var data, camelKey;

            // The calling jQuery object (element matches) is not empty
            // (and therefore has an element appears at this[ 0 ]) and the
            // `value` parameter was not undefined. An empty jQuery object
            // will result in `undefined` for elem = this[ 0 ] which will
            // throw an exception if an attempt to read a data cache is made.
            if ( elem && value === undefined ) {

                // Attempt to get data from the cache
                // with the key as-is
                data = dataUser.get( elem, key ) ||

                    // Try to find dashed key if it exists (gh-2779)
                    // This is for 2.2.x only
                    dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() );

                if ( data !== undefined ) {
                    return data;
                }

                camelKey = jQuery.camelCase( key );

                // Attempt to get data from the cache
                // with the key camelized
                data = dataUser.get( elem, camelKey );
                if ( data !== undefined ) {
                    return data;
                }

                // Attempt to "discover" the data in
                // HTML5 custom data-* attrs
                data = dataAttr( elem, camelKey, undefined );
                if ( data !== undefined ) {
                    return data;
                }

                // We tried really hard, but the data doesn't exist.
                return;
            }

            // Set the data...
            camelKey = jQuery.camelCase( key );
            this.each( function() {

                // First, attempt to store a copy or reference of any
                // data that might've been store with a camelCased key.
                var data = dataUser.get( this, camelKey );

                // For HTML5 data-* attribute interop, we have to
                // store property names with dashes in a camelCase form.
                // This might not apply to all properties...*
                dataUser.set( this, camelKey, value );

                // *... In the case of properties that might _actually_
                // have dashes, we need to also store a copy of that
                // unchanged property.
                if ( key.indexOf( "-" ) > -1 && data !== undefined ) {
                    dataUser.set( this, key, value );
                }
            } );
        }, null, value, arguments.length > 1, null, true );
    },

    removeData: function( key ) {
        return this.each( function() {
            dataUser.remove( this, key );
        } );
    }
} );


jQuery.extend( {
    queue: function( elem, type, data ) {
        var queue;

        if ( elem ) {
            type = ( type || "fx" ) + "queue";
            queue = dataPriv.get( elem, type );

            // Speed up dequeue by getting out quickly if this is just a lookup
            if ( data ) {
                if ( !queue || jQuery.isArray( data ) ) {
                    queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
                } else {
                    queue.push( data );
                }
            }
            return queue || [];
        }
    },

    dequeue: function( elem, type ) {
        type = type || "fx";

        var queue = jQuery.queue( elem, type ),
            startLength = queue.length,
            fn = queue.shift(),
            hooks = jQuery._queueHooks( elem, type ),
            next = function() {
                jQuery.dequeue( elem, type );
            };

        // If the fx queue is dequeued, always remove the progress sentinel
        if ( fn === "inprogress" ) {
            fn = queue.shift();
            startLength--;
        }

        if ( fn ) {

            // Add a progress sentinel to prevent the fx queue from being
            // automatically dequeued
            if ( type === "fx" ) {
                queue.unshift( "inprogress" );
            }

            // Clear up the last queue stop function
            delete hooks.stop;
            fn.call( elem, next, hooks );
        }

        if ( !startLength && hooks ) {
            hooks.empty.fire();
        }
    },

    // Not public - generate a queueHooks object, or return the current one
    _queueHooks: function( elem, type ) {
        var key = type + "queueHooks";
        return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
            empty: jQuery.Callbacks( "once memory" ).add( function() {
                dataPriv.remove( elem, [ type + "queue", key ] );
            } )
        } );
    }
} );

jQuery.fn.extend( {
    queue: function( type, data ) {
        var setter = 2;

        if ( typeof type !== "string" ) {
            data = type;
            type = "fx";
            setter--;
        }

        if ( arguments.length < setter ) {
            return jQuery.queue( this[ 0 ], type );
        }

        return data === undefined ?
            this :
            this.each( function() {
                var queue = jQuery.queue( this, type, data );

                // Ensure a hooks for this queue
                jQuery._queueHooks( this, type );

                if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
                    jQuery.dequeue( this, type );
                }
            } );
    },
    dequeue: function( type ) {
        return this.each( function() {
            jQuery.dequeue( this, type );
        } );
    },
    clearQueue: function( type ) {
        return this.queue( type || "fx", [] );
    },

    // Get a promise resolved when queues of a certain type
    // are emptied (fx is the type by default)
    promise: function( type, obj ) {
        var tmp,
            count = 1,
            defer = jQuery.Deferred(),
            elements = this,
            i = this.length,
            resolve = function() {
                if ( !( --count ) ) {
                    defer.resolveWith( elements, [ elements ] );
                }
            };

        if ( typeof type !== "string" ) {
            obj = type;
            type = undefined;
        }
        type = type || "fx";

        while ( i-- ) {
            tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
            if ( tmp && tmp.empty ) {
                count++;
                tmp.empty.add( resolve );
            }
        }
        resolve();
        return defer.promise( obj );
    }
} );
var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;

var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );


var cssExpand = [ "Top", "Right", "Bottom", "Left" ];

var isHidden = function( elem, el ) {

        // isHidden might be called from jQuery#filter function;
        // in that case, element will be second argument
        elem = el || elem;
        return jQuery.css( elem, "display" ) === "none" ||
            !jQuery.contains( elem.ownerDocument, elem );
    };



function adjustCSS( elem, prop, valueParts, tween ) {
    var adjusted,
        scale = 1,
        maxIterations = 20,
        currentValue = tween ?
            function() { return tween.cur(); } :
            function() { return jQuery.css( elem, prop, "" ); },
        initial = currentValue(),
        unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),

        // Starting value computation is required for potential unit mismatches
        initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
            rcssNum.exec( jQuery.css( elem, prop ) );

    if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {

        // Trust units reported by jQuery.css
        unit = unit || initialInUnit[ 3 ];

        // Make sure we update the tween properties later on
        valueParts = valueParts || [];

        // Iteratively approximate from a nonzero starting point
        initialInUnit = +initial || 1;

        do {

            // If previous iteration zeroed out, double until we get *something*.
            // Use string for doubling so we don't accidentally see scale as unchanged below
            scale = scale || ".5";

            // Adjust and apply
            initialInUnit = initialInUnit / scale;
            jQuery.style( elem, prop, initialInUnit + unit );

        // Update scale, tolerating zero or NaN from tween.cur()
        // Break the loop if scale is unchanged or perfect, or if we've just had enough.
        } while (
            scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
        );
    }

    if ( valueParts ) {
        initialInUnit = +initialInUnit || +initial || 0;

        // Apply relative offset (+=/-=) if specified
        adjusted = valueParts[ 1 ] ?
            initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
            +valueParts[ 2 ];
        if ( tween ) {
            tween.unit = unit;
            tween.start = initialInUnit;
            tween.end = adjusted;
        }
    }
    return adjusted;
}
var rcheckableType = ( /^(?:checkbox|radio)$/i );

var rtagName = ( /<([\w:-]+)/ );

var rscriptType = ( /^$|\/(?:java|ecma)script/i );



// We have to close these tags to support XHTML (#13200)
var wrapMap = {

    // Support: IE9
    option: [ 1, "<select multiple='multiple'>", "</select>" ],

    // XHTML parsers do not magically insert elements in the
    // same way that tag soup parsers do. So we cannot shorten
    // this by omitting <tbody> or other required elements.
    thead: [ 1, "<table>", "</table>" ],
    col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
    tr: [ 2, "<table><tbody>", "</tbody></table>" ],
    td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],

    _default: [ 0, "", "" ]
};

// Support: IE9
wrapMap.optgroup = wrapMap.option;

wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;


function getAll( context, tag ) {

    // Support: IE9-11+
    // Use typeof to avoid zero-argument method invocation on host objects (#15151)
    var ret = typeof context.getElementsByTagName !== "undefined" ?
            context.getElementsByTagName( tag || "*" ) :
            typeof context.querySelectorAll !== "undefined" ?
                context.querySelectorAll( tag || "*" ) :
            [];

    return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
        jQuery.merge( [ context ], ret ) :
        ret;
}


// Mark scripts as having already been evaluated
function setGlobalEval( elems, refElements ) {
    var i = 0,
        l = elems.length;

    for ( ; i < l; i++ ) {
        dataPriv.set(
            elems[ i ],
            "globalEval",
            !refElements || dataPriv.get( refElements[ i ], "globalEval" )
        );
    }
}


var rhtml = /<|&#?\w+;/;

function buildFragment( elems, context, scripts, selection, ignored ) {
    var elem, tmp, tag, wrap, contains, j,
        fragment = context.createDocumentFragment(),
        nodes = [],
        i = 0,
        l = elems.length;

    for ( ; i < l; i++ ) {
        elem = elems[ i ];

        if ( elem || elem === 0 ) {

            // Add nodes directly
            if ( jQuery.type( elem ) === "object" ) {

                // Support: Android<4.1, PhantomJS<2
                // push.apply(_, arraylike) throws on ancient WebKit
                jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );

            // Convert non-html into a text node
            } else if ( !rhtml.test( elem ) ) {
                nodes.push( context.createTextNode( elem ) );

            // Convert html into DOM nodes
            } else {
                tmp = tmp || fragment.appendChild( context.createElement( "div" ) );

                // Deserialize a standard representation
                tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
                wrap = wrapMap[ tag ] || wrapMap._default;
                tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];

                // Descend through wrappers to the right content
                j = wrap[ 0 ];
                while ( j-- ) {
                    tmp = tmp.lastChild;
                }

                // Support: Android<4.1, PhantomJS<2
                // push.apply(_, arraylike) throws on ancient WebKit
                jQuery.merge( nodes, tmp.childNodes );

                // Remember the top-level container
                tmp = fragment.firstChild;

                // Ensure the created nodes are orphaned (#12392)
                tmp.textContent = "";
            }
        }
    }

    // Remove wrapper from fragment
    fragment.textContent = "";

    i = 0;
    while ( ( elem = nodes[ i++ ] ) ) {

        // Skip elements already in the context collection (trac-4087)
        if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
            if ( ignored ) {
                ignored.push( elem );
            }
            continue;
        }

        contains = jQuery.contains( elem.ownerDocument, elem );

        // Append to fragment
        tmp = getAll( fragment.appendChild( elem ), "script" );

        // Preserve script evaluation history
        if ( contains ) {
            setGlobalEval( tmp );
        }

        // Capture executables
        if ( scripts ) {
            j = 0;
            while ( ( elem = tmp[ j++ ] ) ) {
                if ( rscriptType.test( elem.type || "" ) ) {
                    scripts.push( elem );
                }
            }
        }
    }

    return fragment;
}


( function() {
    var fragment = document.createDocumentFragment(),
        div = fragment.appendChild( document.createElement( "div" ) ),
        input = document.createElement( "input" );

    // Support: Android 4.0-4.3, Safari<=5.1
    // Check state lost if the name is set (#11217)
    // Support: Windows Web Apps (WWA)
    // `name` and `type` must use .setAttribute for WWA (#14901)
    input.setAttribute( "type", "radio" );
    input.setAttribute( "checked", "checked" );
    input.setAttribute( "name", "t" );

    div.appendChild( input );

    // Support: Safari<=5.1, Android<4.2
    // Older WebKit doesn't clone checked state correctly in fragments
    support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;

    // Support: IE<=11+
    // Make sure textarea (and checkbox) defaultValue is properly cloned
    div.innerHTML = "<textarea>x</textarea>";
    support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
} )();


var
    rkeyEvent = /^key/,
    rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
    rtypenamespace = /^([^.]*)(?:\.(.+)|)/;

function returnTrue() {
    return true;
}

function returnFalse() {
    return false;
}

// Support: IE9
// See #13393 for more info
function safeActiveElement() {
    try {
        return document.activeElement;
    } catch ( err ) { }
}

function on( elem, types, selector, data, fn, one ) {
    var origFn, type;

    // Types can be a map of types/handlers
    if ( typeof types === "object" ) {

        // ( types-Object, selector, data )
        if ( typeof selector !== "string" ) {

            // ( types-Object, data )
            data = data || selector;
            selector = undefined;
        }
        for ( type in types ) {
            on( elem, type, selector, data, types[ type ], one );
        }
        return elem;
    }

    if ( data == null && fn == null ) {

        // ( types, fn )
        fn = selector;
        data = selector = undefined;
    } else if ( fn == null ) {
        if ( typeof selector === "string" ) {

            // ( types, selector, fn )
            fn = data;
            data = undefined;
        } else {

            // ( types, data, fn )
            fn = data;
            data = selector;
            selector = undefined;
        }
    }
    if ( fn === false ) {
        fn = returnFalse;
    } else if ( !fn ) {
        return elem;
    }

    if ( one === 1 ) {
        origFn = fn;
        fn = function( event ) {

            // Can use an empty set, since event contains the info
            jQuery().off( event );
            return origFn.apply( this, arguments );
        };

        // Use same guid so caller can remove using origFn
        fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
    }
    return elem.each( function() {
        jQuery.event.add( this, types, fn, data, selector );
    } );
}

/*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards' addEvent library for many of the ideas.
 */
jQuery.event = {

    global: {},

    add: function( elem, types, handler, data, selector ) {

        var handleObjIn, eventHandle, tmp,
            events, t, handleObj,
            special, handlers, type, namespaces, origType,
            elemData = dataPriv.get( elem );

        // Don't attach events to noData or text/comment nodes (but allow plain objects)
        if ( !elemData ) {
            return;
        }

        // Caller can pass in an object of custom data in lieu of the handler
        if ( handler.handler ) {
            handleObjIn = handler;
            handler = handleObjIn.handler;
            selector = handleObjIn.selector;
        }

        // Make sure that the handler has a unique ID, used to find/remove it later
        if ( !handler.guid ) {
            handler.guid = jQuery.guid++;
        }

        // Init the element's event structure and main handler, if this is the first
        if ( !( events = elemData.events ) ) {
            events = elemData.events = {};
        }
        if ( !( eventHandle = elemData.handle ) ) {
            eventHandle = elemData.handle = function( e ) {

                // Discard the second event of a jQuery.event.trigger() and
                // when an event is called after a page has unloaded
                return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
                    jQuery.event.dispatch.apply( elem, arguments ) : undefined;
            };
        }

        // Handle multiple events separated by a space
        types = ( types || "" ).match( rnotwhite ) || [ "" ];
        t = types.length;
        while ( t-- ) {
            tmp = rtypenamespace.exec( types[ t ] ) || [];
            type = origType = tmp[ 1 ];
            namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();

            // There *must* be a type, no attaching namespace-only handlers
            if ( !type ) {
                continue;
            }

            // If event changes its type, use the special event handlers for the changed type
            special = jQuery.event.special[ type ] || {};

            // If selector defined, determine special event api type, otherwise given type
            type = ( selector ? special.delegateType : special.bindType ) || type;

            // Update special based on newly reset type
            special = jQuery.event.special[ type ] || {};

            // handleObj is passed to all event handlers
            handleObj = jQuery.extend( {
                type: type,
                origType: origType,
                data: data,
                handler: handler,
                guid: handler.guid,
                selector: selector,
                needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
                namespace: namespaces.join( "." )
            }, handleObjIn );

            // Init the event handler queue if we're the first
            if ( !( handlers = events[ type ] ) ) {
                handlers = events[ type ] = [];
                handlers.delegateCount = 0;

                // Only use addEventListener if the special events handler returns false
                if ( !special.setup ||
                    special.setup.call( elem, data, namespaces, eventHandle ) === false ) {

                    if ( elem.addEventListener ) {
                        elem.addEventListener( type, eventHandle );
                    }
                }
            }

            if ( special.add ) {
                special.add.call( elem, handleObj );

                if ( !handleObj.handler.guid ) {
                    handleObj.handler.guid = handler.guid;
                }
            }

            // Add to the element's handler list, delegates in front
            if ( selector ) {
                handlers.splice( handlers.delegateCount++, 0, handleObj );
            } else {
                handlers.push( handleObj );
            }

            // Keep track of which events have ever been used, for event optimization
            jQuery.event.global[ type ] = true;
        }

    },

    // Detach an event or set of events from an element
    remove: function( elem, types, handler, selector, mappedTypes ) {

        var j, origCount, tmp,
            events, t, handleObj,
            special, handlers, type, namespaces, origType,
            elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );

        if ( !elemData || !( events = elemData.events ) ) {
            return;
        }

        // Once for each type.namespace in types; type may be omitted
        types = ( types || "" ).match( rnotwhite ) || [ "" ];
        t = types.length;
        while ( t-- ) {
            tmp = rtypenamespace.exec( types[ t ] ) || [];
            type = origType = tmp[ 1 ];
            namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();

            // Unbind all events (on this namespace, if provided) for the element
            if ( !type ) {
                for ( type in events ) {
                    jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
                }
                continue;
            }

            special = jQuery.event.special[ type ] || {};
            type = ( selector ? special.delegateType : special.bindType ) || type;
            handlers = events[ type ] || [];
            tmp = tmp[ 2 ] &&
                new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );

            // Remove matching events
            origCount = j = handlers.length;
            while ( j-- ) {
                handleObj = handlers[ j ];

                if ( ( mappedTypes || origType === handleObj.origType ) &&
                    ( !handler || handler.guid === handleObj.guid ) &&
                    ( !tmp || tmp.test( handleObj.namespace ) ) &&
                    ( !selector || selector === handleObj.selector ||
                        selector === "**" && handleObj.selector ) ) {
                    handlers.splice( j, 1 );

                    if ( handleObj.selector ) {
                        handlers.delegateCount--;
                    }
                    if ( special.remove ) {
                        special.remove.call( elem, handleObj );
                    }
                }
            }

            // Remove generic event handler if we removed something and no more handlers exist
            // (avoids potential for endless recursion during removal of special event handlers)
            if ( origCount && !handlers.length ) {
                if ( !special.teardown ||
                    special.teardown.call( elem, namespaces, elemData.handle ) === false ) {

                    jQuery.removeEvent( elem, type, elemData.handle );
                }

                delete events[ type ];
            }
        }

        // Remove data and the expando if it's no longer used
        if ( jQuery.isEmptyObject( events ) ) {
            dataPriv.remove( elem, "handle events" );
        }
    },

    dispatch: function( event ) {

        // Make a writable jQuery.Event from the native event object
        event = jQuery.event.fix( event );

        var i, j, ret, matched, handleObj,
            handlerQueue = [],
            args = slice.call( arguments ),
            handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
            special = jQuery.event.special[ event.type ] || {};

        // Use the fix-ed jQuery.Event rather than the (read-only) native event
        args[ 0 ] = event;
        event.delegateTarget = this;

        // Call the preDispatch hook for the mapped type, and let it bail if desired
        if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
            return;
        }

        // Determine handlers
        handlerQueue = jQuery.event.handlers.call( this, event, handlers );

        // Run delegates first; they may want to stop propagation beneath us
        i = 0;
        while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
            event.currentTarget = matched.elem;

            j = 0;
            while ( ( handleObj = matched.handlers[ j++ ] ) &&
                !event.isImmediatePropagationStopped() ) {

                // Triggered event must either 1) have no namespace, or 2) have namespace(s)
                // a subset or equal to those in the bound event (both can have no namespace).
                if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {

                    event.handleObj = handleObj;
                    event.data = handleObj.data;

                    ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
                        handleObj.handler ).apply( matched.elem, args );

                    if ( ret !== undefined ) {
                        if ( ( event.result = ret ) === false ) {
                            event.preventDefault();
                            event.stopPropagation();
                        }
                    }
                }
            }
        }

        // Call the postDispatch hook for the mapped type
        if ( special.postDispatch ) {
            special.postDispatch.call( this, event );
        }

        return event.result;
    },

    handlers: function( event, handlers ) {
        var i, matches, sel, handleObj,
            handlerQueue = [],
            delegateCount = handlers.delegateCount,
            cur = event.target;

        // Support (at least): Chrome, IE9
        // Find delegate handlers
        // Black-hole SVG <use> instance trees (#13180)
        //
        // Support: Firefox<=42+
        // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
        if ( delegateCount && cur.nodeType &&
            ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {

            for ( ; cur !== this; cur = cur.parentNode || this ) {

                // Don't check non-elements (#13208)
                // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
                if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
                    matches = [];
                    for ( i = 0; i < delegateCount; i++ ) {
                        handleObj = handlers[ i ];

                        // Don't conflict with Object.prototype properties (#13203)
                        sel = handleObj.selector + " ";

                        if ( matches[ sel ] === undefined ) {
                            matches[ sel ] = handleObj.needsContext ?
                                jQuery( sel, this ).index( cur ) > -1 :
                                jQuery.find( sel, this, null, [ cur ] ).length;
                        }
                        if ( matches[ sel ] ) {
                            matches.push( handleObj );
                        }
                    }
                    if ( matches.length ) {
                        handlerQueue.push( { elem: cur, handlers: matches } );
                    }
                }
            }
        }

        // Add the remaining (directly-bound) handlers
        if ( delegateCount < handlers.length ) {
            handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
        }

        return handlerQueue;
    },

    // Includes some event props shared by KeyEvent and MouseEvent
    props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " +
        "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ),

    fixHooks: {},

    keyHooks: {
        props: "char charCode key keyCode".split( " " ),
        filter: function( event, original ) {

            // Add which for key events
            if ( event.which == null ) {
                event.which = original.charCode != null ? original.charCode : original.keyCode;
            }

            return event;
        }
    },

    mouseHooks: {
        props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " +
            "screenX screenY toElement" ).split( " " ),
        filter: function( event, original ) {
            var eventDoc, doc, body,
                button = original.button;

            // Calculate pageX/Y if missing and clientX/Y available
            if ( event.pageX == null && original.clientX != null ) {
                eventDoc = event.target.ownerDocument || document;
                doc = eventDoc.documentElement;
                body = eventDoc.body;

                event.pageX = original.clientX +
                    ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
                    ( doc && doc.clientLeft || body && body.clientLeft || 0 );
                event.pageY = original.clientY +
                    ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) -
                    ( doc && doc.clientTop  || body && body.clientTop  || 0 );
            }

            // Add which for click: 1 === left; 2 === middle; 3 === right
            // Note: button is not normalized, so don't use it
            if ( !event.which && button !== undefined ) {
                event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
            }

            return event;
        }
    },

    fix: function( event ) {
        if ( event[ jQuery.expando ] ) {
            return event;
        }

        // Create a writable copy of the event object and normalize some properties
        var i, prop, copy,
            type = event.type,
            originalEvent = event,
            fixHook = this.fixHooks[ type ];

        if ( !fixHook ) {
            this.fixHooks[ type ] = fixHook =
                rmouseEvent.test( type ) ? this.mouseHooks :
                rkeyEvent.test( type ) ? this.keyHooks :
                {};
        }
        copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

        event = new jQuery.Event( originalEvent );

        i = copy.length;
        while ( i-- ) {
            prop = copy[ i ];
            event[ prop ] = originalEvent[ prop ];
        }

        // Support: Cordova 2.5 (WebKit) (#13255)
        // All events should have a target; Cordova deviceready doesn't
        if ( !event.target ) {
            event.target = document;
        }

        // Support: Safari 6.0+, Chrome<28
        // Target should not be a text node (#504, #13143)
        if ( event.target.nodeType === 3 ) {
            event.target = event.target.parentNode;
        }

        return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
    },

    special: {
        load: {

            // Prevent triggered image.load events from bubbling to window.load
            noBubble: true
        },
        focus: {

            // Fire native event if possible so blur/focus sequence is correct
            trigger: function() {
                if ( this !== safeActiveElement() && this.focus ) {
                    this.focus();
                    return false;
                }
            },
            delegateType: "focusin"
        },
        blur: {
            trigger: function() {
                if ( this === safeActiveElement() && this.blur ) {
                    this.blur();
                    return false;
                }
            },
            delegateType: "focusout"
        },
        click: {

            // For checkbox, fire native event so checked state will be right
            trigger: function() {
                if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
                    this.click();
                    return false;
                }
            },

            // For cross-browser consistency, don't fire native .click() on links
            _default: function( event ) {
                return jQuery.nodeName( event.target, "a" );
            }
        },

        beforeunload: {
            postDispatch: function( event ) {

                // Support: Firefox 20+
                // Firefox doesn't alert if the returnValue field is not set.
                if ( event.result !== undefined && event.originalEvent ) {
                    event.originalEvent.returnValue = event.result;
                }
            }
        }
    }
};

jQuery.removeEvent = function( elem, type, handle ) {

    // This "if" is needed for plain objects
    if ( elem.removeEventListener ) {
        elem.removeEventListener( type, handle );
    }
};

jQuery.Event = function( src, props ) {

    // Allow instantiation without the 'new' keyword
    if ( !( this instanceof jQuery.Event ) ) {
        return new jQuery.Event( src, props );
    }

    // Event object
    if ( src && src.type ) {
        this.originalEvent = src;
        this.type = src.type;

        // Events bubbling up the document may have been marked as prevented
        // by a handler lower down the tree; reflect the correct value.
        this.isDefaultPrevented = src.defaultPrevented ||
                src.defaultPrevented === undefined &&

                // Support: Android<4.0
                src.returnValue === false ?
            returnTrue :
            returnFalse;

    // Event type
    } else {
        this.type = src;
    }

    // Put explicitly provided properties onto the event object
    if ( props ) {
        jQuery.extend( this, props );
    }

    // Create a timestamp if incoming event doesn't have one
    this.timeStamp = src && src.timeStamp || jQuery.now();

    // Mark it as fixed
    this[ jQuery.expando ] = true;
};

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
    constructor: jQuery.Event,
    isDefaultPrevented: returnFalse,
    isPropagationStopped: returnFalse,
    isImmediatePropagationStopped: returnFalse,
    isSimulated: false,

    preventDefault: function() {
        var e = this.originalEvent;

        this.isDefaultPrevented = returnTrue;

        if ( e && !this.isSimulated ) {
            e.preventDefault();
        }
    },
    stopPropagation: function() {
        var e = this.originalEvent;

        this.isPropagationStopped = returnTrue;

        if ( e && !this.isSimulated ) {
            e.stopPropagation();
        }
    },
    stopImmediatePropagation: function() {
        var e = this.originalEvent;

        this.isImmediatePropagationStopped = returnTrue;

        if ( e && !this.isSimulated ) {
            e.stopImmediatePropagation();
        }

        this.stopPropagation();
    }
};

// Create mouseenter/leave events using mouseover/out and event-time checks
// so that event delegation works in jQuery.
// Do the same for pointerenter/pointerleave and pointerover/pointerout
//
// Support: Safari 7 only
// Safari sends mouseenter too often; see:
// https://code.google.com/p/chromium/issues/detail?id=470258
// for the description of the bug (it existed in older Chrome versions as well).
jQuery.each( {
    mouseenter: "mouseover",
    mouseleave: "mouseout",
    pointerenter: "pointerover",
    pointerleave: "pointerout"
}, function( orig, fix ) {
    jQuery.event.special[ orig ] = {
        delegateType: fix,
        bindType: fix,

        handle: function( event ) {
            var ret,
                target = this,
                related = event.relatedTarget,
                handleObj = event.handleObj;

            // For mouseenter/leave call the handler if related is outside the target.
            // NB: No relatedTarget if the mouse left/entered the browser window
            if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
                event.type = handleObj.origType;
                ret = handleObj.handler.apply( this, arguments );
                event.type = fix;
            }
            return ret;
        }
    };
} );

jQuery.fn.extend( {
    on: function( types, selector, data, fn ) {
        return on( this, types, selector, data, fn );
    },
    one: function( types, selector, data, fn ) {
        return on( this, types, selector, data, fn, 1 );
    },
    off: function( types, selector, fn ) {
        var handleObj, type;
        if ( types && types.preventDefault && types.handleObj ) {

            // ( event )  dispatched jQuery.Event
            handleObj = types.handleObj;
            jQuery( types.delegateTarget ).off(
                handleObj.namespace ?
                    handleObj.origType + "." + handleObj.namespace :
                    handleObj.origType,
                handleObj.selector,
                handleObj.handler
            );
            return this;
        }
        if ( typeof types === "object" ) {

            // ( types-object [, selector] )
            for ( type in types ) {
                this.off( type, selector, types[ type ] );
            }
            return this;
        }
        if ( selector === false || typeof selector === "function" ) {

            // ( types [, fn] )
            fn = selector;
            selector = undefined;
        }
        if ( fn === false ) {
            fn = returnFalse;
        }
        return this.each( function() {
            jQuery.event.remove( this, types, fn, selector );
        } );
    }
} );


var
    rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,

    // Support: IE 10-11, Edge 10240+
    // In IE/Edge using regex groups here causes severe slowdowns.
    // See https://connect.microsoft.com/IE/feedback/details/1736512/
    rnoInnerhtml = /<script|<style|<link/i,

    // checked="checked" or checked
    rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
    rscriptTypeMasked = /^true\/(.*)/,
    rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;

// Manipulating tables requires a tbody
function manipulationTarget( elem, content ) {
    return jQuery.nodeName( elem, "table" ) &&
        jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?

        elem.getElementsByTagName( "tbody" )[ 0 ] ||
            elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) :
        elem;
}

// Replace/restore the type attribute of script elements for safe DOM manipulation
function disableScript( elem ) {
    elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
    return elem;
}
function restoreScript( elem ) {
    var match = rscriptTypeMasked.exec( elem.type );

    if ( match ) {
        elem.type = match[ 1 ];
    } else {
        elem.removeAttribute( "type" );
    }

    return elem;
}

function cloneCopyEvent( src, dest ) {
    var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;

    if ( dest.nodeType !== 1 ) {
        return;
    }

    // 1. Copy private data: events, handlers, etc.
    if ( dataPriv.hasData( src ) ) {
        pdataOld = dataPriv.access( src );
        pdataCur = dataPriv.set( dest, pdataOld );
        events = pdataOld.events;

        if ( events ) {
            delete pdataCur.handle;
            pdataCur.events = {};

            for ( type in events ) {
                for ( i = 0, l = events[ type ].length; i < l; i++ ) {
                    jQuery.event.add( dest, type, events[ type ][ i ] );
                }
            }
        }
    }

    // 2. Copy user data
    if ( dataUser.hasData( src ) ) {
        udataOld = dataUser.access( src );
        udataCur = jQuery.extend( {}, udataOld );

        dataUser.set( dest, udataCur );
    }
}

// Fix IE bugs, see support tests
function fixInput( src, dest ) {
    var nodeName = dest.nodeName.toLowerCase();

    // Fails to persist the checked state of a cloned checkbox or radio button.
    if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
        dest.checked = src.checked;

    // Fails to return the selected option to the default selected state when cloning options
    } else if ( nodeName === "input" || nodeName === "textarea" ) {
        dest.defaultValue = src.defaultValue;
    }
}

function domManip( collection, args, callback, ignored ) {

    // Flatten any nested arrays
    args = concat.apply( [], args );

    var fragment, first, scripts, hasScripts, node, doc,
        i = 0,
        l = collection.length,
        iNoClone = l - 1,
        value = args[ 0 ],
        isFunction = jQuery.isFunction( value );

    // We can't cloneNode fragments that contain checked, in WebKit
    if ( isFunction ||
            ( l > 1 && typeof value === "string" &&
                !support.checkClone && rchecked.test( value ) ) ) {
        return collection.each( function( index ) {
            var self = collection.eq( index );
            if ( isFunction ) {
                args[ 0 ] = value.call( this, index, self.html() );
            }
            domManip( self, args, callback, ignored );
        } );
    }

    if ( l ) {
        fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
        first = fragment.firstChild;

        if ( fragment.childNodes.length === 1 ) {
            fragment = first;
        }

        // Require either new content or an interest in ignored elements to invoke the callback
        if ( first || ignored ) {
            scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
            hasScripts = scripts.length;

            // Use the original fragment for the last item
            // instead of the first because it can end up
            // being emptied incorrectly in certain situations (#8070).
            for ( ; i < l; i++ ) {
                node = fragment;

                if ( i !== iNoClone ) {
                    node = jQuery.clone( node, true, true );

                    // Keep references to cloned scripts for later restoration
                    if ( hasScripts ) {

                        // Support: Android<4.1, PhantomJS<2
                        // push.apply(_, arraylike) throws on ancient WebKit
                        jQuery.merge( scripts, getAll( node, "script" ) );
                    }
                }

                callback.call( collection[ i ], node, i );
            }

            if ( hasScripts ) {
                doc = scripts[ scripts.length - 1 ].ownerDocument;

                // Reenable scripts
                jQuery.map( scripts, restoreScript );

                // Evaluate executable scripts on first document insertion
                for ( i = 0; i < hasScripts; i++ ) {
                    node = scripts[ i ];
                    if ( rscriptType.test( node.type || "" ) &&
                        !dataPriv.access( node, "globalEval" ) &&
                        jQuery.contains( doc, node ) ) {

                        if ( node.src ) {

                            // Optional AJAX dependency, but won't run scripts if not present
                            if ( jQuery._evalUrl ) {
                                jQuery._evalUrl( node.src );
                            }
                        } else {
                            jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
                        }
                    }
                }
            }
        }
    }

    return collection;
}

function remove( elem, selector, keepData ) {
    var node,
        nodes = selector ? jQuery.filter( selector, elem ) : elem,
        i = 0;

    for ( ; ( node = nodes[ i ] ) != null; i++ ) {
        if ( !keepData && node.nodeType === 1 ) {
            jQuery.cleanData( getAll( node ) );
        }

        if ( node.parentNode ) {
            if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
                setGlobalEval( getAll( node, "script" ) );
            }
            node.parentNode.removeChild( node );
        }
    }

    return elem;
}

jQuery.extend( {
    htmlPrefilter: function( html ) {
        return html.replace( rxhtmlTag, "<$1></$2>" );
    },

    clone: function( elem, dataAndEvents, deepDataAndEvents ) {
        var i, l, srcElements, destElements,
            clone = elem.cloneNode( true ),
            inPage = jQuery.contains( elem.ownerDocument, elem );

        // Fix IE cloning issues
        if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
                !jQuery.isXMLDoc( elem ) ) {

            // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
            destElements = getAll( clone );
            srcElements = getAll( elem );

            for ( i = 0, l = srcElements.length; i < l; i++ ) {
                fixInput( srcElements[ i ], destElements[ i ] );
            }
        }

        // Copy the events from the original to the clone
        if ( dataAndEvents ) {
            if ( deepDataAndEvents ) {
                srcElements = srcElements || getAll( elem );
                destElements = destElements || getAll( clone );

                for ( i = 0, l = srcElements.length; i < l; i++ ) {
                    cloneCopyEvent( srcElements[ i ], destElements[ i ] );
                }
            } else {
                cloneCopyEvent( elem, clone );
            }
        }

        // Preserve script evaluation history
        destElements = getAll( clone, "script" );
        if ( destElements.length > 0 ) {
            setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
        }

        // Return the cloned set
        return clone;
    },

    cleanData: function( elems ) {
        var data, elem, type,
            special = jQuery.event.special,
            i = 0;

        for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
            if ( acceptData( elem ) ) {
                if ( ( data = elem[ dataPriv.expando ] ) ) {
                    if ( data.events ) {
                        for ( type in data.events ) {
                            if ( special[ type ] ) {
                                jQuery.event.remove( elem, type );

                            // This is a shortcut to avoid jQuery.event.remove's overhead
                            } else {
                                jQuery.removeEvent( elem, type, data.handle );
                            }
                        }
                    }

                    // Support: Chrome <= 35-45+
                    // Assign undefined instead of using delete, see Data#remove
                    elem[ dataPriv.expando ] = undefined;
                }
                if ( elem[ dataUser.expando ] ) {

                    // Support: Chrome <= 35-45+
                    // Assign undefined instead of using delete, see Data#remove
                    elem[ dataUser.expando ] = undefined;
                }
            }
        }
    }
} );

jQuery.fn.extend( {

    // Keep domManip exposed until 3.0 (gh-2225)
    domManip: domManip,

    detach: function( selector ) {
        return remove( this, selector, true );
    },

    remove: function( selector ) {
        return remove( this, selector );
    },

    text: function( value ) {
        return access( this, function( value ) {
            return value === undefined ?
                jQuery.text( this ) :
                this.empty().each( function() {
                    if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
                        this.textContent = value;
                    }
                } );
        }, null, value, arguments.length );
    },

    append: function() {
        return domManip( this, arguments, function( elem ) {
            if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
                var target = manipulationTarget( this, elem );
                target.appendChild( elem );
            }
        } );
    },

    prepend: function() {
        return domManip( this, arguments, function( elem ) {
            if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
                var target = manipulationTarget( this, elem );
                target.insertBefore( elem, target.firstChild );
            }
        } );
    },

    before: function() {
        return domManip( this, arguments, function( elem ) {
            if ( this.parentNode ) {
                this.parentNode.insertBefore( elem, this );
            }
        } );
    },

    after: function() {
        return domManip( this, arguments, function( elem ) {
            if ( this.parentNode ) {
                this.parentNode.insertBefore( elem, this.nextSibling );
            }
        } );
    },

    empty: function() {
        var elem,
            i = 0;

        for ( ; ( elem = this[ i ] ) != null; i++ ) {
            if ( elem.nodeType === 1 ) {

                // Prevent memory leaks
                jQuery.cleanData( getAll( elem, false ) );

                // Remove any remaining nodes
                elem.textContent = "";
            }
        }

        return this;
    },

    clone: function( dataAndEvents, deepDataAndEvents ) {
        dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
        deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

        return this.map( function() {
            return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
        } );
    },

    html: function( value ) {
        return access( this, function( value ) {
            var elem = this[ 0 ] || {},
                i = 0,
                l = this.length;

            if ( value === undefined && elem.nodeType === 1 ) {
                return elem.innerHTML;
            }

            // See if we can take a shortcut and just use innerHTML
            if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
                !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {

                value = jQuery.htmlPrefilter( value );

                try {
                    for ( ; i < l; i++ ) {
                        elem = this[ i ] || {};

                        // Remove element nodes and prevent memory leaks
                        if ( elem.nodeType === 1 ) {
                            jQuery.cleanData( getAll( elem, false ) );
                            elem.innerHTML = value;
                        }
                    }

                    elem = 0;

                // If using innerHTML throws an exception, use the fallback method
                } catch ( e ) {}
            }

            if ( elem ) {
                this.empty().append( value );
            }
        }, null, value, arguments.length );
    },

    replaceWith: function() {
        var ignored = [];

        // Make the changes, replacing each non-ignored context element with the new content
        return domManip( this, arguments, function( elem ) {
            var parent = this.parentNode;

            if ( jQuery.inArray( this, ignored ) < 0 ) {
                jQuery.cleanData( getAll( this ) );
                if ( parent ) {
                    parent.replaceChild( elem, this );
                }
            }

        // Force callback invocation
        }, ignored );
    }
} );

jQuery.each( {
    appendTo: "append",
    prependTo: "prepend",
    insertBefore: "before",
    insertAfter: "after",
    replaceAll: "replaceWith"
}, function( name, original ) {
    jQuery.fn[ name ] = function( selector ) {
        var elems,
            ret = [],
            insert = jQuery( selector ),
            last = insert.length - 1,
            i = 0;

        for ( ; i <= last; i++ ) {
            elems = i === last ? this : this.clone( true );
            jQuery( insert[ i ] )[ original ]( elems );

            // Support: QtWebKit
            // .get() because push.apply(_, arraylike) throws
            push.apply( ret, elems.get() );
        }

        return this.pushStack( ret );
    };
} );


var iframe,
    elemdisplay = {

        // Support: Firefox
        // We have to pre-define these values for FF (#10227)
        HTML: "block",
        BODY: "block"
    };

/**
 * Retrieve the actual display of a element
 * @param {String} name nodeName of the element
 * @param {Object} doc Document object
 */

// Called only from within defaultDisplay
function actualDisplay( name, doc ) {
    var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),

        display = jQuery.css( elem[ 0 ], "display" );

    // We don't have any data stored on the element,
    // so use "detach" method as fast way to get rid of the element
    elem.detach();

    return display;
}

/**
 * Try to determine the default display value of an element
 * @param {String} nodeName
 */
function defaultDisplay( nodeName ) {
    var doc = document,
        display = elemdisplay[ nodeName ];

    if ( !display ) {
        display = actualDisplay( nodeName, doc );

        // If the simple way fails, read from inside an iframe
        if ( display === "none" || !display ) {

            // Use the already-created iframe if possible
            iframe = ( iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" ) )
                .appendTo( doc.documentElement );

            // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
            doc = iframe[ 0 ].contentDocument;

            // Support: IE
            doc.write();
            doc.close();

            display = actualDisplay( nodeName, doc );
            iframe.detach();
        }

        // Store the correct default display
        elemdisplay[ nodeName ] = display;
    }

    return display;
}
var rmargin = ( /^margin/ );

var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );

var getStyles = function( elem ) {

        // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
        // IE throws on elements created in popups
        // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
        var view = elem.ownerDocument.defaultView;

        if ( !view || !view.opener ) {
            view = window;
        }

        return view.getComputedStyle( elem );
    };

var swap = function( elem, options, callback, args ) {
    var ret, name,
        old = {};

    // Remember the old values, and insert the new ones
    for ( name in options ) {
        old[ name ] = elem.style[ name ];
        elem.style[ name ] = options[ name ];
    }

    ret = callback.apply( elem, args || [] );

    // Revert the old values
    for ( name in options ) {
        elem.style[ name ] = old[ name ];
    }

    return ret;
};


var documentElement = document.documentElement;



( function() {
    var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
        container = document.createElement( "div" ),
        div = document.createElement( "div" );

    // Finish early in limited (non-browser) environments
    if ( !div.style ) {
        return;
    }

    // Support: IE9-11+
    // Style of cloned element affects source element cloned (#8908)
    div.style.backgroundClip = "content-box";
    div.cloneNode( true ).style.backgroundClip = "";
    support.clearCloneStyle = div.style.backgroundClip === "content-box";

    container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
        "padding:0;margin-top:1px;position:absolute";
    container.appendChild( div );

    // Executing both pixelPosition & boxSizingReliable tests require only one layout
    // so they're executed at the same time to save the second computation.
    function computeStyleTests() {
        div.style.cssText =

            // Support: Firefox<29, Android 2.3
            // Vendor-prefix box-sizing
            "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;" +
            "position:relative;display:block;" +
            "margin:auto;border:1px;padding:1px;" +
            "top:1%;width:50%";
        div.innerHTML = "";
        documentElement.appendChild( container );

        var divStyle = window.getComputedStyle( div );
        pixelPositionVal = divStyle.top !== "1%";
        reliableMarginLeftVal = divStyle.marginLeft === "2px";
        boxSizingReliableVal = divStyle.width === "4px";

        // Support: Android 4.0 - 4.3 only
        // Some styles come back with percentage values, even though they shouldn't
        div.style.marginRight = "50%";
        pixelMarginRightVal = divStyle.marginRight === "4px";

        documentElement.removeChild( container );
    }

    jQuery.extend( support, {
        pixelPosition: function() {

            // This test is executed only once but we still do memoizing
            // since we can use the boxSizingReliable pre-computing.
            // No need to check if the test was already performed, though.
            computeStyleTests();
            return pixelPositionVal;
        },
        boxSizingReliable: function() {
            if ( boxSizingReliableVal == null ) {
                computeStyleTests();
            }
            return boxSizingReliableVal;
        },
        pixelMarginRight: function() {

            // Support: Android 4.0-4.3
            // We're checking for boxSizingReliableVal here instead of pixelMarginRightVal
            // since that compresses better and they're computed together anyway.
            if ( boxSizingReliableVal == null ) {
                computeStyleTests();
            }
            return pixelMarginRightVal;
        },
        reliableMarginLeft: function() {

            // Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37
            if ( boxSizingReliableVal == null ) {
                computeStyleTests();
            }
            return reliableMarginLeftVal;
        },
        reliableMarginRight: function() {

            // Support: Android 2.3
            // Check if div with explicit width and no margin-right incorrectly
            // gets computed margin-right based on width of container. (#3333)
            // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
            // This support function is only executed once so no memoizing is needed.
            var ret,
                marginDiv = div.appendChild( document.createElement( "div" ) );

            // Reset CSS: box-sizing; display; margin; border; padding
            marginDiv.style.cssText = div.style.cssText =

                // Support: Android 2.3
                // Vendor-prefix box-sizing
                "-webkit-box-sizing:content-box;box-sizing:content-box;" +
                "display:block;margin:0;border:0;padding:0";
            marginDiv.style.marginRight = marginDiv.style.width = "0";
            div.style.width = "1px";
            documentElement.appendChild( container );

            ret = !parseFloat( window.getComputedStyle( marginDiv ).marginRight );

            documentElement.removeChild( container );
            div.removeChild( marginDiv );

            return ret;
        }
    } );
} )();


function curCSS( elem, name, computed ) {
    var width, minWidth, maxWidth, ret,
        style = elem.style;

    computed = computed || getStyles( elem );
    ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;

    // Support: Opera 12.1x only
    // Fall back to style even without computed
    // computed is undefined for elems on document fragments
    if ( ( ret === "" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {
        ret = jQuery.style( elem, name );
    }

    // Support: IE9
    // getPropertyValue is only needed for .css('filter') (#12537)
    if ( computed ) {

        // A tribute to the "awesome hack by Dean Edwards"
        // Android Browser returns percentage for some values,
        // but width seems to be reliably pixels.
        // This is against the CSSOM draft spec:
        // http://dev.w3.org/csswg/cssom/#resolved-values
        if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {

            // Remember the original values
            width = style.width;
            minWidth = style.minWidth;
            maxWidth = style.maxWidth;

            // Put in the new values to get a computed value out
            style.minWidth = style.maxWidth = style.width = ret;
            ret = computed.width;

            // Revert the changed values
            style.width = width;
            style.minWidth = minWidth;
            style.maxWidth = maxWidth;
        }
    }

    return ret !== undefined ?

        // Support: IE9-11+
        // IE returns zIndex value as an integer.
        ret + "" :
        ret;
}


function addGetHookIf( conditionFn, hookFn ) {

    // Define the hook, we'll check on the first run if it's really needed.
    return {
        get: function() {
            if ( conditionFn() ) {

                // Hook not needed (or it's not possible to use it due
                // to missing dependency), remove it.
                delete this.get;
                return;
            }

            // Hook needed; redefine it so that the support test is not executed again.
            return ( this.get = hookFn ).apply( this, arguments );
        }
    };
}


var

    // Swappable if display is none or starts with table
    // except "table", "table-cell", or "table-caption"
    // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
    rdisplayswap = /^(none|table(?!-c[ea]).+)/,

    cssShow = { position: "absolute", visibility: "hidden", display: "block" },
    cssNormalTransform = {
        letterSpacing: "0",
        fontWeight: "400"
    },

    cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
    emptyStyle = document.createElement( "div" ).style;

// Return a css property mapped to a potentially vendor prefixed property
function vendorPropName( name ) {

    // Shortcut for names that are not vendor prefixed
    if ( name in emptyStyle ) {
        return name;
    }

    // Check for vendor prefixed names
    var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
        i = cssPrefixes.length;

    while ( i-- ) {
        name = cssPrefixes[ i ] + capName;
        if ( name in emptyStyle ) {
            return name;
        }
    }
}

function setPositiveNumber( elem, value, subtract ) {

    // Any relative (+/-) values have already been
    // normalized at this point
    var matches = rcssNum.exec( value );
    return matches ?

        // Guard against undefined "subtract", e.g., when used as in cssHooks
        Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
        value;
}

function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
    var i = extra === ( isBorderBox ? "border" : "content" ) ?

        // If we already have the right measurement, avoid augmentation
        4 :

        // Otherwise initialize for horizontal or vertical properties
        name === "width" ? 1 : 0,

        val = 0;

    for ( ; i < 4; i += 2 ) {

        // Both box models exclude margin, so add it if we want it
        if ( extra === "margin" ) {
            val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
        }

        if ( isBorderBox ) {

            // border-box includes padding, so remove it if we want content
            if ( extra === "content" ) {
                val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
            }

            // At this point, extra isn't border nor margin, so remove border
            if ( extra !== "margin" ) {
                val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
            }
        } else {

            // At this point, extra isn't content, so add padding
            val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );

            // At this point, extra isn't content nor padding, so add border
            if ( extra !== "padding" ) {
                val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
            }
        }
    }

    return val;
}

function getWidthOrHeight( elem, name, extra ) {

    // Start with offset property, which is equivalent to the border-box value
    var valueIsBorderBox = true,
        val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
        styles = getStyles( elem ),
        isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";

    // Some non-html elements return undefined for offsetWidth, so check for null/undefined
    // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
    // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
    if ( val <= 0 || val == null ) {

        // Fall back to computed then uncomputed css if necessary
        val = curCSS( elem, name, styles );
        if ( val < 0 || val == null ) {
            val = elem.style[ name ];
        }

        // Computed unit is not pixels. Stop here and return.
        if ( rnumnonpx.test( val ) ) {
            return val;
        }

        // Check for style in case a browser which returns unreliable values
        // for getComputedStyle silently falls back to the reliable elem.style
        valueIsBorderBox = isBorderBox &&
            ( support.boxSizingReliable() || val === elem.style[ name ] );

        // Normalize "", auto, and prepare for extra
        val = parseFloat( val ) || 0;
    }

    // Use the active box-sizing model to add/subtract irrelevant styles
    return ( val +
        augmentWidthOrHeight(
            elem,
            name,
            extra || ( isBorderBox ? "border" : "content" ),
            valueIsBorderBox,
            styles
        )
    ) + "px";
}

function showHide( elements, show ) {
    var display, elem, hidden,
        values = [],
        index = 0,
        length = elements.length;

    for ( ; index < length; index++ ) {
        elem = elements[ index ];
        if ( !elem.style ) {
            continue;
        }

        values[ index ] = dataPriv.get( elem, "olddisplay" );
        display = elem.style.display;
        if ( show ) {

            // Reset the inline display of this element to learn if it is
            // being hidden by cascaded rules or not
            if ( !values[ index ] && display === "none" ) {
                elem.style.display = "";
            }

            // Set elements which have been overridden with display: none
            // in a stylesheet to whatever the default browser style is
            // for such an element
            if ( elem.style.display === "" && isHidden( elem ) ) {
                values[ index ] = dataPriv.access(
                    elem,
                    "olddisplay",
                    defaultDisplay( elem.nodeName )
                );
            }
        } else {
            hidden = isHidden( elem );

            if ( display !== "none" || !hidden ) {
                dataPriv.set(
                    elem,
                    "olddisplay",
                    hidden ? display : jQuery.css( elem, "display" )
                );
            }
        }
    }

    // Set the display of most of the elements in a second loop
    // to avoid the constant reflow
    for ( index = 0; index < length; index++ ) {
        elem = elements[ index ];
        if ( !elem.style ) {
            continue;
        }
        if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
            elem.style.display = show ? values[ index ] || "" : "none";
        }
    }

    return elements;
}

jQuery.extend( {

    // Add in style property hooks for overriding the default
    // behavior of getting and setting a style property
    cssHooks: {
        opacity: {
            get: function( elem, computed ) {
                if ( computed ) {

                    // We should always get a number back from opacity
                    var ret = curCSS( elem, "opacity" );
                    return ret === "" ? "1" : ret;
                }
            }
        }
    },

    // Don't automatically add "px" to these possibly-unitless properties
    cssNumber: {
        "animationIterationCount": true,
        "columnCount": true,
        "fillOpacity": true,
        "flexGrow": true,
        "flexShrink": true,
        "fontWeight": true,
        "lineHeight": true,
        "opacity": true,
        "order": true,
        "orphans": true,
        "widows": true,
        "zIndex": true,
        "zoom": true
    },

    // Add in properties whose names you wish to fix before
    // setting or getting the value
    cssProps: {
        "float": "cssFloat"
    },

    // Get and set the style property on a DOM Node
    style: function( elem, name, value, extra ) {

        // Don't set styles on text and comment nodes
        if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
            return;
        }

        // Make sure that we're working with the right name
        var ret, type, hooks,
            origName = jQuery.camelCase( name ),
            style = elem.style;

        name = jQuery.cssProps[ origName ] ||
            ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );

        // Gets hook for the prefixed version, then unprefixed version
        hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

        // Check if we're setting a value
        if ( value !== undefined ) {
            type = typeof value;

            // Convert "+=" or "-=" to relative numbers (#7345)
            if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
                value = adjustCSS( elem, name, ret );

                // Fixes bug #9237
                type = "number";
            }

            // Make sure that null and NaN values aren't set (#7116)
            if ( value == null || value !== value ) {
                return;
            }

            // If a number was passed in, add the unit (except for certain CSS properties)
            if ( type === "number" ) {
                value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
            }

            // Support: IE9-11+
            // background-* props affect original clone's values
            if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
                style[ name ] = "inherit";
            }

            // If a hook was provided, use that value, otherwise just set the specified value
            if ( !hooks || !( "set" in hooks ) ||
                ( value = hooks.set( elem, value, extra ) ) !== undefined ) {

                style[ name ] = value;
            }

        } else {

            // If a hook was provided get the non-computed value from there
            if ( hooks && "get" in hooks &&
                ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {

                return ret;
            }

            // Otherwise just get the value from the style object
            return style[ name ];
        }
    },

    css: function( elem, name, extra, styles ) {
        var val, num, hooks,
            origName = jQuery.camelCase( name );

        // Make sure that we're working with the right name
        name = jQuery.cssProps[ origName ] ||
            ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );

        // Try prefixed name followed by the unprefixed name
        hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

        // If a hook was provided get the computed value from there
        if ( hooks && "get" in hooks ) {
            val = hooks.get( elem, true, extra );
        }

        // Otherwise, if a way to get the computed value exists, use that
        if ( val === undefined ) {
            val = curCSS( elem, name, styles );
        }

        // Convert "normal" to computed value
        if ( val === "normal" && name in cssNormalTransform ) {
            val = cssNormalTransform[ name ];
        }

        // Make numeric if forced or a qualifier was provided and val looks numeric
        if ( extra === "" || extra ) {
            num = parseFloat( val );
            return extra === true || isFinite( num ) ? num || 0 : val;
        }
        return val;
    }
} );

jQuery.each( [ "height", "width" ], function( i, name ) {
    jQuery.cssHooks[ name ] = {
        get: function( elem, computed, extra ) {
            if ( computed ) {

                // Certain elements can have dimension info if we invisibly show them
                // but it must have a current display style that would benefit
                return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
                    elem.offsetWidth === 0 ?
                        swap( elem, cssShow, function() {
                            return getWidthOrHeight( elem, name, extra );
                        } ) :
                        getWidthOrHeight( elem, name, extra );
            }
        },

        set: function( elem, value, extra ) {
            var matches,
                styles = extra && getStyles( elem ),
                subtract = extra && augmentWidthOrHeight(
                    elem,
                    name,
                    extra,
                    jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
                    styles
                );

            // Convert to pixels if value adjustment is needed
            if ( subtract && ( matches = rcssNum.exec( value ) ) &&
                ( matches[ 3 ] || "px" ) !== "px" ) {

                elem.style[ name ] = value;
                value = jQuery.css( elem, name );
            }

            return setPositiveNumber( elem, value, subtract );
        }
    };
} );

jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
    function( elem, computed ) {
        if ( computed ) {
            return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
                elem.getBoundingClientRect().left -
                    swap( elem, { marginLeft: 0 }, function() {
                        return elem.getBoundingClientRect().left;
                    } )
                ) + "px";
        }
    }
);

// Support: Android 2.3
jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
    function( elem, computed ) {
        if ( computed ) {
            return swap( elem, { "display": "inline-block" },
                curCSS, [ elem, "marginRight" ] );
        }
    }
);

// These hooks are used by animate to expand properties
jQuery.each( {
    margin: "",
    padding: "",
    border: "Width"
}, function( prefix, suffix ) {
    jQuery.cssHooks[ prefix + suffix ] = {
        expand: function( value ) {
            var i = 0,
                expanded = {},

                // Assumes a single number if not a string
                parts = typeof value === "string" ? value.split( " " ) : [ value ];

            for ( ; i < 4; i++ ) {
                expanded[ prefix + cssExpand[ i ] + suffix ] =
                    parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
            }

            return expanded;
        }
    };

    if ( !rmargin.test( prefix ) ) {
        jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
    }
} );

jQuery.fn.extend( {
    css: function( name, value ) {
        return access( this, function( elem, name, value ) {
            var styles, len,
                map = {},
                i = 0;

            if ( jQuery.isArray( name ) ) {
                styles = getStyles( elem );
                len = name.length;

                for ( ; i < len; i++ ) {
                    map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
                }

                return map;
            }

            return value !== undefined ?
                jQuery.style( elem, name, value ) :
                jQuery.css( elem, name );
        }, name, value, arguments.length > 1 );
    },
    show: function() {
        return showHide( this, true );
    },
    hide: function() {
        return showHide( this );
    },
    toggle: function( state ) {
        if ( typeof state === "boolean" ) {
            return state ? this.show() : this.hide();
        }

        return this.each( function() {
            if ( isHidden( this ) ) {
                jQuery( this ).show();
            } else {
                jQuery( this ).hide();
            }
        } );
    }
} );


function Tween( elem, options, prop, end, easing ) {
    return new Tween.prototype.init( elem, options, prop, end, easing );
}
jQuery.Tween = Tween;

Tween.prototype = {
    constructor: Tween,
    init: function( elem, options, prop, end, easing, unit ) {
        this.elem = elem;
        this.prop = prop;
        this.easing = easing || jQuery.easing._default;
        this.options = options;
        this.start = this.now = this.cur();
        this.end = end;
        this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
    },
    cur: function() {
        var hooks = Tween.propHooks[ this.prop ];

        return hooks && hooks.get ?
            hooks.get( this ) :
            Tween.propHooks._default.get( this );
    },
    run: function( percent ) {
        var eased,
            hooks = Tween.propHooks[ this.prop ];

        if ( this.options.duration ) {
            this.pos = eased = jQuery.easing[ this.easing ](
                percent, this.options.duration * percent, 0, 1, this.options.duration
            );
        } else {
            this.pos = eased = percent;
        }
        this.now = ( this.end - this.start ) * eased + this.start;

        if ( this.options.step ) {
            this.options.step.call( this.elem, this.now, this );
        }

        if ( hooks && hooks.set ) {
            hooks.set( this );
        } else {
            Tween.propHooks._default.set( this );
        }
        return this;
    }
};

Tween.prototype.init.prototype = Tween.prototype;

Tween.propHooks = {
    _default: {
        get: function( tween ) {
            var result;

            // Use a property on the element directly when it is not a DOM element,
            // or when there is no matching style property that exists.
            if ( tween.elem.nodeType !== 1 ||
                tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
                return tween.elem[ tween.prop ];
            }

            // Passing an empty string as a 3rd parameter to .css will automatically
            // attempt a parseFloat and fallback to a string if the parse fails.
            // Simple values such as "10px" are parsed to Float;
            // complex values such as "rotate(1rad)" are returned as-is.
            result = jQuery.css( tween.elem, tween.prop, "" );

            // Empty strings, null, undefined and "auto" are converted to 0.
            return !result || result === "auto" ? 0 : result;
        },
        set: function( tween ) {

            // Use step hook for back compat.
            // Use cssHook if its there.
            // Use .style if available and use plain properties where available.
            if ( jQuery.fx.step[ tween.prop ] ) {
                jQuery.fx.step[ tween.prop ]( tween );
            } else if ( tween.elem.nodeType === 1 &&
                ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
                    jQuery.cssHooks[ tween.prop ] ) ) {
                jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
            } else {
                tween.elem[ tween.prop ] = tween.now;
            }
        }
    }
};

// Support: IE9
// Panic based approach to setting things on disconnected nodes
Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
    set: function( tween ) {
        if ( tween.elem.nodeType && tween.elem.parentNode ) {
            tween.elem[ tween.prop ] = tween.now;
        }
    }
};

jQuery.easing = {
    linear: function( p ) {
        return p;
    },
    swing: function( p ) {
        return 0.5 - Math.cos( p * Math.PI ) / 2;
    },
    _default: "swing"
};

jQuery.fx = Tween.prototype.init;

// Back Compat <1.8 extension point
jQuery.fx.step = {};




var
    fxNow, timerId,
    rfxtypes = /^(?:toggle|show|hide)$/,
    rrun = /queueHooks$/;

// Animations created synchronously will run synchronously
function createFxNow() {
    window.setTimeout( function() {
        fxNow = undefined;
    } );
    return ( fxNow = jQuery.now() );
}

// Generate parameters to create a standard animation
function genFx( type, includeWidth ) {
    var which,
        i = 0,
        attrs = { height: type };

    // If we include width, step value is 1 to do all cssExpand values,
    // otherwise step value is 2 to skip over Left and Right
    includeWidth = includeWidth ? 1 : 0;
    for ( ; i < 4 ; i += 2 - includeWidth ) {
        which = cssExpand[ i ];
        attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
    }

    if ( includeWidth ) {
        attrs.opacity = attrs.width = type;
    }

    return attrs;
}

function createTween( value, prop, animation ) {
    var tween,
        collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
        index = 0,
        length = collection.length;
    for ( ; index < length; index++ ) {
        if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {

            // We're done with this property
            return tween;
        }
    }
}

function defaultPrefilter( elem, props, opts ) {
    /* jshint validthis: true */
    var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
        anim = this,
        orig = {},
        style = elem.style,
        hidden = elem.nodeType && isHidden( elem ),
        dataShow = dataPriv.get( elem, "fxshow" );

    // Handle queue: false promises
    if ( !opts.queue ) {
        hooks = jQuery._queueHooks( elem, "fx" );
        if ( hooks.unqueued == null ) {
            hooks.unqueued = 0;
            oldfire = hooks.empty.fire;
            hooks.empty.fire = function() {
                if ( !hooks.unqueued ) {
                    oldfire();
                }
            };
        }
        hooks.unqueued++;

        anim.always( function() {

            // Ensure the complete handler is called before this completes
            anim.always( function() {
                hooks.unqueued--;
                if ( !jQuery.queue( elem, "fx" ).length ) {
                    hooks.empty.fire();
                }
            } );
        } );
    }

    // Height/width overflow pass
    if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {

        // Make sure that nothing sneaks out
        // Record all 3 overflow attributes because IE9-10 do not
        // change the overflow attribute when overflowX and
        // overflowY are set to the same value
        opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];

        // Set display property to inline-block for height/width
        // animations on inline elements that are having width/height animated
        display = jQuery.css( elem, "display" );

        // Test default display if display is currently "none"
        checkDisplay = display === "none" ?
            dataPriv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;

        if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
            style.display = "inline-block";
        }
    }

    if ( opts.overflow ) {
        style.overflow = "hidden";
        anim.always( function() {
            style.overflow = opts.overflow[ 0 ];
            style.overflowX = opts.overflow[ 1 ];
            style.overflowY = opts.overflow[ 2 ];
        } );
    }

    // show/hide pass
    for ( prop in props ) {
        value = props[ prop ];
        if ( rfxtypes.exec( value ) ) {
            delete props[ prop ];
            toggle = toggle || value === "toggle";
            if ( value === ( hidden ? "hide" : "show" ) ) {

                // If there is dataShow left over from a stopped hide or show
                // and we are going to proceed with show, we should pretend to be hidden
                if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
                    hidden = true;
                } else {
                    continue;
                }
            }
            orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );

        // Any non-fx value stops us from restoring the original display value
        } else {
            display = undefined;
        }
    }

    if ( !jQuery.isEmptyObject( orig ) ) {
        if ( dataShow ) {
            if ( "hidden" in dataShow ) {
                hidden = dataShow.hidden;
            }
        } else {
            dataShow = dataPriv.access( elem, "fxshow", {} );
        }

        // Store state if its toggle - enables .stop().toggle() to "reverse"
        if ( toggle ) {
            dataShow.hidden = !hidden;
        }
        if ( hidden ) {
            jQuery( elem ).show();
        } else {
            anim.done( function() {
                jQuery( elem ).hide();
            } );
        }
        anim.done( function() {
            var prop;

            dataPriv.remove( elem, "fxshow" );
            for ( prop in orig ) {
                jQuery.style( elem, prop, orig[ prop ] );
            }
        } );
        for ( prop in orig ) {
            tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );

            if ( !( prop in dataShow ) ) {
                dataShow[ prop ] = tween.start;
                if ( hidden ) {
                    tween.end = tween.start;
                    tween.start = prop === "width" || prop === "height" ? 1 : 0;
                }
            }
        }

    // If this is a noop like .hide().hide(), restore an overwritten display value
    } else if ( ( display === "none" ? defaultDisplay( elem.nodeName ) : display ) === "inline" ) {
        style.display = display;
    }
}

function propFilter( props, specialEasing ) {
    var index, name, easing, value, hooks;

    // camelCase, specialEasing and expand cssHook pass
    for ( index in props ) {
        name = jQuery.camelCase( index );
        easing = specialEasing[ name ];
        value = props[ index ];
        if ( jQuery.isArray( value ) ) {
            easing = value[ 1 ];
            value = props[ index ] = value[ 0 ];
        }

        if ( index !== name ) {
            props[ name ] = value;
            delete props[ index ];
        }

        hooks = jQuery.cssHooks[ name ];
        if ( hooks && "expand" in hooks ) {
            value = hooks.expand( value );
            delete props[ name ];

            // Not quite $.extend, this won't overwrite existing keys.
            // Reusing 'index' because we have the correct "name"
            for ( index in value ) {
                if ( !( index in props ) ) {
                    props[ index ] = value[ index ];
                    specialEasing[ index ] = easing;
                }
            }
        } else {
            specialEasing[ name ] = easing;
        }
    }
}

function Animation( elem, properties, options ) {
    var result,
        stopped,
        index = 0,
        length = Animation.prefilters.length,
        deferred = jQuery.Deferred().always( function() {

            // Don't match elem in the :animated selector
            delete tick.elem;
        } ),
        tick = function() {
            if ( stopped ) {
                return false;
            }
            var currentTime = fxNow || createFxNow(),
                remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),

                // Support: Android 2.3
                // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
                temp = remaining / animation.duration || 0,
                percent = 1 - temp,
                index = 0,
                length = animation.tweens.length;

            for ( ; index < length ; index++ ) {
                animation.tweens[ index ].run( percent );
            }

            deferred.notifyWith( elem, [ animation, percent, remaining ] );

            if ( percent < 1 && length ) {
                return remaining;
            } else {
                deferred.resolveWith( elem, [ animation ] );
                return false;
            }
        },
        animation = deferred.promise( {
            elem: elem,
            props: jQuery.extend( {}, properties ),
            opts: jQuery.extend( true, {
                specialEasing: {},
                easing: jQuery.easing._default
            }, options ),
            originalProperties: properties,
            originalOptions: options,
            startTime: fxNow || createFxNow(),
            duration: options.duration,
            tweens: [],
            createTween: function( prop, end ) {
                var tween = jQuery.Tween( elem, animation.opts, prop, end,
                        animation.opts.specialEasing[ prop ] || animation.opts.easing );
                animation.tweens.push( tween );
                return tween;
            },
            stop: function( gotoEnd ) {
                var index = 0,

                    // If we are going to the end, we want to run all the tweens
                    // otherwise we skip this part
                    length = gotoEnd ? animation.tweens.length : 0;
                if ( stopped ) {
                    return this;
                }
                stopped = true;
                for ( ; index < length ; index++ ) {
                    animation.tweens[ index ].run( 1 );
                }

                // Resolve when we played the last frame; otherwise, reject
                if ( gotoEnd ) {
                    deferred.notifyWith( elem, [ animation, 1, 0 ] );
                    deferred.resolveWith( elem, [ animation, gotoEnd ] );
                } else {
                    deferred.rejectWith( elem, [ animation, gotoEnd ] );
                }
                return this;
            }
        } ),
        props = animation.props;

    propFilter( props, animation.opts.specialEasing );

    for ( ; index < length ; index++ ) {
        result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
        if ( result ) {
            if ( jQuery.isFunction( result.stop ) ) {
                jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
                    jQuery.proxy( result.stop, result );
            }
            return result;
        }
    }

    jQuery.map( props, createTween, animation );

    if ( jQuery.isFunction( animation.opts.start ) ) {
        animation.opts.start.call( elem, animation );
    }

    jQuery.fx.timer(
        jQuery.extend( tick, {
            elem: elem,
            anim: animation,
            queue: animation.opts.queue
        } )
    );

    // attach callbacks from options
    return animation.progress( animation.opts.progress )
        .done( animation.opts.done, animation.opts.complete )
        .fail( animation.opts.fail )
        .always( animation.opts.always );
}

jQuery.Animation = jQuery.extend( Animation, {
    tweeners: {
        "*": [ function( prop, value ) {
            var tween = this.createTween( prop, value );
            adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
            return tween;
        } ]
    },

    tweener: function( props, callback ) {
        if ( jQuery.isFunction( props ) ) {
            callback = props;
            props = [ "*" ];
        } else {
            props = props.match( rnotwhite );
        }

        var prop,
            index = 0,
            length = props.length;

        for ( ; index < length ; index++ ) {
            prop = props[ index ];
            Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
            Animation.tweeners[ prop ].unshift( callback );
        }
    },

    prefilters: [ defaultPrefilter ],

    prefilter: function( callback, prepend ) {
        if ( prepend ) {
            Animation.prefilters.unshift( callback );
        } else {
            Animation.prefilters.push( callback );
        }
    }
} );

jQuery.speed = function( speed, easing, fn ) {
    var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
        complete: fn || !fn && easing ||
            jQuery.isFunction( speed ) && speed,
        duration: speed,
        easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
    };

    opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ?
        opt.duration : opt.duration in jQuery.fx.speeds ?
            jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;

    // Normalize opt.queue - true/undefined/null -> "fx"
    if ( opt.queue == null || opt.queue === true ) {
        opt.queue = "fx";
    }

    // Queueing
    opt.old = opt.complete;

    opt.complete = function() {
        if ( jQuery.isFunction( opt.old ) ) {
            opt.old.call( this );
        }

        if ( opt.queue ) {
            jQuery.dequeue( this, opt.queue );
        }
    };

    return opt;
};

jQuery.fn.extend( {
    fadeTo: function( speed, to, easing, callback ) {

        // Show any hidden elements after setting opacity to 0
        return this.filter( isHidden ).css( "opacity", 0 ).show()

            // Animate to the value specified
            .end().animate( { opacity: to }, speed, easing, callback );
    },
    animate: function( prop, speed, easing, callback ) {
        var empty = jQuery.isEmptyObject( prop ),
            optall = jQuery.speed( speed, easing, callback ),
            doAnimation = function() {

                // Operate on a copy of prop so per-property easing won't be lost
                var anim = Animation( this, jQuery.extend( {}, prop ), optall );

                // Empty animations, or finishing resolves immediately
                if ( empty || dataPriv.get( this, "finish" ) ) {
                    anim.stop( true );
                }
            };
            doAnimation.finish = doAnimation;

        return empty || optall.queue === false ?
            this.each( doAnimation ) :
            this.queue( optall.queue, doAnimation );
    },
    stop: function( type, clearQueue, gotoEnd ) {
        var stopQueue = function( hooks ) {
            var stop = hooks.stop;
            delete hooks.stop;
            stop( gotoEnd );
        };

        if ( typeof type !== "string" ) {
            gotoEnd = clearQueue;
            clearQueue = type;
            type = undefined;
        }
        if ( clearQueue && type !== false ) {
            this.queue( type || "fx", [] );
        }

        return this.each( function() {
            var dequeue = true,
                index = type != null && type + "queueHooks",
                timers = jQuery.timers,
                data = dataPriv.get( this );

            if ( index ) {
                if ( data[ index ] && data[ index ].stop ) {
                    stopQueue( data[ index ] );
                }
            } else {
                for ( index in data ) {
                    if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
                        stopQueue( data[ index ] );
                    }
                }
            }

            for ( index = timers.length; index--; ) {
                if ( timers[ index ].elem === this &&
                    ( type == null || timers[ index ].queue === type ) ) {

                    timers[ index ].anim.stop( gotoEnd );
                    dequeue = false;
                    timers.splice( index, 1 );
                }
            }

            // Start the next in the queue if the last step wasn't forced.
            // Timers currently will call their complete callbacks, which
            // will dequeue but only if they were gotoEnd.
            if ( dequeue || !gotoEnd ) {
                jQuery.dequeue( this, type );
            }
        } );
    },
    finish: function( type ) {
        if ( type !== false ) {
            type = type || "fx";
        }
        return this.each( function() {
            var index,
                data = dataPriv.get( this ),
                queue = data[ type + "queue" ],
                hooks = data[ type + "queueHooks" ],
                timers = jQuery.timers,
                length = queue ? queue.length : 0;

            // Enable finishing flag on private data
            data.finish = true;

            // Empty the queue first
            jQuery.queue( this, type, [] );

            if ( hooks && hooks.stop ) {
                hooks.stop.call( this, true );
            }

            // Look for any active animations, and finish them
            for ( index = timers.length; index--; ) {
                if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
                    timers[ index ].anim.stop( true );
                    timers.splice( index, 1 );
                }
            }

            // Look for any animations in the old queue and finish them
            for ( index = 0; index < length; index++ ) {
                if ( queue[ index ] && queue[ index ].finish ) {
                    queue[ index ].finish.call( this );
                }
            }

            // Turn off finishing flag
            delete data.finish;
        } );
    }
} );

jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
    var cssFn = jQuery.fn[ name ];
    jQuery.fn[ name ] = function( speed, easing, callback ) {
        return speed == null || typeof speed === "boolean" ?
            cssFn.apply( this, arguments ) :
            this.animate( genFx( name, true ), speed, easing, callback );
    };
} );

// Generate shortcuts for custom animations
jQuery.each( {
    slideDown: genFx( "show" ),
    slideUp: genFx( "hide" ),
    slideToggle: genFx( "toggle" ),
    fadeIn: { opacity: "show" },
    fadeOut: { opacity: "hide" },
    fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
    jQuery.fn[ name ] = function( speed, easing, callback ) {
        return this.animate( props, speed, easing, callback );
    };
} );

jQuery.timers = [];
jQuery.fx.tick = function() {
    var timer,
        i = 0,
        timers = jQuery.timers;

    fxNow = jQuery.now();

    for ( ; i < timers.length; i++ ) {
        timer = timers[ i ];

        // Checks the timer has not already been removed
        if ( !timer() && timers[ i ] === timer ) {
            timers.splice( i--, 1 );
        }
    }

    if ( !timers.length ) {
        jQuery.fx.stop();
    }
    fxNow = undefined;
};

jQuery.fx.timer = function( timer ) {
    jQuery.timers.push( timer );
    if ( timer() ) {
        jQuery.fx.start();
    } else {
        jQuery.timers.pop();
    }
};

jQuery.fx.interval = 13;
jQuery.fx.start = function() {
    if ( !timerId ) {
        timerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
    }
};

jQuery.fx.stop = function() {
    window.clearInterval( timerId );

    timerId = null;
};

jQuery.fx.speeds = {
    slow: 600,
    fast: 200,

    // Default speed
    _default: 400
};


// Based off of the plugin by Clint Helfers, with permission.
// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
jQuery.fn.delay = function( time, type ) {
    time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
    type = type || "fx";

    return this.queue( type, function( next, hooks ) {
        var timeout = window.setTimeout( next, time );
        hooks.stop = function() {
            window.clearTimeout( timeout );
        };
    } );
};


( function() {
    var input = document.createElement( "input" ),
        select = document.createElement( "select" ),
        opt = select.appendChild( document.createElement( "option" ) );

    input.type = "checkbox";

    // Support: iOS<=5.1, Android<=4.2+
    // Default value for a checkbox should be "on"
    support.checkOn = input.value !== "";

    // Support: IE<=11+
    // Must access selectedIndex to make default options select
    support.optSelected = opt.selected;

    // Support: Android<=2.3
    // Options inside disabled selects are incorrectly marked as disabled
    select.disabled = true;
    support.optDisabled = !opt.disabled;

    // Support: IE<=11+
    // An input loses its value after becoming a radio
    input = document.createElement( "input" );
    input.value = "t";
    input.type = "radio";
    support.radioValue = input.value === "t";
} )();


var boolHook,
    attrHandle = jQuery.expr.attrHandle;

jQuery.fn.extend( {
    attr: function( name, value ) {
        return access( this, jQuery.attr, name, value, arguments.length > 1 );
    },

    removeAttr: function( name ) {
        return this.each( function() {
            jQuery.removeAttr( this, name );
        } );
    }
} );

jQuery.extend( {
    attr: function( elem, name, value ) {
        var ret, hooks,
            nType = elem.nodeType;

        // Don't get/set attributes on text, comment and attribute nodes
        if ( nType === 3 || nType === 8 || nType === 2 ) {
            return;
        }

        // Fallback to prop when attributes are not supported
        if ( typeof elem.getAttribute === "undefined" ) {
            return jQuery.prop( elem, name, value );
        }

        // All attributes are lowercase
        // Grab necessary hook if one is defined
        if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
            name = name.toLowerCase();
            hooks = jQuery.attrHooks[ name ] ||
                ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
        }

        if ( value !== undefined ) {
            if ( value === null ) {
                jQuery.removeAttr( elem, name );
                return;
            }

            if ( hooks && "set" in hooks &&
                ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
                return ret;
            }

            elem.setAttribute( name, value + "" );
            return value;
        }

        if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
            return ret;
        }

        ret = jQuery.find.attr( elem, name );

        // Non-existent attributes return null, we normalize to undefined
        return ret == null ? undefined : ret;
    },

    attrHooks: {
        type: {
            set: function( elem, value ) {
                if ( !support.radioValue && value === "radio" &&
                    jQuery.nodeName( elem, "input" ) ) {
                    var val = elem.value;
                    elem.setAttribute( "type", value );
                    if ( val ) {
                        elem.value = val;
                    }
                    return value;
                }
            }
        }
    },

    removeAttr: function( elem, value ) {
        var name, propName,
            i = 0,
            attrNames = value && value.match( rnotwhite );

        if ( attrNames && elem.nodeType === 1 ) {
            while ( ( name = attrNames[ i++ ] ) ) {
                propName = jQuery.propFix[ name ] || name;

                // Boolean attributes get special treatment (#10870)
                if ( jQuery.expr.match.bool.test( name ) ) {

                    // Set corresponding property to false
                    elem[ propName ] = false;
                }

                elem.removeAttribute( name );
            }
        }
    }
} );

// Hooks for boolean attributes
boolHook = {
    set: function( elem, value, name ) {
        if ( value === false ) {

            // Remove boolean attributes when set to false
            jQuery.removeAttr( elem, name );
        } else {
            elem.setAttribute( name, name );
        }
        return name;
    }
};
jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
    var getter = attrHandle[ name ] || jQuery.find.attr;

    attrHandle[ name ] = function( elem, name, isXML ) {
        var ret, handle;
        if ( !isXML ) {

            // Avoid an infinite loop by temporarily removing this function from the getter
            handle = attrHandle[ name ];
            attrHandle[ name ] = ret;
            ret = getter( elem, name, isXML ) != null ?
                name.toLowerCase() :
                null;
            attrHandle[ name ] = handle;
        }
        return ret;
    };
} );




var rfocusable = /^(?:input|select|textarea|button)$/i,
    rclickable = /^(?:a|area)$/i;

jQuery.fn.extend( {
    prop: function( name, value ) {
        return access( this, jQuery.prop, name, value, arguments.length > 1 );
    },

    removeProp: function( name ) {
        return this.each( function() {
            delete this[ jQuery.propFix[ name ] || name ];
        } );
    }
} );

jQuery.extend( {
    prop: function( elem, name, value ) {
        var ret, hooks,
            nType = elem.nodeType;

        // Don't get/set properties on text, comment and attribute nodes
        if ( nType === 3 || nType === 8 || nType === 2 ) {
            return;
        }

        if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {

            // Fix name and attach hooks
            name = jQuery.propFix[ name ] || name;
            hooks = jQuery.propHooks[ name ];
        }

        if ( value !== undefined ) {
            if ( hooks && "set" in hooks &&
                ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
                return ret;
            }

            return ( elem[ name ] = value );
        }

        if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
            return ret;
        }

        return elem[ name ];
    },

    propHooks: {
        tabIndex: {
            get: function( elem ) {

                // elem.tabIndex doesn't always return the
                // correct value when it hasn't been explicitly set
                // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
                // Use proper attribute retrieval(#12072)
                var tabindex = jQuery.find.attr( elem, "tabindex" );

                return tabindex ?
                    parseInt( tabindex, 10 ) :
                    rfocusable.test( elem.nodeName ) ||
                        rclickable.test( elem.nodeName ) && elem.href ?
                            0 :
                            -1;
            }
        }
    },

    propFix: {
        "for": "htmlFor",
        "class": "className"
    }
} );

// Support: IE <=11 only
// Accessing the selectedIndex property
// forces the browser to respect setting selected
// on the option
// The getter ensures a default option is selected
// when in an optgroup
if ( !support.optSelected ) {
    jQuery.propHooks.selected = {
        get: function( elem ) {
            var parent = elem.parentNode;
            if ( parent && parent.parentNode ) {
                parent.parentNode.selectedIndex;
            }
            return null;
        },
        set: function( elem ) {
            var parent = elem.parentNode;
            if ( parent ) {
                parent.selectedIndex;

                if ( parent.parentNode ) {
                    parent.parentNode.selectedIndex;
                }
            }
        }
    };
}

jQuery.each( [
    "tabIndex",
    "readOnly",
    "maxLength",
    "cellSpacing",
    "cellPadding",
    "rowSpan",
    "colSpan",
    "useMap",
    "frameBorder",
    "contentEditable"
], function() {
    jQuery.propFix[ this.toLowerCase() ] = this;
} );




var rclass = /[\t\r\n\f]/g;

function getClass( elem ) {
    return elem.getAttribute && elem.getAttribute( "class" ) || "";
}

jQuery.fn.extend( {
    addClass: function( value ) {
        var classes, elem, cur, curValue, clazz, j, finalValue,
            i = 0;

        if ( jQuery.isFunction( value ) ) {
            return this.each( function( j ) {
                jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
            } );
        }

        if ( typeof value === "string" && value ) {
            classes = value.match( rnotwhite ) || [];

            while ( ( elem = this[ i++ ] ) ) {
                curValue = getClass( elem );
                cur = elem.nodeType === 1 &&
                    ( " " + curValue + " " ).replace( rclass, " " );

                if ( cur ) {
                    j = 0;
                    while ( ( clazz = classes[ j++ ] ) ) {
                        if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
                            cur += clazz + " ";
                        }
                    }

                    // Only assign if different to avoid unneeded rendering.
                    finalValue = jQuery.trim( cur );
                    if ( curValue !== finalValue ) {
                        elem.setAttribute( "class", finalValue );
                    }
                }
            }
        }

        return this;
    },

    removeClass: function( value ) {
        var classes, elem, cur, curValue, clazz, j, finalValue,
            i = 0;

        if ( jQuery.isFunction( value ) ) {
            return this.each( function( j ) {
                jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
            } );
        }

        if ( !arguments.length ) {
            return this.attr( "class", "" );
        }

        if ( typeof value === "string" && value ) {
            classes = value.match( rnotwhite ) || [];

            while ( ( elem = this[ i++ ] ) ) {
                curValue = getClass( elem );

                // This expression is here for better compressibility (see addClass)
                cur = elem.nodeType === 1 &&
                    ( " " + curValue + " " ).replace( rclass, " " );

                if ( cur ) {
                    j = 0;
                    while ( ( clazz = classes[ j++ ] ) ) {

                        // Remove *all* instances
                        while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
                            cur = cur.replace( " " + clazz + " ", " " );
                        }
                    }

                    // Only assign if different to avoid unneeded rendering.
                    finalValue = jQuery.trim( cur );
                    if ( curValue !== finalValue ) {
                        elem.setAttribute( "class", finalValue );
                    }
                }
            }
        }

        return this;
    },

    toggleClass: function( value, stateVal ) {
        var type = typeof value;

        if ( typeof stateVal === "boolean" && type === "string" ) {
            return stateVal ? this.addClass( value ) : this.removeClass( value );
        }

        if ( jQuery.isFunction( value ) ) {
            return this.each( function( i ) {
                jQuery( this ).toggleClass(
                    value.call( this, i, getClass( this ), stateVal ),
                    stateVal
                );
            } );
        }

        return this.each( function() {
            var className, i, self, classNames;

            if ( type === "string" ) {

                // Toggle individual class names
                i = 0;
                self = jQuery( this );
                classNames = value.match( rnotwhite ) || [];

                while ( ( className = classNames[ i++ ] ) ) {

                    // Check each className given, space separated list
                    if ( self.hasClass( className ) ) {
                        self.removeClass( className );
                    } else {
                        self.addClass( className );
                    }
                }

            // Toggle whole class name
            } else if ( value === undefined || type === "boolean" ) {
                className = getClass( this );
                if ( className ) {

                    // Store className if set
                    dataPriv.set( this, "__className__", className );
                }

                // If the element has a class name or if we're passed `false`,
                // then remove the whole classname (if there was one, the above saved it).
                // Otherwise bring back whatever was previously saved (if anything),
                // falling back to the empty string if nothing was stored.
                if ( this.setAttribute ) {
                    this.setAttribute( "class",
                        className || value === false ?
                        "" :
                        dataPriv.get( this, "__className__" ) || ""
                    );
                }
            }
        } );
    },

    hasClass: function( selector ) {
        var className, elem,
            i = 0;

        className = " " + selector + " ";
        while ( ( elem = this[ i++ ] ) ) {
            if ( elem.nodeType === 1 &&
                ( " " + getClass( elem ) + " " ).replace( rclass, " " )
                    .indexOf( className ) > -1
            ) {
                return true;
            }
        }

        return false;
    }
} );




var rreturn = /\r/g,
    rspaces = /[\x20\t\r\n\f]+/g;

jQuery.fn.extend( {
    val: function( value ) {
        var hooks, ret, isFunction,
            elem = this[ 0 ];

        if ( !arguments.length ) {
            if ( elem ) {
                hooks = jQuery.valHooks[ elem.type ] ||
                    jQuery.valHooks[ elem.nodeName.toLowerCase() ];

                if ( hooks &&
                    "get" in hooks &&
                    ( ret = hooks.get( elem, "value" ) ) !== undefined
                ) {
                    return ret;
                }

                ret = elem.value;

                return typeof ret === "string" ?

                    // Handle most common string cases
                    ret.replace( rreturn, "" ) :

                    // Handle cases where value is null/undef or number
                    ret == null ? "" : ret;
            }

            return;
        }

        isFunction = jQuery.isFunction( value );

        return this.each( function( i ) {
            var val;

            if ( this.nodeType !== 1 ) {
                return;
            }

            if ( isFunction ) {
                val = value.call( this, i, jQuery( this ).val() );
            } else {
                val = value;
            }

            // Treat null/undefined as ""; convert numbers to string
            if ( val == null ) {
                val = "";

            } else if ( typeof val === "number" ) {
                val += "";

            } else if ( jQuery.isArray( val ) ) {
                val = jQuery.map( val, function( value ) {
                    return value == null ? "" : value + "";
                } );
            }

            hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];

            // If set returns undefined, fall back to normal setting
            if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
                this.value = val;
            }
        } );
    }
} );

jQuery.extend( {
    valHooks: {
        option: {
            get: function( elem ) {

                var val = jQuery.find.attr( elem, "value" );
                return val != null ?
                    val :

                    // Support: IE10-11+
                    // option.text throws exceptions (#14686, #14858)
                    // Strip and collapse whitespace
                    // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
                    jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
            }
        },
        select: {
            get: function( elem ) {
                var value, option,
                    options = elem.options,
                    index = elem.selectedIndex,
                    one = elem.type === "select-one" || index < 0,
                    values = one ? null : [],
                    max = one ? index + 1 : options.length,
                    i = index < 0 ?
                        max :
                        one ? index : 0;

                // Loop through all the selected options
                for ( ; i < max; i++ ) {
                    option = options[ i ];

                    // IE8-9 doesn't update selected after form reset (#2551)
                    if ( ( option.selected || i === index ) &&

                            // Don't return options that are disabled or in a disabled optgroup
                            ( support.optDisabled ?
                                !option.disabled : option.getAttribute( "disabled" ) === null ) &&
                            ( !option.parentNode.disabled ||
                                !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {

                        // Get the specific value for the option
                        value = jQuery( option ).val();

                        // We don't need an array for one selects
                        if ( one ) {
                            return value;
                        }

                        // Multi-Selects return an array
                        values.push( value );
                    }
                }

                return values;
            },

            set: function( elem, value ) {
                var optionSet, option,
                    options = elem.options,
                    values = jQuery.makeArray( value ),
                    i = options.length;

                while ( i-- ) {
                    option = options[ i ];
                    if ( option.selected =
                        jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
                    ) {
                        optionSet = true;
                    }
                }

                // Force browsers to behave consistently when non-matching value is set
                if ( !optionSet ) {
                    elem.selectedIndex = -1;
                }
                return values;
            }
        }
    }
} );

// Radios and checkboxes getter/setter
jQuery.each( [ "radio", "checkbox" ], function() {
    jQuery.valHooks[ this ] = {
        set: function( elem, value ) {
            if ( jQuery.isArray( value ) ) {
                return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
            }
        }
    };
    if ( !support.checkOn ) {
        jQuery.valHooks[ this ].get = function( elem ) {
            return elem.getAttribute( "value" ) === null ? "on" : elem.value;
        };
    }
} );




// Return jQuery for attributes-only inclusion


var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;

jQuery.extend( jQuery.event, {

    trigger: function( event, data, elem, onlyHandlers ) {

        var i, cur, tmp, bubbleType, ontype, handle, special,
            eventPath = [ elem || document ],
            type = hasOwn.call( event, "type" ) ? event.type : event,
            namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];

        cur = tmp = elem = elem || document;

        // Don't do events on text and comment nodes
        if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
            return;
        }

        // focus/blur morphs to focusin/out; ensure we're not firing them right now
        if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
            return;
        }

        if ( type.indexOf( "." ) > -1 ) {

            // Namespaced trigger; create a regexp to match event type in handle()
            namespaces = type.split( "." );
            type = namespaces.shift();
            namespaces.sort();
        }
        ontype = type.indexOf( ":" ) < 0 && "on" + type;

        // Caller can pass in a jQuery.Event object, Object, or just an event type string
        event = event[ jQuery.expando ] ?
            event :
            new jQuery.Event( type, typeof event === "object" && event );

        // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
        event.isTrigger = onlyHandlers ? 2 : 3;
        event.namespace = namespaces.join( "." );
        event.rnamespace = event.namespace ?
            new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
            null;

        // Clean up the event in case it is being reused
        event.result = undefined;
        if ( !event.target ) {
            event.target = elem;
        }

        // Clone any incoming data and prepend the event, creating the handler arg list
        data = data == null ?
            [ event ] :
            jQuery.makeArray( data, [ event ] );

        // Allow special events to draw outside the lines
        special = jQuery.event.special[ type ] || {};
        if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
            return;
        }

        // Determine event propagation path in advance, per W3C events spec (#9951)
        // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
        if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

            bubbleType = special.delegateType || type;
            if ( !rfocusMorph.test( bubbleType + type ) ) {
                cur = cur.parentNode;
            }
            for ( ; cur; cur = cur.parentNode ) {
                eventPath.push( cur );
                tmp = cur;
            }

            // Only add window if we got to document (e.g., not plain obj or detached DOM)
            if ( tmp === ( elem.ownerDocument || document ) ) {
                eventPath.push( tmp.defaultView || tmp.parentWindow || window );
            }
        }

        // Fire handlers on the event path
        i = 0;
        while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {

            event.type = i > 1 ?
                bubbleType :
                special.bindType || type;

            // jQuery handler
            handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
                dataPriv.get( cur, "handle" );
            if ( handle ) {
                handle.apply( cur, data );
            }

            // Native handler
            handle = ontype && cur[ ontype ];
            if ( handle && handle.apply && acceptData( cur ) ) {
                event.result = handle.apply( cur, data );
                if ( event.result === false ) {
                    event.preventDefault();
                }
            }
        }
        event.type = type;

        // If nobody prevented the default action, do it now
        if ( !onlyHandlers && !event.isDefaultPrevented() ) {

            if ( ( !special._default ||
                special._default.apply( eventPath.pop(), data ) === false ) &&
                acceptData( elem ) ) {

                // Call a native DOM method on the target with the same name name as the event.
                // Don't do default actions on window, that's where global variables be (#6170)
                if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {

                    // Don't re-trigger an onFOO event when we call its FOO() method
                    tmp = elem[ ontype ];

                    if ( tmp ) {
                        elem[ ontype ] = null;
                    }

                    // Prevent re-triggering of the same event, since we already bubbled it above
                    jQuery.event.triggered = type;
                    elem[ type ]();
                    jQuery.event.triggered = undefined;

                    if ( tmp ) {
                        elem[ ontype ] = tmp;
                    }
                }
            }
        }

        return event.result;
    },

    // Piggyback on a donor event to simulate a different one
    // Used only for `focus(in | out)` events
    simulate: function( type, elem, event ) {
        var e = jQuery.extend(
            new jQuery.Event(),
            event,
            {
                type: type,
                isSimulated: true
            }
        );

        jQuery.event.trigger( e, null, elem );
    }

} );

jQuery.fn.extend( {

    trigger: function( type, data ) {
        return this.each( function() {
            jQuery.event.trigger( type, data, this );
        } );
    },
    triggerHandler: function( type, data ) {
        var elem = this[ 0 ];
        if ( elem ) {
            return jQuery.event.trigger( type, data, elem, true );
        }
    }
} );


jQuery.each( ( "blur focus focusin focusout load resize scroll unload click dblclick " +
    "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
    "change select submit keydown keypress keyup error contextmenu" ).split( " " ),
    function( i, name ) {

    // Handle event binding
    jQuery.fn[ name ] = function( data, fn ) {
        return arguments.length > 0 ?
            this.on( name, null, data, fn ) :
            this.trigger( name );
    };
} );

jQuery.fn.extend( {
    hover: function( fnOver, fnOut ) {
        return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
    }
} );




support.focusin = "onfocusin" in window;


// Support: Firefox
// Firefox doesn't have focus(in | out) events
// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
//
// Support: Chrome, Safari
// focus(in | out) events fire after focus & blur events,
// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857
if ( !support.focusin ) {
    jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {

        // Attach a single capturing handler on the document while someone wants focusin/focusout
        var handler = function( event ) {
            jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
        };

        jQuery.event.special[ fix ] = {
            setup: function() {
                var doc = this.ownerDocument || this,
                    attaches = dataPriv.access( doc, fix );

                if ( !attaches ) {
                    doc.addEventListener( orig, handler, true );
                }
                dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
            },
            teardown: function() {
                var doc = this.ownerDocument || this,
                    attaches = dataPriv.access( doc, fix ) - 1;

                if ( !attaches ) {
                    doc.removeEventListener( orig, handler, true );
                    dataPriv.remove( doc, fix );

                } else {
                    dataPriv.access( doc, fix, attaches );
                }
            }
        };
    } );
}
var location = window.location;

var nonce = jQuery.now();

var rquery = ( /\?/ );



// Support: Android 2.3
// Workaround failure to string-cast null input
jQuery.parseJSON = function( data ) {
    return JSON.parse( data + "" );
};


// Cross-browser xml parsing
jQuery.parseXML = function( data ) {
    var xml;
    if ( !data || typeof data !== "string" ) {
        return null;
    }

    // Support: IE9
    try {
        xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
    } catch ( e ) {
        xml = undefined;
    }

    if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
        jQuery.error( "Invalid XML: " + data );
    }
    return xml;
};


var
    rhash = /#.*$/,
    rts = /([?&])_=[^&]*/,
    rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,

    // #7653, #8125, #8152: local protocol detection
    rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
    rnoContent = /^(?:GET|HEAD)$/,
    rprotocol = /^\/\//,

    /* Prefilters
     * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
     * 2) These are called:
     *    - BEFORE asking for a transport
     *    - AFTER param serialization (s.data is a string if s.processData is true)
     * 3) key is the dataType
     * 4) the catchall symbol "*" can be used
     * 5) execution will start with transport dataType and THEN continue down to "*" if needed
     */
    prefilters = {},

    /* Transports bindings
     * 1) key is the dataType
     * 2) the catchall symbol "*" can be used
     * 3) selection will start with transport dataType and THEN go to "*" if needed
     */
    transports = {},

    // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
    allTypes = "*/".concat( "*" ),

    // Anchor tag for parsing the document origin
    originAnchor = document.createElement( "a" );
    originAnchor.href = location.href;

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {

    // dataTypeExpression is optional and defaults to "*"
    return function( dataTypeExpression, func ) {

        if ( typeof dataTypeExpression !== "string" ) {
            func = dataTypeExpression;
            dataTypeExpression = "*";
        }

        var dataType,
            i = 0,
            dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];

        if ( jQuery.isFunction( func ) ) {

            // For each dataType in the dataTypeExpression
            while ( ( dataType = dataTypes[ i++ ] ) ) {

                // Prepend if requested
                if ( dataType[ 0 ] === "+" ) {
                    dataType = dataType.slice( 1 ) || "*";
                    ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );

                // Otherwise append
                } else {
                    ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
                }
            }
        }
    };
}

// Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {

    var inspected = {},
        seekingTransport = ( structure === transports );

    function inspect( dataType ) {
        var selected;
        inspected[ dataType ] = true;
        jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
            var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
            if ( typeof dataTypeOrTransport === "string" &&
                !seekingTransport && !inspected[ dataTypeOrTransport ] ) {

                options.dataTypes.unshift( dataTypeOrTransport );
                inspect( dataTypeOrTransport );
                return false;
            } else if ( seekingTransport ) {
                return !( selected = dataTypeOrTransport );
            }
        } );
        return selected;
    }

    return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes #9887
function ajaxExtend( target, src ) {
    var key, deep,
        flatOptions = jQuery.ajaxSettings.flatOptions || {};

    for ( key in src ) {
        if ( src[ key ] !== undefined ) {
            ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
        }
    }
    if ( deep ) {
        jQuery.extend( true, target, deep );
    }

    return target;
}

/* Handles responses to an ajax request:
 * - finds the right dataType (mediates between content-type and expected dataType)
 * - returns the corresponding response
 */
function ajaxHandleResponses( s, jqXHR, responses ) {

    var ct, type, finalDataType, firstDataType,
        contents = s.contents,
        dataTypes = s.dataTypes;

    // Remove auto dataType and get content-type in the process
    while ( dataTypes[ 0 ] === "*" ) {
        dataTypes.shift();
        if ( ct === undefined ) {
            ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
        }
    }

    // Check if we're dealing with a known content-type
    if ( ct ) {
        for ( type in contents ) {
            if ( contents[ type ] && contents[ type ].test( ct ) ) {
                dataTypes.unshift( type );
                break;
            }
        }
    }

    // Check to see if we have a response for the expected dataType
    if ( dataTypes[ 0 ] in responses ) {
        finalDataType = dataTypes[ 0 ];
    } else {

        // Try convertible dataTypes
        for ( type in responses ) {
            if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
                finalDataType = type;
                break;
            }
            if ( !firstDataType ) {
                firstDataType = type;
            }
        }

        // Or just use first one
        finalDataType = finalDataType || firstDataType;
    }

    // If we found a dataType
    // We add the dataType to the list if needed
    // and return the corresponding response
    if ( finalDataType ) {
        if ( finalDataType !== dataTypes[ 0 ] ) {
            dataTypes.unshift( finalDataType );
        }
        return responses[ finalDataType ];
    }
}

/* Chain conversions given the request and the original response
 * Also sets the responseXXX fields on the jqXHR instance
 */
function ajaxConvert( s, response, jqXHR, isSuccess ) {
    var conv2, current, conv, tmp, prev,
        converters = {},

        // Work with a copy of dataTypes in case we need to modify it for conversion
        dataTypes = s.dataTypes.slice();

    // Create converters map with lowercased keys
    if ( dataTypes[ 1 ] ) {
        for ( conv in s.converters ) {
            converters[ conv.toLowerCase() ] = s.converters[ conv ];
        }
    }

    current = dataTypes.shift();

    // Convert to each sequential dataType
    while ( current ) {

        if ( s.responseFields[ current ] ) {
            jqXHR[ s.responseFields[ current ] ] = response;
        }

        // Apply the dataFilter if provided
        if ( !prev && isSuccess && s.dataFilter ) {
            response = s.dataFilter( response, s.dataType );
        }

        prev = current;
        current = dataTypes.shift();

        if ( current ) {

        // There's only work to do if current dataType is non-auto
            if ( current === "*" ) {

                current = prev;

            // Convert response if prev dataType is non-auto and differs from current
            } else if ( prev !== "*" && prev !== current ) {

                // Seek a direct converter
                conv = converters[ prev + " " + current ] || converters[ "* " + current ];

                // If none found, seek a pair
                if ( !conv ) {
                    for ( conv2 in converters ) {

                        // If conv2 outputs current
                        tmp = conv2.split( " " );
                        if ( tmp[ 1 ] === current ) {

                            // If prev can be converted to accepted input
                            conv = converters[ prev + " " + tmp[ 0 ] ] ||
                                converters[ "* " + tmp[ 0 ] ];
                            if ( conv ) {

                                // Condense equivalence converters
                                if ( conv === true ) {
                                    conv = converters[ conv2 ];

                                // Otherwise, insert the intermediate dataType
                                } else if ( converters[ conv2 ] !== true ) {
                                    current = tmp[ 0 ];
                                    dataTypes.unshift( tmp[ 1 ] );
                                }
                                break;
                            }
                        }
                    }
                }

                // Apply converter (if not an equivalence)
                if ( conv !== true ) {

                    // Unless errors are allowed to bubble, catch and return them
                    if ( conv && s.throws ) {
                        response = conv( response );
                    } else {
                        try {
                            response = conv( response );
                        } catch ( e ) {
                            return {
                                state: "parsererror",
                                error: conv ? e : "No conversion from " + prev + " to " + current
                            };
                        }
                    }
                }
            }
        }
    }

    return { state: "success", data: response };
}

jQuery.extend( {

    // Counter for holding the number of active queries
    active: 0,

    // Last-Modified header cache for next request
    lastModified: {},
    etag: {},

    ajaxSettings: {
        url: location.href,
        type: "GET",
        isLocal: rlocalProtocol.test( location.protocol ),
        global: true,
        processData: true,
        async: true,
        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
        /*
        timeout: 0,
        data: null,
        dataType: null,
        username: null,
        password: null,
        cache: null,
        throws: false,
        traditional: false,
        headers: {},
        */

        accepts: {
            "*": allTypes,
            text: "text/plain",
            html: "text/html",
            xml: "application/xml, text/xml",
            json: "application/json, text/javascript"
        },

        contents: {
            xml: /\bxml\b/,
            html: /\bhtml/,
            json: /\bjson\b/
        },

        responseFields: {
            xml: "responseXML",
            text: "responseText",
            json: "responseJSON"
        },

        // Data converters
        // Keys separate source (or catchall "*") and destination types with a single space
        converters: {

            // Convert anything to text
            "* text": String,

            // Text to html (true = no transformation)
            "text html": true,

            // Evaluate text as a json expression
            "text json": jQuery.parseJSON,

            // Parse text as xml
            "text xml": jQuery.parseXML
        },

        // For options that shouldn't be deep extended:
        // you can add your own custom options here if
        // and when you create one that shouldn't be
        // deep extended (see ajaxExtend)
        flatOptions: {
            url: true,
            context: true
        }
    },

    // Creates a full fledged settings object into target
    // with both ajaxSettings and settings fields.
    // If target is omitted, writes into ajaxSettings.
    ajaxSetup: function( target, settings ) {
        return settings ?

            // Building a settings object
            ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :

            // Extending ajaxSettings
            ajaxExtend( jQuery.ajaxSettings, target );
    },

    ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
    ajaxTransport: addToPrefiltersOrTransports( transports ),

    // Main method
    ajax: function( url, options ) {

        // If url is an object, simulate pre-1.5 signature
        if ( typeof url === "object" ) {
            options = url;
            url = undefined;
        }

        // Force options to be an object
        options = options || {};

        var transport,

            // URL without anti-cache param
            cacheURL,

            // Response headers
            responseHeadersString,
            responseHeaders,

            // timeout handle
            timeoutTimer,

            // Url cleanup var
            urlAnchor,

            // To know if global events are to be dispatched
            fireGlobals,

            // Loop variable
            i,

            // Create the final options object
            s = jQuery.ajaxSetup( {}, options ),

            // Callbacks context
            callbackContext = s.context || s,

            // Context for global events is callbackContext if it is a DOM node or jQuery collection
            globalEventContext = s.context &&
                ( callbackContext.nodeType || callbackContext.jquery ) ?
                    jQuery( callbackContext ) :
                    jQuery.event,

            // Deferreds
            deferred = jQuery.Deferred(),
            completeDeferred = jQuery.Callbacks( "once memory" ),

            // Status-dependent callbacks
            statusCode = s.statusCode || {},

            // Headers (they are sent all at once)
            requestHeaders = {},
            requestHeadersNames = {},

            // The jqXHR state
            state = 0,

            // Default abort message
            strAbort = "canceled",

            // Fake xhr
            jqXHR = {
                readyState: 0,

                // Builds headers hashtable if needed
                getResponseHeader: function( key ) {
                    var match;
                    if ( state === 2 ) {
                        if ( !responseHeaders ) {
                            responseHeaders = {};
                            while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
                                responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
                            }
                        }
                        match = responseHeaders[ key.toLowerCase() ];
                    }
                    return match == null ? null : match;
                },

                // Raw string
                getAllResponseHeaders: function() {
                    return state === 2 ? responseHeadersString : null;
                },

                // Caches the header
                setRequestHeader: function( name, value ) {
                    var lname = name.toLowerCase();
                    if ( !state ) {
                        name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
                        requestHeaders[ name ] = value;
                    }
                    return this;
                },

                // Overrides response content-type header
                overrideMimeType: function( type ) {
                    if ( !state ) {
                        s.mimeType = type;
                    }
                    return this;
                },

                // Status-dependent callbacks
                statusCode: function( map ) {
                    var code;
                    if ( map ) {
                        if ( state < 2 ) {
                            for ( code in map ) {

                                // Lazy-add the new callback in a way that preserves old ones
                                statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
                            }
                        } else {

                            // Execute the appropriate callbacks
                            jqXHR.always( map[ jqXHR.status ] );
                        }
                    }
                    return this;
                },

                // Cancel the request
                abort: function( statusText ) {
                    var finalText = statusText || strAbort;
                    if ( transport ) {
                        transport.abort( finalText );
                    }
                    done( 0, finalText );
                    return this;
                }
            };

        // Attach deferreds
        deferred.promise( jqXHR ).complete = completeDeferred.add;
        jqXHR.success = jqXHR.done;
        jqXHR.error = jqXHR.fail;

        // Remove hash character (#7531: and string promotion)
        // Add protocol if not provided (prefilters might expect it)
        // Handle falsy url in the settings object (#10093: consistency with old signature)
        // We also use the url parameter if available
        s.url = ( ( url || s.url || location.href ) + "" ).replace( rhash, "" )
            .replace( rprotocol, location.protocol + "//" );

        // Alias method option to type as per ticket #12004
        s.type = options.method || options.type || s.method || s.type;

        // Extract dataTypes list
        s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];

        // A cross-domain request is in order when the origin doesn't match the current origin.
        if ( s.crossDomain == null ) {
            urlAnchor = document.createElement( "a" );

            // Support: IE8-11+
            // IE throws exception if url is malformed, e.g. http://example.com:80x/
            try {
                urlAnchor.href = s.url;

                // Support: IE8-11+
                // Anchor's host property isn't correctly set when s.url is relative
                urlAnchor.href = urlAnchor.href;
                s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
                    urlAnchor.protocol + "//" + urlAnchor.host;
            } catch ( e ) {

                // If there is an error parsing the URL, assume it is crossDomain,
                // it can be rejected by the transport if it is invalid
                s.crossDomain = true;
            }
        }

        // Convert data if not already a string
        if ( s.data && s.processData && typeof s.data !== "string" ) {
            s.data = jQuery.param( s.data, s.traditional );
        }

        // Apply prefilters
        inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

        // If request was aborted inside a prefilter, stop there
        if ( state === 2 ) {
            return jqXHR;
        }

        // We can fire global events as of now if asked to
        // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
        fireGlobals = jQuery.event && s.global;

        // Watch for a new set of requests
        if ( fireGlobals && jQuery.active++ === 0 ) {
            jQuery.event.trigger( "ajaxStart" );
        }

        // Uppercase the type
        s.type = s.type.toUpperCase();

        // Determine if request has content
        s.hasContent = !rnoContent.test( s.type );

        // Save the URL in case we're toying with the If-Modified-Since
        // and/or If-None-Match header later on
        cacheURL = s.url;

        // More options handling for requests with no content
        if ( !s.hasContent ) {

            // If data is available, append data to url
            if ( s.data ) {
                cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );

                // #9682: remove data so that it's not used in an eventual retry
                delete s.data;
            }

            // Add anti-cache in url if needed
            if ( s.cache === false ) {
                s.url = rts.test( cacheURL ) ?

                    // If there is already a '_' parameter, set its value
                    cacheURL.replace( rts, "$1_=" + nonce++ ) :

                    // Otherwise add one to the end
                    cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
            }
        }

        // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
        if ( s.ifModified ) {
            if ( jQuery.lastModified[ cacheURL ] ) {
                jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
            }
            if ( jQuery.etag[ cacheURL ] ) {
                jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
            }
        }

        // Set the correct header, if data is being sent
        if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
            jqXHR.setRequestHeader( "Content-Type", s.contentType );
        }

        // Set the Accepts header for the server, depending on the dataType
        jqXHR.setRequestHeader(
            "Accept",
            s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
                s.accepts[ s.dataTypes[ 0 ] ] +
                    ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
                s.accepts[ "*" ]
        );

        // Check for headers option
        for ( i in s.headers ) {
            jqXHR.setRequestHeader( i, s.headers[ i ] );
        }

        // Allow custom headers/mimetypes and early abort
        if ( s.beforeSend &&
            ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {

            // Abort if not done already and return
            return jqXHR.abort();
        }

        // Aborting is no longer a cancellation
        strAbort = "abort";

        // Install callbacks on deferreds
        for ( i in { success: 1, error: 1, complete: 1 } ) {
            jqXHR[ i ]( s[ i ] );
        }

        // Get transport
        transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

        // If no transport, we auto-abort
        if ( !transport ) {
            done( -1, "No Transport" );
        } else {
            jqXHR.readyState = 1;

            // Send global event
            if ( fireGlobals ) {
                globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
            }

            // If request was aborted inside ajaxSend, stop there
            if ( state === 2 ) {
                return jqXHR;
            }

            // Timeout
            if ( s.async && s.timeout > 0 ) {
                timeoutTimer = window.setTimeout( function() {
                    jqXHR.abort( "timeout" );
                }, s.timeout );
            }

            try {
                state = 1;
                transport.send( requestHeaders, done );
            } catch ( e ) {

                // Propagate exception as error if not done
                if ( state < 2 ) {
                    done( -1, e );

                // Simply rethrow otherwise
                } else {
                    throw e;
                }
            }
        }

        // Callback for when everything is done
        function done( status, nativeStatusText, responses, headers ) {
            var isSuccess, success, error, response, modified,
                statusText = nativeStatusText;

            // Called once
            if ( state === 2 ) {
                return;
            }

            // State is "done" now
            state = 2;

            // Clear timeout if it exists
            if ( timeoutTimer ) {
                window.clearTimeout( timeoutTimer );
            }

            // Dereference transport for early garbage collection
            // (no matter how long the jqXHR object will be used)
            transport = undefined;

            // Cache response headers
            responseHeadersString = headers || "";

            // Set readyState
            jqXHR.readyState = status > 0 ? 4 : 0;

            // Determine if successful
            isSuccess = status >= 200 && status < 300 || status === 304;

            // Get response data
            if ( responses ) {
                response = ajaxHandleResponses( s, jqXHR, responses );
            }

            // Convert no matter what (that way responseXXX fields are always set)
            response = ajaxConvert( s, response, jqXHR, isSuccess );

            // If successful, handle type chaining
            if ( isSuccess ) {

                // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
                if ( s.ifModified ) {
                    modified = jqXHR.getResponseHeader( "Last-Modified" );
                    if ( modified ) {
                        jQuery.lastModified[ cacheURL ] = modified;
                    }
                    modified = jqXHR.getResponseHeader( "etag" );
                    if ( modified ) {
                        jQuery.etag[ cacheURL ] = modified;
                    }
                }

                // if no content
                if ( status === 204 || s.type === "HEAD" ) {
                    statusText = "nocontent";

                // if not modified
                } else if ( status === 304 ) {
                    statusText = "notmodified";

                // If we have data, let's convert it
                } else {
                    statusText = response.state;
                    success = response.data;
                    error = response.error;
                    isSuccess = !error;
                }
            } else {

                // Extract error from statusText and normalize for non-aborts
                error = statusText;
                if ( status || !statusText ) {
                    statusText = "error";
                    if ( status < 0 ) {
                        status = 0;
                    }
                }
            }

            // Set data for the fake xhr object
            jqXHR.status = status;
            jqXHR.statusText = ( nativeStatusText || statusText ) + "";

            // Success/Error
            if ( isSuccess ) {
                deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
            } else {
                deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
            }

            // Status-dependent callbacks
            jqXHR.statusCode( statusCode );
            statusCode = undefined;

            if ( fireGlobals ) {
                globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
                    [ jqXHR, s, isSuccess ? success : error ] );
            }

            // Complete
            completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );

            if ( fireGlobals ) {
                globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );

                // Handle the global AJAX counter
                if ( !( --jQuery.active ) ) {
                    jQuery.event.trigger( "ajaxStop" );
                }
            }
        }

        return jqXHR;
    },

    getJSON: function( url, data, callback ) {
        return jQuery.get( url, data, callback, "json" );
    },

    getScript: function( url, callback ) {
        return jQuery.get( url, undefined, callback, "script" );
    }
} );

jQuery.each( [ "get", "post" ], function( i, method ) {
    jQuery[ method ] = function( url, data, callback, type ) {

        // Shift arguments if data argument was omitted
        if ( jQuery.isFunction( data ) ) {
            type = type || callback;
            callback = data;
            data = undefined;
        }

        // The url can be an options object (which then must have .url)
        return jQuery.ajax( jQuery.extend( {
            url: url,
            type: method,
            dataType: type,
            data: data,
            success: callback
        }, jQuery.isPlainObject( url ) && url ) );
    };
} );


jQuery._evalUrl = function( url ) {
    return jQuery.ajax( {
        url: url,

        // Make this explicit, since user can override this through ajaxSetup (#11264)
        type: "GET",
        dataType: "script",
        async: false,
        global: false,
        "throws": true
    } );
};


jQuery.fn.extend( {
    wrapAll: function( html ) {
        var wrap;

        if ( jQuery.isFunction( html ) ) {
            return this.each( function( i ) {
                jQuery( this ).wrapAll( html.call( this, i ) );
            } );
        }

        if ( this[ 0 ] ) {

            // The elements to wrap the target around
            wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );

            if ( this[ 0 ].parentNode ) {
                wrap.insertBefore( this[ 0 ] );
            }

            wrap.map( function() {
                var elem = this;

                while ( elem.firstElementChild ) {
                    elem = elem.firstElementChild;
                }

                return elem;
            } ).append( this );
        }

        return this;
    },

    wrapInner: function( html ) {
        if ( jQuery.isFunction( html ) ) {
            return this.each( function( i ) {
                jQuery( this ).wrapInner( html.call( this, i ) );
            } );
        }

        return this.each( function() {
            var self = jQuery( this ),
                contents = self.contents();

            if ( contents.length ) {
                contents.wrapAll( html );

            } else {
                self.append( html );
            }
        } );
    },

    wrap: function( html ) {
        var isFunction = jQuery.isFunction( html );

        return this.each( function( i ) {
            jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
        } );
    },

    unwrap: function() {
        return this.parent().each( function() {
            if ( !jQuery.nodeName( this, "body" ) ) {
                jQuery( this ).replaceWith( this.childNodes );
            }
        } ).end();
    }
} );


jQuery.expr.filters.hidden = function( elem ) {
    return !jQuery.expr.filters.visible( elem );
};
jQuery.expr.filters.visible = function( elem ) {

    // Support: Opera <= 12.12
    // Opera reports offsetWidths and offsetHeights less than zero on some elements
    // Use OR instead of AND as the element is not visible if either is true
    // See tickets #10406 and #13132
    return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem.getClientRects().length > 0;
};




var r20 = /%20/g,
    rbracket = /\[\]$/,
    rCRLF = /\r?\n/g,
    rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
    rsubmittable = /^(?:input|select|textarea|keygen)/i;

function buildParams( prefix, obj, traditional, add ) {
    var name;

    if ( jQuery.isArray( obj ) ) {

        // Serialize array item.
        jQuery.each( obj, function( i, v ) {
            if ( traditional || rbracket.test( prefix ) ) {

                // Treat each array item as a scalar.
                add( prefix, v );

            } else {

                // Item is non-scalar (array or object), encode its numeric index.
                buildParams(
                    prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
                    v,
                    traditional,
                    add
                );
            }
        } );

    } else if ( !traditional && jQuery.type( obj ) === "object" ) {

        // Serialize object item.
        for ( name in obj ) {
            buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
        }

    } else {

        // Serialize scalar item.
        add( prefix, obj );
    }
}

// Serialize an array of form elements or a set of
// key/values into a query string
jQuery.param = function( a, traditional ) {
    var prefix,
        s = [],
        add = function( key, value ) {

            // If value is a function, invoke it and return its value
            value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
            s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
        };

    // Set traditional to true for jQuery <= 1.3.2 behavior.
    if ( traditional === undefined ) {
        traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
    }

    // If an array was passed in, assume that it is an array of form elements.
    if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {

        // Serialize the form elements
        jQuery.each( a, function() {
            add( this.name, this.value );
        } );

    } else {

        // If traditional, encode the "old" way (the way 1.3.2 or older
        // did it), otherwise encode params recursively.
        for ( prefix in a ) {
            buildParams( prefix, a[ prefix ], traditional, add );
        }
    }

    // Return the resulting serialization
    return s.join( "&" ).replace( r20, "+" );
};

jQuery.fn.extend( {
    serialize: function() {
        return jQuery.param( this.serializeArray() );
    },
    serializeArray: function() {
        return this.map( function() {

            // Can add propHook for "elements" to filter or add form elements
            var elements = jQuery.prop( this, "elements" );
            return elements ? jQuery.makeArray( elements ) : this;
        } )
        .filter( function() {
            var type = this.type;

            // Use .is( ":disabled" ) so that fieldset[disabled] works
            return this.name && !jQuery( this ).is( ":disabled" ) &&
                rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
                ( this.checked || !rcheckableType.test( type ) );
        } )
        .map( function( i, elem ) {
            var val = jQuery( this ).val();

            return val == null ?
                null :
                jQuery.isArray( val ) ?
                    jQuery.map( val, function( val ) {
                        return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
                    } ) :
                    { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
        } ).get();
    }
} );


jQuery.ajaxSettings.xhr = function() {
    try {
        return new window.XMLHttpRequest();
    } catch ( e ) {}
};

var xhrSuccessStatus = {

        // File protocol always yields status code 0, assume 200
        0: 200,

        // Support: IE9
        // #1450: sometimes IE returns 1223 when it should be 204
        1223: 204
    },
    xhrSupported = jQuery.ajaxSettings.xhr();

support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
support.ajax = xhrSupported = !!xhrSupported;

jQuery.ajaxTransport( function( options ) {
    var callback, errorCallback;

    // Cross domain only allowed if supported through XMLHttpRequest
    if ( support.cors || xhrSupported && !options.crossDomain ) {
        return {
            send: function( headers, complete ) {
                var i,
                    xhr = options.xhr();

                xhr.open(
                    options.type,
                    options.url,
                    options.async,
                    options.username,
                    options.password
                );

                // Apply custom fields if provided
                if ( options.xhrFields ) {
                    for ( i in options.xhrFields ) {
                        xhr[ i ] = options.xhrFields[ i ];
                    }
                }

                // Override mime type if needed
                if ( options.mimeType && xhr.overrideMimeType ) {
                    xhr.overrideMimeType( options.mimeType );
                }

                // X-Requested-With header
                // For cross-domain requests, seeing as conditions for a preflight are
                // akin to a jigsaw puzzle, we simply never set it to be sure.
                // (it can always be set on a per-request basis or even using ajaxSetup)
                // For same-domain requests, won't change header if already provided.
                if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
                    headers[ "X-Requested-With" ] = "XMLHttpRequest";
                }

                // Set headers
                for ( i in headers ) {
                    xhr.setRequestHeader( i, headers[ i ] );
                }

                // Callback
                callback = function( type ) {
                    return function() {
                        if ( callback ) {
                            callback = errorCallback = xhr.onload =
                                xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;

                            if ( type === "abort" ) {
                                xhr.abort();
                            } else if ( type === "error" ) {

                                // Support: IE9
                                // On a manual native abort, IE9 throws
                                // errors on any property access that is not readyState
                                if ( typeof xhr.status !== "number" ) {
                                    complete( 0, "error" );
                                } else {
                                    complete(

                                        // File: protocol always yields status 0; see #8605, #14207
                                        xhr.status,
                                        xhr.statusText
                                    );
                                }
                            } else {
                                complete(
                                    xhrSuccessStatus[ xhr.status ] || xhr.status,
                                    xhr.statusText,

                                    // Support: IE9 only
                                    // IE9 has no XHR2 but throws on binary (trac-11426)
                                    // For XHR2 non-text, let the caller handle it (gh-2498)
                                    ( xhr.responseType || "text" ) !== "text"  ||
                                    typeof xhr.responseText !== "string" ?
                                        { binary: xhr.response } :
                                        { text: xhr.responseText },
                                    xhr.getAllResponseHeaders()
                                );
                            }
                        }
                    };
                };

                // Listen to events
                xhr.onload = callback();
                errorCallback = xhr.onerror = callback( "error" );

                // Support: IE9
                // Use onreadystatechange to replace onabort
                // to handle uncaught aborts
                if ( xhr.onabort !== undefined ) {
                    xhr.onabort = errorCallback;
                } else {
                    xhr.onreadystatechange = function() {

                        // Check readyState before timeout as it changes
                        if ( xhr.readyState === 4 ) {

                            // Allow onerror to be called first,
                            // but that will not handle a native abort
                            // Also, save errorCallback to a variable
                            // as xhr.onerror cannot be accessed
                            window.setTimeout( function() {
                                if ( callback ) {
                                    errorCallback();
                                }
                            } );
                        }
                    };
                }

                // Create the abort callback
                callback = callback( "abort" );

                try {

                    // Do send the request (this may raise an exception)
                    xhr.send( options.hasContent && options.data || null );
                } catch ( e ) {

                    // #14683: Only rethrow if this hasn't been notified as an error yet
                    if ( callback ) {
                        throw e;
                    }
                }
            },

            abort: function() {
                if ( callback ) {
                    callback();
                }
            }
        };
    }
} );




// Install script dataType
jQuery.ajaxSetup( {
    accepts: {
        script: "text/javascript, application/javascript, " +
            "application/ecmascript, application/x-ecmascript"
    },
    contents: {
        script: /\b(?:java|ecma)script\b/
    },
    converters: {
        "text script": function( text ) {
            jQuery.globalEval( text );
            return text;
        }
    }
} );

// Handle cache's special case and crossDomain
jQuery.ajaxPrefilter( "script", function( s ) {
    if ( s.cache === undefined ) {
        s.cache = false;
    }
    if ( s.crossDomain ) {
        s.type = "GET";
    }
} );

// Bind script tag hack transport
jQuery.ajaxTransport( "script", function( s ) {

    // This transport only deals with cross domain requests
    if ( s.crossDomain ) {
        var script, callback;
        return {
            send: function( _, complete ) {
                script = jQuery( "<script>" ).prop( {
                    charset: s.scriptCharset,
                    src: s.url
                } ).on(
                    "load error",
                    callback = function( evt ) {
                        script.remove();
                        callback = null;
                        if ( evt ) {
                            complete( evt.type === "error" ? 404 : 200, evt.type );
                        }
                    }
                );

                // Use native DOM manipulation to avoid our domManip AJAX trickery
                document.head.appendChild( script[ 0 ] );
            },
            abort: function() {
                if ( callback ) {
                    callback();
                }
            }
        };
    }
} );




var oldCallbacks = [],
    rjsonp = /(=)\?(?=&|$)|\?\?/;

// Default jsonp settings
jQuery.ajaxSetup( {
    jsonp: "callback",
    jsonpCallback: function() {
        var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
        this[ callback ] = true;
        return callback;
    }
} );

// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

    var callbackName, overwritten, responseContainer,
        jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
            "url" :
            typeof s.data === "string" &&
                ( s.contentType || "" )
                    .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
                rjsonp.test( s.data ) && "data"
        );

    // Handle iff the expected data type is "jsonp" or we have a parameter to set
    if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {

        // Get callback name, remembering preexisting value associated with it
        callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
            s.jsonpCallback() :
            s.jsonpCallback;

        // Insert callback into url or form data
        if ( jsonProp ) {
            s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
        } else if ( s.jsonp !== false ) {
            s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
        }

        // Use data converter to retrieve json after script execution
        s.converters[ "script json" ] = function() {
            if ( !responseContainer ) {
                jQuery.error( callbackName + " was not called" );
            }
            return responseContainer[ 0 ];
        };

        // Force json dataType
        s.dataTypes[ 0 ] = "json";

        // Install callback
        overwritten = window[ callbackName ];
        window[ callbackName ] = function() {
            responseContainer = arguments;
        };

        // Clean-up function (fires after converters)
        jqXHR.always( function() {

            // If previous value didn't exist - remove it
            if ( overwritten === undefined ) {
                jQuery( window ).removeProp( callbackName );

            // Otherwise restore preexisting value
            } else {
                window[ callbackName ] = overwritten;
            }

            // Save back as free
            if ( s[ callbackName ] ) {

                // Make sure that re-using the options doesn't screw things around
                s.jsonpCallback = originalSettings.jsonpCallback;

                // Save the callback name for future use
                oldCallbacks.push( callbackName );
            }

            // Call if it was a function and we have a response
            if ( responseContainer && jQuery.isFunction( overwritten ) ) {
                overwritten( responseContainer[ 0 ] );
            }

            responseContainer = overwritten = undefined;
        } );

        // Delegate to script
        return "script";
    }
} );




// Argument "data" should be string of html
// context (optional): If specified, the fragment will be created in this context,
// defaults to document
// keepScripts (optional): If true, will include scripts passed in the html string
jQuery.parseHTML = function( data, context, keepScripts ) {
    if ( !data || typeof data !== "string" ) {
        return null;
    }
    if ( typeof context === "boolean" ) {
        keepScripts = context;
        context = false;
    }
    context = context || document;

    var parsed = rsingleTag.exec( data ),
        scripts = !keepScripts && [];

    // Single tag
    if ( parsed ) {
        return [ context.createElement( parsed[ 1 ] ) ];
    }

    parsed = buildFragment( [ data ], context, scripts );

    if ( scripts && scripts.length ) {
        jQuery( scripts ).remove();
    }

    return jQuery.merge( [], parsed.childNodes );
};


// Keep a copy of the old load method
var _load = jQuery.fn.load;

/**
 * Load a url into a page
 */
jQuery.fn.load = function( url, params, callback ) {
    if ( typeof url !== "string" && _load ) {
        return _load.apply( this, arguments );
    }

    var selector, type, response,
        self = this,
        off = url.indexOf( " " );

    if ( off > -1 ) {
        selector = jQuery.trim( url.slice( off ) );
        url = url.slice( 0, off );
    }

    // If it's a function
    if ( jQuery.isFunction( params ) ) {

        // We assume that it's the callback
        callback = params;
        params = undefined;

    // Otherwise, build a param string
    } else if ( params && typeof params === "object" ) {
        type = "POST";
    }

    // If we have elements to modify, make the request
    if ( self.length > 0 ) {
        jQuery.ajax( {
            url: url,

            // If "type" variable is undefined, then "GET" method will be used.
            // Make value of this field explicit since
            // user can override it through ajaxSetup method
            type: type || "GET",
            dataType: "html",
            data: params
        } ).done( function( responseText ) {

            // Save response for use in complete callback
            response = arguments;

            self.html( selector ?

                // If a selector was specified, locate the right elements in a dummy div
                // Exclude scripts to avoid IE 'Permission Denied' errors
                jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :

                // Otherwise use the full result
                responseText );

        // If the request succeeds, this function gets "data", "status", "jqXHR"
        // but they are ignored because response was set above.
        // If it fails, this function gets "jqXHR", "status", "error"
        } ).always( callback && function( jqXHR, status ) {
            self.each( function() {
                callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
            } );
        } );
    }

    return this;
};




// Attach a bunch of functions for handling common AJAX events
jQuery.each( [
    "ajaxStart",
    "ajaxStop",
    "ajaxComplete",
    "ajaxError",
    "ajaxSuccess",
    "ajaxSend"
], function( i, type ) {
    jQuery.fn[ type ] = function( fn ) {
        return this.on( type, fn );
    };
} );




jQuery.expr.filters.animated = function( elem ) {
    return jQuery.grep( jQuery.timers, function( fn ) {
        return elem === fn.elem;
    } ).length;
};




/**
 * Gets a window from an element
 */
function getWindow( elem ) {
    return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
}

jQuery.offset = {
    setOffset: function( elem, options, i ) {
        var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
            position = jQuery.css( elem, "position" ),
            curElem = jQuery( elem ),
            props = {};

        // Set position first, in-case top/left are set even on static elem
        if ( position === "static" ) {
            elem.style.position = "relative";
        }

        curOffset = curElem.offset();
        curCSSTop = jQuery.css( elem, "top" );
        curCSSLeft = jQuery.css( elem, "left" );
        calculatePosition = ( position === "absolute" || position === "fixed" ) &&
            ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;

        // Need to be able to calculate position if either
        // top or left is auto and position is either absolute or fixed
        if ( calculatePosition ) {
            curPosition = curElem.position();
            curTop = curPosition.top;
            curLeft = curPosition.left;

        } else {
            curTop = parseFloat( curCSSTop ) || 0;
            curLeft = parseFloat( curCSSLeft ) || 0;
        }

        if ( jQuery.isFunction( options ) ) {

            // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
            options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
        }

        if ( options.top != null ) {
            props.top = ( options.top - curOffset.top ) + curTop;
        }
        if ( options.left != null ) {
            props.left = ( options.left - curOffset.left ) + curLeft;
        }

        if ( "using" in options ) {
            options.using.call( elem, props );

        } else {
            curElem.css( props );
        }
    }
};

jQuery.fn.extend( {
    offset: function( options ) {
        if ( arguments.length ) {
            return options === undefined ?
                this :
                this.each( function( i ) {
                    jQuery.offset.setOffset( this, options, i );
                } );
        }

        var docElem, win,
            elem = this[ 0 ],
            box = { top: 0, left: 0 },
            doc = elem && elem.ownerDocument;

        if ( !doc ) {
            return;
        }

        docElem = doc.documentElement;

        // Make sure it's not a disconnected DOM node
        if ( !jQuery.contains( docElem, elem ) ) {
            return box;
        }

        box = elem.getBoundingClientRect();
        win = getWindow( doc );
        return {
            top: box.top + win.pageYOffset - docElem.clientTop,
            left: box.left + win.pageXOffset - docElem.clientLeft
        };
    },

    position: function() {
        if ( !this[ 0 ] ) {
            return;
        }

        var offsetParent, offset,
            elem = this[ 0 ],
            parentOffset = { top: 0, left: 0 };

        // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
        // because it is its only offset parent
        if ( jQuery.css( elem, "position" ) === "fixed" ) {

            // Assume getBoundingClientRect is there when computed position is fixed
            offset = elem.getBoundingClientRect();

        } else {

            // Get *real* offsetParent
            offsetParent = this.offsetParent();

            // Get correct offsets
            offset = this.offset();
            if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
                parentOffset = offsetParent.offset();
            }

            // Add offsetParent borders
            parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
            parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
        }

        // Subtract parent offsets and element margins
        return {
            top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
            left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
        };
    },

    // This method will return documentElement in the following cases:
    // 1) For the element inside the iframe without offsetParent, this method will return
    //    documentElement of the parent window
    // 2) For the hidden or detached element
    // 3) For body or html element, i.e. in case of the html node - it will return itself
    //
    // but those exceptions were never presented as a real life use-cases
    // and might be considered as more preferable results.
    //
    // This logic, however, is not guaranteed and can change at any point in the future
    offsetParent: function() {
        return this.map( function() {
            var offsetParent = this.offsetParent;

            while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
                offsetParent = offsetParent.offsetParent;
            }

            return offsetParent || documentElement;
        } );
    }
} );

// Create scrollLeft and scrollTop methods
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
    var top = "pageYOffset" === prop;

    jQuery.fn[ method ] = function( val ) {
        return access( this, function( elem, method, val ) {
            var win = getWindow( elem );

            if ( val === undefined ) {
                return win ? win[ prop ] : elem[ method ];
            }

            if ( win ) {
                win.scrollTo(
                    !top ? val : win.pageXOffset,
                    top ? val : win.pageYOffset
                );

            } else {
                elem[ method ] = val;
            }
        }, method, val, arguments.length );
    };
} );

// Support: Safari<7-8+, Chrome<37-44+
// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
// getComputedStyle returns percent when specified for top/left/bottom/right;
// rather than make the css module depend on the offset module, just check for it here
jQuery.each( [ "top", "left" ], function( i, prop ) {
    jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
        function( elem, computed ) {
            if ( computed ) {
                computed = curCSS( elem, prop );

                // If curCSS returns percentage, fallback to offset
                return rnumnonpx.test( computed ) ?
                    jQuery( elem ).position()[ prop ] + "px" :
                    computed;
            }
        }
    );
} );


// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
    jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
        function( defaultExtra, funcName ) {

        // Margin is only for outerHeight, outerWidth
        jQuery.fn[ funcName ] = function( margin, value ) {
            var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
                extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );

            return access( this, function( elem, type, value ) {
                var doc;

                if ( jQuery.isWindow( elem ) ) {

                    // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
                    // isn't a whole lot we can do. See pull request at this URL for discussion:
                    // https://github.com/jquery/jquery/pull/764
                    return elem.document.documentElement[ "client" + name ];
                }

                // Get document width or height
                if ( elem.nodeType === 9 ) {
                    doc = elem.documentElement;

                    // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
                    // whichever is greatest
                    return Math.max(
                        elem.body[ "scroll" + name ], doc[ "scroll" + name ],
                        elem.body[ "offset" + name ], doc[ "offset" + name ],
                        doc[ "client" + name ]
                    );
                }

                return value === undefined ?

                    // Get width or height on the element, requesting but not forcing parseFloat
                    jQuery.css( elem, type, extra ) :

                    // Set width or height on the element
                    jQuery.style( elem, type, value, extra );
            }, type, chainable ? margin : undefined, chainable, null );
        };
    } );
} );


jQuery.fn.extend( {

    bind: function( types, data, fn ) {
        return this.on( types, null, data, fn );
    },
    unbind: function( types, fn ) {
        return this.off( types, null, fn );
    },

    delegate: function( selector, types, data, fn ) {
        return this.on( types, selector, data, fn );
    },
    undelegate: function( selector, types, fn ) {

        // ( namespace ) or ( selector, types [, fn] )
        return arguments.length === 1 ?
            this.off( selector, "**" ) :
            this.off( types, selector || "**", fn );
    },
    size: function() {
        return this.length;
    }
} );

jQuery.fn.andSelf = jQuery.fn.addBack;




// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.

// Note that for maximum portability, libraries that are not jQuery should
// declare themselves as anonymous modules, and avoid setting a global if an
// AMD loader is present. jQuery is a special case. For more information, see
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon

if ( typeof define === "function" && define.amd ) {
    define( "jquery", [], function() {
        return jQuery;
    } );
}



var

    // Map over jQuery in case of overwrite
    _jQuery = window.jQuery,

    // Map over the $ in case of overwrite
    _$ = window.$;

jQuery.noConflict = function( deep ) {
    if ( window.$ === jQuery ) {
        window.$ = _$;
    }

    if ( deep && window.jQuery === jQuery ) {
        window.jQuery = _jQuery;
    }

    return jQuery;
};

// Expose jQuery and $ identifiers, even in AMD
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( !noGlobal ) {
    window.jQuery = window.$ = jQuery;
}

return jQuery;
}));

;;(function() {
/*!
 * @overview  Ember - JavaScript Application Framework
 * @copyright Copyright 2011-2016 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   2.6.2
 */

var enifed, requireModule, require, Ember;
var mainContext = this;

(function() {
  var isNode = typeof window === 'undefined' &&
    typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';

  if (!isNode) {
    Ember = this.Ember = this.Ember || {};
  }

  if (typeof Ember === 'undefined') { Ember = {}; }

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

    enifed = function(name, deps, callback) {
      var value = { };

      if (!callback) {
        value.deps = [];
        value.callback = deps;
      } else {
        value.deps = deps;
        value.callback = callback;
      }

      registry[name] = value;
    };

    require = requireModule = function(name) {
      return internalRequire(name, null);
    };

    // setup `require` module
    require['default'] = require;

    require.has = function registryHas(moduleName) {
      return !!registry[moduleName] || !!registry[moduleName + '/index'];
    };

    function missingModule(name, referrerName) {
      if (referrerName) {
        throw new Error('Could not find module ' + name + ' required by: ' + referrerName);
      } else {
        throw new Error('Could not find module ' + name);
      }
    }

    function internalRequire(_name, referrerName) {
      var name = _name;
      var mod = registry[name];

      if (!mod) {
        name = name + '/index';
        mod = registry[name];
      }

      var exports = seen[name];

      if (exports !== undefined) {
        return exports;
      }

      exports = seen[name] = {};

      if (!mod) {
        missingModule(_name, referrerName);
      }

      var deps = mod.deps;
      var callback = mod.callback;
      var length = deps.length;
      var reified = new Array(length);

      for (var i = 0; i < length; i++) {
        if (deps[i] === 'exports') {
          reified[i] = exports;
        } else if (deps[i] === 'require') {
          reified[i] = require;
        } else {
          reified[i] = internalRequire(deps[i], name);
        }
      }

      callback.apply(this, reified);

      return exports;
    }

    requireModule._eak_seen = registry;

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

enifed('backburner', ['exports', 'backburner/utils', 'backburner/platform', 'backburner/binary-search', 'backburner/deferred-action-queues'], function (exports, _backburnerUtils, _backburnerPlatform, _backburnerBinarySearch, _backburnerDeferredActionQueues) {
  'use strict';

  exports.default = Backburner;

  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 = [];
    this._eventCallbacks = {
      end: [],
      begin: []
    };

    var _this = this;
    this._boundClearItems = function () {
      clearItems();
    };

    this._timerTimeoutId = undefined;
    this._timers = [];

    this._platform = this.options._platform || _backburnerPlatform.default;

    this._boundRunExpiredTimers = function () {
      _this._runExpiredTimers();
    };
  }

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

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

      this.currentInstance = new _backburnerDeferredActionQueues.default(this.queueNames, options);
      this._trigger('begin', this.currentInstance, previousInstance);
      if (onBegin) {
        onBegin(this.currentInstance, previousInstance);
      }
    },

    end: function () {
      var options = this.options;
      var onEnd = options && options.onEnd;
      var currentInstance = this.currentInstance;
      var 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;
          }
          this._trigger('end', currentInstance, nextInstance);
          if (onEnd) {
            onEnd(currentInstance, nextInstance);
          }
        }
      }
    },

    /**
     Trigger an event. Supports up to two arguments. Designed around
     triggering transition events from one run loop instance to the
     next, which requires an argument for the first instance and then
     an argument for the next instance.
      @private
     @method _trigger
     @param {String} eventName
     @param {any} arg1
     @param {any} arg2
     */
    _trigger: function (eventName, arg1, arg2) {
      var callbacks = this._eventCallbacks[eventName];
      if (callbacks) {
        for (var i = 0; i < callbacks.length; i++) {
          callbacks[i](arg1, arg2);
        }
      }
    },

    on: function (eventName, callback) {
      if (typeof callback !== 'function') {
        throw new TypeError('Callback must be a function');
      }
      var callbacks = this._eventCallbacks[eventName];
      if (callbacks) {
        callbacks.push(callback);
      } else {
        throw new TypeError('Cannot on() event "' + eventName + '" because it does not exist');
      }
    },

    off: function (eventName, callback) {
      if (eventName) {
        var callbacks = this._eventCallbacks[eventName];
        var callbackFound = false;
        if (!callbacks) return;
        if (callback) {
          for (var i = 0; i < callbacks.length; i++) {
            if (callbacks[i] === callback) {
              callbackFound = true;
              callbacks.splice(i, 1);
              i--;
            }
          }
        }
        if (!callbackFound) {
          throw new TypeError('Cannot off() callback that does not exist');
        }
      } else {
        throw new TypeError('Cannot off() event "' + eventName + '" because it does not exist');
      }
    },

    run: function () /* target, method, args */{
      var length = arguments.length;
      var method, target, args;

      if (length === 1) {
        method = arguments[0];
        target = null;
      } else {
        target = arguments[0];
        method = arguments[1];
      }

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

      if (length > 2) {
        args = new Array(length - 2);
        for (var i = 0, l = length - 2; i < l; i++) {
          args[i] = arguments[i + 2];
        }
      } else {
        args = [];
      }

      var onError = getOnError(this.options);

      this.begin();

      // 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();
          }
        }
      }
    },

    /*
      Join the passed method with an existing queue and execute immediately,
      if there isn't one use `Backburner#run`.
       The join method is like the run method except that it will schedule into
      an existing queue if one already exists. In either case, the join method will
      immediately execute the passed in function and return its result.
       @method join
      @param {Object} target
      @param {Function} method The method to be executed
      @param {any} args The method arguments
      @return method result
    */
    join: function () /* target, method, args */{
      if (!this.currentInstance) {
        return this.run.apply(this, arguments);
      }

      var length = arguments.length;
      var method, target;

      if (length === 1) {
        method = arguments[0];
        target = null;
      } else {
        target = arguments[0];
        method = arguments[1];
      }

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

      if (length === 1) {
        return method();
      } else if (length === 2) {
        return method.call(target);
      } else {
        var args = new Array(length - 2);
        for (var i = 0, l = length - 2; i < l; i++) {
          args[i] = arguments[i + 2];
        }
        return method.apply(target, args);
      }
    },

    /*
      Defer the passed function to run inside the specified queue.
       @method defer
      @param {String} queueName
      @param {Object} target
      @param {Function|String} method The method or method name to be executed
      @param {any} args The method arguments
      @return method result
    */
    defer: function (queueName /* , target, method, args */) {
      var length = arguments.length;
      var method, target, args;

      if (length === 2) {
        method = arguments[1];
        target = null;
      } else {
        target = arguments[1];
        method = arguments[2];
      }

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

      var stack = this.DEBUG ? new Error() : undefined;

      if (length > 3) {
        args = new Array(length - 3);
        for (var i = 3; i < length; i++) {
          args[i - 3] = arguments[i];
        }
      } else {
        args = undefined;
      }

      if (!this.currentInstance) {
        createAutorun(this);
      }
      return this.currentInstance.schedule(queueName, target, method, args, false, stack);
    },

    deferOnce: function (queueName /* , target, method, args */) {
      var length = arguments.length;
      var method, target, args;

      if (length === 2) {
        method = arguments[1];
        target = null;
      } else {
        target = arguments[1];
        method = arguments[2];
      }

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

      var stack = this.DEBUG ? new Error() : undefined;

      if (length > 3) {
        args = new Array(length - 3);
        for (var i = 3; i < length; i++) {
          args[i - 3] = arguments[i];
        }
      } else {
        args = undefined;
      }

      if (!this.currentInstance) {
        createAutorun(this);
      }
      return this.currentInstance.schedule(queueName, target, method, args, true, stack);
    },

    setTimeout: function () {
      var l = arguments.length;
      var args = new Array(l);

      for (var x = 0; x < l; x++) {
        args[x] = arguments[x];
      }

      var 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 (_backburnerUtils.isFunction(methodOrWait) || _backburnerUtils.isFunction(methodOrTarget[methodOrWait])) {
          target = args.shift();
          method = args.shift();
          wait = 0;
        } else if (_backburnerUtils.isCoercableNumber(methodOrWait)) {
          method = args.shift();
          wait = args.shift();
        } else {
          method = args.shift();
          wait = 0;
        }
      } else {
        var last = args[args.length - 1];

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

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

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

      var executeAt = Date.now() + parseInt(wait !== wait ? 0 : wait, 10);

      if (_backburnerUtils.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);
        }
      }

      return this._setTimeout(fn, executeAt);
    },

    _setTimeout: function (fn, executeAt) {
      if (this._timers.length === 0) {
        this._timers.push(executeAt, fn);
        this._installTimerTimeout();
        return fn;
      }

      // find position to insert
      var i = _backburnerBinarySearch.default(executeAt, this._timers);

      this._timers.splice(i, 0, executeAt, fn);

      // we should be the new earliest timer if i == 0
      if (i === 0) {
        this._reinstallTimerTimeout();
      }

      return fn;
    },

    throttle: function (target, method /* , args, wait, [immediate] */) {
      var backburner = this;
      var args = new Array(arguments.length);
      for (var i = 0; i < arguments.length; i++) {
        args[i] = arguments[i];
      }
      var immediate = args.pop();
      var wait, throttler, index, timer;

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

      wait = parseInt(wait, 10);

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

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

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

      throttler = [target, method, timer];

      this._throttlers.push(throttler);

      return throttler;
    },

    debounce: function (target, method /* , args, wait, [immediate] */) {
      var backburner = this;
      var args = new Array(arguments.length);
      for (var i = 0; i < arguments.length; i++) {
        args[i] = arguments[i];
      }

      var immediate = args.pop();
      var wait, index, debouncee, timer;

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

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

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

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

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

      debouncee = [target, method, timer];

      backburner._debouncees.push(debouncee);

      return debouncee;
    },

    cancelTimers: function () {
      _backburnerUtils.each(this._throttlers, this._boundClearItems);
      this._throttlers = [];

      _backburnerUtils.each(this._debouncees, this._boundClearItems);
      this._debouncees = [];

      this._clearTimerTimeout();
      this._timers = [];

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

    hasTimers: function () {
      return !!this._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 = this._timers.length; i < l; i += 2) {
          if (this._timers[i + 1] === timer) {
            this._timers.splice(i, 2); // remove the two elements
            if (i === 0) {
              this._reinstallTimerTimeout();
            }
            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);
          this._platform.clearTimeout(timer[2]);
          return true;
        }
      }

      return false;
    },

    _runExpiredTimers: function () {
      this._timerTimeoutId = undefined;
      this.run(this, this._scheduleExpiredTimers);
    },

    _scheduleExpiredTimers: function () {
      var n = Date.now();
      var timers = this._timers;
      var i = 0;
      var l = timers.length;
      for (; i < l; i += 2) {
        var executeAt = timers[i];
        var fn = timers[i + 1];
        if (executeAt <= n) {
          this.schedule(this.options.defaultQueue, null, fn);
        } else {
          break;
        }
      }
      timers.splice(0, i);
      this._installTimerTimeout();
    },

    _reinstallTimerTimeout: function () {
      this._clearTimerTimeout();
      this._installTimerTimeout();
    },

    _clearTimerTimeout: function () {
      if (!this._timerTimeoutId) {
        return;
      }
      this._platform.clearTimeout(this._timerTimeoutId);
      this._timerTimeoutId = undefined;
    },

    _installTimerTimeout: function () {
      if (!this._timers.length) {
        return;
      }
      var minExpiresAt = this._timers[0];
      var n = Date.now();
      var wait = Math.max(0, minExpiresAt - n);
      this._timerTimeoutId = this._platform.setTimeout(this._boundRunExpiredTimers, wait);
    }
  };

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

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

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

  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;
    var 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 clearItems(item) {
    this._platform.clearTimeout(item[2]);
  }
});
enifed("backburner/binary-search", ["exports"], function (exports) {
  "use strict";

  exports.default = binarySearch;

  function binarySearch(time, timers) {
    var start = 0;
    var end = timers.length - 2;
    var 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;
  }
});
enifed('backburner/deferred-action-queues', ['exports', 'backburner/utils', 'backburner/queue'], function (exports, _backburnerUtils, _backburnerQueue) {
  'use strict';

  exports.default = DeferredActionQueues;

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

    this.options = options;

    _backburnerUtils.each(queueNames, function (queueName) {
      queues[queueName] = new _backburnerQueue.default(queueName, options[queueName], options);
    });
  }

  function noSuchQueue(name) {
    throw new Error('You attempted to schedule an action in a queue (' + name + ') that doesn\'t exist');
  }

  function noSuchMethod(name) {
    throw new Error('You attempted to schedule an action in a queue (' + name + ') for a method that doesn\'t exist');
  }

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

      if (!queue) {
        noSuchQueue(name);
      }

      if (!method) {
        noSuchMethod(name);
      }

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

    flush: function () {
      var queues = this.queues;
      var queueNames = this.queueNames;
      var queueName, queue;
      var queueNameIndex = 0;
      var numberOfQueues = queueNames.length;

      while (queueNameIndex < numberOfQueues) {
        queueName = queueNames[queueNameIndex];
        queue = queues[queueName];

        var numberOfQueueItems = queue._queue.length;

        if (numberOfQueueItems === 0) {
          queueNameIndex++;
        } else {
          queue.flush(false /* async */);
          queueNameIndex = 0;
        }
      }
    }
  };
});
enifed('backburner/platform', ['exports'], function (exports) {
  'use strict';

  var GlobalContext;

  /* global self */
  if (typeof self === 'object') {
    GlobalContext = self;

    /* global global */
  } else if (typeof global === 'object') {
      GlobalContext = global;

      /* global window */
    } else if (typeof window === 'object') {
        GlobalContext = window;
      } else {
        throw new Error('no global: `self`, `global` nor `window` was found');
      }

  exports.default = GlobalContext;
});
enifed('backburner/queue', ['exports', 'backburner/utils'], function (exports, _backburnerUtils) {
  'use strict';

  exports.default = Queue;

  function Queue(name, options, globalOptions) {
    this.name = name;
    this.globalOptions = globalOptions || {};
    this.options = options;
    this._queue = [];
    this.targetQueues = {};
    this._queueBeingFlushed = undefined;
  }

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

      return {
        queue: this,
        target: target,
        method: method
      };
    },

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

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

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

      queue.push(target, method, args, stack);
    },

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

      for (var i = 0, l = targetQueue.length; i < l; i += 2) {
        var currentMethod = targetQueue[i];
        var currentIndex = targetQueue[i + 1];

        if (currentMethod === method) {
          queue[currentIndex + 2] = args; // replace args
          queue[currentIndex + 3] = stack; // replace stack
          return;
        }
      }

      targetQueue.push(method, queue.push(target, method, args, stack) - 4);
    },

    pushUniqueWithGuid: function (guid, target, method, args, stack) {
      var hasLocalQueue = this.targetQueues[guid];

      if (hasLocalQueue) {
        this.targetQueue(hasLocalQueue, target, method, args, stack);
      } else {
        this.targetQueues[guid] = [method, this._queue.push(target, method, args, stack) - 4];
      }

      return {
        queue: this,
        target: target,
        method: method
      };
    },

    pushUnique: function (target, method, args, stack) {
      var KEY = this.globalOptions.GUID_KEY;

      if (target && KEY) {
        var guid = target[KEY];
        if (guid) {
          return this.pushUniqueWithGuid(guid, target, method, args, stack);
        }
      }

      this.pushUniqueWithoutGuid(target, method, args, stack);

      return {
        queue: this,
        target: target,
        method: method
      };
    },

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

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

    flush: function (sync) {
      var queue = this._queue;
      var length = queue.length;

      if (length === 0) {
        return;
      }

      var globalOptions = this.globalOptions;
      var options = this.options;
      var before = options && options.before;
      var after = options && options.after;
      var onError = globalOptions.onError || globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod];
      var target, method, args, errorRecordedForStack;
      var invoke = onError ? this.invokeWithOnError : this.invoke;

      this.targetQueues = Object.create(null);
      var queueItems = this._queueBeingFlushed = this._queue.slice();
      this._queue = [];

      if (before) {
        before();
      }

      for (var i = 0; i < length; i += 4) {
        target = queueItems[i];
        method = queueItems[i + 1];
        args = queueItems[i + 2];
        errorRecordedForStack = queueItems[i + 3]; // Debugging assistance

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

        // method could have been nullified / canceled during flush
        if (method) {
          //
          //    ** Attention intrepid developer **
          //
          //    To find out the stack of this task when it was scheduled onto
          //    the run loop, add the following to your app.js:
          //
          //    Ember.run.backburner.DEBUG = true; // NOTE: This slows your app, don't leave it on in production.
          //
          //    Once that is in place, when you are at a breakpoint and navigate
          //    here in the stack explorer, you can look at `errorRecordedForStack.stack`,
          //    which will be the captured stack when this job was scheduled.
          //
          invoke(target, method, args, onError, errorRecordedForStack);
        }
      }

      if (after) {
        after();
      }

      this._queueBeingFlushed = undefined;

      if (sync !== false && this._queue.length > 0) {
        // check if new items have been added
        this.flush(true);
      }
    },

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

      if (GUID_KEY && this.targetQueues && target) {
        var targetQueue = this.targetQueues[target[GUID_KEY]];

        if (targetQueue) {
          for (i = 0, l = targetQueue.length; i < l; i++) {
            if (targetQueue[i] === method) {
              targetQueue.splice(i, 1);
            }
          }
        }
      }

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

        if (currentTarget === target && currentMethod === 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 === target && currentMethod === method) {
          // don't mess with array during flush
          // just nullify the method
          queue[i + 1] = null;
          return true;
        }
      }
    }
  };
});
enifed('backburner/utils', ['exports'], function (exports) {
  'use strict';

  exports.each = each;
  exports.isString = isString;
  exports.isFunction = isFunction;
  exports.isNumber = isNumber;
  exports.isCoercableNumber = isCoercableNumber;
  var NUMBER = /\d+/;

  function each(collection, callback) {
    for (var i = 0; i < collection.length; i++) {
      callback(collection[i]);
    }
  }

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

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

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

  function isCoercableNumber(number) {
    return isNumber(number) || NUMBER.test(number);
  }
});
enifed('container/container', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-metal/dictionary', 'ember-metal/features', 'container/owner', 'ember-runtime/mixins/container_proxy', 'ember-metal/symbol'], function (exports, _emberMetalCore, _emberMetalDebug, _emberMetalDictionary, _emberMetalFeatures, _containerOwner, _emberRuntimeMixinsContainer_proxy, _emberMetalSymbol) {
  'use strict';

  var CONTAINER_OVERRIDE = _emberMetalSymbol.default('CONTAINER_OVERRIDE');

  /**
   A container used to instantiate and cache objects.

   Every `Container` must be associated with a `Registry`, which is referenced
   to determine the factory and options that should be used to instantiate
   objects.

   The public API for `Container` is still in flux and should not be considered
   stable.

   @private
   @class Container
   */
  function Container(registry, options) {
    this.registry = registry;
    this.owner = options && options.owner ? options.owner : null;
    this.cache = _emberMetalDictionary.default(options && options.cache ? options.cache : null);
    this.factoryCache = _emberMetalDictionary.default(options && options.factoryCache ? options.factoryCache : null);
    this.validationCache = _emberMetalDictionary.default(options && options.validationCache ? options.validationCache : null);
    this._fakeContainerToInject = _emberRuntimeMixinsContainer_proxy.buildFakeContainerWithDeprecations(this);
    this[CONTAINER_OVERRIDE] = undefined;
  }

  Container.prototype = {
    /**
     @private
     @property owner
     @type Object
     */
    owner: null,

    /**
     @private
     @property registry
     @type Registry
     @since 1.11.0
     */
    registry: null,

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

    /**
     @private
     @property factoryCache
     @type InheritingDict
     */
    factoryCache: null,

    /**
     @private
     @property validationCache
     @type InheritingDict
     */
    validationCache: null,

    /**
     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 registry = new Registry();
     var container = registry.container();
      registry.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 registry = new Registry();
     var container = registry.container();
      registry.register('api:twitter', Twitter);
      var twitter = container.lookup('api:twitter', { singleton: false });
     var twitter2 = container.lookup('api:twitter', { singleton: false });
      twitter === twitter2; //=> false
     ```
      @private
     @method lookup
     @param {String} fullName
     @param {Object} [options]
     @param {String} [options.source] The fullname of the request source (used for local lookup)
     @return {any}
     */
    lookup: function (fullName, options) {
      _emberMetalDebug.assert('fullName must be a proper full name', this.registry.validateFullName(fullName));
      return lookup(this, this.registry.normalize(fullName), options);
    },

    /**
     Given a fullName, return the corresponding factory.
      @private
     @method lookupFactory
     @param {String} fullName
     @param {Object} [options]
     @param {String} [options.source] The fullname of the request source (used for local lookup)
     @return {any}
     */
    lookupFactory: function (fullName, options) {
      _emberMetalDebug.assert('fullName must be a proper full name', this.registry.validateFullName(fullName));
      return factoryFor(this, this.registry.normalize(fullName), options);
    },

    /**
     A depth first traversal, destroying the container, its descendant containers and all
     their managed objects.
      @private
     @method destroy
     */
    destroy: function () {
      eachDestroyable(this, function (item) {
        if (item.destroy) {
          item.destroy();
        }
      });

      this.isDestroyed = true;
    },

    /**
     Clear either the entire cache or just the cache for a particular key.
      @private
     @method reset
     @param {String} fullName optional key to reset; if missing, resets everything
     */
    reset: function (fullName) {
      if (arguments.length > 0) {
        resetMember(this, this.registry.normalize(fullName));
      } else {
        resetCache(this);
      }
    },

    /**
     Returns an object that can be used to provide an owner to a
     manually created instance.
      @private
     @method ownerInjection
     @returns { Object }
    */
    ownerInjection: function () {
      var _ref;

      return _ref = {}, _ref[_containerOwner.OWNER] = this.owner, _ref;
    }
  };

  function isSingleton(container, fullName) {
    return container.registry.getOption(fullName, 'singleton') !== false;
  }

  function lookup(container, fullName) {
    var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

    if (options.source) {
      fullName = container.registry.expandLocalLookup(fullName, options);

      // if expandLocalLookup returns falsey, we do not support local lookup
      if (!fullName) {
        return;
      }
    }

    if (container.cache[fullName] !== undefined && options.singleton !== false) {
      return container.cache[fullName];
    }

    var value = instantiate(container, fullName);

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

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

    return value;
  }

  function markInjectionsAsDynamic(injections) {
    injections._dynamic = true;
  }

  function areInjectionsDynamic(injections) {
    return !!injections._dynamic;
  }

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

    if (arguments.length > 1) {
      var container = arguments[0];
      var injections = [];
      var injection;

      for (var i = 1, l = arguments.length; i < l; i++) {
        if (arguments[i]) {
          injections = injections.concat(arguments[i]);
        }
      }

      container.registry.validateInjections(injections);

      for (i = 0, l = injections.length; i < l; i++) {
        injection = injections[i];
        hash[injection.property] = lookup(container, injection.fullName);
        if (!isSingleton(container, injection.fullName)) {
          markInjectionsAsDynamic(hash);
        }
      }
    }

    return hash;
  }

  function factoryFor(container, fullName) {
    var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

    var registry = container.registry;

    if (options.source) {
      fullName = registry.expandLocalLookup(fullName, options);

      // if expandLocalLookup returns falsey, we do not support local lookup
      if (!fullName) {
        return;
      }
    }

    var cache = container.factoryCache;
    if (cache[fullName]) {
      return cache[fullName];
    }
    var factory = registry.resolve(fullName);
    if (factory === undefined) {
      return;
    }

    var type = fullName.split(':')[0];
    if (!factory || typeof factory.extend !== 'function' || !_emberMetalCore.default.MODEL_FACTORY_INJECTIONS && type === 'model') {
      if (factory && typeof factory._onLookup === 'function') {
        factory._onLookup(fullName);
      }

      // TODO: think about a 'safe' merge style extension
      // for now just fallback to create time injection
      cache[fullName] = factory;
      return factory;
    } else {
      var injections = injectionsFor(container, fullName);
      var factoryInjections = factoryInjectionsFor(container, fullName);
      var cacheable = !areInjectionsDynamic(injections) && !areInjectionsDynamic(factoryInjections);

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

      var injectedFactory = factory.extend(injections);

      // TODO - remove all `container` injections when Ember reaches v3.0.0
      injectDeprecatedContainer(injectedFactory.prototype, container);
      injectedFactory.reopenClass(factoryInjections);

      if (factory && typeof factory._onLookup === 'function') {
        factory._onLookup(fullName);
      }

      if (cacheable) {
        cache[fullName] = injectedFactory;
      }

      return injectedFactory;
    }
  }

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

    var injections = buildInjections(container, registry.getTypeInjections(type), registry.getInjections(fullName));
    injections._debugContainerKey = fullName;

    _containerOwner.setOwner(injections, container.owner);

    return injections;
  }

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

    var factoryInjections = buildInjections(container, registry.getFactoryTypeInjections(type), registry.getFactoryInjections(fullName));
    factoryInjections._debugContainerKey = fullName;

    return factoryInjections;
  }

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

    if (container.registry.getOption(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.');
      }

      validationCache = container.validationCache;

      _emberMetalDebug.runInDebug(function () {
        // Ensure that all lazy injections are valid at instantiation time
        if (!validationCache[fullName] && typeof factory._lazyInjections === 'function') {
          lazyInjections = factory._lazyInjections();
          lazyInjections = container.registry.normalizeInjectionsHash(lazyInjections);

          container.registry.validateInjections(lazyInjections);
        }
      });

      validationCache[fullName] = true;

      var obj = undefined;

      if (typeof factory.extend === 'function') {
        // assume the factory was extendable and is already injected
        obj = 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
        var injections = injectionsFor(container, fullName);

        // Ensure that a container is available to an object during instantiation.
        // TODO - remove when Ember reaches v3.0.0
        // This "fake" container will be replaced after instantiation with a
        // property that raises deprecations every time it is accessed.
        injections.container = container._fakeContainerToInject;
        obj = factory.create(injections);

        // TODO - remove when Ember reaches v3.0.0
        if (!Object.isFrozen(obj) && 'container' in obj) {
          injectDeprecatedContainer(obj, container);
        }
      }

      return obj;
    }
  }

  // TODO - remove when Ember reaches v3.0.0
  function injectDeprecatedContainer(object, container) {
    Object.defineProperty(object, 'container', {
      configurable: true,
      enumerable: false,
      get: function () {
        _emberMetalDebug.deprecate('Using the injected `container` is deprecated. Please use the `getOwner` helper instead to access the owner of this object.', false, { id: 'ember-application.injected-container', until: '3.0.0', url: 'http://emberjs.com/deprecations/v2.x#toc_injected-container-access' });
        return this[CONTAINER_OVERRIDE] || container;
      },

      set: function (value) {
        _emberMetalDebug.deprecate('Providing the `container` property to ' + this + ' is deprecated. Please use `Ember.setOwner` or `owner.ownerInjection()` instead to provide an owner to the instance being created.', false, { id: 'ember-application.injected-container', until: '3.0.0', url: 'http://emberjs.com/deprecations/v2.x#toc_injected-container-access' });

        this[CONTAINER_OVERRIDE] = value;

        return value;
      }
    });
  }

  function eachDestroyable(container, callback) {
    var cache = container.cache;
    var keys = Object.keys(cache);
    var key, value;

    for (var i = 0, l = keys.length; i < l; i++) {
      key = keys[i];
      value = cache[key];

      if (container.registry.getOption(key, 'instantiate') !== false) {
        callback(value);
      }
    }
  }

  function resetCache(container) {
    eachDestroyable(container, function (value) {
      if (value.destroy) {
        value.destroy();
      }
    });

    container.cache.dict = _emberMetalDictionary.default(null);
  }

  function resetMember(container, fullName) {
    var member = container.cache[fullName];

    delete container.factoryCache[fullName];

    if (member) {
      delete container.cache[fullName];

      if (member.destroy) {
        member.destroy();
      }
    }
  }

  exports.default = Container;
});
enifed('container/index', ['exports', 'ember-metal/core', 'container/registry', 'container/container', 'container/owner'], function (exports, _emberMetalCore, _containerRegistry, _containerContainer, _containerOwner) {
  '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'))`);
  */
  _emberMetalCore.default.MODEL_FACTORY_INJECTIONS = false;

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

  exports.Registry = _containerRegistry.default;
  exports.Container = _containerContainer.default;
  exports.getOwner = _containerOwner.getOwner;
  exports.setOwner = _containerOwner.setOwner;
});
enifed('container/owner', ['exports', 'ember-metal/symbol'], function (exports, _emberMetalSymbol) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  exports.getOwner = getOwner;
  exports.setOwner = setOwner;
  var OWNER = _emberMetalSymbol.default('OWNER');

  exports.OWNER = OWNER;
  /**
    Framework objects in an Ember application (components, services, routes, etc.)
    are created via a factory and dependency injection system. Each of these
    objects is the responsibility of an "owner", which handled its
    instantiation and manages its lifetime.

    `getOwner` fetches the owner object responsible for an instance. This can
    be used to lookup or resolve other class instances, or register new factories
    into the owner.

    For example, this component dynamically looks up a service based on the
    `audioType` passed as an attribute:

    ```
    // app/components/play-audio.js
    import Ember from 'ember';

    // Usage:
    //
    //   {{play-audio audioType=model.audioType audioFile=model.file}}
    //
    export default Ember.Component.extend({
      audioService: Ember.computed('audioType', function() {
        let owner = Ember.getOwner(this);
        return owner.lookup(`service:${this.get('audioType')}`);
      }),
      click() {
        let player = this.get('audioService');
        player.play(this.get('audioFile'));
      }
    });
    ```

    @method getOwner
    @param {Object} object An object with an owner.
    @return {Object} An owner object.
    @for Ember
    @public
  */

  function getOwner(object) {
    return object[OWNER];
  }

  /**
    `setOwner` forces a new owner on a given object instance. This is primarily
    useful in some testing cases.

    @method setOwner
    @param {Object} object An object with an owner.
    @return {Object} An owner object.
    @for Ember
    @public
  */

  function setOwner(object, owner) {
    object[OWNER] = owner;
  }
});
enifed('container/registry', ['exports', 'ember-metal/features', 'ember-metal/debug', 'ember-metal/dictionary', 'ember-metal/empty_object', 'ember-metal/assign', 'container/container', 'ember-metal/utils'], function (exports, _emberMetalFeatures, _emberMetalDebug, _emberMetalDictionary, _emberMetalEmpty_object, _emberMetalAssign, _containerContainer, _emberMetalUtils) {
  'use strict';

  exports.privatize = privatize;

  var VALID_FULL_NAME_REGEXP = /^[^:]+:[^:]+$/;

  /**
   A registry used to store factory and option information keyed
   by type.

   A `Registry` stores the factory and option information needed by a
   `Container` to instantiate and cache objects.

   The API for `Registry` is still in flux and should not be considered stable.

   @private
   @class Registry
   @since 1.11.0
  */
  function Registry(options) {
    this.fallback = options && options.fallback ? options.fallback : null;

    if (options && options.resolver) {
      this.resolver = options.resolver;

      if (typeof this.resolver === 'function') {
        deprecateResolverFunction(this);
      }
    }

    this.registrations = _emberMetalDictionary.default(options && options.registrations ? options.registrations : null);

    this._typeInjections = _emberMetalDictionary.default(null);
    this._injections = _emberMetalDictionary.default(null);
    this._factoryTypeInjections = _emberMetalDictionary.default(null);
    this._factoryInjections = _emberMetalDictionary.default(null);

    this._localLookupCache = new _emberMetalEmpty_object.default();
    this._normalizeCache = _emberMetalDictionary.default(null);
    this._resolveCache = _emberMetalDictionary.default(null);
    this._failCache = _emberMetalDictionary.default(null);

    this._options = _emberMetalDictionary.default(null);
    this._typeOptions = _emberMetalDictionary.default(null);
  }

  Registry.prototype = {
    /**
     A backup registry for resolving registrations when no matches can be found.
      @private
     @property fallback
     @type Registry
     */
    fallback: null,

    /**
     An object that has a `resolve` method that resolves a name.
      @private
     @property resolver
     @type Resolver
     */
    resolver: null,

    /**
     @private
     @property registrations
     @type InheritingDict
     */
    registrations: null,

    /**
     @private
      @property _typeInjections
     @type InheritingDict
     */
    _typeInjections: null,

    /**
     @private
      @property _injections
     @type InheritingDict
     */
    _injections: null,

    /**
     @private
      @property _factoryTypeInjections
     @type InheritingDict
     */
    _factoryTypeInjections: null,

    /**
     @private
      @property _factoryInjections
     @type InheritingDict
     */
    _factoryInjections: null,

    /**
     @private
      @property _normalizeCache
     @type InheritingDict
     */
    _normalizeCache: null,

    /**
     @private
      @property _resolveCache
     @type InheritingDict
     */
    _resolveCache: null,

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

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

    /**
     Creates a container based on this registry.
      @private
     @method container
     @param {Object} options
     @return {Container} created container
     */
    container: function (options) {
      return new _containerContainer.default(this, options);
    },

    /**
     Registers a factory for later injection.
      Example:
      ```javascript
     var registry = new Registry();
      registry.register('model:user', Person, {singleton: false });
     registry.register('fruit:favorite', Orange);
     registry.register('communication:main', Email, {singleton: false});
     ```
      @private
     @method register
     @param {String} fullName
     @param {Function} factory
     @param {Object} options
     */
    register: function (fullName, factory) {
      var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

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

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

      var normalizedName = this.normalize(fullName);

      if (this._resolveCache[normalizedName]) {
        throw new Error('Cannot re-register: `' + fullName + '`, as it has already been resolved.');
      }

      delete this._failCache[normalizedName];
      this.registrations[normalizedName] = factory;
      this._options[normalizedName] = options;
    },

    /**
     Unregister a fullName
      ```javascript
     var registry = new Registry();
     registry.register('model:user', User);
      registry.resolve('model:user').create() instanceof User //=> true
      registry.unregister('model:user')
     registry.resolve('model:user') === undefined //=> true
     ```
      @private
     @method unregister
     @param {String} fullName
     */
    unregister: function (fullName) {
      _emberMetalDebug.assert('fullName must be a proper full name', this.validateFullName(fullName));

      var normalizedName = this.normalize(fullName);

      this._localLookupCache = new _emberMetalEmpty_object.default();

      delete this.registrations[normalizedName];
      delete this._resolveCache[normalizedName];
      delete this._failCache[normalizedName];
      delete this._options[normalizedName];
    },

    /**
     Given a fullName return the corresponding factory.
      By default `resolve` will retrieve the factory from
     the registry.
      ```javascript
     var registry = new Registry();
     registry.register('api:twitter', Twitter);
      registry.resolve('api:twitter') // => Twitter
     ```
      Optionally the registry 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 registry = new Registry();
     registry.resolver = function(fullName) {
        // lookup via the module system of choice
      };
      // the twitter factory is added to the module system
     registry.resolve('api:twitter') // => Twitter
     ```
      @private
     @method resolve
     @param {String} fullName
     @param {Object} [options]
     @param {String} [options.source] the fullname of the request source (used for local lookups)
     @return {Function} fullName's factory
     */
    resolve: function (fullName, options) {
      _emberMetalDebug.assert('fullName must be a proper full name', this.validateFullName(fullName));
      var factory = resolve(this, this.normalize(fullName), options);
      if (factory === undefined && this.fallback) {
        var _fallback;

        factory = (_fallback = this.fallback).resolve.apply(_fallback, arguments);
      }
      return factory;
    },

    /**
     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`.
      @private
     @method describe
     @param {String} fullName
     @return {string} described fullName
     */
    describe: function (fullName) {
      if (this.resolver && this.resolver.lookupDescription) {
        return this.resolver.lookupDescription(fullName);
      } else if (this.fallback) {
        return this.fallback.describe(fullName);
      } else {
        return fullName;
      }
    },

    /**
     A hook to enable custom fullName normalization behaviour
      @private
     @method normalizeFullName
     @param {String} fullName
     @return {string} normalized fullName
     */
    normalizeFullName: function (fullName) {
      if (this.resolver && this.resolver.normalize) {
        return this.resolver.normalize(fullName);
      } else if (this.fallback) {
        return this.fallback.normalizeFullName(fullName);
      } else {
        return fullName;
      }
    },

    /**
     Normalize a fullName based on the application's conventions
      @private
     @method normalize
     @param {String} fullName
     @return {string} normalized fullName
     */
    normalize: function (fullName) {
      return this._normalizeCache[fullName] || (this._normalizeCache[fullName] = this.normalizeFullName(fullName));
    },

    /**
     @method makeToString
      @private
     @param {any} factory
     @param {string} fullName
     @return {function} toString function
     */
    makeToString: function (factory, fullName) {
      if (this.resolver && this.resolver.makeToString) {
        return this.resolver.makeToString(factory, fullName);
      } else if (this.fallback) {
        return this.fallback.makeToString(factory, fullName);
      } else {
        return factory.toString();
      }
    },

    /**
     Given a fullName check if the container is aware of its factory
     or singleton instance.
      @private
     @method has
     @param {String} fullName
     @param {Object} [options]
     @param {String} [options.source] the fullname of the request source (used for local lookups)
     @return {Boolean}
     */
    has: function (fullName, options) {
      if (!this.isValidFullName(fullName)) {
        return false;
      }

      var source = undefined;

      source = options && options.source && this.normalize(options.source);

      return has(this, this.normalize(fullName), source);
    },

    /**
     Allow registering options for all factories of a type.
      ```javascript
     var registry = new Registry();
     var container = registry.container();
      // if all of type `connection` must not be singletons
     registry.optionsForType('connection', { singleton: false });
      registry.register('connection:twitter', TwitterConnection);
     registry.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
     ```
      @private
     @method optionsForType
     @param {String} type
     @param {Object} options
     */
    optionsForType: function (type, options) {
      this._typeOptions[type] = options;
    },

    getOptionsForType: function (type) {
      var optionsForType = this._typeOptions[type];
      if (optionsForType === undefined && this.fallback) {
        optionsForType = this.fallback.getOptionsForType(type);
      }
      return optionsForType;
    },

    /**
     @private
     @method options
     @param {String} fullName
     @param {Object} options
     */
    options: function (fullName) {
      var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

      var normalizedName = this.normalize(fullName);
      this._options[normalizedName] = options;
    },

    getOptions: function (fullName) {
      var normalizedName = this.normalize(fullName);
      var options = this._options[normalizedName];
      if (options === undefined && this.fallback) {
        options = this.fallback.getOptions(fullName);
      }
      return options;
    },

    getOption: function (fullName, optionName) {
      var options = this._options[fullName];

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

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

      if (options && options[optionName] !== undefined) {
        return options[optionName];
      } else if (this.fallback) {
        return this.fallback.getOption(fullName, optionName);
      }
    },

    /**
     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 registry = new Registry();
     var container = registry.container();
      registry.register('router:main', Router);
     registry.register('controller:user', UserController);
     registry.register('controller:post', PostController);
      registry.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) {
      _emberMetalDebug.assert('fullName must be a proper full name', this.validateFullName(fullName));

      var fullNameType = fullName.split(':')[0];
      if (fullNameType === type) {
        throw new Error('Cannot inject a `' + fullName + '` on other ' + type + '(s).');
      }

      var injections = this._typeInjections[type] || (this._typeInjections[type] = []);

      injections.push({
        property: property,
        fullName: 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 registry = new Registry();
     var container = registry.container();
      registry.register('source:main', Source);
     registry.register('model:user', User);
     registry.register('model:post', Post);
      // injecting one fullName on another fullName
     // eg. each user model gets a post model
     registry.injection('model:user', 'post', 'model:post');
      // injecting one fullName on another type
     registry.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
     ```
      @private
     @method injection
     @param {String} factoryName
     @param {String} property
     @param {String} injectionName
     */
    injection: function (fullName, property, injectionName) {
      this.validateFullName(injectionName);
      var normalizedInjectionName = this.normalize(injectionName);

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

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

      var injections = this._injections[normalizedName] || (this._injections[normalizedName] = []);

      injections.push({
        property: property,
        fullName: 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 registry = new Registry();
      registry.register('store:main', SomeStore);
      registry.factoryTypeInjection('model', 'store', 'store:main');
      var store = registry.lookup('store:main');
     var UserFactory = registry.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) {
      var injections = this._factoryTypeInjections[type] || (this._factoryTypeInjections[type] = []);

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

    /**
     Defines factory injection rules.
      Similar to regular injection rules, but are run against factories, via
     `Registry#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 registry = new Registry();
     var container = registry.container();
      registry.register('store:main', Store);
     registry.register('store:secondary', OtherStore);
     registry.register('model:user', User);
     registry.register('model:post', Post);
      // injecting one fullName on another type
     registry.factoryInjection('model', 'store', 'store:main');
      // injecting one fullName on another fullName
     registry.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
     ```
      @private
     @method factoryInjection
     @param {String} factoryName
     @param {String} property
     @param {String} injectionName
     */
    factoryInjection: function (fullName, property, injectionName) {
      var normalizedName = this.normalize(fullName);
      var normalizedInjectionName = this.normalize(injectionName);

      this.validateFullName(injectionName);

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

      var injections = this._factoryInjections[normalizedName] || (this._factoryInjections[normalizedName] = []);

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

    /**
     @private
     @method knownForType
     @param {String} type the type to iterate over
    */
    knownForType: function (type) {
      var fallbackKnown = undefined,
          resolverKnown = undefined;

      var localKnown = _emberMetalDictionary.default(null);
      var registeredNames = Object.keys(this.registrations);
      for (var index = 0, _length = registeredNames.length; index < _length; index++) {
        var fullName = registeredNames[index];
        var itemType = fullName.split(':')[0];

        if (itemType === type) {
          localKnown[fullName] = true;
        }
      }

      if (this.fallback) {
        fallbackKnown = this.fallback.knownForType(type);
      }

      if (this.resolver && this.resolver.knownForType) {
        resolverKnown = this.resolver.knownForType(type);
      }

      return _emberMetalAssign.default({}, fallbackKnown, localKnown, resolverKnown);
    },

    validateFullName: function (fullName) {
      if (!this.isValidFullName(fullName)) {
        throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName);
      }

      return true;
    },

    isValidFullName: function (fullName) {
      return !!VALID_FULL_NAME_REGEXP.test(fullName);
    },

    validateInjections: function (injections) {
      if (!injections) {
        return;
      }

      var fullName;

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

        if (!this.has(fullName)) {
          throw new Error('Attempting to inject an unknown injection: `' + fullName + '`');
        }
      }
    },

    normalizeInjectionsHash: function (hash) {
      var injections = [];

      for (var key in hash) {
        if (hash.hasOwnProperty(key)) {
          _emberMetalDebug.assert('Expected a proper full name, given \'' + hash[key] + '\'', this.validateFullName(hash[key]));

          injections.push({
            property: key,
            fullName: hash[key]
          });
        }
      }

      return injections;
    },

    getInjections: function (fullName) {
      var injections = this._injections[fullName] || [];
      if (this.fallback) {
        injections = injections.concat(this.fallback.getInjections(fullName));
      }
      return injections;
    },

    getTypeInjections: function (type) {
      var injections = this._typeInjections[type] || [];
      if (this.fallback) {
        injections = injections.concat(this.fallback.getTypeInjections(type));
      }
      return injections;
    },

    getFactoryInjections: function (fullName) {
      var injections = this._factoryInjections[fullName] || [];
      if (this.fallback) {
        injections = injections.concat(this.fallback.getFactoryInjections(fullName));
      }
      return injections;
    },

    getFactoryTypeInjections: function (type) {
      var injections = this._factoryTypeInjections[type] || [];
      if (this.fallback) {
        injections = injections.concat(this.fallback.getFactoryTypeInjections(type));
      }
      return injections;
    }
  };

  function deprecateResolverFunction(registry) {
    _emberMetalDebug.deprecate('Passing a `resolver` function into a Registry is deprecated. Please pass in a Resolver object with a `resolve` method.', false, { id: 'ember-application.registry-resolver-as-function', until: '3.0.0', url: 'http://emberjs.com/deprecations/v2.x#toc_registry-resolver-as-function' });
    registry.resolver = {
      resolve: registry.resolver
    };
  }

  /**
    Given a fullName and a source fullName returns the fully resolved
    fullName. Used to allow for local lookup.
     ```javascript
    var registry = new Registry();
     // the twitter factory is added to the module system
    registry.expandLocalLookup('component:post-title', { source: 'template:post' }) // => component:post/post-title
    ```
     @private
    @method expandLocalLookup
    @param {String} fullName
    @param {Object} [options]
    @param {String} [options.source] the fullname of the request source (used for local lookups)
    @return {String} fullName
  */
  Registry.prototype.expandLocalLookup = function Registry_expandLocalLookup(fullName, options) {
    if (this.resolver && this.resolver.expandLocalLookup) {
      _emberMetalDebug.assert('fullName must be a proper full name', this.validateFullName(fullName));
      _emberMetalDebug.assert('options.source must be provided to expandLocalLookup', options && options.source);
      _emberMetalDebug.assert('options.source must be a proper full name', this.validateFullName(options.source));

      var normalizedFullName = this.normalize(fullName);
      var normalizedSource = this.normalize(options.source);

      return expandLocalLookup(this, normalizedFullName, normalizedSource);
    } else if (this.fallback) {
      return this.fallback.expandLocalLookup(fullName, options);
    } else {
      return null;
    }
  };

  function expandLocalLookup(registry, normalizedName, normalizedSource) {
    var cache = registry._localLookupCache;
    var normalizedNameCache = cache[normalizedName];

    if (!normalizedNameCache) {
      normalizedNameCache = cache[normalizedName] = new _emberMetalEmpty_object.default();
    }

    var cached = normalizedNameCache[normalizedSource];

    if (cached !== undefined) {
      return cached;
    }

    var expanded = registry.resolver.expandLocalLookup(normalizedName, normalizedSource);

    return normalizedNameCache[normalizedSource] = expanded;
  }

  function resolve(registry, normalizedName, options) {
    if (options && options.source) {
      // when `source` is provided expand normalizedName
      // and source into the full normalizedName
      normalizedName = registry.expandLocalLookup(normalizedName, options);

      // if expandLocalLookup returns falsey, we do not support local lookup
      if (!normalizedName) {
        return;
      }
    }

    var cached = registry._resolveCache[normalizedName];
    if (cached !== undefined) {
      return cached;
    }
    if (registry._failCache[normalizedName]) {
      return;
    }

    var resolved = undefined;

    if (registry.resolver) {
      resolved = registry.resolver.resolve(normalizedName);
    }

    if (resolved === undefined) {
      resolved = registry.registrations[normalizedName];
    }

    if (resolved === undefined) {
      registry._failCache[normalizedName] = true;
    } else {
      registry._resolveCache[normalizedName] = resolved;
    }

    return resolved;
  }

  function has(registry, fullName, source) {
    return registry.resolve(fullName, { source: source }) !== undefined;
  }

  var privateNames = _emberMetalDictionary.default(null);
  var privateSuffix = Math.floor(Math.random() * new Date()) + '';

  function privatize(_ref) {
    var fullName = _ref[0];

    var name = privateNames[fullName];
    if (name) {
      return name;
    }

    var _fullName$split = fullName.split(':');

    var type = _fullName$split[0];
    var rawName = _fullName$split[1];

    return privateNames[fullName] = _emberMetalUtils.intern(type + ':' + rawName + '-' + privateSuffix);
  }

  exports.default = Registry;
});
enifed('dag-map', ['exports', 'vertex', 'visit'], function (exports, _vertex, _visit) {
  'use strict';

  exports.default = DAG;

  /**
   * DAG stands for Directed acyclic graph.
   *
   * It is used to build a graph of dependencies checking that there isn't circular
   * dependencies. p.e Registering initializers with a certain precedence order.
   *
   * @class DAG
   * @constructor
   */

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

  /**
   * Adds a vertex entry to the graph unless it is already added.
   *
   * @private
   * @method add
   * @param {String} name The name of the vertex to add
   */
  DAG.prototype.add = function (name) {
    if (!name) {
      throw new Error("Can't add Vertex without name");
    }
    if (this.vertices[name] !== undefined) {
      return this.vertices[name];
    }
    var vertex = new _vertex.default(name);
    this.vertices[name] = vertex;
    this.names.push(name);
    return vertex;
  };

  /**
   * Adds a vertex to the graph and sets its value.
   *
   * @private
   * @method map
   * @param {String} name The name of the vertex.
   * @param         value The value to put in the vertex.
   */
  DAG.prototype.map = function (name, value) {
    this.add(name).value = value;
  };

  /**
   * Connects the vertices with the given names, adding them to the graph if
   * necessary, only if this does not produce is any circular dependency.
   *
   * @private
   * @method addEdge
   * @param {String} fromName The name the vertex where the edge starts.
   * @param {String} toName The name the vertex where the edge ends.
   */
  DAG.prototype.addEdge = function (fromName, toName) {
    if (!fromName || !toName || fromName === toName) {
      return;
    }
    var from = this.add(fromName);
    var to = this.add(toName);
    if (to.incoming.hasOwnProperty(fromName)) {
      return;
    }
    function checkCycle(vertex, path) {
      if (vertex.name === toName) {
        throw new Error("cycle detected: " + toName + " <- " + path.join(" <- "));
      }
    }
    _visit.default(from, checkCycle);
    from.hasOutgoing = true;
    to.incoming[fromName] = from;
    to.incomingNames.push(fromName);
  };

  /**
   * Visits all the vertex of the graph calling the given function with each one,
   * ensuring that the vertices are visited respecting their precedence.
   *
   * @method  topsort
   * @param {Function} fn The function to be invoked on each vertex.
   */
  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.default(vertex, fn, visited);
      }
    }
  };

  /**
   * Adds a vertex with the given name and value to the graph and joins it with the
   * vertices referenced in _before_ and _after_. If there isn't vertices with those
   * names, they are added too.
   *
   * If either _before_ or _after_ are falsy/empty, the added vertex will not have
   * an incoming/outgoing edge.
   *
   * @method addEdges
   * @param {String} name The name of the vertex to be added.
   * @param         value The value of that vertex.
   * @param        before An string or array of strings with the names of the vertices before
   *                      which this vertex must be visited.
   * @param         after An string or array of strings with the names of the vertex after
   *                      which this vertex must be 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);
        }
      }
    }
  };
});
enifed('dag-map.umd', ['exports', 'dag-map/platform', 'dag-map'], function (exports, _dagMapPlatform, _dagMap) {
  'use strict';

  /* global define:true module:true window: true */
  if (typeof define === 'function' && define.amd) {
    define(function () {
      return _dagMap.default;
    });
  } else if (typeof module !== 'undefined' && module.exports) {
    module.exports = _dagMap.default;
  } else if (typeof _dagMapPlatform.default !== 'undefined') {
    _dagMapPlatform.default['DAG'] = _dagMap.default;
  }
});
enifed('dag-map/platform', ['exports'], function (exports) {
  'use strict';

  var platform;

  /* global self */
  if (typeof self === 'object') {
    platform = self;

    /* global global */
  } else if (typeof global === 'object') {
      platform = global;
    } else {
      throw new Error('no global: `self` or `global` found');
    }

  exports.default = platform;
});
enifed("dom-helper", ["exports", "htmlbars-runtime/morph", "morph-attr", "dom-helper/build-html-dom", "dom-helper/classes", "dom-helper/prop"], function (exports, _htmlbarsRuntimeMorph, _morphAttr, _domHelperBuildHtmlDom, _domHelperClasses, _domHelperProp) {
  /*globals module, URL*/

  "use strict";

  var doc = typeof document === 'undefined' ? false : document;

  var deletesBlankTextNodes = doc && (function (document) {
    var element = document.createElement('div');
    element.appendChild(document.createTextNode(''));
    var clonedElement = element.cloneNode(true);
    return clonedElement.childNodes.length === 0;
  })(doc);

  var ignoresCheckedAttribute = doc && (function (document) {
    var element = document.createElement('input');
    element.setAttribute('checked', 'checked');
    var clonedElement = element.cloneNode(false);
    return !clonedElement.checked;
  })(doc);

  var canRemoveSvgViewBoxAttribute = doc && (doc.createElementNS ? (function (document) {
    var element = document.createElementNS(_domHelperBuildHtmlDom.svgNamespace, 'svg');
    element.setAttribute('viewBox', '0 0 100 100');
    element.removeAttribute('viewBox');
    return !element.getAttribute('viewBox');
  })(doc) : true);

  var canClone = doc && (function (document) {
    var element = document.createElement('div');
    element.appendChild(document.createTextNode(' '));
    element.appendChild(document.createTextNode(' '));
    var clonedElement = element.cloneNode(true);
    return clonedElement.childNodes[0].nodeValue === ' ';
  })(doc);

  // This is not the namespace of the element, but of
  // the elements inside that elements.
  function interiorNamespace(element) {
    if (element && element.namespaceURI === _domHelperBuildHtmlDom.svgNamespace && !_domHelperBuildHtmlDom.svgHTMLIntegrationPoints[element.tagName]) {
      return _domHelperBuildHtmlDom.svgNamespace;
    } else {
      return null;
    }
  }

  // The HTML spec allows for "omitted start tags". These tags are optional
  // when their intended child is the first thing in the parent tag. For
  // example, this is a tbody start tag:
  //
  // <table>
  //   <tbody>
  //     <tr>
  //
  // The tbody may be omitted, and the browser will accept and render:
  //
  // <table>
  //   <tr>
  //
  // However, the omitted start tag will still be added to the DOM. Here
  // we test the string and context to see if the browser is about to
  // perform this cleanup.
  //
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags
  // describes which tags are omittable. The spec for tbody and colgroup
  // explains this behavior:
  //
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-tbody-element
  // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-colgroup-element
  //

  var omittedStartTagChildTest = /<([\w:]+)/;
  function detectOmittedStartTag(string, contextualElement) {
    // Omitted start tags are only inside table tags.
    if (contextualElement.tagName === 'TABLE') {
      var omittedStartTagChildMatch = omittedStartTagChildTest.exec(string);
      if (omittedStartTagChildMatch) {
        var omittedStartTagChild = omittedStartTagChildMatch[1];
        // It is already asserted that the contextual element is a table
        // and not the proper start tag. Just see if a tag was omitted.
        return omittedStartTagChild === 'tr' || omittedStartTagChild === 'col';
      }
    }
  }

  function buildSVGDOM(html, dom) {
    var div = dom.document.createElement('div');
    div.innerHTML = '<svg>' + html + '</svg>';
    return div.firstChild.childNodes;
  }

  var guid = 1;

  function ElementMorph(element, dom, namespace) {
    this.element = element;
    this.dom = dom;
    this.namespace = namespace;
    this.guid = "element" + guid++;

    this._state = undefined;
    this.isDirty = true;
  }

  ElementMorph.prototype.getState = function () {
    if (!this._state) {
      this._state = {};
    }

    return this._state;
  };

  ElementMorph.prototype.setState = function (newState) {
    /*jshint -W093 */

    return this._state = newState;
  };

  // renderAndCleanup calls `clear` on all items in the morph map
  // just before calling `destroy` on the morph.
  //
  // As a future refactor this could be changed to set the property
  // back to its original/default value.
  ElementMorph.prototype.clear = function () {};

  ElementMorph.prototype.destroy = function () {
    this.element = null;
    this.dom = null;
  };

  /*
   * A class wrapping DOM functions to address environment compatibility,
   * namespaces, contextual elements for morph un-escaped content
   * insertion.
   *
   * When entering a template, a DOMHelper should be passed:
   *
   *   template(context, { hooks: hooks, dom: new DOMHelper() });
   *
   * TODO: support foreignObject as a passed contextual element. It has
   * a namespace (svg) that does not match its internal namespace
   * (xhtml).
   *
   * @class DOMHelper
   * @constructor
   * @param {HTMLDocument} _document The document DOM methods are proxied to
   */
  function DOMHelper(_document) {
    this.document = _document || document;
    if (!this.document) {
      throw new Error("A document object must be passed to the DOMHelper, or available on the global scope");
    }
    this.canClone = canClone;
    this.namespace = null;

    installEnvironmentSpecificMethods(this);
  }

  var prototype = DOMHelper.prototype;
  prototype.constructor = DOMHelper;

  prototype.getElementById = function (id, rootNode) {
    rootNode = rootNode || this.document;
    return rootNode.getElementById(id);
  };

  prototype.insertBefore = function (element, childElement, referenceChild) {
    return element.insertBefore(childElement, referenceChild);
  };

  prototype.appendChild = function (element, childElement) {
    return element.appendChild(childElement);
  };

  var itemAt;

  // It appears that sometimes, in yet to be itentified scenarios PhantomJS 2.0
  // crashes on childNodes.item(index), but works as expected with childNodes[index];
  //
  // Although it would be nice to move to childNodes[index] in all scenarios,
  // this would require SimpleDOM to maintain the childNodes array. This would be
  // quite costly, in both dev time and runtime.
  //
  // So instead, we choose the best possible method and call it a day.
  //
  /*global navigator */
  if (typeof navigator !== 'undefined' && navigator.userAgent.indexOf('PhantomJS')) {
    itemAt = function (nodes, index) {
      return nodes[index];
    };
  } else {
    itemAt = function (nodes, index) {
      return nodes.item(index);
    };
  }

  prototype.childAt = function (element, indices) {
    var child = element;

    for (var i = 0; i < indices.length; i++) {
      child = itemAt(child.childNodes, indices[i]);
    }

    return child;
  };

  // Note to a Fellow Implementor:
  // Ahh, accessing a child node at an index. Seems like it should be so simple,
  // doesn't it? Unfortunately, this particular method has caused us a surprising
  // amount of pain. As you'll note below, this method has been modified to walk
  // the linked list of child nodes rather than access the child by index
  // directly, even though there are two (2) APIs in the DOM that do this for us.
  // If you're thinking to yourself, "What an oversight! What an opportunity to
  // optimize this code!" then to you I say: stop! For I have a tale to tell.
  //
  // First, this code must be compatible with simple-dom for rendering on the
  // server where there is no real DOM. Previously, we accessed a child node
  // directly via `element.childNodes[index]`. While we *could* in theory do a
  // full-fidelity simulation of a live `childNodes` array, this is slow,
  // complicated and error-prone.
  //
  // "No problem," we thought, "we'll just use the similar
  // `childNodes.item(index)` API." Then, we could just implement our own `item`
  // method in simple-dom and walk the child node linked list there, allowing
  // us to retain the performance advantages of the (surely optimized) `item()`
  // API in the browser.
  //
  // Unfortunately, an enterprising soul named Samy Alzahrani discovered that in
  // IE8, accessing an item out-of-bounds via `item()` causes an exception where
  // other browsers return null. This necessitated a... check of
  // `childNodes.length`, bringing us back around to having to support a
  // full-fidelity `childNodes` array!
  //
  // Worst of all, Kris Selden investigated how browsers are actualy implemented
  // and discovered that they're all linked lists under the hood anyway. Accessing
  // `childNodes` requires them to allocate a new live collection backed by that
  // linked list, which is itself a rather expensive operation. Our assumed
  // optimization had backfired! That is the danger of magical thinking about
  // the performance of native implementations.
  //
  // And this, my friends, is why the following implementation just walks the
  // linked list, as surprised as that may make you. Please ensure you understand
  // the above before changing this and submitting a PR.
  //
  // Tom Dale, January 18th, 2015, Portland OR
  prototype.childAtIndex = function (element, index) {
    var node = element.firstChild;

    for (var idx = 0; node && idx < index; idx++) {
      node = node.nextSibling;
    }

    return node;
  };

  prototype.appendText = function (element, text) {
    return element.appendChild(this.document.createTextNode(text));
  };

  prototype.setAttribute = function (element, name, value) {
    element.setAttribute(name, String(value));
  };

  prototype.getAttribute = function (element, name) {
    return element.getAttribute(name);
  };

  prototype.setAttributeNS = function (element, namespace, name, value) {
    element.setAttributeNS(namespace, name, String(value));
  };

  prototype.getAttributeNS = function (element, namespace, name) {
    return element.getAttributeNS(namespace, name);
  };

  if (canRemoveSvgViewBoxAttribute) {
    prototype.removeAttribute = function (element, name) {
      element.removeAttribute(name);
    };
  } else {
    prototype.removeAttribute = function (element, name) {
      if (element.tagName === 'svg' && name === 'viewBox') {
        element.setAttribute(name, null);
      } else {
        element.removeAttribute(name);
      }
    };
  }

  prototype.setPropertyStrict = function (element, name, value) {
    if (value === undefined) {
      value = null;
    }

    if (value === null && (name === 'value' || name === 'type' || name === 'src')) {
      value = '';
    }

    element[name] = value;
  };

  prototype.getPropertyStrict = function (element, name) {
    return element[name];
  };

  prototype.setProperty = function (element, name, value, namespace) {
    if (element.namespaceURI === _domHelperBuildHtmlDom.svgNamespace) {
      if (_domHelperProp.isAttrRemovalValue(value)) {
        element.removeAttribute(name);
      } else {
        if (namespace) {
          element.setAttributeNS(namespace, name, value);
        } else {
          element.setAttribute(name, value);
        }
      }
    } else {
      var _normalizeProperty = _domHelperProp.normalizeProperty(element, name);

      var normalized = _normalizeProperty.normalized;
      var type = _normalizeProperty.type;

      if (type === 'prop') {
        element[normalized] = value;
      } else {
        if (_domHelperProp.isAttrRemovalValue(value)) {
          element.removeAttribute(name);
        } else {
          if (namespace && element.setAttributeNS) {
            element.setAttributeNS(namespace, name, value);
          } else {
            element.setAttribute(name, value);
          }
        }
      }
    }
  };

  if (doc && doc.createElementNS) {
    // Only opt into namespace detection if a contextualElement
    // is passed.
    prototype.createElement = function (tagName, contextualElement) {
      var namespace = this.namespace;
      if (contextualElement) {
        if (tagName === 'svg') {
          namespace = _domHelperBuildHtmlDom.svgNamespace;
        } else {
          namespace = interiorNamespace(contextualElement);
        }
      }
      if (namespace) {
        return this.document.createElementNS(namespace, tagName);
      } else {
        return this.document.createElement(tagName);
      }
    };
    prototype.setAttributeNS = function (element, namespace, name, value) {
      element.setAttributeNS(namespace, name, String(value));
    };
  } else {
    prototype.createElement = function (tagName) {
      return this.document.createElement(tagName);
    };
    prototype.setAttributeNS = function (element, namespace, name, value) {
      element.setAttribute(name, String(value));
    };
  }

  prototype.addClasses = _domHelperClasses.addClasses;
  prototype.removeClasses = _domHelperClasses.removeClasses;

  prototype.setNamespace = function (ns) {
    this.namespace = ns;
  };

  prototype.detectNamespace = function (element) {
    this.namespace = interiorNamespace(element);
  };

  prototype.createDocumentFragment = function () {
    return this.document.createDocumentFragment();
  };

  prototype.createTextNode = function (text) {
    return this.document.createTextNode(text);
  };

  prototype.createComment = function (text) {
    return this.document.createComment(text);
  };

  prototype.repairClonedNode = function (element, blankChildTextNodes, isChecked) {
    if (deletesBlankTextNodes && blankChildTextNodes.length > 0) {
      for (var i = 0, len = blankChildTextNodes.length; i < len; i++) {
        var textNode = this.document.createTextNode(''),
            offset = blankChildTextNodes[i],
            before = this.childAtIndex(element, offset);
        if (before) {
          element.insertBefore(textNode, before);
        } else {
          element.appendChild(textNode);
        }
      }
    }
    if (ignoresCheckedAttribute && isChecked) {
      element.setAttribute('checked', 'checked');
    }
  };

  prototype.cloneNode = function (element, deep) {
    var clone = element.cloneNode(!!deep);
    return clone;
  };

  prototype.AttrMorphClass = _morphAttr.default;

  prototype.createAttrMorph = function (element, attrName, namespace) {
    return this.AttrMorphClass.create(element, attrName, this, namespace);
  };

  prototype.ElementMorphClass = ElementMorph;

  prototype.createElementMorph = function (element, namespace) {
    return new this.ElementMorphClass(element, this, namespace);
  };

  prototype.createUnsafeAttrMorph = function (element, attrName, namespace) {
    var morph = this.createAttrMorph(element, attrName, namespace);
    morph.escaped = false;
    return morph;
  };

  prototype.MorphClass = _htmlbarsRuntimeMorph.default;

  prototype.createMorph = function (parent, start, end, contextualElement) {
    if (contextualElement && contextualElement.nodeType === 11) {
      throw new Error("Cannot pass a fragment as the contextual element to createMorph");
    }

    if (!contextualElement && parent && parent.nodeType === 1) {
      contextualElement = parent;
    }
    var morph = new this.MorphClass(this, contextualElement);
    morph.firstNode = start;
    morph.lastNode = end;
    return morph;
  };

  prototype.createFragmentMorph = function (contextualElement) {
    if (contextualElement && contextualElement.nodeType === 11) {
      throw new Error("Cannot pass a fragment as the contextual element to createMorph");
    }

    var fragment = this.createDocumentFragment();
    return _htmlbarsRuntimeMorph.default.create(this, contextualElement, fragment);
  };

  prototype.replaceContentWithMorph = function (element) {
    var firstChild = element.firstChild;

    if (!firstChild) {
      var comment = this.createComment('');
      this.appendChild(element, comment);
      return _htmlbarsRuntimeMorph.default.create(this, element, comment);
    } else {
      var morph = _htmlbarsRuntimeMorph.default.attach(this, element, firstChild, element.lastChild);
      morph.clear();
      return morph;
    }
  };

  prototype.createUnsafeMorph = function (parent, start, end, contextualElement) {
    var morph = this.createMorph(parent, start, end, contextualElement);
    morph.parseTextAsHTML = true;
    return morph;
  };

  // This helper is just to keep the templates good looking,
  // passing integers instead of element references.
  prototype.createMorphAt = function (parent, startIndex, endIndex, contextualElement) {
    var single = startIndex === endIndex;
    var start = this.childAtIndex(parent, startIndex);
    var end = single ? start : this.childAtIndex(parent, endIndex);
    return this.createMorph(parent, start, end, contextualElement);
  };

  prototype.createUnsafeMorphAt = function (parent, startIndex, endIndex, contextualElement) {
    var morph = this.createMorphAt(parent, startIndex, endIndex, contextualElement);
    morph.parseTextAsHTML = true;
    return morph;
  };

  prototype.insertMorphBefore = function (element, referenceChild, contextualElement) {
    var insertion = this.document.createComment('');
    element.insertBefore(insertion, referenceChild);
    return this.createMorph(element, insertion, insertion, contextualElement);
  };

  prototype.appendMorph = function (element, contextualElement) {
    var insertion = this.document.createComment('');
    element.appendChild(insertion);
    return this.createMorph(element, insertion, insertion, contextualElement);
  };

  prototype.insertBoundary = function (fragment, index) {
    // this will always be null or firstChild
    var child = index === null ? null : this.childAtIndex(fragment, index);
    this.insertBefore(fragment, this.createTextNode(''), child);
  };

  prototype.setMorphHTML = function (morph, html) {
    morph.setHTML(html);
  };

  prototype.parseHTML = function (html, contextualElement) {
    var childNodes;

    if (interiorNamespace(contextualElement) === _domHelperBuildHtmlDom.svgNamespace) {
      childNodes = buildSVGDOM(html, this);
    } else {
      var nodes = _domHelperBuildHtmlDom.buildHTMLDOM(html, contextualElement, this);
      if (detectOmittedStartTag(html, contextualElement)) {
        var node = nodes[0];
        while (node && node.nodeType !== 1) {
          node = node.nextSibling;
        }
        childNodes = node.childNodes;
      } else {
        childNodes = nodes;
      }
    }

    // Copy node list to a fragment.
    var fragment = this.document.createDocumentFragment();

    if (childNodes && childNodes.length > 0) {
      var currentNode = childNodes[0];

      // We prepend an <option> to <select> boxes to absorb any browser bugs
      // related to auto-select behavior. Skip past it.
      if (contextualElement.tagName === 'SELECT') {
        currentNode = currentNode.nextSibling;
      }

      while (currentNode) {
        var tempNode = currentNode;
        currentNode = currentNode.nextSibling;

        fragment.appendChild(tempNode);
      }
    }

    return fragment;
  };

  var nodeURL;
  var parsingNode;

  function installEnvironmentSpecificMethods(domHelper) {
    var protocol = browserProtocolForURL.call(domHelper, 'foobar:baz');

    // Test to see if our DOM implementation parses
    // and normalizes URLs.
    if (protocol === 'foobar:') {
      // Swap in the method that doesn't do this test now that
      // we know it works.
      domHelper.protocolForURL = browserProtocolForURL;
    } else if (typeof URL === 'object') {
      // URL globally provided, likely from FastBoot's sandbox
      nodeURL = URL;
      domHelper.protocolForURL = nodeProtocolForURL;
    } else if (typeof module === 'object' && typeof module.require === 'function') {
      // Otherwise, we need to fall back to our own URL parsing.
      // Global `require` is shadowed by Ember's loader so we have to use the fully
      // qualified `module.require`.
      nodeURL = module.require('url');
      domHelper.protocolForURL = nodeProtocolForURL;
    } else {
      throw new Error("DOM Helper could not find valid URL parsing mechanism");
    }

    // A SimpleDOM-specific extension that allows us to place HTML directly
    // into the DOM tree, for when the output target is always serialized HTML.
    if (domHelper.document.createRawHTMLSection) {
      domHelper.setMorphHTML = nodeSetMorphHTML;
    }
  }

  function nodeSetMorphHTML(morph, html) {
    var section = this.document.createRawHTMLSection(html);
    morph.setNode(section);
  }

  function browserProtocolForURL(url) {
    if (!parsingNode) {
      parsingNode = this.document.createElement('a');
    }

    parsingNode.href = url;
    return parsingNode.protocol;
  }

  function nodeProtocolForURL(url) {
    var protocol = nodeURL.parse(url).protocol;
    return protocol === null ? ':' : protocol;
  }

  exports.default = DOMHelper;
});
enifed('dom-helper/build-html-dom', ['exports'], function (exports) {
  /* global XMLSerializer:false */
  'use strict';

  var svgHTMLIntegrationPoints = { foreignObject: 1, desc: 1, title: 1 };
  exports.svgHTMLIntegrationPoints = svgHTMLIntegrationPoints;
  var svgNamespace = 'http://www.w3.org/2000/svg';

  exports.svgNamespace = svgNamespace;
  var doc = typeof document === 'undefined' ? false : document;

  // Safari does not like using innerHTML on SVG HTML integration
  // points (desc/title/foreignObject).
  var needsIntegrationPointFix = doc && (function (document) {
    if (document.createElementNS === undefined) {
      return;
    }
    // In FF title will not accept innerHTML.
    var testEl = document.createElementNS(svgNamespace, 'title');
    testEl.innerHTML = "<div></div>";
    return testEl.childNodes.length === 0 || testEl.childNodes[0].nodeType !== 1;
  })(doc);

  // 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 = doc && (function (document) {
    var testEl = document.createElement('div');
    testEl.innerHTML = "<div></div>";
    testEl.firstChild.innerHTML = "<script><\/script>";
    return testEl.firstChild.innerHTML === '';
  })(doc);

  // 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 = doc && (function (document) {
    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';
  })(doc);

  var tagNamesRequiringInnerHTMLFix = doc && (function (document) {
    var tagNamesRequiringInnerHTMLFix;
    // IE 9 and earlier don't allow us to set innerHTML on col, colgroup, frameset,
    // html, style, table, tbody, tfoot, thead, title, tr. Detect this and add
    // them to an initial list of corrected tags.
    //
    // Here we are only dealing with the ones which can have child nodes.
    //
    var tableNeedsInnerHTMLFix;
    var tableInnerHTMLTestElement = document.createElement('table');
    try {
      tableInnerHTMLTestElement.innerHTML = '<tbody></tbody>';
    } catch (e) {} finally {
      tableNeedsInnerHTMLFix = tableInnerHTMLTestElement.childNodes.length === 0;
    }
    if (tableNeedsInnerHTMLFix) {
      tagNamesRequiringInnerHTMLFix = {
        colgroup: ['table'],
        table: [],
        tbody: ['table'],
        tfoot: ['table'],
        thead: ['table'],
        tr: ['table', 'tbody']
      };
    }

    // IE 8 doesn't allow setting innerHTML on a select tag. Detect this and
    // add it to the list of corrected tags.
    //
    var selectInnerHTMLTestElement = document.createElement('select');
    selectInnerHTMLTestElement.innerHTML = '<option></option>';
    if (!selectInnerHTMLTestElement.childNodes[0]) {
      tagNamesRequiringInnerHTMLFix = tagNamesRequiringInnerHTMLFix || {};
      tagNamesRequiringInnerHTMLFix.select = [];
    }
    return tagNamesRequiringInnerHTMLFix;
  })(doc);

  function scriptSafeInnerHTML(element, html) {
    // without a leading text node, IE will drop a leading script tag.
    html = '&shy;' + html;

    element.innerHTML = html;

    var nodes = element.childNodes;

    // Look for &shy; to remove it.
    var shyElement = nodes[0];
    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") {
      var newValue = shyElement.nodeValue.slice(1);
      if (newValue.length) {
        shyElement.nodeValue = shyElement.nodeValue.slice(1);
      } else {
        shyElement.parentNode.removeChild(shyElement);
      }
    }

    return nodes;
  }

  function buildDOMWithFix(html, contextualElement) {
    var tagName = contextualElement.tagName;

    // Firefox versions < 11 do not have support for element.outerHTML.
    var outerHTML = contextualElement.outerHTML || new XMLSerializer().serializeToString(contextualElement);
    if (!outerHTML) {
      throw "Can't set innerHTML on " + tagName + " in this browser";
    }

    html = fixSelect(html, contextualElement);

    var wrappingTags = tagNamesRequiringInnerHTMLFix[tagName.toLowerCase()];

    var startTag = outerHTML.match(new RegExp("<" + tagName + "([^>]*)>", 'i'))[0];
    var endTag = '</' + tagName + '>';

    var wrappedHTML = [startTag, html, endTag];

    var i = wrappingTags.length;
    var wrappedDepth = 1 + i;
    while (i--) {
      wrappedHTML.unshift('<' + wrappingTags[i] + '>');
      wrappedHTML.push('</' + wrappingTags[i] + '>');
    }

    var wrapper = document.createElement('div');
    scriptSafeInnerHTML(wrapper, wrappedHTML.join(''));
    var element = wrapper;
    while (wrappedDepth--) {
      element = element.firstChild;
      while (element && element.nodeType !== 1) {
        element = element.nextSibling;
      }
    }
    while (element && element.tagName !== tagName) {
      element = element.nextSibling;
    }
    return element ? element.childNodes : [];
  }

  var buildDOM;
  if (needsShy) {
    buildDOM = function buildDOM(html, contextualElement, dom) {
      html = fixSelect(html, contextualElement);

      contextualElement = dom.cloneNode(contextualElement, false);
      scriptSafeInnerHTML(contextualElement, html);
      return contextualElement.childNodes;
    };
  } else {
    buildDOM = function buildDOM(html, contextualElement, dom) {
      html = fixSelect(html, contextualElement);

      contextualElement = dom.cloneNode(contextualElement, false);
      contextualElement.innerHTML = html;
      return contextualElement.childNodes;
    };
  }

  function fixSelect(html, contextualElement) {
    if (contextualElement.tagName === 'SELECT') {
      html = "<option></option>" + html;
    }

    return html;
  }

  var buildIESafeDOM;
  if (tagNamesRequiringInnerHTMLFix || movesWhitespace) {
    buildIESafeDOM = function buildIESafeDOM(html, contextualElement, dom) {
      // Make a list of the leading text on script nodes. Include
      // script tags without any whitespace for easier processing later.
      var spacesBefore = [];
      var spacesAfter = [];
      if (typeof html === 'string') {
        html = html.replace(/(\s*)(<script)/g, function (match, spaces, tag) {
          spacesBefore.push(spaces);
          return tag;
        });

        html = html.replace(/(<\/script>)(\s*)/g, function (match, tag, spaces) {
          spacesAfter.push(spaces);
          return tag;
        });
      }

      // Fetch nodes
      var nodes;
      if (tagNamesRequiringInnerHTMLFix[contextualElement.tagName.toLowerCase()]) {
        // buildDOMWithFix uses string wrappers for problematic innerHTML.
        nodes = buildDOMWithFix(html, contextualElement);
      } else {
        nodes = buildDOM(html, contextualElement, dom);
      }

      // Build a list of script tags, the nodes themselves will be
      // mutated as we add test nodes.
      var i, j, node, nodeScriptNodes;
      var scriptNodes = [];
      for (i = 0; i < nodes.length; i++) {
        node = nodes[i];
        if (node.nodeType !== 1) {
          continue;
        }
        if (node.tagName === 'SCRIPT') {
          scriptNodes.push(node);
        } else {
          nodeScriptNodes = node.getElementsByTagName('script');
          for (j = 0; j < nodeScriptNodes.length; j++) {
            scriptNodes.push(nodeScriptNodes[j]);
          }
        }
      }

      // Walk the script tags and put back their leading text nodes.
      var scriptNode, textNode, spaceBefore, spaceAfter;
      for (i = 0; i < scriptNodes.length; i++) {
        scriptNode = scriptNodes[i];
        spaceBefore = spacesBefore[i];
        if (spaceBefore && spaceBefore.length > 0) {
          textNode = dom.document.createTextNode(spaceBefore);
          scriptNode.parentNode.insertBefore(textNode, scriptNode);
        }

        spaceAfter = spacesAfter[i];
        if (spaceAfter && spaceAfter.length > 0) {
          textNode = dom.document.createTextNode(spaceAfter);
          scriptNode.parentNode.insertBefore(textNode, scriptNode.nextSibling);
        }
      }

      return nodes;
    };
  } else {
    buildIESafeDOM = buildDOM;
  }

  var buildHTMLDOM;
  if (needsIntegrationPointFix) {
    exports.buildHTMLDOM = buildHTMLDOM = function buildHTMLDOM(html, contextualElement, dom) {
      if (svgHTMLIntegrationPoints[contextualElement.tagName]) {
        return buildIESafeDOM(html, document.createElement('div'), dom);
      } else {
        return buildIESafeDOM(html, contextualElement, dom);
      }
    };
  } else {
    exports.buildHTMLDOM = buildHTMLDOM = buildIESafeDOM;
  }

  exports.buildHTMLDOM = buildHTMLDOM;
});
enifed('dom-helper/classes', ['exports'], function (exports) {
  'use strict';

  var doc = typeof document === 'undefined' ? false : document;

  // PhantomJS has a broken classList. See https://github.com/ariya/phantomjs/issues/12782
  var canClassList = doc && (function () {
    var d = document.createElement('div');
    if (!d.classList) {
      return false;
    }
    d.classList.add('boo');
    d.classList.add('boo', 'baz');
    return d.className === 'boo baz';
  })();

  function buildClassList(element) {
    var classString = element.getAttribute('class') || '';
    return classString !== '' && classString !== ' ' ? classString.split(' ') : [];
  }

  function intersect(containingArray, valuesArray) {
    var containingIndex = 0;
    var containingLength = containingArray.length;
    var valuesIndex = 0;
    var valuesLength = valuesArray.length;

    var intersection = new Array(valuesLength);

    // TODO: rewrite this loop in an optimal manner
    for (; containingIndex < containingLength; containingIndex++) {
      valuesIndex = 0;
      for (; valuesIndex < valuesLength; valuesIndex++) {
        if (valuesArray[valuesIndex] === containingArray[containingIndex]) {
          intersection[valuesIndex] = containingIndex;
          break;
        }
      }
    }

    return intersection;
  }

  function addClassesViaAttribute(element, classNames) {
    var existingClasses = buildClassList(element);

    var indexes = intersect(existingClasses, classNames);
    var didChange = false;

    for (var i = 0, l = classNames.length; i < l; i++) {
      if (indexes[i] === undefined) {
        didChange = true;
        existingClasses.push(classNames[i]);
      }
    }

    if (didChange) {
      element.setAttribute('class', existingClasses.length > 0 ? existingClasses.join(' ') : '');
    }
  }

  function removeClassesViaAttribute(element, classNames) {
    var existingClasses = buildClassList(element);

    var indexes = intersect(classNames, existingClasses);
    var didChange = false;
    var newClasses = [];

    for (var i = 0, l = existingClasses.length; i < l; i++) {
      if (indexes[i] === undefined) {
        newClasses.push(existingClasses[i]);
      } else {
        didChange = true;
      }
    }

    if (didChange) {
      element.setAttribute('class', newClasses.length > 0 ? newClasses.join(' ') : '');
    }
  }

  var addClasses, removeClasses;
  if (canClassList) {
    exports.addClasses = addClasses = function addClasses(element, classNames) {
      if (element.classList) {
        if (classNames.length === 1) {
          element.classList.add(classNames[0]);
        } else if (classNames.length === 2) {
          element.classList.add(classNames[0], classNames[1]);
        } else {
          element.classList.add.apply(element.classList, classNames);
        }
      } else {
        addClassesViaAttribute(element, classNames);
      }
    };
    exports.removeClasses = removeClasses = function removeClasses(element, classNames) {
      if (element.classList) {
        if (classNames.length === 1) {
          element.classList.remove(classNames[0]);
        } else if (classNames.length === 2) {
          element.classList.remove(classNames[0], classNames[1]);
        } else {
          element.classList.remove.apply(element.classList, classNames);
        }
      } else {
        removeClassesViaAttribute(element, classNames);
      }
    };
  } else {
    exports.addClasses = addClasses = addClassesViaAttribute;
    exports.removeClasses = removeClasses = removeClassesViaAttribute;
  }

  exports.addClasses = addClasses;
  exports.removeClasses = removeClasses;
});
enifed('dom-helper/prop', ['exports'], function (exports) {
  'use strict';

  exports.isAttrRemovalValue = isAttrRemovalValue;
  exports.normalizeProperty = normalizeProperty;

  function isAttrRemovalValue(value) {
    return value === null || value === undefined;
  }

  /*
   *
   * @method normalizeProperty
   * @param element {HTMLElement}
   * @param slotName {String}
   * @returns {Object} { name, type }
   */

  function normalizeProperty(element, slotName) {
    var type, normalized;

    if (slotName in element) {
      normalized = slotName;
      type = 'prop';
    } else {
      var lower = slotName.toLowerCase();
      if (lower in element) {
        type = 'prop';
        normalized = lower;
      } else {
        type = 'attr';
        normalized = slotName;
      }
    }

    if (type === 'prop' && (normalized.toLowerCase() === 'style' || preferAttr(element.tagName, normalized))) {
      type = 'attr';
    }

    return { normalized: normalized, type: type };
  }

  // properties that MUST be set as attributes, due to:
  // * browser bug
  // * strange spec outlier
  var ATTR_OVERRIDES = {

    // phantomjs < 2.0 lets you set it as a prop but won't reflect it
    // back to the attribute. button.getAttribute('type') === null
    BUTTON: { type: true, form: true },

    INPUT: {
      // TODO: remove when IE8 is droped
      // Some versions of IE (IE8) throw an exception when setting
      // `input.list = 'somestring'`:
      // https://github.com/emberjs/ember.js/issues/10908
      // https://github.com/emberjs/ember.js/issues/11364
      list: true,
      // Some version of IE (like IE9) actually throw an exception
      // if you set input.type = 'something-unknown'
      type: true,
      form: true,
      // Chrome 46.0.2464.0: 'autocorrect' in document.createElement('input') === false
      // Safari 8.0.7: 'autocorrect' in document.createElement('input') === false
      // Mobile Safari (iOS 8.4 simulator): 'autocorrect' in document.createElement('input') === true
      autocorrect: true
    },

    // element.form is actually a legitimate readOnly property, that is to be
    // mutated, but must be mutated by setAttribute...
    SELECT: { form: true },
    OPTION: { form: true },
    TEXTAREA: { form: true },
    LABEL: { form: true },
    FIELDSET: { form: true },
    LEGEND: { form: true },
    OBJECT: { form: true }
  };

  function preferAttr(tagName, propName) {
    var tag = ATTR_OVERRIDES[tagName.toUpperCase()];
    return tag && tag[propName.toLowerCase()] || false;
  }
});
enifed('ember-application/index', ['exports', 'ember-metal/core', 'ember-metal/features', 'ember-runtime/system/lazy_load', 'ember-application/system/resolver', 'ember-application/system/application', 'ember-application/system/application-instance', 'ember-application/system/engine', 'ember-application/system/engine-instance'], function (exports, _emberMetalCore, _emberMetalFeatures, _emberRuntimeSystemLazy_load, _emberApplicationSystemResolver, _emberApplicationSystemApplication, _emberApplicationSystemApplicationInstance, _emberApplicationSystemEngine, _emberApplicationSystemEngineInstance) {
  'use strict';

  _emberMetalCore.default.Application = _emberApplicationSystemApplication.default;
  _emberMetalCore.default.Resolver = _emberApplicationSystemResolver.Resolver;
  _emberMetalCore.default.DefaultResolver = _emberApplicationSystemResolver.default;

  _emberRuntimeSystemLazy_load.runLoadHooks('Ember.Application', _emberApplicationSystemApplication.default);
});

/**
@module ember
@submodule ember-application
*/

// Expose `EngineInstance` and `ApplicationInstance` for easy overriding.
// Reanalyze whether to continue exposing these after feature flag is removed.
enifed('ember-application/system/application-instance', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/symbol', 'ember-metal/run_loop', 'ember-metal/computed', 'ember-runtime/mixins/registry_proxy', 'ember-metal/assign', 'ember-metal/environment', 'ember-runtime/ext/rsvp', 'ember-views/system/jquery', 'ember-application/system/engine-instance'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalSymbol, _emberMetalRun_loop, _emberMetalComputed, _emberRuntimeMixinsRegistry_proxy, _emberMetalAssign, _emberMetalEnvironment, _emberRuntimeExtRsvp, _emberViewsSystemJquery, _emberApplicationSystemEngineInstance) {
  /**
  @module ember
  @submodule ember-application
  */

  'use strict';

  var INTERNAL_BOOT_OPTIONS = _emberMetalSymbol.default('INTERNAL_BOOT_OPTIONS');

  exports.INTERNAL_BOOT_OPTIONS = INTERNAL_BOOT_OPTIONS;
  var BootOptions = undefined;

  /**
    The `ApplicationInstance` encapsulates all of the stateful aspects of a
    running `Application`.

    At a high-level, we break application boot into two distinct phases:

    * Definition time, where all of the classes, templates, and other
      dependencies are loaded (typically in the browser).
    * Run time, where we begin executing the application once everything
      has loaded.

    Definition time can be expensive and only needs to happen once since it is
    an idempotent operation. For example, between test runs and FastBoot
    requests, the application stays the same. It is only the state that we want
    to reset.

    That state is what the `ApplicationInstance` manages: it is responsible for
    creating the container that contains all application state, and disposing of
    it once the particular test run or FastBoot request has finished.

    @public
    @class Ember.ApplicationInstance
    @extends Ember.EngineInstance
  */

  var ApplicationInstance = _emberApplicationSystemEngineInstance.default.extend({
    /**
      The `Application` for which this is an instance.
       @property {Ember.Application} application
      @private
    */
    application: 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.
       @private
      @property {Object} customEvents
    */
    customEvents: null,

    /**
      The root DOM element of the Application as an element or a
      [jQuery-compatible selector
      string](http://api.jquery.com/category/selectors/).
       @private
      @property {String|DOMElement} rootElement
    */
    rootElement: null,

    init: function () {
      this._super.apply(this, arguments);

      // Register this instance in the per-instance registry.
      //
      // Why do we need to register the instance in the first place?
      // Because we need a good way for the root route (a.k.a ApplicationRoute)
      // to notify us when it has created the root-most view. That view is then
      // appended to the rootElement, in the case of apps, to the fixture harness
      // in tests, or rendered to a string in the case of FastBoot.
      this.register('-application-instance:main', this, { instantiate: false });

      this._booted = false;
    },

    /**
      Initialize the `Ember.ApplicationInstance` and return a promise that resolves
      with the instance itself when the boot process is complete.
       The primary task here is to run any registered instance initializers.
       See the documentation on `BootOptions` for the options it takes.
       @private
      @method boot
      @param options
      @return {Promise<Ember.ApplicationInstance,Error>}
    */
    boot: function () {
      var _this = this;

      var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

      if (this._bootPromise) {
        return this._bootPromise;
      }

      this._bootPromise = new _emberRuntimeExtRsvp.default.Promise(function (resolve) {
        return resolve(_this._bootSync(options));
      });

      return this._bootPromise;
    },

    /**
      Unfortunately, a lot of existing code assumes booting an instance is
      synchronous – specifically, a lot of tests assumes the last call to
      `app.advanceReadiness()` or `app.reset()` will result in a new instance
      being fully-booted when the current runloop completes.
       We would like new code (like the `visit` API) to stop making this assumption,
      so we created the asynchronous version above that returns a promise. But until
      we have migrated all the code, we would have to expose this method for use
      *internally* in places where we need to boot an instance synchronously.
       @private
    */
    _bootSync: function (options) {
      if (this._booted) {
        return this;
      }

      options = new BootOptions(options);

      var registry = this.__registry__;

      registry.register('-environment:main', options.toEnvironment(), { instantiate: false });
      registry.injection('view', '_environment', '-environment:main');
      registry.injection('route', '_environment', '-environment:main');

      registry.register('service:-document', options.document, { instantiate: false });

      if (options.isInteractive) {
        registry.injection('view', 'renderer', 'renderer:-dom');
        registry.injection('component', 'renderer', 'renderer:-dom');
      } else {
        registry.injection('view', 'renderer', 'renderer:-inert');
        registry.injection('component', 'renderer', 'renderer:-inert');
      }

      if (options.rootElement) {
        this.rootElement = options.rootElement;
      } else {
        this.rootElement = this.application.rootElement;
      }

      if (options.location) {
        var router = _emberMetalProperty_get.get(this, 'router');
        _emberMetalProperty_set.set(router, 'location', options.location);
      }

      this.application.runInstanceInitializers(this);

      if (options.isInteractive) {
        this.setupEventDispatcher();
      }

      this._booted = true;

      return this;
    },

    router: _emberMetalComputed.computed(function () {
      return this.lookup('router:main');
    }).readOnly(),

    /**
      This hook is called by the root-most Route (a.k.a. the ApplicationRoute)
      when it has finished creating the root View. By default, we simply take the
      view and append it to the `rootElement` specified on the Application.
       In cases like FastBoot and testing, we can override this hook and implement
      custom behavior, such as serializing to a string and sending over an HTTP
      socket rather than appending to DOM.
       @param view {Ember.View} the root-most view
      @private
    */
    didCreateRootView: function (view) {
      view.appendTo(this.rootElement);
    },

    /**
      Tells the router to start routing. The router will ask the location for the
      current URL of the page to determine the initial URL to start routing to.
      To start the app at a specific URL, call `handleURL` instead.
       @private
    */
    startRouting: function () {
      var router = _emberMetalProperty_get.get(this, 'router');
      router.startRouting();
      this._didSetupRouter = true;
    },

    /**
      @private
       Sets up the router, initializing the child router and configuring the
      location before routing begins.
       Because setup should only occur once, multiple calls to `setupRouter`
      beyond the first call have no effect.
    */
    setupRouter: function () {
      if (this._didSetupRouter) {
        return;
      }
      this._didSetupRouter = true;

      var router = _emberMetalProperty_get.get(this, 'router');
      router.setupRouter();
    },

    /**
      Directs the router to route to a particular URL. This is useful in tests,
      for example, to tell the app to start at a particular URL.
       @param url {String} the URL the router should route to
      @private
    */
    handleURL: function (url) {
      var router = _emberMetalProperty_get.get(this, 'router');

      this.setupRouter();
      return router.handleURL(url);
    },

    /**
      @private
    */
    setupEventDispatcher: function () {
      var dispatcher = this.lookup('event_dispatcher:main');
      var applicationCustomEvents = _emberMetalProperty_get.get(this.application, 'customEvents');
      var instanceCustomEvents = _emberMetalProperty_get.get(this, 'customEvents');

      var customEvents = _emberMetalAssign.default({}, applicationCustomEvents, instanceCustomEvents);
      dispatcher.setup(customEvents, this.rootElement);

      return dispatcher;
    },

    /**
      Returns the current URL of the app instance. This is useful when your
      app does not update the browsers URL bar (i.e. it uses the `'none'`
      location adapter).
       @public
      @return {String} the current URL
    */
    getURL: function () {
      var router = _emberMetalProperty_get.get(this, 'router');
      return _emberMetalProperty_get.get(router, 'url');
    },

    // `instance.visit(url)` should eventually replace `instance.handleURL()`;
    // the test helpers can probably be switched to use this implementation too

    /**
      Navigate the instance to a particular URL. This is useful in tests, for
      example, or to tell the app to start at a particular URL. This method
      returns a promise that resolves with the app instance when the transition
      is complete, or rejects if the transion was aborted due to an error.
       @public
      @param url {String} the destination URL
      @return {Promise}
    */
    visit: function (url) {
      var _this2 = this;

      this.setupRouter();

      var router = _emberMetalProperty_get.get(this, 'router');

      var handleResolve = function () {
        // Resolve only after rendering is complete
        return new _emberRuntimeExtRsvp.default.Promise(function (resolve) {
          // TODO: why is this necessary? Shouldn't 'actions' queue be enough?
          // Also, aren't proimses supposed to be async anyway?
          _emberMetalRun_loop.default.next(null, resolve, _this2);
        });
      };

      var handleReject = function (error) {
        if (error.error) {
          throw error.error;
        } else if (error.name === 'TransitionAborted' && router.router.activeTransition) {
          return router.router.activeTransition.then(handleResolve, handleReject);
        } else if (error.name === 'TransitionAborted') {
          throw new Error(error.message);
        } else {
          throw error;
        }
      };

      var location = _emberMetalProperty_get.get(router, 'location');

      // Keeps the location adapter's internal URL in-sync
      location.setURL(url);

      // getURL returns the set url with the rootURL stripped off
      return router.handleURL(location.getURL()).then(handleResolve, handleReject);
    }
  });

  /**
    A list of boot-time configuration options for customizing the behavior of
    an `Ember.ApplicationInstance`.

    This is an interface class that exists purely to document the available
    options; you do not need to construct it manually. Simply pass a regular
    JavaScript object containing the desired options into methods that require
    one of these options object:

    ```javascript
    MyApp.visit("/", { location: "none", rootElement: "#container" });
    ```

    Not all combinations of the supported options are valid. See the documentation
    on `Ember.Application#visit` for the supported configurations.

    Internal, experimental or otherwise unstable flags are marked as private.

    @class BootOptions
    @namespace Ember.ApplicationInstance
    @public
  */
  BootOptions = function BootOptions() {
    var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

    /**
      Provide a specific instance of jQuery. This is useful in conjunction with
      the `document` option, as it allows you to use a copy of `jQuery` that is
      appropriately bound to the foreign `document` (e.g. a jsdom).
       This is highly experimental and support very incomplete at the moment.
       @property jQuery
      @type Object
      @default auto-detected
      @private
    */
    this.jQuery = _emberViewsSystemJquery.default; // This default is overridable below

    /**
      Interactive mode: whether we need to set up event delegation and invoke
      lifecycle callbacks on Components.
       @property isInteractive
      @type boolean
      @default auto-detected
      @private
    */
    this.isInteractive = _emberMetalEnvironment.default.hasDOM; // This default is overridable below

    /**
      Run in a full browser environment.
       When this flag is set to `false`, it will disable most browser-specific
      and interactive features. Specifically:
       * It does not use `jQuery` to append the root view; the `rootElement`
        (either specified as a subsequent option or on the application itself)
        must already be an `Element` in the given `document` (as opposed to a
        string selector).
       * It does not set up an `EventDispatcher`.
       * It does not run any `Component` lifecycle hooks (such as `didInsertElement`).
       * It sets the `location` option to `"none"`. (If you would like to use
        the location adapter specified in the app's router instead, you can also
        specify `{ location: null }` to specifically opt-out.)
       @property isBrowser
      @type boolean
      @default auto-detected
      @public
    */
    if (options.isBrowser !== undefined) {
      this.isBrowser = !!options.isBrowser;
    } else {
      this.isBrowser = _emberMetalEnvironment.default.hasDOM;
    }

    if (!this.isBrowser) {
      this.jQuery = null;
      this.isInteractive = false;
      this.location = 'none';
    }

    /**
      Disable rendering completely.
       When this flag is set to `true`, it will disable the entire rendering
      pipeline. Essentially, this puts the app into "routing-only" mode. No
      templates will be rendered, and no Components will be created.
       @property shouldRender
      @type boolean
      @default true
      @public
    */
    if (options.shouldRender !== undefined) {
      this.shouldRender = !!options.shouldRender;
    } else {
      this.shouldRender = true;
    }

    if (!this.shouldRender) {
      this.jQuery = null;
      this.isInteractive = false;
    }

    /**
      If present, render into the given `Document` object instead of the
      global `window.document` object.
       In practice, this is only useful in non-browser environment or in
      non-interactive mode, because Ember's `jQuery` dependency is
      implicitly bound to the current document, causing event delegation
      to not work properly when the app is rendered into a foreign
      document object (such as an iframe's `contentDocument`).
       In non-browser mode, this could be a "`Document`-like" object as
      Ember only interact with a small subset of the DOM API in non-
      interactive mode. While the exact requirements have not yet been
      formalized, the `SimpleDOM` library's implementation is known to
      work.
       @property document
      @type Document
      @default the global `document` object
      @public
    */
    if (options.document) {
      this.document = options.document;
    } else {
      this.document = typeof document !== 'undefined' ? document : null;
    }

    /**
      If present, overrides the application's `rootElement` property on
      the instance. This is useful for testing environment, where you
      might want to append the root view to a fixture area.
       In non-browser mode, because Ember does not have access to jQuery,
      this options must be specified as a DOM `Element` object instead of
      a selector string.
       See the documentation on `Ember.Applications`'s `rootElement` for
      details.
       @property rootElement
      @type String|Element
      @default null
      @public
     */
    if (options.rootElement) {
      this.rootElement = options.rootElement;
    }

    // Set these options last to give the user a chance to override the
    // defaults from the "combo" options like `isBrowser` (although in
    // practice, the resulting combination is probably invalid)

    /**
      If present, overrides the router's `location` property with this
      value. This is useful for environments where trying to modify the
      URL would be inappropriate.
       @property location
      @type string
      @default null
      @public
    */
    if (options.location !== undefined) {
      this.location = options.location;
    }

    if (options.jQuery !== undefined) {
      this.jQuery = options.jQuery;
    }

    if (options.isInteractive !== undefined) {
      this.isInteractive = !!options.isInteractive;
    }
  };

  BootOptions.prototype.toEnvironment = function () {
    var env = _emberMetalAssign.default({}, _emberMetalEnvironment.default);
    // For compatibility with existing code
    env.hasDOM = this.isBrowser;
    env.options = this;
    return env;
  };

  Object.defineProperty(ApplicationInstance.prototype, 'container', {
    configurable: true,
    enumerable: false,
    get: function () {
      var instance = this;
      return {
        lookup: function () {
          _emberMetalDebug.deprecate('Using `ApplicationInstance.container.lookup` is deprecated. Please use `ApplicationInstance.lookup` instead.', false, {
            id: 'ember-application.app-instance-container',
            until: '3.0.0',
            url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-applicationinstance-container'
          });
          return instance.lookup.apply(instance, arguments);
        }
      };
    }
  });

  Object.defineProperty(ApplicationInstance.prototype, 'registry', {
    configurable: true,
    enumerable: false,
    get: function () {
      return _emberRuntimeMixinsRegistry_proxy.buildFakeRegistryWithDeprecations(this, 'ApplicationInstance');
    }
  });

  exports.default = ApplicationInstance;
});
enifed('ember-application/system/application', ['exports', 'ember-metal', 'ember-metal/debug', 'ember-metal/property_get', 'ember-runtime/system/lazy_load', 'ember-metal/run_loop', 'ember-runtime/controllers/controller', 'ember-htmlbars/system/dom-helper', 'ember-metal-views', 'ember-htmlbars/templates/top-level-view', 'ember-routing-views/views/outlet', 'ember-views/views/view', '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-application/system/application-instance', 'ember-views/views/text_field', 'ember-views/views/text_area', 'ember-views/views/checkbox', 'ember-routing-views/components/link-to', 'ember-routing/services/routing', 'ember-extension-support/container_debug_adapter', 'ember-runtime/mixins/registry_proxy', 'container/registry', 'ember-metal/environment', 'ember-runtime/ext/rsvp', 'ember-application/system/engine', 'require'], function (exports, _emberMetal, _emberMetalDebug, _emberMetalProperty_get, _emberRuntimeSystemLazy_load, _emberMetalRun_loop, _emberRuntimeControllersController, _emberHtmlbarsSystemDomHelper, _emberMetalViews, _emberHtmlbarsTemplatesTopLevelView, _emberRoutingViewsViewsOutlet, _emberViewsViewsView, _emberViewsSystemEvent_dispatcher, _emberViewsSystemJquery, _emberRoutingSystemRoute, _emberRoutingSystemRouter, _emberRoutingLocationHash_location, _emberRoutingLocationHistory_location, _emberRoutingLocationAuto_location, _emberRoutingLocationNone_location, _emberRoutingSystemCache, _emberApplicationSystemApplicationInstance, _emberViewsViewsText_field, _emberViewsViewsText_area, _emberViewsViewsCheckbox, _emberRoutingViewsComponentsLinkTo, _emberRoutingServicesRouting, _emberExtensionSupportContainer_debug_adapter, _emberRuntimeMixinsRegistry_proxy, _containerRegistry, _emberMetalEnvironment, _emberRuntimeExtRsvp, _emberApplicationSystemEngine, _require2) {
  /**
  @module ember
  @submodule ember-application
  */
  'use strict';

  exports._resetLegacyAddonWarnings = _resetLegacyAddonWarnings;

  var _templateObject = _taggedTemplateLiteralLoose(['-bucket-cache:main'], ['-bucket-cache:main']),
      _templateObject2 = _taggedTemplateLiteralLoose(['template:components/-default'], ['template:components/-default']);

  function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; }

  var librariesRegistered = false;

  var warnedAboutLegacyViewAddon = false;
  var warnedAboutLegacyControllerAddon = false;

  // For testing

  function _resetLegacyAddonWarnings() {
    warnedAboutLegacyViewAddon = false;
    warnedAboutLegacyControllerAddon = false;
  }

  /**
    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
    var App = Ember.Application.create({
      customEvents: {
        // add support for the paste event
        paste: 'paste'
      }
    });
    ```

    To prevent Ember from setting up a listener for a default event,
    specify the event name with a `null` value in the `customEvents`
    property:

    ```javascript
    var App = Ember.Application.create({
      customEvents: {
        // prevent listeners for mouseenter/mouseleave events
        mouseenter: null,
        mouseleave: null
      }
    });
    ```

    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
    var 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 events Ember components use, see
    [components/handling-events](https://guides.emberjs.com/v2.6.0/components/handling-events/#toc_event-names).

    ### Initializers

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

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

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

    Initializers provide an opportunity to access the internal registry, 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
    var 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.Engine
    @uses RegistryProxyMixin
    @public
  */

  var Application = _emberApplicationSystemEngine.default.extend({
    _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'
      @public
    */
    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
      @public
    */
    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. Setting an event to
      a value of `null` will prevent a default event listener from being
      added for that event.
       To add new events to be listened to:
       ```javascript
      var App = Ember.Application.create({
        customEvents: {
          // add support for the paste event
          paste: 'paste'
        }
      });
      ```
       To prevent default events from being listened to:
       ```javascript
      var App = Ember.Application.create({
        customEvents: {
          // remove support for mouseenter / mouseleave events
          mouseenter: null,
          mouseleave: null
        }
      });
      ```
      @property customEvents
      @type Object
      @default null
      @public
    */
    customEvents: null,

    /**
      Whether the application should automatically start routing and render
      templates to the `rootElement` on DOM ready. While default by true,
      other environments such as FastBoot or a testing harness can set this
      property to `false` and control the precise timing and behavior of the boot
      process.
       @property autoboot
      @type Boolean
      @default true
      @private
    */
    autoboot: true,

    /**
      Whether the application should be configured for the legacy "globals mode".
      Under this mode, the Application object serves as a global namespace for all
      classes.
       ```javascript
      var App = Ember.Application.create({
        ...
      });
       App.Router.reopen({
        location: 'none'
      });
       App.Router.map({
        ...
      });
       App.MyComponent = Ember.Component.extend({
        ...
      });
      ```
       This flag also exposes other internal APIs that assumes the existence of
      a special "default instance", like `App.__container__.lookup(...)`.
       This option is currently not configurable, its value is derived from
      the `autoboot` flag – disabling `autoboot` also implies opting-out of
      globals mode support, although they are ultimately orthogonal concerns.
       Some of the global modes features are already deprecated in 1.x. The
      existence of this flag is to untangle the globals mode code paths from
      the autoboot code paths, so that these legacy features can be reviewed
      for deprecation/removal separately.
       Forcing the (autoboot=true, _globalsMode=false) here and running the tests
      would reveal all the places where we are still relying on these legacy
      behavior internally (mostly just tests).
       @property _globalsMode
      @type Boolean
      @default true
      @private
    */
    _globalsMode: true,

    init: function (options) {
      this._super.apply(this, arguments);

      if (!this.$) {
        this.$ = _emberViewsSystemJquery.default;
      }

      registerLibraries();
      logLibraryVersions();

      // Start off the number of deferrals at 1. This will be decremented by
      // the Application's own `boot` method.
      this._readinessDeferrals = 1;
      this._booted = false;

      this.autoboot = this._globalsMode = !!this.autoboot;

      if (this._globalsMode) {
        this._prepareForGlobalsMode();
      }

      if (this.autoboot) {
        this.waitForDOMReady();
      }
    },

    /**
      Create an ApplicationInstance for this application.
       @private
      @method buildInstance
      @return {Ember.ApplicationInstance} the application instance
    */
    buildInstance: function () {
      var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

      options.base = this;
      options.application = this;
      return _emberApplicationSystemApplicationInstance.default.create(options);
    },

    /**
      Enable the legacy globals mode by allowing this application to act
      as a global namespace. See the docs on the `_globalsMode` property
      for details.
       Most of these features are already deprecated in 1.x, so we can
      stop using them internally and try to remove them.
       @private
      @method _prepareForGlobalsMode
    */
    _prepareForGlobalsMode: function () {
      // Create subclass of Ember.Router for this Application instance.
      // This is to ensure that someone reopening `App.Router` does not
      // tamper with the default `Ember.Router`.
      this.Router = (this.Router || _emberRoutingSystemRouter.default).extend();

      this._buildDeprecatedInstance();
    },

    /*
      Build the deprecated instance for legacy globals mode support.
      Called when creating and resetting the application.
       This is orthogonal to autoboot: the deprecated instance needs to
      be created at Application construction (not boot) time to expose
      App.__container__ and the global Ember.View.views registry. If
      autoboot sees that this instance exists, it will continue booting
      it to avoid doing unncessary work (as opposed to building a new
      instance at boot time), but they are otherwise unrelated.
       @private
      @method _buildDeprecatedInstance
    */
    _buildDeprecatedInstance: function () {
      // Build a default instance
      var instance = this.buildInstance();

      // Legacy support for App.__container__ and other global methods
      // on App that rely on a single, default instance.
      this.__deprecatedInstance__ = instance;
      this.__container__ = instance.__container__;

      // For the default instance only, set the view registry to the global
      // Ember.View.views hash for backwards-compatibility.
      _emberViewsViewsView.default.views = instance.lookup('-view-registry:main');
    },

    /**
      Automatically kick-off the boot process for the application once the
      DOM has become ready.
       The initialization itself is scheduled on the actions queue which
      ensures that code-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 waitForDOMReady
    */
    waitForDOMReady: function () {
      if (!this.$ || this.$.isReady) {
        _emberMetalRun_loop.default.schedule('actions', this, 'domReady');
      } else {
        this.$().ready(_emberMetalRun_loop.default.bind(this, 'domReady'));
      }
    },

    /**
      This is the autoboot flow:
       1. Boot the app by calling `this.boot()`
      2. Create an instance (or use the `__deprecatedInstance__` in globals mode)
      3. Boot the instance by calling `instance.boot()`
      4. Invoke the `App.ready()` callback
      5. Kick-off routing on the instance
       Ideally, this is all we would need to do:
       ```javascript
      _autoBoot() {
        this.boot().then(() => {
          let instance = (this._globalsMode) ? this.__deprecatedInstance__ : this.buildInstance();
          return instance.boot();
        }).then((instance) => {
          App.ready();
          instance.startRouting();
        });
      }
      ```
       Unfortunately, we cannot actually write this because we need to participate
      in the "synchronous" boot process. While the code above would work fine on
      the initial boot (i.e. DOM ready), when `App.reset()` is called, we need to
      boot a new instance synchronously (see the documentation on `_bootSync()`
      for details).
       Because of this restriction, the actual logic of this method is located
      inside `didBecomeReady()`.
       @private
      @method domReady
    */
    domReady: function () {
      if (this.isDestroyed) {
        return;
      }

      this._bootSync();

      // Continues to `didBecomeReady`
    },

    /**
      Use this to defer readiness until some condition is true.
       Example:
       ```javascript
      var App = Ember.Application.create();
       App.deferReadiness();
       // Ember.$ is a reference to the jQuery object/function
      Ember.$.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
      @public
    */
    deferReadiness: function () {
      _emberMetalDebug.assert('You must call deferReadiness on an instance of Ember.Application', this instanceof Application);
      _emberMetalDebug.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}
      @public
    */
    advanceReadiness: function () {
      _emberMetalDebug.assert('You must call advanceReadiness on an instance of Ember.Application', this instanceof Application);
      this._readinessDeferrals--;

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

    /**
      Initialize the application and return a promise that resolves with the `Ember.Application`
      object when the boot process is complete.
       Run any application 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.
       By default, this method is called automatically on "DOM ready"; however, if autoboot
      is disabled, this is automatically called when the first application instance is
      created via `visit`.
       @private
      @method boot
      @return {Promise<Ember.Application,Error>}
    */
    boot: function () {
      if (this._bootPromise) {
        return this._bootPromise;
      }

      try {
        this._bootSync();
      } catch (_) {
        // Ignore th error: in the asynchronous boot path, the error is already reflected
        // in the promise rejection
      }

      return this._bootPromise;
    },

    /**
      Unfortunately, a lot of existing code assumes the booting process is
      "synchronous". Specifically, a lot of tests assumes the last call to
      `app.advanceReadiness()` or `app.reset()` will result in the app being
      fully-booted when the current runloop completes.
       We would like new code (like the `visit` API) to stop making this assumption,
      so we created the asynchronous version above that returns a promise. But until
      we have migrated all the code, we would have to expose this method for use
      *internally* in places where we need to boot an app "synchronously".
       @private
    */
    _bootSync: function () {
      if (this._booted) {
        return;
      }

      if (_emberMetal.default.ENV._ENABLE_LEGACY_VIEW_SUPPORT && !warnedAboutLegacyViewAddon) {
        _emberMetalDebug.deprecate('Support for the `ember-legacy-views` addon will end soon, please remove it from your application.', false, { id: 'ember-legacy-views', until: '2.6.0', url: 'http://emberjs.com/deprecations/v1.x/#toc_ember-view' });

        warnedAboutLegacyViewAddon = true;
      }

      if (_emberMetal.default.ENV._ENABLE_LEGACY_CONTROLLER_SUPPORT && !warnedAboutLegacyControllerAddon) {
        _emberMetalDebug.warn('Support for the `ember-legacy-controllers` has been removed, please remove it from your application.', false, { id: 'ember-legacy-controllers', url: 'http://emberjs.com/deprecations/v1.x/#toc_objectcontroller' });

        warnedAboutLegacyControllerAddon = true;
      }

      // Even though this returns synchronously, we still need to make sure the
      // boot promise exists for book-keeping purposes: if anything went wrong in
      // the boot process, we need to store the error as a rejection on the boot
      // promise so that a future caller of `boot()` can tell what failed.
      var defer = this._bootResolver = new _emberRuntimeExtRsvp.default.defer();
      this._bootPromise = defer.promise;

      try {
        this.runInitializers();
        _emberRuntimeSystemLazy_load.runLoadHooks('application', this);
        this.advanceReadiness();
        // Continues to `didBecomeReady`
      } catch (error) {
        // For the asynchronous boot path
        defer.reject(error);

        // For the synchronous boot path
        throw error;
      }
    },

    /**
      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('second 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
      @public
    */
    reset: function () {
      _emberMetalDebug.assert('Calling reset() on instances of `Ember.Application` is not\n            supported when globals mode is disabled; call `visit()` to\n            create new `Ember.ApplicationInstance`s and dispose them\n            via their `destroy()` method instead.', this._globalsMode && this.autoboot);

      var instance = this.__deprecatedInstance__;

      this._readinessDeferrals = 1;
      this._bootPromise = null;
      this._bootResolver = null;
      this._booted = false;

      function handleReset() {
        _emberMetalRun_loop.default(instance, 'destroy');
        this._buildDeprecatedInstance();
        _emberMetalRun_loop.default.schedule('actions', this, '_bootSync');
      }

      _emberMetalRun_loop.default.join(this, handleReset);
    },

    /**
      @private
      @method didBecomeReady
    */
    didBecomeReady: function () {
      try {
        // TODO: Is this still needed for _globalsMode = false?
        if (!_emberMetal.default.testing) {
          // Eagerly name all classes that are already loaded
          _emberMetal.default.Namespace.processAll();
          _emberMetal.default.BOOTED = true;
        }

        // See documentation on `_autoboot()` for details
        if (this.autoboot) {
          var instance = undefined;

          if (this._globalsMode) {
            // If we already have the __deprecatedInstance__ lying around, boot it to
            // avoid unnecessary work
            instance = this.__deprecatedInstance__;
          } else {
            // Otherwise, build an instance and boot it. This is currently unreachable,
            // because we forced _globalsMode to === autoboot; but having this branch
            // allows us to locally toggle that flag for weeding out legacy globals mode
            // dependencies independently
            instance = this.buildInstance();
          }

          instance._bootSync();

          // TODO: App.ready() is not called when autoboot is disabled, is this correct?
          this.ready();

          instance.startRouting();
        }

        // For the asynchronous boot path
        this._bootResolver.resolve(this);

        // For the synchronous boot path
        this._booted = true;
      } catch (error) {
        // For the asynchronous boot path
        this._bootResolver.reject(error);

        // For the synchronous boot path
        throw error;
      }
    },

    /**
      Called when the Application has become ready, immediately before routing
      begins. The call will be delayed until the DOM has become ready.
       @event ready
      @public
    */
    ready: function () {
      return this;
    },

    // This method must be moved to the application instance object
    willDestroy: function () {
      this._super.apply(this, arguments);
      _emberMetal.default.BOOTED = false;
      this._booted = false;
      this._bootPromise = null;
      this._bootResolver = null;

      if (_emberRuntimeSystemLazy_load._loaded.application === this) {
        _emberRuntimeSystemLazy_load._loaded.application = undefined;
      }

      if (this._globalsMode && this.__deprecatedInstance__) {
        this.__deprecatedInstance__.destroy();
      }
    },

    /**
      Boot a new instance of `Ember.ApplicationInstance` for the current
      application and navigate it to the given `url`. Returns a `Promise` that
      resolves with the instance when the initial routing and rendering is
      complete, or rejects with any error that occured during the boot process.
       When `autoboot` is disabled, calling `visit` would first cause the
      application to boot, which runs the application initializers.
       This method also takes a hash of boot-time configuration options for
      customizing the instance's behavior. See the documentation on
      `Ember.ApplicationInstance.BootOptions` for details.
       `Ember.ApplicationInstance.BootOptions` is an interface class that exists
      purely to document the available options; you do not need to construct it
      manually. Simply pass a regular JavaScript object containing of the
      desired options:
       ```javascript
      MyApp.visit("/", { location: "none", rootElement: "#container" });
      ```
       ### Supported Scenarios
       While the `BootOptions` class exposes a large number of knobs, not all
      combinations of them are valid; certain incompatible combinations might
      result in unexpected behavior.
       For example, booting the instance in the full browser environment
      while specifying a foriegn `document` object (e.g. `{ isBrowser: true,
      document: iframe.contentDocument }`) does not work correctly today,
      largely due to Ember's jQuery dependency.
       Currently, there are three officially supported scenarios/configurations.
      Usages outside of these scenarios are not guaranteed to work, but please
      feel free to file bug reports documenting your experience and any issues
      you encountered to help expand support.
       #### Browser Applications (Manual Boot)
       The setup is largely similar to how Ember works out-of-the-box. Normally,
      Ember will boot a default instance for your Application on "DOM ready".
      However, you can customize this behavior by disabling `autoboot`.
       For example, this allows you to render a miniture demo of your application
      into a specific area on your marketing website:
       ```javascript
      import MyApp from 'my-app';
       $(function() {
        let App = MyApp.create({ autoboot: false });
         let options = {
          // Override the router's location adapter to prevent it from updating
          // the URL in the address bar
          location: 'none',
           // Override the default `rootElement` on the app to render into a
          // specific `div` on the page
          rootElement: '#demo'
        };
         // Start the app at the special demo URL
        App.visit('/demo', options);
      });
      ````
       Or perhaps you might want to boot two instances of your app on the same
      page for a split-screen multiplayer experience:
       ```javascript
      import MyApp from 'my-app';
       $(function() {
        let App = MyApp.create({ autoboot: false });
         let sessionId = MyApp.generateSessionID();
         let player1 = App.visit(`/matches/join?name=Player+1&session=${sessionId}`, { rootElement: '#left', location: 'none' });
        let player2 = App.visit(`/matches/join?name=Player+2&session=${sessionId}`, { rootElement: '#right', location: 'none' });
         Promise.all([player1, player2]).then(() => {
          // Both apps have completed the initial render
          $('#loading').fadeOut();
        });
      });
      ```
       Do note that each app instance maintains their own registry/container, so
      they will run in complete isolation by default.
       #### Server-Side Rendering (also known as FastBoot)
       This setup allows you to run your Ember app in a server environment using
      Node.js and render its content into static HTML for SEO purposes.
       ```javascript
      const HTMLSerializer = new SimpleDOM.HTMLSerializer(SimpleDOM.voidMap);
       function renderURL(url) {
        let dom = new SimpleDOM.Document();
        let rootElement = dom.body;
        let options = { isBrowser: false, document: dom, rootElement: rootElement };
         return MyApp.visit(options).then(instance => {
          try {
            return HTMLSerializer.serialize(rootElement.firstChild);
          } finally {
            instance.destroy();
          }
        });
      }
      ```
       In this scenario, because Ember does not have access to a global `document`
      object in the Node.js environment, you must provide one explicitly. In practice,
      in the non-browser environment, the stand-in `document` object only need to
      implement a limited subset of the full DOM API. The `SimpleDOM` library is known
      to work.
       Since there is no access to jQuery in the non-browser environment, you must also
      specify a DOM `Element` object in the same `document` for the `rootElement` option
      (as opposed to a selector string like `"body"`).
       See the documentation on the `isBrowser`, `document` and `rootElement` properties
      on `Ember.ApplicationInstance.BootOptions` for details.
       #### Server-Side Resource Discovery
       This setup allows you to run the routing layer of your Ember app in a server
      environment using Node.js and completely disable rendering. This allows you
      to simulate and discover the resources (i.e. AJAX requests) needed to fufill
      a given request and eagerly "push" these resources to the client.
       ```app/initializers/network-service.js
      import BrowserNetworkService from 'app/services/network/browser';
      import NodeNetworkService from 'app/services/network/node';
       // Inject a (hypothetical) service for abstracting all AJAX calls and use
      // the appropiate implementaion on the client/server. This also allows the
      // server to log all the AJAX calls made during a particular request and use
      // that for resource-discovery purpose.
       export function initialize(application) {
        if (window) { // browser
          application.register('service:network', BrowserNetworkService);
        } else { // node
          application.register('service:network', NodeNetworkService);
        }
         application.inject('route', 'network', 'service:network');
      };
       export default {
        name: 'network-service',
        initialize: initialize
      };
      ```
       ```app/routes/post.js
      import Ember from 'ember';
       // An example of how the (hypothetical) service is used in routes.
       export default Ember.Route.extend({
        model(params) {
          return this.network.fetch(`/api/posts/${params.post_id}.json`);
        },
         afterModel(post) {
          if (post.isExternalContent) {
            return this.network.fetch(`/api/external/?url=${post.externalURL}`);
          } else {
            return post;
          }
        }
      });
      ```
       ```javascript
      // Finally, put all the pieces together
       function discoverResourcesFor(url) {
        return MyApp.visit(url, { isBrowser: false, shouldRender: false }).then(instance => {
          let networkService = instance.lookup('service:network');
          return networkService.requests; // => { "/api/posts/123.json": "..." }
        });
      }
      ```
       @public
      @method visit
      @param url {String} The initial URL to navigate to
      @param options {Ember.ApplicationInstance.BootOptions}
      @return {Promise<Ember.ApplicationInstance, Error>}
    */
    visit: function (url, options) {
      var _this = this;

      return this.boot().then(function () {
        return _this.buildInstance().boot(options).then(function (instance) {
          return instance.visit(url);
        });
      });
    }
  });

  Object.defineProperty(Application.prototype, 'registry', {
    configurable: true,
    enumerable: false,
    get: function () {
      return _emberRuntimeMixinsRegistry_proxy.buildFakeRegistryWithDeprecations(this, 'Application');
    }
  });

  Application.reopenClass({
    /**
      This creates a registry with the default Ember naming conventions.
       It also configures the registry:
       * 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 buildRegistry
      @static
      @param {Ember.Application} namespace the application for which to
        build the registry
      @return {Ember.Registry} the built registry
      @public
    */
    buildRegistry: function (application) {
      var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

      var registry = this._super.apply(this, arguments);
      registry.register('application:main', application, { instantiate: false });

      if (options[_emberApplicationSystemEngine.GLIMMER]) {
        glimmerSetupRegistry(registry);
      } else {
        htmlbarsSetupRegistry(registry);
      }

      return registry;
    }
  });

  function commonSetupRegistry(registry) {
    registry.optionsForType('component', { singleton: false });
    registry.optionsForType('view', { singleton: false });
    registry.injection('renderer', 'dom', 'service:-dom-helper');

    registry.register('controller:basic', _emberRuntimeControllersController.default, { instantiate: false });

    registry.injection('service:-dom-helper', 'document', 'service:-document');

    registry.register('-view-registry:main', { create: function () {
        return {};
      } });

    registry.injection('view', '_viewRegistry', '-view-registry:main');

    registry.injection('route', '_topLevelViewTemplate', 'template:-outlet');

    registry.register('route:basic', _emberRoutingSystemRoute.default);
    registry.register('event_dispatcher:main', _emberViewsSystemEvent_dispatcher.default);

    registry.injection('router:main', 'namespace', 'application:main');
    registry.injection('view:-outlet', 'namespace', 'application:main');

    registry.register('location:auto', _emberRoutingLocationAuto_location.default);
    registry.register('location:hash', _emberRoutingLocationHash_location.default);
    registry.register('location:history', _emberRoutingLocationHistory_location.default);
    registry.register('location:none', _emberRoutingLocationNone_location.default);

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

    registry.register(_containerRegistry.privatize(_templateObject), _emberRoutingSystemCache.default);
    registry.injection('router', '_bucketCache', _containerRegistry.privatize(_templateObject));
    registry.injection('route', '_bucketCache', _containerRegistry.privatize(_templateObject));
    registry.injection('controller', '_bucketCache', _containerRegistry.privatize(_templateObject));

    registry.injection('route', 'router', 'router:main');

    registry.register('component:-text-field', _emberViewsViewsText_field.default);
    registry.register('component:-text-area', _emberViewsViewsText_area.default);
    registry.register('component:-checkbox', _emberViewsViewsCheckbox.default);
    registry.register('component:link-to', _emberRoutingViewsComponentsLinkTo.default);

    // Register the routing service...
    registry.register('service:-routing', _emberRoutingServicesRouting.default);
    // Then inject the app router into it
    registry.injection('service:-routing', 'router', 'router:main');

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

    registry.register('container-debug-adapter:main', _emberExtensionSupportContainer_debug_adapter.default);
  }

  function glimmerSetupRegistry(registry) {
    commonSetupRegistry(registry);

    var Environment = _require2.default('ember-glimmer/environment').default;
    registry.register('service:-glimmer-environment', Environment);
    registry.injection('service:-glimmer-environment', 'dom', 'service:-dom-helper');
    registry.injection('renderer', 'env', 'service:-glimmer-environment');

    var OutletView = _require2.default('ember-glimmer/ember-routing-view').OutletView;
    registry.register('view:-outlet', OutletView);

    var _require = _require2.default('ember-glimmer/ember-metal-views');

    var InteractiveRenderer = _require.InteractiveRenderer;
    var InertRenderer = _require.InertRenderer;

    registry.register('renderer:-dom', InteractiveRenderer);
    registry.register('renderer:-inert', InertRenderer);

    var DOMHelper = _require2.default('ember-glimmer/dom').default;

    registry.register('service:-dom-helper', {
      create: function (_ref) {
        var document = _ref.document;
        return new DOMHelper(document);
      }
    });

    var glimmerOutletTemplate = _require2.default('ember-glimmer/templates/outlet').default;
    var glimmerComponentTemplate = _require2.default('ember-glimmer/templates/component').default;
    registry.register(_containerRegistry.privatize(_templateObject2), glimmerComponentTemplate);
    registry.register('template:-outlet', glimmerOutletTemplate);
    registry.injection('view:-outlet', 'template', 'template:-outlet');
    registry.injection('template', 'env', 'service:-glimmer-environment');

    registry.optionsForType('helper', { instantiate: false });
  }

  function htmlbarsSetupRegistry(registry) {
    commonSetupRegistry(registry);

    registry.optionsForType('template', { instantiate: false });
    registry.register('view:-outlet', _emberRoutingViewsViewsOutlet.OutletView);

    var InteractiveRenderer = _emberMetalViews.InteractiveRenderer;
    var InertRenderer = _emberMetalViews.InertRenderer;

    registry.register('renderer:-dom', InteractiveRenderer);
    registry.register('renderer:-inert', InertRenderer);

    registry.register('service:-dom-helper', {
      create: function (_ref2) {
        var document = _ref2.document;
        return new _emberHtmlbarsSystemDomHelper.default(document);
      }
    });

    registry.register('template:-outlet', _emberHtmlbarsTemplatesTopLevelView.default);
    registry.register('view:toplevel', _emberViewsViewsView.default.extend());
  }

  function registerLibraries() {
    if (!librariesRegistered) {
      librariesRegistered = true;

      if (_emberMetalEnvironment.default.hasDOM) {
        _emberMetal.default.libraries.registerCoreLibrary('jQuery', _emberViewsSystemJquery.default().jquery);
      }
    }
  }

  function logLibraryVersions() {
    if (_emberMetal.default.LOG_VERSION) {
      // we only need to see this once per Application#init
      _emberMetal.default.LOG_VERSION = false;
      var libs = _emberMetal.default.libraries._registry;

      var nameLengths = libs.map(function (item) {
        return _emberMetalProperty_get.get(item, 'name.length');
      });

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

      _emberMetalDebug.debug('-------------------------------');
      for (var i = 0, l = libs.length; i < l; i++) {
        var lib = libs[i];
        var spaces = new Array(maxNameLength - lib.name.length + 1).join(' ');
        _emberMetalDebug.debug([lib.name, spaces, ' : ', lib.version].join(''));
      }
      _emberMetalDebug.debug('-------------------------------');
    }
  }

  exports.default = Application;
});
// Ember.libraries, LOG_VERSION, Namespace, BOOTED
enifed('ember-application/system/engine-instance', ['exports', 'ember-runtime/system/object', 'container/registry', 'ember-runtime/mixins/container_proxy', 'ember-runtime/mixins/registry_proxy', 'ember-metal/run_loop'], function (exports, _emberRuntimeSystemObject, _containerRegistry, _emberRuntimeMixinsContainer_proxy, _emberRuntimeMixinsRegistry_proxy, _emberMetalRun_loop) {
  /**
  @module ember
  @submodule ember-application
  */

  'use strict';

  /**
    The `EngineInstance` encapsulates all of the stateful aspects of a
    running `Engine`.

    @public
    @class Ember.EngineInstance
    @extends Ember.Object
    @uses RegistryProxyMixin
    @uses ContainerProxyMixin
    @category ember-application-engines
  */

  var EngineInstance = _emberRuntimeSystemObject.default.extend(_emberRuntimeMixinsRegistry_proxy.default, _emberRuntimeMixinsContainer_proxy.default, {
    /**
      The base `Engine` for which this is an instance.
       @property {Ember.Engine} engine
      @private
    */
    base: null,

    init: function () {
      this._super.apply(this, arguments);

      var base = this.base;

      if (!base) {
        base = this.application;
        this.base = base;
      }

      // Create a per-instance registry that will use the application's registry
      // as a fallback for resolving registrations.
      var registry = this.__registry__ = new _containerRegistry.default({
        fallback: base.__registry__
      });

      // Create a per-instance container from the instance's registry
      this.__container__ = registry.container({ owner: this });
    },

    /**
     Unregister a factory.
      Overrides `RegistryProxy#unregister` in order to clear any cached instances
     of the unregistered factory.
      @public
     @method unregister
     @param {String} fullName
     */
    unregister: function (fullName) {
      this.__container__.reset(fullName);
      this._super.apply(this, arguments);
    },

    /**
      @private
    */
    willDestroy: function () {
      this._super.apply(this, arguments);
      _emberMetalRun_loop.default(this.__container__, 'destroy');
    }
  });

  exports.default = EngineInstance;
});
enifed('ember-application/system/engine', ['exports', 'ember-runtime/system/namespace', 'container/registry', 'ember-runtime/mixins/registry_proxy', 'dag-map', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/debug', 'ember-metal/utils', 'ember-metal/empty_object', 'ember-application/system/resolver', 'ember-application/system/engine-instance', 'ember-metal/features', 'ember-metal/symbol'], function (exports, _emberRuntimeSystemNamespace, _containerRegistry, _emberRuntimeMixinsRegistry_proxy, _dagMap, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalDebug, _emberMetalUtils, _emberMetalEmpty_object, _emberApplicationSystemResolver, _emberApplicationSystemEngineInstance, _emberMetalFeatures, _emberMetalSymbol) {
  /**
  @module ember
  @submodule ember-application
  */
  'use strict';

  var GLIMMER = _emberMetalSymbol.default('GLIMMER');

  exports.GLIMMER = GLIMMER;
  function props(obj) {
    var properties = [];

    for (var key in obj) {
      properties.push(key);
    }

    return properties;
  }

  /**
    The `Engine` class contains core functionality for both applications and
    engines.

    Each engine manages a registry that's used for dependency injection and
    exposed through `RegistryProxy`.

    Engines also manage initializers and instance initializers.

    Engines can spawn `EngineInstance` instances via `buildInstance()`.

    @class Engine
    @namespace Ember
    @extends Ember.Namespace
    @uses RegistryProxy
    @category ember-application-engines
    @public
  */
  var Engine = _emberRuntimeSystemNamespace.default.extend(_emberRuntimeMixinsRegistry_proxy.default, {
    init: function () {
      this._super.apply(this, arguments);

      if (this[GLIMMER] === undefined) {
        this[GLIMMER] = _emberMetalFeatures.default('ember-glimmer');
      }

      this.buildRegistry();
    },

    /**
      Create an EngineInstance for this application.
       @private
      @method buildInstance
      @return {Ember.EngineInstance} the application instance
    */
    buildInstance: function () {
      var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

      options.base = this;
      return _emberApplicationSystemEngineInstance.default.create(options);
    },

    /**
      Build and configure the registry for the current application.
       @private
      @method buildRegistry
      @return {Ember.Registry} the configured registry
    */
    buildRegistry: function () {
      var _constructor$buildRegistry;

      var registry = this.__registry__ = this.constructor.buildRegistry(this, (_constructor$buildRegistry = {}, _constructor$buildRegistry[GLIMMER] = this[GLIMMER], _constructor$buildRegistry));

      return registry;
    },

    /**
      @private
      @method initializer
    */
    initializer: function (options) {
      this.constructor.initializer(options);
    },

    /**
      @private
      @method instanceInitializer
    */
    instanceInitializer: function (options) {
      this.constructor.instanceInitializer(options);
    },

    /**
      @private
      @method runInitializers
    */
    runInitializers: function () {
      var _this = this;

      this._runInitializer('initializers', function (name, initializer) {
        _emberMetalDebug.assert('No application initializer named \'' + name + '\'', !!initializer);
        if (initializer.initialize.length === 2) {
          _emberMetalDebug.deprecate('The `initialize` method for Application initializer \'' + name + '\' should take only one argument - `App`, an instance of an `Application`.', false, {
            id: 'ember-application.app-initializer-initialize-arguments',
            until: '3.0.0',
            url: 'http://emberjs.com/deprecations/v2.x/#toc_initializer-arity'
          });

          initializer.initialize(_this.__registry__, _this);
        } else {
          initializer.initialize(_this);
        }
      });
    },

    /**
      @private
      @since 1.12.0
      @method runInstanceInitializers
    */
    runInstanceInitializers: function (instance) {
      this._runInitializer('instanceInitializers', function (name, initializer) {
        _emberMetalDebug.assert('No instance initializer named \'' + name + '\'', !!initializer);
        initializer.initialize(instance);
      });
    },

    _runInitializer: function (bucketName, cb) {
      var initializersByName = _emberMetalProperty_get.get(this.constructor, bucketName);
      var initializers = props(initializersByName);
      var graph = new _dagMap.default();
      var initializer;

      for (var i = 0; i < initializers.length; i++) {
        initializer = initializersByName[initializers[i]];
        graph.addEdges(initializer.name, initializer, initializer.before, initializer.after);
      }

      graph.topsort(function (vertex) {
        cb(vertex.name, vertex.value);
      });
    }
  });

  Engine.reopenClass({
    initializers: new _emberMetalEmpty_object.default(),
    instanceInitializers: new _emberMetalEmpty_object.default(),

    /**
      The goal of initializers should be to register dependencies and injections.
      This phase runs once. Because these initializers may load code, they are
      allowed to defer application readiness and advance it. If you need to access
      the container or store you should use an InstanceInitializer that will be run
      after all initializers and therefore after all code is loaded and the app is
      ready.
       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(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(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(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(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(application) {
          Ember.debug('Post initializer!');
        }
      });
       // DEBUG: Pre initializer!
      // DEBUG: First initializer!
      // DEBUG: Second initializer!
      // DEBUG: Post initializer!
      ```
       * `initialize` is a callback function that receives one argument,
        `application`, on which you can operate.
       Example of using `application` to register an adapter:
       ```javascript
      Ember.Application.initializer({
        name: 'api-adapter',
         initialize: function(application) {
          application.register('api-adapter:main', ApiAdapter);
        }
      });
      ```
       @method initializer
      @param initializer {Object}
      @public
    */

    initializer: buildInitializerMethod('initializers', 'initializer'),

    /**
      Instance initializers run after all initializers have run. Because
      instance initializers run after the app is fully set up. We have access
      to the store, container, and other items. However, these initializers run
      after code has loaded and are not allowed to defer readiness.
       Instance 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 instanceInitializer is
      registered. This must be a unique name, as trying to register two
      instanceInitializer with the same name will result in an error.
       ```javascript
      Ember.Application.instanceInitializer({
        name: 'namedinstanceInitializer',
         initialize: function(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.
       * See Ember.Application.initializer for discussion on the usage of before
      and after.
       Example instanceInitializer to preload data into the store.
       ```javascript
      Ember.Application.initializer({
        name: 'preload-data',
         initialize: function(application) {
          var userConfig, userConfigEncoded, store;
          // We have a HTML escaped JSON representation of the user's basic
          // configuration generated server side and stored in the DOM of the main
          // index.html file. This allows the app to have access to a set of data
          // without making any additional remote calls. Good for basic data that is
          // needed for immediate rendering of the page. Keep in mind, this data,
          // like all local models and data can be manipulated by the user, so it
          // should not be relied upon for security or authorization.
          //
          // Grab the encoded data from the meta tag
          userConfigEncoded = Ember.$('head meta[name=app-user-config]').attr('content');
          // Unescape the text, then parse the resulting JSON into a real object
          userConfig = JSON.parse(unescape(userConfigEncoded));
          // Lookup the store
          store = application.lookup('service:store');
          // Push the encoded JSON into the store
          store.pushPayload(userConfig);
        }
      });
      ```
       @method instanceInitializer
      @param instanceInitializer
      @public
    */
    instanceInitializer: buildInitializerMethod('instanceInitializers', 'instance initializer'),

    /**
      This creates a registry with the default Ember naming conventions.
       It also configures the registry:
       * 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 buildRegistry
      @static
      @param {Ember.Application} namespace the application for which to
        build the registry
      @return {Ember.Registry} the built registry
      @public
    */
    buildRegistry: function (namespace) {
      var registry = new _containerRegistry.default({
        resolver: resolverFor(namespace)
      });

      registry.set = _emberMetalProperty_set.set;

      return registry;
    },

    /**
      Set this to provide an alternate class to `Ember.DefaultResolver`
        @deprecated Use 'Resolver' instead
      @property resolver
      @public
    */
    resolver: null,

    /**
      Set this to provide an alternate class to `Ember.DefaultResolver`
       @property resolver
      @public
    */
    Resolver: null
  });

  /**
    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) {
    var ResolverClass = namespace.get('Resolver') || _emberApplicationSystemResolver.default;

    return ResolverClass.create({
      namespace: namespace
    });
  }

  function buildInitializerMethod(bucketName, humanName) {
    return 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[bucketName] !== undefined && this.superclass[bucketName] === this[bucketName]) {
        var attrs = {};
        attrs[bucketName] = Object.create(this[bucketName]);
        this.reopenClass(attrs);
      }

      _emberMetalDebug.assert('The ' + humanName + ' \'' + initializer.name + '\' has already been registered', !this[bucketName][initializer.name]);
      _emberMetalDebug.assert('An ' + humanName + ' cannot be registered without an initialize function', _emberMetalUtils.canInvoke(initializer, 'initialize'));
      _emberMetalDebug.assert('An ' + humanName + ' cannot be registered without a name property', initializer.name !== undefined);

      this[bucketName][initializer.name] = initializer;
    };
  }

  exports.default = Engine;
});
enifed('ember-application/system/resolver', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-runtime/system/string', 'ember-runtime/system/object', 'ember-runtime/system/namespace', 'ember-htmlbars/helpers', 'ember-application/utils/validate-type', 'ember-metal/dictionary', 'ember-htmlbars/template_registry'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberRuntimeSystemString, _emberRuntimeSystemObject, _emberRuntimeSystemNamespace, _emberHtmlbarsHelpers, _emberApplicationUtilsValidateType, _emberMetalDictionary, _emberHtmlbarsTemplate_registry) {
  /**
  @module ember
  @submodule ember-application
  */

  'use strict';

  var Resolver = _emberRuntimeSystemObject.default.extend({
    /*
      This will be set to the Application instance when it is
      created.
       @property namespace
    */
    namespace: null,
    normalize: null, // required
    resolve: null, // required
    parseName: null, // required
    lookupDescription: null, // required
    makeToString: null, // required
    resolveOther: null, // required
    _logLookup: null // required
  });

  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
    @public
  */

  exports.default = _emberRuntimeSystemObject.default.extend({
    /**
      This will be set to the Application instance when it is
      created.
       @property namespace
      @public
    */
    namespace: null,

    init: function () {
      this._parseNameCache = _emberMetalDictionary.default(null);
    },
    normalize: function (fullName) {
      var _fullName$split = fullName.split(':', 2);

      var type = _fullName$split[0];
      var name = _fullName$split[1];

      _emberMetalDebug.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`.', fullName.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();
          });
        }

        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
      @public
    */
    resolve: function (fullName) {
      var parsedName = this.parseName(fullName);
      var resolveMethodName = parsedName.resolveMethodName;
      var resolved;

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

      resolved = resolved || this.resolveOther(parsedName);

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

      if (resolved) {
        _emberApplicationUtilsValidateType.default(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
      @public
    */

    parseName: function (fullName) {
      return this._parseNameCache[fullName] || (this._parseNameCache[fullName] = this._parseName(fullName));
    },

    _parseName: function (fullName) {
      var _fullName$split2 = fullName.split(':');

      var type = _fullName$split2[0];
      var fullNameWithoutType = _fullName$split2[1];

      var name = fullNameWithoutType;
      var namespace = _emberMetalProperty_get.get(this, 'namespace');
      var root = namespace;
      var lastSlashIndex = name.lastIndexOf('/');
      var dirname = lastSlashIndex !== -1 ? name.slice(0, lastSlashIndex) : null;

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

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

      var resolveMethodName = fullNameWithoutType === 'main' ? 'Main' : _emberRuntimeSystemString.classify(type);

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

      return {
        fullName: fullName,
        type: type,
        fullNameWithoutType: fullNameWithoutType,
        dirname: dirname,
        name: name,
        root: root,
        resolveMethodName: 'resolve' + resolveMethodName
      };
    },

    /**
      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
      @public
    */
    lookupDescription: function (fullName) {
      var parsedName = this.parseName(fullName);
      var description;

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

      description = parsedName.root + '.' + _emberRuntimeSystemString.classify(parsedName.name).replace(/\./g, '');

      if (parsedName.type !== 'model') {
        description += _emberRuntimeSystemString.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
      @public
    */
    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
      @public
    */
    resolveTemplate: function (parsedName) {
      var templateName = parsedName.fullNameWithoutType.replace(/\./g, '/');

      return _emberHtmlbarsTemplate_registry.get(templateName) || _emberHtmlbarsTemplate_registry.get(_emberRuntimeSystemString.decamelize(templateName));
    },

    /**
      Lookup the view using `resolveOther`
       @protected
      @param {Object} parsedName a parseName object with the parsed
        fullName lookup string
      @method resolveView
      @public
    */
    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
      @public
    */
    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
      @public
    */
    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
      @public
    */
    resolveModel: function (parsedName) {
      var className = _emberRuntimeSystemString.classify(parsedName.name);
      var factory = _emberMetalProperty_get.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
      @public
    */
    resolveHelper: function (parsedName) {
      return this.resolveOther(parsedName) || _emberHtmlbarsHelpers.default[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
      @public
    */
    resolveOther: function (parsedName) {
      var className = _emberRuntimeSystemString.classify(parsedName.name) + _emberRuntimeSystemString.classify(parsedName.type);
      var factory = _emberMetalProperty_get.get(parsedName.root, className);
      if (factory) {
        return factory;
      }
    },

    resolveMain: function (parsedName) {
      var className = _emberRuntimeSystemString.classify(parsedName.type);
      return _emberMetalProperty_get.get(parsedName.root, className);
    },

    /**
     @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('.');
      }

      _emberMetalDebug.info(symbol, parsedName.fullName, padding, this.lookupDescription(parsedName.fullName));
    },

    /**
     Used to iterate all items of a given type.
      @method knownForType
     @param {String} type the type to search for
     @private
     */
    knownForType: function (type) {
      var namespace = _emberMetalProperty_get.get(this, 'namespace');
      var suffix = _emberRuntimeSystemString.classify(type);
      var typeRegexp = new RegExp(suffix + '$');

      var known = _emberMetalDictionary.default(null);
      var knownKeys = Object.keys(namespace);
      for (var index = 0, _length = knownKeys.length; index < _length; index++) {
        var _name = knownKeys[index];

        if (typeRegexp.test(_name)) {
          var containerName = this.translateToContainerFullname(type, _name);

          known[containerName] = true;
        }
      }

      return known;
    },

    /**
     Converts provided name from the backing namespace into a container lookup name.
      Examples:
      App.FooBarHelper -> helper:foo-bar
     App.THelper -> helper:t
      @method translateToContainerFullname
     @param {String} type
     @param {String} name
     @private
     */

    translateToContainerFullname: function (type, name) {
      var suffix = _emberRuntimeSystemString.classify(type);
      var namePrefix = name.slice(0, suffix.length * -1);
      var dasherizedName = _emberRuntimeSystemString.dasherize(namePrefix);

      return type + ':' + dasherizedName;
    }
  });
});
enifed('ember-application/utils/validate-type', ['exports', 'ember-metal/debug'], function (exports, _emberMetalDebug) {
  /**
  @module ember
  @submodule ember-application
  */

  'use strict';

  exports.default = validateType;

  var VALIDATED_TYPES = {
    route: ['assert', 'isRouteFactory', 'Ember.Route'],
    component: ['deprecate', 'isComponentFactory', 'Ember.Component'],
    view: ['deprecate', 'isViewFactory', 'Ember.View'],
    service: ['deprecate', 'isServiceFactory', 'Ember.Service']
  };

  function validateType(resolvedType, parsedName) {
    var validationAttributes = VALIDATED_TYPES[parsedName.type];

    if (!validationAttributes) {
      return;
    }

    var action = validationAttributes[0];
    var factoryFlag = validationAttributes[1];
    var expectedType = validationAttributes[2];

    if (action === 'deprecate') {
      _emberMetalDebug.deprecate('In Ember 2.0 ' + parsedName.type + ' factories must have an `' + factoryFlag + '` ' + ('property set to true. You registered ' + resolvedType + ' as a ' + parsedName.type + ' ') + ('factory. Either add the `' + factoryFlag + '` property to this factory or ') + ('extend from ' + expectedType + '.'), !!resolvedType[factoryFlag], { id: 'ember-application.validate-type', until: '3.0.0' });
    } else {
      _emberMetalDebug.assert('Expected ' + parsedName.fullName + ' to resolve to an ' + expectedType + ' but ' + ('instead it was ' + resolvedType + '.'), !!resolvedType[factoryFlag]);
    }
  }
});
enifed('ember-debug/deprecate', ['exports', 'ember-metal/core', 'ember-metal/error', 'ember-metal/logger', 'ember-debug/handlers'], function (exports, _emberMetalCore, _emberMetalError, _emberMetalLogger, _emberDebugHandlers) {
  /*global __fail__*/

  'use strict';

  var _slice = Array.prototype.slice;
  exports.registerHandler = registerHandler;
  exports.default = deprecate;

  function registerHandler(handler) {
    _emberDebugHandlers.registerHandler('deprecate', handler);
  }

  function formatMessage(_message, options) {
    var message = _message;

    if (options && options.id) {
      message = message + (' [deprecation id: ' + options.id + ']');
    }

    if (options && options.url) {
      message += ' See ' + options.url + ' for more details.';
    }

    return message;
  }

  registerHandler(function logDeprecationToConsole(message, options) {
    var updatedMessage = formatMessage(message, options);

    _emberMetalLogger.default.warn('DEPRECATION: ' + updatedMessage);
  });

  var captureErrorForStack = undefined;

  if (new Error().stack) {
    captureErrorForStack = function () {
      return new Error();
    };
  } else {
    captureErrorForStack = function () {
      try {
        __fail__.fail();
      } catch (e) {
        return e;
      }
    };
  }

  registerHandler(function logDeprecationStackTrace(message, options, next) {
    if (_emberMetalCore.default.LOG_STACKTRACE_ON_DEPRECATION) {
      var stackStr = '';
      var error = captureErrorForStack();
      var stack = undefined;

      if (error.stack) {
        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    ');
      }

      var updatedMessage = formatMessage(message, options);

      _emberMetalLogger.default.warn('DEPRECATION: ' + updatedMessage + stackStr);
    } else {
      next.apply(undefined, arguments);
    }
  });

  registerHandler(function raiseOnDeprecation(message, options, next) {
    if (_emberMetalCore.default.ENV.RAISE_ON_DEPRECATION) {
      var updatedMessage = formatMessage(message);

      throw new _emberMetalError.default(updatedMessage);
    } else {
      next.apply(undefined, arguments);
    }
  });

  var missingOptionsDeprecation = 'When calling `Ember.deprecate` you ' + 'must provide an `options` hash as the third parameter.  ' + '`options` should include `id` and `until` properties.';
  exports.missingOptionsDeprecation = missingOptionsDeprecation;
  var missingOptionsIdDeprecation = 'When calling `Ember.deprecate` you must provide `id` in options.';
  exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation;
  var missingOptionsUntilDeprecation = 'When calling `Ember.deprecate` you must provide `until` in options.';

  exports.missingOptionsUntilDeprecation = missingOptionsUntilDeprecation;
  /**
  @module ember
  @submodule ember-debug
  */

  /**
    Display a deprecation warning with the provided message and a stack trace
    (Chrome and Firefox only).

    * In a production build, this method is defined as an empty function (NOP).
    Uses of this method in Ember itself are stripped from the ember.prod.js build.

    @method deprecate
    @param {String} message A description of the deprecation.
    @param {Boolean} test A boolean. If falsy, the deprecation
      will be displayed.
    @param {Object} options An object that can be used to pass
      in a `url` to the transition guide on the emberjs.com website, and a unique
      `id` for this deprecation. The `id` can be used by Ember debugging tools
      to change the behavior (raise, log or silence) for that specific deprecation.
      The `id` should be namespaced by dots, e.g. "view.helper.select".
    @for Ember
    @public
  */

  function deprecate(message, test, options) {
    if (!options || !options.id && !options.until) {
      deprecate(missingOptionsDeprecation, false, {
        id: 'ember-debug.deprecate-options-missing',
        until: '3.0.0',
        url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
      });
    }

    if (options && !options.id) {
      deprecate(missingOptionsIdDeprecation, false, {
        id: 'ember-debug.deprecate-id-missing',
        until: '3.0.0',
        url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
      });
    }

    if (options && !options.until) {
      deprecate(missingOptionsUntilDeprecation, options && options.until, {
        id: 'ember-debug.deprecate-until-missing',
        until: '3.0.0',
        url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
      });
    }

    _emberDebugHandlers.invoke.apply(undefined, ['deprecate'].concat(_slice.call(arguments)));
  }
});
enifed("ember-debug/handlers", ["exports"], function (exports) {
  "use strict";

  exports.registerHandler = registerHandler;
  exports.invoke = invoke;
  var HANDLERS = {};

  exports.HANDLERS = HANDLERS;

  function registerHandler(type, callback) {
    var nextHandler = HANDLERS[type] || function () {};

    HANDLERS[type] = function (message, options) {
      callback(message, options, nextHandler);
    };
  }

  function invoke(type, message, test, options) {
    if (test) {
      return;
    }

    var handlerForType = HANDLERS[type];

    if (!handlerForType) {
      return;
    }

    if (handlerForType) {
      handlerForType(message, options);
    }
  }
});
enifed('ember-debug/index', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-metal/features', 'ember-metal/error', 'ember-metal/logger', 'ember-metal/environment', 'ember-debug/deprecate', 'ember-debug/warn'], function (exports, _emberMetalCore, _emberMetalDebug, _emberMetalFeatures, _emberMetalError, _emberMetalLogger, _emberMetalEnvironment, _emberDebugDeprecate, _emberDebugWarn) {
  'use strict';

  exports._warnIfUsingStrippedFeatureFlags = _warnIfUsingStrippedFeatureFlags;

  /**
  @module ember
  @submodule ember-debug
  */

  /**
  @class Ember
  @public
  */

  /**
    Define an assertion that will throw an exception if the condition is not met.

    * In a production build, this method is defined as an empty function (NOP).
    Uses of this method in Ember itself are stripped from the ember.prod.js build.

    ```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.
    @public
  */
  _emberMetalDebug.setDebugFunction('assert', function assert(desc, test) {
    if (!test) {
      throw new _emberMetalError.default('Assertion Failed: ' + desc);
    }
  });

  /**
    Display a debug notice.

    * In a production build, this method is defined as an empty function (NOP).
    Uses of this method in Ember itself are stripped from the ember.prod.js build.

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

    @method debug
    @param {String} message A debug message to display.
    @public
  */
  _emberMetalDebug.setDebugFunction('debug', function debug(message) {
    _emberMetalLogger.default.debug('DEBUG: ' + message);
  });

  /**
    Display an info notice.

    * In a production build, this method is defined as an empty function (NOP).
    Uses of this method in Ember itself are stripped from the ember.prod.js build.

    @method info
    @private
  */
  _emberMetalDebug.setDebugFunction('info', function info() {
    _emberMetalLogger.default.info.apply(undefined, arguments);
  });

  /**
    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.

    * In a production build, this method is defined as an empty function (NOP).

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

    @method deprecateFunc
    @param {String} message A description of the deprecation.
    @param {Object} [options] The options object for Ember.deprecate.
    @param {Function} func The new function called to replace its deprecated counterpart.
    @return {Function} A new function that wraps the original function with a deprecation warning
    @private
  */
  _emberMetalDebug.setDebugFunction('deprecateFunc', function deprecateFunc() {
    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    if (args.length === 3) {
      var _ret = (function () {
        var message = args[0];
        var options = args[1];
        var func = args[2];

        return {
          v: function () {
            _emberMetalDebug.deprecate(message, false, options);
            return func.apply(this, arguments);
          }
        };
      })();

      if (typeof _ret === 'object') return _ret.v;
    } else {
      var _ret2 = (function () {
        var message = args[0];
        var func = args[1];

        return {
          v: function () {
            _emberMetalDebug.deprecate(message);
            return func.apply(this, arguments);
          }
        };
      })();

      if (typeof _ret2 === 'object') return _ret2.v;
    }
  });

  /**
    Run a function meant for debugging.

    * In a production build, this method is defined as an empty function (NOP).
    Uses of this method in Ember itself are stripped from the ember.prod.js build.

    ```javascript
    Ember.runInDebug(() => {
      Ember.Component.reopen({
        didInsertElement() {
          console.log("I'm happy");
        }
      });
    });
    ```

    @method runInDebug
    @param {Function} func The function to be executed.
    @since 1.5.0
    @public
  */
  _emberMetalDebug.setDebugFunction('runInDebug', function runInDebug(func) {
    func();
  });

  _emberMetalDebug.setDebugFunction('debugSeal', function debugSeal(obj) {
    Object.seal(obj);
  });

  _emberMetalDebug.setDebugFunction('deprecate', _emberDebugDeprecate.default);

  _emberMetalDebug.setDebugFunction('warn', _emberDebugWarn.default);

  /**
    Will call `Ember.warn()` if ENABLE_OPTIONAL_FEATURES or
    any specific FEATURES flag is truthy.

    This method is called automatically in debug canary builds.

    @private
    @method _warnIfUsingStrippedFeatureFlags
    @return {void}
  */

  function _warnIfUsingStrippedFeatureFlags(FEATURES, knownFeatures, featuresWereStripped) {
    if (featuresWereStripped) {
      _emberMetalDebug.warn('Ember.ENV.ENABLE_OPTIONAL_FEATURES is only available in canary builds.', !_emberMetalCore.default.ENV.ENABLE_OPTIONAL_FEATURES, { id: 'ember-debug.feature-flag-with-features-stripped' });

      var keys = Object.keys(FEATURES || {});
      for (var i = 0; i < keys.length; i++) {
        var key = keys[i];
        if (key === 'isEnabled' || !(key in knownFeatures)) {
          continue;
        }

        _emberMetalDebug.warn('FEATURE["' + key + '"] is set as enabled, but FEATURE flags are only available in canary builds.', !FEATURES[key], { id: 'ember-debug.feature-flag-with-features-stripped' });
      }
    }
  }

  if (!_emberMetalCore.default.testing) {
    // Complain if they're using FEATURE flags in builds other than canary
    _emberMetalFeatures.FEATURES['features-stripped-test'] = true;
    var featuresWereStripped = true;

    delete _emberMetalFeatures.FEATURES['features-stripped-test'];
    _warnIfUsingStrippedFeatureFlags(_emberMetalCore.default.ENV.FEATURES, _emberMetalFeatures.KNOWN_FEATURES, featuresWereStripped);

    // Inform the developer about the Ember Inspector if not installed.
    var isFirefox = _emberMetalEnvironment.default.isFirefox;
    var isChrome = _emberMetalEnvironment.default.isChrome;

    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/';
          }

          _emberMetalDebug.debug('For more advanced debugging, install the Ember Inspector from ' + downloadURL);
        }
      }, false);
    }
  }
  /**
    @public
    @class Ember.Debug
  */
  _emberMetalCore.default.Debug = {};

  /**
    Allows for runtime registration of handler functions that override the default deprecation behavior.
    Deprecations are invoked by calls to [Ember.deprecate](http://emberjs.com/api/classes/Ember.html#method_deprecate).
    The following example demonstrates its usage by registering a handler that throws an error if the
    message contains the word "should", otherwise defers to the default handler.

    ```javascript
    Ember.Debug.registerDeprecationHandler((message, options, next) => {
      if (message.indexOf('should') !== -1) {
        throw new Error(`Deprecation message with should: ${message}`);
      } else {
        // defer to whatever handler was registered before this one
        next(message, options);
      }
    }
    ```

    The handler function takes the following arguments:

    <ul>
      <li> <code>message</code> - The message received from the deprecation call.</li>
      <li> <code>options</code> - An object passed in with the deprecation call containing additional information including:</li>
        <ul>
          <li> <code>id</code> - An id of the deprecation in the form of <code>package-name.specific-deprecation</code>.</li>
          <li> <code>until</code> - The Ember version number the feature and deprecation will be removed in.</li>
        </ul>
      <li> <code>next</code> - A function that calls into the previously registered handler.</li>
    </ul>

    @public
    @static
    @method registerDeprecationHandler
    @param handler {Function} A function to handle deprecation calls.
    @since 2.1.0
  */
  _emberMetalCore.default.Debug.registerDeprecationHandler = _emberDebugDeprecate.registerHandler;
  /**
    Allows for runtime registration of handler functions that override the default warning behavior.
    Warnings are invoked by calls made to [Ember.warn](http://emberjs.com/api/classes/Ember.html#method_warn).
    The following example demonstrates its usage by registering a handler that does nothing overriding Ember's
    default warning behavior.

    ```javascript
    // next is not called, so no warnings get the default behavior
    Ember.Debug.registerWarnHandler(() => {});
    ```

    The handler function takes the following arguments:

    <ul>
      <li> <code>message</code> - The message received from the warn call. </li>
      <li> <code>options</code> - An object passed in with the warn call containing additional information including:</li>
        <ul>
          <li> <code>id</code> - An id of the warning in the form of <code>package-name.specific-warning</code>.</li>
        </ul>
      <li> <code>next</code> - A function that calls into the previously registered handler.</li>
    </ul>

    @public
    @static
    @method registerWarnHandler
    @param handler {Function} A function to handle warnings.
    @since 2.1.0
  */
  _emberMetalCore.default.Debug.registerWarnHandler = _emberDebugWarn.registerHandler;

  /*
    We are transitioning away from `ember.js` to `ember.debug.js` to make
    it much clearer that it is only for local development purposes.

    This flag value is changed by the tooling (by a simple string replacement)
    so that if `ember.js` (which must be output for backwards compat reasons) is
    used a nice helpful warning message will be printed out.
  */
  var runningNonEmberDebugJS = false;
  exports.runningNonEmberDebugJS = runningNonEmberDebugJS;
  if (runningNonEmberDebugJS) {
    _emberMetalDebug.warn('Please use `ember.debug.js` instead of `ember.js` for development and debugging.');
  }
});
enifed('ember-debug/warn', ['exports', 'ember-metal/logger', 'ember-metal/debug', 'ember-debug/handlers'], function (exports, _emberMetalLogger, _emberMetalDebug, _emberDebugHandlers) {
  'use strict';

  var _slice = Array.prototype.slice;
  exports.registerHandler = registerHandler;
  exports.default = warn;

  function registerHandler(handler) {
    _emberDebugHandlers.registerHandler('warn', handler);
  }

  registerHandler(function logWarning(message, options) {
    _emberMetalLogger.default.warn('WARNING: ' + message);
    if ('trace' in _emberMetalLogger.default) {
      _emberMetalLogger.default.trace();
    }
  });

  var missingOptionsDeprecation = 'When calling `Ember.warn` you ' + 'must provide an `options` hash as the third parameter.  ' + '`options` should include an `id` property.';
  exports.missingOptionsDeprecation = missingOptionsDeprecation;
  var missingOptionsIdDeprecation = 'When calling `Ember.warn` you must provide `id` in options.';

  exports.missingOptionsIdDeprecation = missingOptionsIdDeprecation;
  /**
  @module ember
  @submodule ember-debug
  */

  /**
    Display a warning with the provided message.

    * In a production build, this method is defined as an empty function (NOP).
    Uses of this method in Ember itself are stripped from the ember.prod.js build.

    @method warn
    @param {String} message A warning to display.
    @param {Boolean} test An optional boolean. If falsy, the warning
      will be displayed.
    @param {Object} options An object that can be used to pass a unique
      `id` for this warning.  The `id` can be used by Ember debugging tools
      to change the behavior (raise, log, or silence) for that specific warning.
      The `id` should be namespaced by dots, e.g. "ember-debug.feature-flag-with-features-stripped"
    @for Ember
    @public
  */

  function warn(message, test, options) {
    if (!options) {
      _emberMetalDebug.deprecate(missingOptionsDeprecation, false, {
        id: 'ember-debug.warn-options-missing',
        until: '3.0.0',
        url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
      });
    }

    if (options && !options.id) {
      _emberMetalDebug.deprecate(missingOptionsIdDeprecation, false, {
        id: 'ember-debug.warn-id-missing',
        until: '3.0.0',
        url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-debug-function-options'
      });
    }

    _emberDebugHandlers.invoke.apply(undefined, ['warn'].concat(_slice.call(arguments)));
  }
});
enifed('ember-extension-support/container_debug_adapter', ['exports', 'ember-metal/core', 'ember-runtime/system/native_array', 'ember-runtime/utils', 'ember-runtime/system/string', 'ember-runtime/system/namespace', 'ember-runtime/system/object'], function (exports, _emberMetalCore, _emberRuntimeSystemNative_array, _emberRuntimeUtils, _emberRuntimeSystemString, _emberRuntimeSystemNamespace, _emberRuntimeSystemObject) {
  'use strict';

  /**
  @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(application) {
        application.register('container-debug-adapter:main', require('app/container-debug-adapter'));
      }
    });
    ```

    @class ContainerDebugAdapter
    @namespace Ember
    @extends Ember.Object
    @since 1.5.0
    @public
  */
  exports.default = _emberRuntimeSystemObject.default.extend({
    /**
      The resolver instance of the application
      being debugged. This property will be injected
      on creation.
       @property resolver
      @default null
      @public
    */
    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.
      @public
    */
    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.
      @public
    */
    catalogEntriesByType: function (type) {
      var namespaces = _emberRuntimeSystemNative_array.A(_emberRuntimeSystemNamespace.default.NAMESPACES);
      var types = _emberRuntimeSystemNative_array.A();
      var typeSuffixRegex = new RegExp(_emberRuntimeSystemString.classify(type) + '$');

      namespaces.forEach(function (namespace) {
        if (namespace !== _emberMetalCore.default) {
          for (var key in namespace) {
            if (!namespace.hasOwnProperty(key)) {
              continue;
            }
            if (typeSuffixRegex.test(key)) {
              var klass = namespace[key];
              if (_emberRuntimeUtils.typeOf(klass) === 'class') {
                types.push(_emberRuntimeSystemString.dasherize(key.replace(typeSuffixRegex, '')));
              }
            }
          }
        }
      });
      return types;
    }
  });
});
enifed('ember-extension-support/data_adapter', ['exports', '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', 'container/owner', 'ember-runtime/mixins/array'], function (exports, _emberMetalProperty_get, _emberMetalRun_loop, _emberRuntimeSystemString, _emberRuntimeSystemNamespace, _emberRuntimeSystemObject, _emberRuntimeSystemNative_array, _emberApplicationSystemApplication, _containerOwner, _emberRuntimeMixinsArray) {
  'use strict';

  /**
  @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(application) {
        application.register('data-adapter:main', DS.DataAdapter);
      }
    });
    ```

    @class DataAdapter
    @namespace Ember
    @extends EmberObject
    @public
  */
  exports.default = _emberRuntimeSystemObject.default.extend({
    init: function () {
      this._super.apply(this, arguments);
      this.releaseMethods = _emberRuntimeSystemNative_array.A();
    },

    /**
      The container-debug-adapter which is used
      to list all models.
       @property containerDebugAdapter
      @default undefined
      @since 1.5.0
      @public
    **/
    containerDebugAdapter: undefined,

    /**
      The number of attributes to send
      as columns. (Enough to make the record
      identifiable).
       @private
      @property attributeLimit
      @default 3
      @since 1.3.0
    */
    attributeLimit: 3,

    /**
       Ember Data > v1.0.0-beta.18
       requires string model names to be passed
       around instead of the actual factories.
        This is a stamp for the Ember Inspector
       to differentiate between the versions
       to be able to support older versions too.
        @public
       @property acceptsModelName
     */
    acceptsModelName: true,

    /**
      Stores all methods that clear observers.
      These methods will be called on destruction.
       @private
      @property releaseMethods
      @since 1.3.0
    */
    releaseMethods: _emberRuntimeSystemNative_array.A(),

    /**
      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 _emberRuntimeSystemNative_array.A();
    },

    /**
      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 _this = this;

      var modelTypes = this.getModelTypes();
      var releaseMethods = _emberRuntimeSystemNative_array.A();
      var typesToSend;

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

      typesAdded(typesToSend);

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

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

    /**
      Fetch the records of a given type and observe them for changes.
       @public
      @method watchRecords
       @param {String} modelName The model name.
       @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} The 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 (modelName, recordsAdded, recordsUpdated, recordsRemoved) {
      var _this2 = this;

      var releaseMethods = _emberRuntimeSystemNative_array.A();
      var klass = this._nameToClass(modelName);
      var records = this.getRecords(klass, modelName);
      var release;

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

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

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

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

      var observer = { didChange: contentDidChange, willChange: function () {
          return this;
        } };
      _emberRuntimeMixinsArray.addArrayObserver(records, this, observer);

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

      recordsAdded(recordsToSend);

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

    /**
      Clear all observers before destruction
      @private
      @method willDestroy
    */
    willDestroy: function () {
      this._super.apply(this, arguments);
      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} The name of the column.
       desc: {String} Humanized description (what would show in a table column name).
    */
    columnsForType: function (type) {
      return _emberRuntimeSystemNative_array.A();
    },

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

    observeModelType: function (modelName, typesUpdated) {
      var _this3 = this;

      var klass = this._nameToClass(modelName);
      var records = this.getRecords(klass, modelName);

      var onChange = function () {
        typesUpdated([_this3.wrapModelType(klass, modelName)]);
      };
      var observer = {
        didChange: function () {
          _emberMetalRun_loop.default.scheduleOnce('actions', this, onChange);
        },
        willChange: function () {
          return this;
        }
      };

      _emberRuntimeMixinsArray.addArrayObserver(records, this, observer);

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

      return release;
    },

    /**
      Wraps a given model type and observes changes to it.
       @private
      @method wrapModelType
      @param {Class} klass A model class.
      @param {String} modelName 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} The name of the type.
            count: {Integer} The number of records available.
            columns: {Columns} An array of columns to describe the record.
            object: {Class} The actual Model type class.
        release: {Function} The function to remove observers.
    */
    wrapModelType: function (klass, name) {
      var records = this.getRecords(klass, name);
      var typeToSend;

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

      return typeToSend;
    },

    /**
      Fetches all models defined in the application.
       @private
      @method getModelTypes
      @return {Array} Array of model types.
    */
    getModelTypes: function () {
      var _this4 = this;

      var containerDebugAdapter = this.get('containerDebugAdapter');
      var types;

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

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

      return _emberRuntimeSystemNative_array.A(types);
    },

    /**
      Loops over all namespaces and all objects
      attached to them.
       @private
      @method _getObjectsOnNamespaces
      @return {Array} Array of model type strings.
    */
    _getObjectsOnNamespaces: function () {
      var _this5 = this;

      var namespaces = _emberRuntimeSystemNative_array.A(_emberRuntimeSystemNamespace.default.NAMESPACES);
      var types = _emberRuntimeSystemNative_array.A();

      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 `lookupFactory` on non-models
          // (especially when `Ember.MODEL_FACTORY_INJECTIONS` is `true`)
          if (!_this5.detect(namespace[key])) {
            continue;
          }
          var name = _emberRuntimeSystemString.dasherize(key);
          if (!(namespace instanceof _emberApplicationSystemApplication.default) && 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 _emberRuntimeSystemNative_array.A();
    },

    /**
      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 };

      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 _emberRuntimeSystemNative_array.A();
    },

    /**
      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 records 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 () {};
    }
  });
});
enifed('ember-extension-support/index', ['exports', 'ember-metal/core', 'ember-extension-support/data_adapter', 'ember-extension-support/container_debug_adapter'], function (exports, _emberMetalCore, _emberExtensionSupportData_adapter, _emberExtensionSupportContainer_debug_adapter) {
  /**
  @module ember
  @submodule ember-extension-support
  */

  'use strict';

  _emberMetalCore.default.DataAdapter = _emberExtensionSupportData_adapter.default;
  _emberMetalCore.default.ContainerDebugAdapter = _emberExtensionSupportContainer_debug_adapter.default;
});
enifed('ember-htmlbars/compat', ['exports', 'ember-metal/core', 'ember-htmlbars/utils/string'], function (exports, _emberMetalCore, _emberHtmlbarsUtilsString) {
  'use strict';

  var EmberHandlebars = _emberMetalCore.default.Handlebars = _emberMetalCore.default.Handlebars || {};

  EmberHandlebars.SafeString = _emberHtmlbarsUtilsString.SafeString;
  EmberHandlebars.Utils = {
    escapeExpression: _emberHtmlbarsUtilsString.escapeExpression
  };

  exports.default = EmberHandlebars;
});
// for Handlebars export
enifed('ember-htmlbars/env', ['exports', 'ember-metal', 'ember-metal/environment', 'htmlbars-runtime', 'ember-metal/assign', 'ember-htmlbars/hooks/subexpr', 'ember-htmlbars/hooks/concat', 'ember-htmlbars/hooks/link-render-node', 'ember-htmlbars/hooks/create-fresh-scope', 'ember-htmlbars/hooks/bind-shadow-scope', 'ember-htmlbars/hooks/bind-self', 'ember-htmlbars/hooks/bind-scope', 'ember-htmlbars/hooks/bind-local', 'ember-htmlbars/hooks/bind-block', 'ember-htmlbars/hooks/update-self', 'ember-htmlbars/hooks/get-root', 'ember-htmlbars/hooks/get-child', 'ember-htmlbars/hooks/get-block', 'ember-htmlbars/hooks/get-value', 'ember-htmlbars/hooks/get-cell-or-value', 'ember-htmlbars/hooks/cleanup-render-node', 'ember-htmlbars/hooks/destroy-render-node', 'ember-htmlbars/hooks/did-render-node', 'ember-htmlbars/hooks/will-cleanup-tree', 'ember-htmlbars/hooks/did-cleanup-tree', 'ember-htmlbars/hooks/classify', 'ember-htmlbars/hooks/component', 'ember-htmlbars/hooks/lookup-helper', 'ember-htmlbars/hooks/has-helper', 'ember-htmlbars/hooks/invoke-helper', 'ember-htmlbars/hooks/element', 'ember-htmlbars/helpers', 'ember-htmlbars/keywords', 'ember-htmlbars/system/dom-helper', 'ember-htmlbars/keywords/debugger', 'ember-htmlbars/keywords/with', 'ember-htmlbars/keywords/outlet', 'ember-htmlbars/keywords/unbound', 'ember-htmlbars/keywords/view', 'ember-htmlbars/keywords/component', 'ember-htmlbars/keywords/element-component', 'ember-htmlbars/keywords/partial', 'ember-htmlbars/keywords/input', 'ember-htmlbars/keywords/textarea', 'ember-htmlbars/keywords/yield', 'ember-htmlbars/keywords/mut', 'ember-htmlbars/keywords/readonly', 'ember-htmlbars/keywords/get'], function (exports, _emberMetal, _emberMetalEnvironment, _htmlbarsRuntime, _emberMetalAssign, _emberHtmlbarsHooksSubexpr, _emberHtmlbarsHooksConcat, _emberHtmlbarsHooksLinkRenderNode, _emberHtmlbarsHooksCreateFreshScope, _emberHtmlbarsHooksBindShadowScope, _emberHtmlbarsHooksBindSelf, _emberHtmlbarsHooksBindScope, _emberHtmlbarsHooksBindLocal, _emberHtmlbarsHooksBindBlock, _emberHtmlbarsHooksUpdateSelf, _emberHtmlbarsHooksGetRoot, _emberHtmlbarsHooksGetChild, _emberHtmlbarsHooksGetBlock, _emberHtmlbarsHooksGetValue, _emberHtmlbarsHooksGetCellOrValue, _emberHtmlbarsHooksCleanupRenderNode, _emberHtmlbarsHooksDestroyRenderNode, _emberHtmlbarsHooksDidRenderNode, _emberHtmlbarsHooksWillCleanupTree, _emberHtmlbarsHooksDidCleanupTree, _emberHtmlbarsHooksClassify, _emberHtmlbarsHooksComponent, _emberHtmlbarsHooksLookupHelper, _emberHtmlbarsHooksHasHelper, _emberHtmlbarsHooksInvokeHelper, _emberHtmlbarsHooksElement, _emberHtmlbarsHelpers, _emberHtmlbarsKeywords, _emberHtmlbarsSystemDomHelper, _emberHtmlbarsKeywordsDebugger, _emberHtmlbarsKeywordsWith, _emberHtmlbarsKeywordsOutlet, _emberHtmlbarsKeywordsUnbound, _emberHtmlbarsKeywordsView, _emberHtmlbarsKeywordsComponent, _emberHtmlbarsKeywordsElementComponent, _emberHtmlbarsKeywordsPartial, _emberHtmlbarsKeywordsInput, _emberHtmlbarsKeywordsTextarea, _emberHtmlbarsKeywordsYield, _emberHtmlbarsKeywordsMut, _emberHtmlbarsKeywordsReadonly, _emberHtmlbarsKeywordsGet) {
  'use strict';

  var emberHooks = _emberMetalAssign.default({}, _htmlbarsRuntime.hooks);
  emberHooks.keywords = _emberHtmlbarsKeywords.default;

  _emberMetalAssign.default(emberHooks, {
    linkRenderNode: _emberHtmlbarsHooksLinkRenderNode.default,
    createFreshScope: _emberHtmlbarsHooksCreateFreshScope.default,
    createChildScope: _emberHtmlbarsHooksCreateFreshScope.createChildScope,
    bindShadowScope: _emberHtmlbarsHooksBindShadowScope.default,
    bindSelf: _emberHtmlbarsHooksBindSelf.default,
    bindScope: _emberHtmlbarsHooksBindScope.default,
    bindLocal: _emberHtmlbarsHooksBindLocal.default,
    bindBlock: _emberHtmlbarsHooksBindBlock.default,
    updateSelf: _emberHtmlbarsHooksUpdateSelf.default,
    getBlock: _emberHtmlbarsHooksGetBlock.default,
    getRoot: _emberHtmlbarsHooksGetRoot.default,
    getChild: _emberHtmlbarsHooksGetChild.default,
    getValue: _emberHtmlbarsHooksGetValue.default,
    getCellOrValue: _emberHtmlbarsHooksGetCellOrValue.default,
    subexpr: _emberHtmlbarsHooksSubexpr.default,
    concat: _emberHtmlbarsHooksConcat.default,
    cleanupRenderNode: _emberHtmlbarsHooksCleanupRenderNode.default,
    destroyRenderNode: _emberHtmlbarsHooksDestroyRenderNode.default,
    willCleanupTree: _emberHtmlbarsHooksWillCleanupTree.default,
    didCleanupTree: _emberHtmlbarsHooksDidCleanupTree.default,
    didRenderNode: _emberHtmlbarsHooksDidRenderNode.default,
    classify: _emberHtmlbarsHooksClassify.default,
    component: _emberHtmlbarsHooksComponent.default,
    lookupHelper: _emberHtmlbarsHooksLookupHelper.default,
    hasHelper: _emberHtmlbarsHooksHasHelper.default,
    invokeHelper: _emberHtmlbarsHooksInvokeHelper.default,
    element: _emberHtmlbarsHooksElement.default
  });

  _emberHtmlbarsKeywords.registerKeyword('debugger', _emberHtmlbarsKeywordsDebugger.default);
  _emberHtmlbarsKeywords.registerKeyword('with', _emberHtmlbarsKeywordsWith.default);
  _emberHtmlbarsKeywords.registerKeyword('outlet', _emberHtmlbarsKeywordsOutlet.default);
  _emberHtmlbarsKeywords.registerKeyword('unbound', _emberHtmlbarsKeywordsUnbound.default);
  _emberHtmlbarsKeywords.registerKeyword('component', _emberHtmlbarsKeywordsComponent.default);
  _emberHtmlbarsKeywords.registerKeyword('@element_component', _emberHtmlbarsKeywordsElementComponent.default);
  _emberHtmlbarsKeywords.registerKeyword('partial', _emberHtmlbarsKeywordsPartial.default);
  _emberHtmlbarsKeywords.registerKeyword('input', _emberHtmlbarsKeywordsInput.default);
  _emberHtmlbarsKeywords.registerKeyword('textarea', _emberHtmlbarsKeywordsTextarea.default);
  _emberHtmlbarsKeywords.registerKeyword('yield', _emberHtmlbarsKeywordsYield.default);
  _emberHtmlbarsKeywords.registerKeyword('mut', _emberHtmlbarsKeywordsMut.default);
  _emberHtmlbarsKeywords.registerKeyword('@mut', _emberHtmlbarsKeywordsMut.privateMut);
  _emberHtmlbarsKeywords.registerKeyword('readonly', _emberHtmlbarsKeywordsReadonly.default);
  _emberHtmlbarsKeywords.registerKeyword('get', _emberHtmlbarsKeywordsGet.default);

  if (_emberMetal.default.ENV._ENABLE_LEGACY_VIEW_SUPPORT) {
    _emberHtmlbarsKeywords.registerKeyword('view', _emberHtmlbarsKeywordsView.default);
  }

  exports.default = {
    hooks: emberHooks,
    helpers: _emberHtmlbarsHelpers.default,
    useFragmentCache: true
  };

  var domHelper = _emberMetalEnvironment.default.hasDOM ? new _emberHtmlbarsSystemDomHelper.default() : null;

  exports.domHelper = domHelper;
});
enifed('ember-htmlbars/glimmer-component', ['exports', 'ember-views/views/core_view', 'ember-views/mixins/view_child_views_support', 'ember-views/mixins/view_state_support', 'ember-views/mixins/template_rendering_support', 'ember-views/mixins/class_names_support', 'ember-views/mixins/instrumentation_support', 'ember-views/mixins/aria_role_support', 'ember-views/mixins/view_support', 'ember-views/views/view'], function (exports, _emberViewsViewsCore_view, _emberViewsMixinsView_child_views_support, _emberViewsMixinsView_state_support, _emberViewsMixinsTemplate_rendering_support, _emberViewsMixinsClass_names_support, _emberViewsMixinsInstrumentation_support, _emberViewsMixinsAria_role_support, _emberViewsMixinsView_support, _emberViewsViewsView) {
  'use strict';

  exports.default = _emberViewsViewsCore_view.default.extend(_emberViewsMixinsView_child_views_support.default, _emberViewsMixinsView_state_support.default, _emberViewsMixinsTemplate_rendering_support.default, _emberViewsMixinsClass_names_support.default, _emberViewsMixinsInstrumentation_support.default, _emberViewsMixinsAria_role_support.default, _emberViewsMixinsView_support.default, {
    isComponent: true,
    isGlimmerComponent: true,

    init: function () {
      this._super.apply(this, arguments);
      this._viewRegistry = this._viewRegistry || _emberViewsViewsView.default.views;
    }
  });
});
enifed('ember-htmlbars/helper', ['exports', 'ember-runtime/system/object'], function (exports, _emberRuntimeSystemObject) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  exports.helper = helper;

  /**
    Ember Helpers are functions that can compute values, and are used in templates.
    For example, this code calls a helper named `format-currency`:

    ```handlebars
    <div>{{format-currency cents currency="$"}}</div>
    ```

    Additionally, a helper can be called as a nested helper (sometimes called a
    subexpression). In this example, the computed value of a helper is passed
    to a component named `show-money`:

    ```handlebars
    {{show-money amount=(format-currency cents currency="$")}}
    ```

    Helpers defined using a class must provide a `compute` function. For example:

    ```js
    export default Ember.Helper.extend({
      compute(params, hash) {
        let cents = params[0];
        let currency = hash.currency;
        return `${currency}${cents * 0.01}`;
      }
    });
    ```

    Each time the input to a helper changes, the `compute` function will be
    called again.

    As instances, these helpers also have access to the container and will accept
    injected dependencies.

    Additionally, class helpers can call `recompute` to force a new computation.

    @class Ember.Helper
    @public
    @since 1.13.0
  */
  var Helper = _emberRuntimeSystemObject.default.extend({
    isHelperInstance: true,

    /**
      On a class-based helper, it may be useful to force a recomputation of that
      helpers value. This is akin to `rerender` on a component.
       For example, this component will rerender when the `currentUser` on a
      session service changes:
       ```js
      // app/helpers/current-user-email.js
      export default Ember.Helper.extend({
        session: Ember.inject.service(),
        onNewUser: Ember.observer('session.currentUser', function() {
          this.recompute();
        }),
        compute() {
          return this.get('session.currentUser.email');
        }
      });
      ```
       @method recompute
      @public
      @since 1.13.0
    */
    recompute: function () {
      this._stream.notify();
    }

    /**
      Override this function when writing a class-based helper.
       @method compute
      @param {Array} params The positional arguments to the helper
      @param {Object} hash The named arguments to the helper
      @public
      @since 1.13.0
    */
  });

  Helper.reopenClass({
    isHelperFactory: true
  });

  /**
    In many cases, the ceremony of a full `Ember.Helper` class is not required.
    The `helper` method create pure-function helpers without instances. For
    example:

    ```js
    // app/helpers/format-currency.js
    export default Ember.Helper.helper(function(params, hash) {
      let cents = params[0];
      let currency = hash.currency;
      return `${currency}${cents * 0.01}`;
    });
    ```

    @static
    @param {Function} helper The helper function
    @method helper
    @public
    @since 1.13.0
  */

  function helper(helperFn) {
    return {
      isHelperInstance: true,
      compute: helperFn
    };
  }

  exports.default = Helper;
});
enifed('ember-htmlbars/helpers', ['exports', 'ember-metal/empty_object'], function (exports, _emberMetalEmpty_object) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  /**
   @private
   @property helpers
  */
  'use strict';

  exports.registerHelper = registerHelper;

  var helpers = new _emberMetalEmpty_object.default();

  /**
  @module ember
  @submodule ember-htmlbars
  */

  /**
    @private
    @method _registerHelper
    @for Ember.HTMLBars
    @param {String} name
    @param {Object|Function} helperFunc The helper function to add.
  */

  function registerHelper(name, helperFunc) {
    helpers[name] = helperFunc;
  }

  exports.default = helpers;
});
enifed('ember-htmlbars/helpers/-html-safe', ['exports', 'htmlbars-util/safe-string'], function (exports, _htmlbarsUtilSafeString) {
  'use strict';

  exports.default = htmlSafeHelper;

  /**
   This private helper is used internally to handle `isVisible: false` for
   Ember.View and Ember.Component.

   @private
   */

  function htmlSafeHelper(_ref) {
    var value = _ref[0];

    return new _htmlbarsUtilSafeString.default(value);
  }
});
enifed('ember-htmlbars/helpers/-join-classes', ['exports'], function (exports) {
  /*
    This private helper is used to join and compact a list of class names.

    @private
  */

  'use strict';

  exports.default = joinClasses;

  function joinClasses(classNames) {
    var result = [];

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

      if (className) {
        result.push(className);
      }
    }

    return result.join(' ');
  }
});
enifed('ember-htmlbars/helpers/-normalize-class', ['exports', 'ember-runtime/system/string', 'ember-metal/path_cache'], function (exports, _emberRuntimeSystemString, _emberMetalPath_cache) {
  'use strict';

  exports.default = normalizeClass;

  /*
    This private helper is used by ComponentNode to convert the classNameBindings
    microsyntax into a class name.

    When a component or view is created, we normalize class name bindings into a
    series of attribute nodes that use this helper.

    @private
  */

  function normalizeClass(params, hash) {
    var propName = params[0];
    var value = params[1];
    var activeClass = hash.activeClass;
    var inactiveClass = hash.inactiveClass;

    // When using the colon syntax, evaluate the truthiness or falsiness
    // of the value to determine which className to return.
    if (activeClass || inactiveClass) {
      if (!!value) {
        return activeClass;
      } else {
        return inactiveClass;
      }

      // If value is a Boolean and true, return the dasherized property
      // name.
    } else if (value === true) {
        // Only apply to last segment in the path.
        if (propName && _emberMetalPath_cache.isPath(propName)) {
          var segments = propName.split('.');
          propName = segments[segments.length - 1];
        }

        return _emberRuntimeSystemString.dasherize(propName);

        // If the value is not false, undefined, or null, return the current
        // value of the property.
      } else if (value !== false && value != null) {
          return value;

          // Nothing to display. Return null so that the old class is removed
          // but no new class is added.
        } else {
            return null;
          }
  }
});
enifed('ember-htmlbars/helpers/concat', ['exports'], function (exports) {
  /**
  @module ember
  @submodule ember-templates
  */

  /**
    Concatenates input params together.
    Example:
    ```handlebars
    {{some-component name=(concat firstName " " lastName)}}
    {{! would pass name="<first name value> <last name value>" to the component}}
    ```
    @public
    @method concat
    @for Ember.Templates.helpers
    @since 1.13.0
  */
  'use strict';

  exports.default = concat;

  function concat(params) {
    return params.join('');
  }
});
enifed('ember-htmlbars/helpers/each-in', ['exports', 'ember-views/streams/should_display'], function (exports, _emberViewsStreamsShould_display) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  /**
    The `{{each-in}}` helper loops over properties on an object. It is unbound,
    in that new (or removed) properties added to the target object will not be
    rendered.

    For example, given a `user` object that looks like:

    ```javascript
    {
      "name": "Shelly Sails",
      "age": 42
    }
    ```

    This template would display all properties on the `user`
    object in a list:

    ```handlebars
    <ul>
    {{#each-in user as |key value|}}
      <li>{{key}}: {{value}}</li>
    {{/each-in}}
    </ul>
    ```

    Outputting their name and age.

    @method each-in
    @for Ember.Templates.helpers
    @public
    @since 2.1.0
  */
  var eachInHelper = function (_ref, hash, blocks) {
    var object = _ref[0];

    var objKeys, prop, i;
    objKeys = object ? Object.keys(object) : [];
    if (_emberViewsStreamsShould_display.default(objKeys)) {
      for (i = 0; i < objKeys.length; i++) {
        prop = objKeys[i];
        blocks.template.yieldItem(prop, [prop, object[prop]]);
      }
    } else if (blocks.inverse.yield) {
      blocks.inverse.yield();
    }
  };

  exports.default = eachInHelper;
});
enifed('ember-htmlbars/helpers/each', ['exports', 'ember-views/streams/should_display', 'ember-htmlbars/utils/decode-each-key'], function (exports, _emberViewsStreamsShould_display, _emberHtmlbarsUtilsDecodeEachKey) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  exports.default = eachHelper;

  /**
    The `{{#each}}` helper loops over elements in a collection. It is an extension
    of the base Handlebars `{{#each}}` helper.

    The default behavior of `{{#each}}` is to yield its inner block once for every
    item in an array passing the item as the first block parameter.

    ```javascript
    var developers = [{name: 'Yehuda'},{name: 'Tom'}, {name: 'Paul'}];
    ```

    ```handlebars
    {{#each developers key="name" as |person|}}
      {{person.name}}
      {{! `this` is whatever it was outside the #each }}
    {{/each}}
    ```

    The same rules apply to arrays of primitives.

    ```javascript
    var developerNames = ['Yehuda', 'Tom', 'Paul']
    ```

    ```handlebars
    {{#each developerNames key="@index" as |name|}}
      {{name}}
    {{/each}}
    ```

    During iteration, the index of each item in the array is provided as a second block parameter.

    ```handlebars
    <ul>
      {{#each people as |person index|}}
        <li>Hello, {{person.name}}! You're number {{index}} in line</li>
      {{/each}}
    </ul>
    ```

    ### Specifying Keys

    The `key` option is used to tell Ember how to determine if the array being
    iterated over with `{{#each}}` has changed between renders. By helping Ember
    detect that some elements in the array are the same, DOM elements can be
    re-used, significantly improving rendering speed.

    For example, here's the `{{#each}}` helper with its `key` set to `id`:

    ```handlebars
    {{#each model key="id" as |item|}}
    {{/each}}
    ```

    When this `{{#each}}` re-renders, Ember will match up the previously rendered
    items (and reorder the generated DOM elements) based on each item's `id`
    property.

    By default the item's own reference is used.

    ### {{else}} condition

    `{{#each}}` can have a matching `{{else}}`. The contents of this block will render
    if the collection is empty.

    ```handlebars
    {{#each developers as |person|}}
      {{person.name}}
    {{else}}
      <p>Sorry, nobody is available for this task.</p>
    {{/each}}
    ```

    @method each
    @for Ember.Templates.helpers
    @public
  */

  function eachHelper(params, hash, blocks) {
    var list = params[0];
    var keyPath = hash.key;

    if (_emberViewsStreamsShould_display.default(list)) {
      forEach(list, function (item, i) {
        var key = _emberHtmlbarsUtilsDecodeEachKey.default(item, keyPath, i);

        blocks.template.yieldItem(key, [item, i]);
      });
    } else if (blocks.inverse.yield) {
      blocks.inverse.yield();
    }
  }

  function forEach(iterable, cb) {
    return iterable.forEach ? iterable.forEach(cb) : Array.prototype.forEach.call(iterable, cb);
  }
});
enifed("ember-htmlbars/helpers/hash", ["exports"], function (exports) {
   /**
   @module ember
   @submodule ember-templates
   */

   /**
      Use the `{{hash}}` helper to create a hash to pass as an option to your
      components. This is specially useful for contextual components where you can
      just yield a hash:
      ```handlebars
      {{yield (hash
         name='Sarah'
         title=office
      )}}
      ```
      Would result in an object such as:
      ```js
      { name: 'Sarah', title: this.get('office') }
      ```
      Where the `title` is bound to updates of the `office` property.
      @method hash
      @for Ember.Templates.helpers
      @param {Object} options
      @return {Object} Hash
      @public
    */

   "use strict";

   exports.default = hashHelper;

   function hashHelper(params, hash, options) {
      return hash;
   }
});
enifed('ember-htmlbars/helpers/if_unless', ['exports', 'ember-metal/debug', 'ember-views/streams/should_display'], function (exports, _emberMetalDebug, _emberViewsStreamsShould_display) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  /**
    Use the `if` block helper to conditionally render a block depending on a
    property. If the property is "falsey", for example: `false`, `undefined`,
   `null`, `""`, `0`, `NaN` or an empty array, the block will not be rendered.

   ```handlebars
    {{! will not render if foo is falsey}}
    {{#if foo}}
      Welcome to the {{foo.bar}}
    {{/if}}
    ```

    You can also specify a template to show if the property is falsey by using
    the `else` helper.

    ```handlebars
    {{! is it raining outside?}}
    {{#if isRaining}}
      Yes, grab an umbrella!
    {{else}}
      No, it's lovely outside!
    {{/if}}
    ```

    You are also able to combine `else` and `if` helpers to create more complex
    conditional logic.

    ```handlebars
    {{#if isMorning}}
      Good morning
    {{else if isAfternoon}}
      Good afternoon
    {{else}}
      Good night
    {{/if}}
    ```

    You can use `if` inline to conditionally render a single property or string.
    This helper acts like a ternary operator. If the first property is truthy,
    the second argument will be displayed, if not, the third argument will be
    displayed

    ```handlebars
    {{if useLongGreeting "Hello" "Hi"}} Dave
    ```

    Finally, you can use the `if` helper inside another helper as a subexpression.

    ```handlebars
    {{some-component height=(if isBig "100" "10")}}
    ```

    @method if
    @for Ember.Templates.helpers
    @public
  */
  function ifHelper(params, hash, options) {
    return ifUnless(params, hash, options, _emberViewsStreamsShould_display.default(params[0]));
  }

  /**
    The `unless` helper is the inverse of the `if` helper. Its block will be
    rendered if the expression contains a falsey value.  All forms of the `if`
    helper can also be used with `unless`.

    @method unless
    @for Ember.Templates.helpers
    @public
  */
  function unlessHelper(params, hash, options) {
    return ifUnless(params, hash, options, !_emberViewsStreamsShould_display.default(params[0]));
  }

  function ifUnless(params, hash, options, truthy) {
    _emberMetalDebug.assert('The block form of the `if` and `unless` helpers expect exactly one ' + 'argument, e.g. `{{#if newMessages}} You have new messages. {{/if}}.`', !options.template.yield || params.length === 1);

    _emberMetalDebug.assert('The inline form of the `if` and `unless` helpers expect two or ' + 'three arguments, e.g. `{{if trialExpired \'Expired\' expiryDate}}` ' + 'or `{{unless isFirstLogin \'Welcome back!\'}}`.', !!options.template.yield || params.length === 2 || params.length === 3);

    if (truthy) {
      if (options.template.yield) {
        options.template.yield();
      } else {
        return params[1];
      }
    } else {
      if (options.inverse.yield) {
        options.inverse.yield();
      } else {
        return params[2];
      }
    }
  }

  exports.ifHelper = ifHelper;
  exports.unlessHelper = unlessHelper;
});
enifed('ember-htmlbars/helpers/loc', ['exports', 'ember-htmlbars/helper', 'ember-runtime/system/string'], function (exports, _emberHtmlbarsHelper, _emberRuntimeSystemString) {
  'use strict';

  /**
  @module ember
  @submodule ember-templates
  */

  /**
    Calls [Ember.String.loc](/api/classes/Ember.String.html#method_loc) with the
    provided string. This is a convenient way to localize text within a template.
    For example:

    ```javascript
    Ember.STRINGS = {
      '_welcome_': 'Bonjour'
    };
    ```

    ```handlebars
    <div class='message'>
      {{loc '_welcome_'}}
    </div>
    ```

    ```html
    <div class='message'>
      Bonjour
    </div>
    ```

    See [Ember.String.loc](/api/classes/Ember.String.html#method_loc) for how to
    set up localized string references.

    @method loc
    @for Ember.Templates.helpers
    @param {String} str The string to format.
    @see {Ember.String#loc}
    @public
  */
  function locHelper(params) {
    return _emberRuntimeSystemString.loc.apply(null, params);
  }

  exports.default = _emberHtmlbarsHelper.helper(locHelper);
});
enifed('ember-htmlbars/helpers/log', ['exports', 'ember-metal/logger'], function (exports, _emberMetalLogger) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  exports.default = logHelper;

  /**
    `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.Templates.helpers
    @param {*} values
    @public
  */

  function logHelper(values) {
    _emberMetalLogger.default.log.apply(null, values);
  }
});
enifed('ember-htmlbars/helpers/with', ['exports', 'ember-views/streams/should_display'], function (exports, _emberViewsStreamsShould_display) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  exports.default = withHelper;

  /**
    Use the `{{with}}` helper when you want to alias a property to a new name. This is helpful
    for semantic clarity as it allows you to retain default scope or to reference a property from another
    `{{with}}` block.

    If the aliased property is "falsey", for example: `false`, `undefined` `null`, `""`, `0`, NaN or
    an empty array, the block will not be rendered.

    ```handlebars
    {{! Will only render if user.posts contains items}}
    {{#with user.posts as |blogPosts|}}
      <div class="notice">
        There are {{blogPosts.length}} blog posts written by {{user.name}}.
      </div>
      {{#each blogPosts as |post|}}
        <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|}}`.

    @method with
    @for Ember.Templates.helpers
    @param {Object} options
    @return {String} HTML string
    @public
  */

  function withHelper(params, hash, options) {
    if (_emberViewsStreamsShould_display.default(params[0])) {
      options.template.yield([params[0]]);
    } else if (options.inverse && options.inverse.yield) {
      options.inverse.yield([]);
    }
  }
});
enifed('ember-htmlbars/hooks/bind-block', ['exports'], function (exports) {
  'use strict';

  exports.default = bindBlock;

  function bindBlock(env, scope, block) {
    var name = arguments.length <= 3 || arguments[3] === undefined ? 'default' : arguments[3];

    scope.bindBlock(name, block);
  }
});
enifed('ember-htmlbars/hooks/bind-local', ['exports', 'ember-metal/streams/stream', 'ember-metal/streams/proxy-stream'], function (exports, _emberMetalStreamsStream, _emberMetalStreamsProxyStream) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = bindLocal;

  function bindLocal(env, scope, key, value) {
    // TODO: What is the cause of these cases?
    if (scope.hasOwnLocal(key)) {
      var existing = scope.getLocal(key);
      if (existing !== value) {
        existing.setSource(value);
      }
    } else {
      var newValue = _emberMetalStreamsStream.wrap(value, _emberMetalStreamsProxyStream.default, key);
      scope.bindLocal(key, newValue);
    }
  }
});
enifed("ember-htmlbars/hooks/bind-scope", ["exports"], function (exports) {
  "use strict";

  exports.default = bindScope;

  function bindScope(env, scope) {}
});
enifed('ember-htmlbars/hooks/bind-self', ['exports', 'ember-metal', 'ember-metal/streams/proxy-stream'], function (exports, _emberMetal, _emberMetalStreamsProxyStream) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = bindSelf;

  function bindSelf(env, scope, self) {
    if (self && self.isView) {
      if (!!_emberMetal.default.ENV._ENABLE_LEGACY_VIEW_SUPPORT) {
        scope.bindLocal('view', newStream(self, 'view'));
      }

      var _selfStream = newStream(self, '');

      if (self.isGlimmerComponent) {
        scope.bindSelf(_selfStream);
      } else {
        scope.bindSelf(newStream(_selfStream.getKey('context'), ''));
      }

      return;
    }

    var selfStream = newStream(self, '');
    scope.bindSelf(selfStream);
  }

  function newStream(newValue, key) {
    return new _emberMetalStreamsProxyStream.default(newValue, key);
  }
});
enifed('ember-htmlbars/hooks/bind-shadow-scope', ['exports', 'ember-metal/streams/proxy-stream'], function (exports, _emberMetalStreamsProxyStream) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = bindShadowScope;

  function bindShadowScope(env, parentScope, shadowScope, options) {
    if (!options) {
      return;
    }

    var view = options.view;
    if (view && !view.isComponent) {
      shadowScope.bindLocal('view', newStream(view, 'view'));

      if (view.isView) {
        shadowScope.bindSelf(newStream(shadowScope.getLocal('view').getKey('context'), ''));
      }
    }

    shadowScope.bindView(view);

    if (view && options.attrs) {
      shadowScope.bindComponent(view);
    }

    if ('attrs' in options) {
      shadowScope.bindAttrs(options.attrs);
    }

    return shadowScope;
  }

  function newStream(newValue, key) {
    return new _emberMetalStreamsProxyStream.default(newValue, key);
  }
});
enifed('ember-htmlbars/hooks/classify', ['exports', 'ember-htmlbars/utils/is-component'], function (exports, _emberHtmlbarsUtilsIsComponent) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = classify;

  function classify(env, scope, path) {
    if (_emberHtmlbarsUtilsIsComponent.default(env, scope, path)) {
      return 'component';
    }

    return null;
  }
});
enifed("ember-htmlbars/hooks/cleanup-render-node", ["exports"], function (exports) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  "use strict";

  exports.default = cleanupRenderNode;

  function cleanupRenderNode(renderNode) {
    if (renderNode.cleanup) {
      renderNode.cleanup();
    }
  }
});
enifed('ember-htmlbars/hooks/component', ['exports', 'ember-metal/features', 'ember-metal/debug', 'ember-htmlbars/node-managers/component-node-manager', 'ember-views/system/build-component-template', 'ember-htmlbars/utils/lookup-component', 'ember-metal/assign', 'ember-metal/empty_object', 'ember-metal/cache', 'ember-htmlbars/system/lookup-helper', 'ember-htmlbars/utils/extract-positional-params', 'ember-htmlbars/keywords/closure-component'], function (exports, _emberMetalFeatures, _emberMetalDebug, _emberHtmlbarsNodeManagersComponentNodeManager, _emberViewsSystemBuildComponentTemplate, _emberHtmlbarsUtilsLookupComponent, _emberMetalAssign, _emberMetalEmpty_object, _emberMetalCache, _emberHtmlbarsSystemLookupHelper, _emberHtmlbarsUtilsExtractPositionalParams, _emberHtmlbarsKeywordsClosureComponent) {
  'use strict';

  exports.default = componentHook;

  var IS_ANGLE_CACHE = new _emberMetalCache.default(1000, function (key) {
    return key.match(/^(@?)<(.*)>$/);
  });

  function componentHook(renderNode, env, scope, _tagName, params, attrs, templates, visitor) {
    var state = renderNode.getState();

    var tagName = _tagName;
    if (_emberHtmlbarsSystemLookupHelper.CONTAINS_DOT_CACHE.get(tagName)) {
      var stream = env.hooks.get(env, scope, tagName);
      var componentCell = stream.value();
      if (_emberHtmlbarsKeywordsClosureComponent.isComponentCell(componentCell)) {
        tagName = componentCell[_emberHtmlbarsKeywordsClosureComponent.COMPONENT_PATH];

        /*
         * Processing positional params before merging into a hash must be done
         * here to avoid problems with rest positional parameters rendered using
         * the dot notation.
         *
         * Closure components (for the contextual component feature) do not
         * actually keep the positional params, but process them at each level.
         * Therefore, when rendering a closure component with the component
         * helper we process the parameters and attributes and then merge those
         * on top of the closure component attributes.
         *
         */
        var newAttrs = _emberMetalAssign.default(new _emberMetalEmpty_object.default(), attrs);
        _emberHtmlbarsKeywordsClosureComponent.processPositionalParamsFromCell(componentCell, params, newAttrs);
        params = [];
        attrs = _emberHtmlbarsKeywordsClosureComponent.mergeInNewHash(componentCell[_emberHtmlbarsKeywordsClosureComponent.COMPONENT_HASH], newAttrs);
      }
    }

    // Determine if this is an initial render or a re-render.
    if (state.manager) {
      var sm = state.manager;
      var templateMeta = null;
      if (sm.block) {
        templateMeta = sm.block.template.meta;
      } else if (sm.scope && sm.scope._view) {
        templateMeta = sm.scope._view.template.meta;
      }
      env.meta.moduleName = templateMeta && templateMeta.moduleName || env.meta && env.meta.moduleName;
      _emberHtmlbarsUtilsExtractPositionalParams.default(renderNode, sm.component.constructor, params, attrs, false);
      state.manager.rerender(env, attrs, visitor);
      return;
    }

    var isAngleBracket = false;
    var isTopLevel = false;
    var isDasherized = false;

    var angles = IS_ANGLE_CACHE.get(tagName);

    if (angles) {
      tagName = angles[2];
      isAngleBracket = true;
      isTopLevel = !!angles[1];
    }

    if (_emberHtmlbarsSystemLookupHelper.CONTAINS_DASH_CACHE.get(tagName)) {
      isDasherized = true;
    }

    var parentView = env.view;

    // | Top-level    | Invocation: <foo-bar>    | Invocation: {{foo-bar}}  |
    // ----------------------------------------------------------------------
    // | <div>        | <div> is component el    | no special semantics (a) |
    // | <foo-bar>    | <foo-bar> is identity el | EWTF                     |
    // | <bar-baz>    | recursive invocation     | no special semantics     |
    // | {{anything}} | EWTF                     | no special semantics     |
    //
    // (a) needs to be implemented specially, because the usual semantics of
    //     <div> are defined by the compiled template, and we need to emulate
    //     those semantics.

    var currentComponent = env.view;
    var isInvokedWithAngles = currentComponent && currentComponent._isAngleBracket;
    var isInvokedWithCurlies = currentComponent && !currentComponent._isAngleBracket;

    // <div> at the top level of a <foo-bar> invocation.
    var isComponentHTMLElement = isAngleBracket && !isDasherized && isInvokedWithAngles;

    // <foo-bar> at the top level of a <foo-bar> invocation.
    var isComponentIdentityElement = isAngleBracket && isTopLevel && tagName === env.view.tagName;

    // <div> at the top level of a {{foo-bar}} invocation.
    var isNormalHTMLElement = isAngleBracket && !isDasherized && isInvokedWithCurlies;

    var component = undefined,
        layout = undefined;
    if (isDasherized || !isAngleBracket) {
      var options = {};

      var moduleName = env.meta && env.meta.moduleName;

      if (moduleName) {
        options.source = 'template:' + moduleName;
      }

      var result = _emberHtmlbarsUtilsLookupComponent.default(env.owner, tagName, options);

      component = result.component;
      layout = result.layout;

      if (isAngleBracket && isDasherized && !component && !layout) {
        isComponentHTMLElement = true;
      } else {
        _emberMetalDebug.assert('HTMLBars error: Could not find component named "' + tagName + '" (no component or template with that name was found)', !!(component || layout));
      }
    }

    if (isComponentIdentityElement || isComponentHTMLElement) {
      // Inside the layout for <foo-bar> invoked with angles, this is the top-level element
      // for the component. It can either be `<foo-bar>` (the "identity element") or any
      // normal HTML element (non-dasherized).
      var templateOptions = {
        component: currentComponent,
        tagName: tagName,
        isAngleBracket: true,
        isComponentElement: true,
        outerAttrs: scope.getAttrs(),
        parentScope: scope
      };

      var contentOptions = { templates: templates, scope: scope };

      var _buildComponentTemplate = _emberViewsSystemBuildComponentTemplate.default(templateOptions, attrs, contentOptions);

      var block = _buildComponentTemplate.block;

      block.invoke(env, [], undefined, renderNode, scope, visitor);
    } else if (isNormalHTMLElement) {
      var block = _emberViewsSystemBuildComponentTemplate.buildHTMLTemplate(tagName, attrs, { templates: templates, scope: scope });
      block.invoke(env, [], undefined, renderNode, scope, visitor);
    } else {
      // Invoking a component from the outside (either via <foo-bar> angle brackets
      // or {{foo-bar}} legacy curlies).

      var manager = _emberHtmlbarsNodeManagersComponentNodeManager.default.create(renderNode, env, {
        tagName: tagName,
        params: params,
        attrs: attrs,
        parentView: parentView,
        templates: templates,
        isAngleBracket: isAngleBracket,
        isTopLevel: isTopLevel,
        component: component,
        layout: layout,
        parentScope: scope
      });

      state.manager = manager;
      manager.render(env, visitor);
    }
  }
});
enifed('ember-htmlbars/hooks/concat', ['exports', 'ember-metal/streams/utils'], function (exports, _emberMetalStreamsUtils) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = concat;

  function concat(env, parts) {
    return _emberMetalStreamsUtils.concat(parts, '');
  }
});
enifed('ember-htmlbars/hooks/create-fresh-scope', ['exports', 'ember-metal/streams/proxy-stream', 'ember-metal/empty_object'], function (exports, _emberMetalStreamsProxyStream, _emberMetalEmpty_object) {
  'use strict';

  exports.default = createFreshScope;
  exports.createChildScope = createChildScope;

  /*
    Ember's implementation of HTMLBars creates an enriched scope.

    * self: same as HTMLBars, this field represents the dynamic lookup
      of root keys that are not special keywords or block arguments.
    * blocks: same as HTMLBars, a bundle of named blocks the layout
      can yield to.
    * component: indicates that the scope is the layout of a component,
      which is used to trigger lifecycle hooks for the component when
      one of the streams in its layout fires.
    * attrs: a map of key-value attributes sent in by the invoker of
      a template, and available in the component's layout.
    * locals: a map of locals, produced by block params (`as |a b|`)
    * localPresent: a map of available locals to avoid expensive
      `hasOwnProperty` checks.

    The `self` field has two special meanings:

    * If `self` is a view (`isView`), the actual HTMLBars `self` becomes
      the view's `context`. This is legacy semantics; components always
      use the component itself as the `this`.
    * If `self` is a view, two special locals are created: `view` and
      `controller`. These locals are legacy semantics.

    **IMPORTANT**: There are two places in Ember where the ambient
    controller is looked up. Both of those places use the presence
    of `scope.locals.view` to indicate that the controller lookup
    should be dynamic off of the ambient view. If `scope.locals.view`
    does not exist, the code assumes that it is inside of a top-level
    template (without a view) and uses the `self` itself as the
    controller. This means that if you remove `scope.locals.view`
    (perhaps because we are finally ready to shed the view keyword),
    there may be unexpected consequences on controller semantics.
    If this happens to you, I hope you find this comment. - YK & TD

    In practice, this means that with the exceptions of top-level
    view-less templates and the legacy `controller=foo` semantics,
    the controller hierarchy is managed dynamically by looking at
    the current view's `controller`.
  */

  function Scope(parent) {
    this._self = undefined;
    this._blocks = undefined;
    this._component = undefined;
    this._view = undefined;
    this._attrs = undefined;
    this._locals = undefined;
    this._localPresent = undefined;
    this.overrideController = undefined;
    this.parent = parent;
  }

  var proto = Scope.prototype;

  proto.getSelf = function () {
    return this._self || this.parent.getSelf();
  };

  proto.bindSelf = function (self) {
    this._self = self;
  };

  proto.updateSelf = function (self, key) {
    var existing = this._self;

    if (existing) {
      existing.setSource(self);
    } else {
      this._self = new _emberMetalStreamsProxyStream.default(self, key);
    }
  };

  proto.getBlock = function (name) {
    if (!this._blocks) {
      return this.parent.getBlock(name);
    }
    return this._blocks[name] || this.parent.getBlock(name);
  };

  proto.hasBlock = function (name) {
    if (!this._blocks) {
      return this.parent.hasBlock(name);
    }
    return !!(this._blocks[name] || this.parent.hasBlock(name));
  };

  proto.bindBlock = function (name, block) {
    if (!this._blocks) {
      this._blocks = new _emberMetalEmpty_object.default();
    }
    this._blocks[name] = block;
  };

  proto.getComponent = function () {
    return this._component || this.parent.getComponent();
  };

  proto.bindComponent = function (component) {
    this._component = component;
  };

  proto.getView = function () {
    return this._view || this.parent.getView();
  };

  proto.bindView = function (view) {
    this._view = view;
  };

  proto.getAttrs = function () {
    return this._attrs || this.parent.getAttrs();
  };

  proto.bindAttrs = function (attrs) {
    this._attrs = attrs;
  };

  proto.hasLocal = function (name) {
    if (!this._localPresent) {
      return this.parent.hasLocal(name);
    }
    return this._localPresent[name] || this.parent.hasLocal(name);
  };

  proto.hasOwnLocal = function (name) {
    return this._localPresent && this._localPresent[name];
  };

  proto.getLocal = function (name) {
    if (!this._localPresent) {
      return this.parent.getLocal(name);
    }
    return this._localPresent[name] ? this._locals[name] : this.parent.getLocal(name);
  };

  proto.bindLocal = function (name, value) {
    if (!this._localPresent) {
      this._localPresent = new _emberMetalEmpty_object.default();
      this._locals = new _emberMetalEmpty_object.default();
    }

    this._localPresent[name] = true;
    this._locals[name] = value;
  };

  var EMPTY = {
    _self: undefined,
    _blocks: undefined,
    _component: undefined,
    _view: undefined,
    _attrs: undefined,
    _locals: undefined,
    _localPresent: undefined,
    overrideController: undefined,

    getSelf: function () {
      return null;
    },
    bindSelf: function (self) {
      return null;
    },
    updateSelf: function (self, key) {
      return null;
    },
    getBlock: function (name) {
      return null;
    },
    bindBlock: function (name, block) {
      return null;
    },
    hasBlock: function (name) {
      return false;
    },
    getComponent: function () {
      return null;
    },
    bindComponent: function () {
      return null;
    },
    getView: function () {
      return null;
    },
    bindView: function (view) {
      return null;
    },
    getAttrs: function () {
      return null;
    },
    bindAttrs: function (attrs) {
      return null;
    },
    hasLocal: function (name) {
      return false;
    },
    hasOwnLocal: function (name) {
      return false;
    },
    getLocal: function (name) {
      return null;
    },
    bindLocal: function (name, value) {
      return null;
    }
  };

  function createFreshScope() {
    return new Scope(EMPTY);
  }

  function createChildScope(parent) {
    return new Scope(parent);
  }
});
enifed("ember-htmlbars/hooks/destroy-render-node", ["exports"], function (exports) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  "use strict";

  exports.default = destroyRenderNode;

  function destroyRenderNode(renderNode) {
    if (renderNode.emberView) {
      renderNode.emberView.destroy();
    }

    var streamUnsubscribers = renderNode.streamUnsubscribers;
    if (streamUnsubscribers) {
      for (var i = 0, l = streamUnsubscribers.length; i < l; i++) {
        streamUnsubscribers[i]();
      }
    }
  }
});
enifed("ember-htmlbars/hooks/did-cleanup-tree", ["exports"], function (exports) {
  "use strict";

  exports.default = didCleanupTree;

  function didCleanupTree(env) {
    // Once we have finsihed cleaning up the render node and sub-nodes, reset
    // state tracking which view those render nodes belonged to.
    env.view.ownerView._destroyingSubtreeForView = null;
  }
});
enifed("ember-htmlbars/hooks/did-render-node", ["exports"], function (exports) {
  "use strict";

  exports.default = didRenderNode;

  function didRenderNode(morph, env) {
    env.renderedNodes.add(morph);
  }
});
enifed('ember-htmlbars/hooks/element', ['exports', 'ember-htmlbars/system/lookup-helper', 'htmlbars-runtime/hooks', 'ember-htmlbars/system/invoke-helper'], function (exports, _emberHtmlbarsSystemLookupHelper, _htmlbarsRuntimeHooks, _emberHtmlbarsSystemInvokeHelper) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = emberElement;

  function emberElement(morph, env, scope, path, params, hash, visitor) {
    if (_htmlbarsRuntimeHooks.handleRedirect(morph, env, scope, path, params, hash, null, null, visitor)) {
      return;
    }

    var result;
    var helper = _emberHtmlbarsSystemLookupHelper.findHelper(path, scope.getSelf(), env);
    if (helper) {
      var helperStream = _emberHtmlbarsSystemInvokeHelper.buildHelperStream(helper, params, hash, { element: morph.element }, env, scope, path);
      result = helperStream.value();
    } else {
      result = env.hooks.get(env, scope, path);
    }

    env.hooks.getValue(result);
  }
});
enifed("ember-htmlbars/hooks/get-block", ["exports"], function (exports) {
  "use strict";

  exports.default = getBlock;

  function getBlock(scope, key) {
    return scope.getBlock(key);
  }
});
enifed('ember-htmlbars/hooks/get-cell-or-value', ['exports', 'ember-metal/streams/utils', 'ember-htmlbars/keywords/mut'], function (exports, _emberMetalStreamsUtils, _emberHtmlbarsKeywordsMut) {
  'use strict';

  exports.default = getCellOrValue;

  function getCellOrValue(ref) {
    if (ref && ref[_emberHtmlbarsKeywordsMut.MUTABLE_REFERENCE]) {
      // Reify the mutable reference into a mutable cell.
      return ref.cell();
    }

    // Get the value out of the reference.
    return _emberMetalStreamsUtils.read(ref);
  }
});
enifed('ember-htmlbars/hooks/get-child', ['exports', 'ember-metal/streams/utils'], function (exports, _emberMetalStreamsUtils) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = getChild;

  function getChild(parent, key) {
    if (_emberMetalStreamsUtils.isStream(parent)) {
      return parent.getKey(key);
    }

    // This should only happen when we are looking at an `attrs` hash.
    // That might change if it is possible to pass object literals
    // through the templating system.
    return parent[key];
  }
});
enifed('ember-htmlbars/hooks/get-root', ['exports'], function (exports) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = getRoot;

  function getRoot(scope, key) {
    if (key === 'this') {
      return [scope.getSelf()];
    } else if (key === 'hasBlock') {
      return [!!scope.hasBlock('default')];
    } else if (key === 'hasBlockParams') {
      var block = scope.getBlock('default');
      return [!!block && block.arity];
    } else if (scope.hasLocal(key)) {
      return [scope.getLocal(key)];
    } else {
      return [getKey(scope, key)];
    }
  }

  function getKey(scope, key) {
    if (key === 'attrs') {
      var _attrs = scope.getAttrs();
      if (_attrs) {
        return _attrs;
      }
    }

    var self = scope.getSelf() || scope.getLocal('view');

    if (self) {
      return self.getKey(key);
    }

    var attrs = scope.getAttrs();
    if (attrs && key in attrs) {
      // TODO: attrs
      // deprecate("You accessed the `" + key + "` attribute directly. Please use `attrs." + key + "` instead.");
      return attrs[key];
    }
  }
});
enifed('ember-htmlbars/hooks/get-value', ['exports', 'ember-metal/streams/utils', 'ember-views/compat/attrs-proxy'], function (exports, _emberMetalStreamsUtils, _emberViewsCompatAttrsProxy) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = getValue;

  function getValue(ref) {
    var value = _emberMetalStreamsUtils.read(ref);

    if (value && value[_emberViewsCompatAttrsProxy.MUTABLE_CELL]) {
      return value.value;
    }

    return value;
  }
});
enifed('ember-htmlbars/hooks/has-helper', ['exports', 'ember-htmlbars/system/lookup-helper'], function (exports, _emberHtmlbarsSystemLookupHelper) {
  'use strict';

  exports.default = hasHelperHook;

  function hasHelperHook(env, scope, helperName) {
    if (env.helpers[helperName]) {
      return true;
    }

    var owner = env.owner;
    if (_emberHtmlbarsSystemLookupHelper.validateLazyHelperName(helperName, owner, env.hooks.keywords)) {
      var registrationName = 'helper:' + helperName;
      if (owner.hasRegistration(registrationName)) {
        return true;
      }

      var options = {};
      var moduleName = env.meta && env.meta.moduleName;
      if (moduleName) {
        options.source = 'template:' + moduleName;
      }

      if (owner.hasRegistration(registrationName, options)) {
        return true;
      }
    }

    return false;
  }
});
enifed('ember-htmlbars/hooks/invoke-helper', ['exports', 'ember-htmlbars/system/invoke-helper', 'ember-htmlbars/utils/subscribe'], function (exports, _emberHtmlbarsSystemInvokeHelper, _emberHtmlbarsUtilsSubscribe) {
  'use strict';

  exports.default = invokeHelper;

  function invokeHelper(morph, env, scope, visitor, params, hash, helper, templates, context) {
    var helperStream = _emberHtmlbarsSystemInvokeHelper.buildHelperStream(helper, params, hash, templates, env, scope);

    // Ember.Helper helpers are pure values, thus linkable.
    if (helperStream.linkable) {
      if (morph) {
        // When processing an inline expression, the params and hash have already
        // been linked. Thus, HTMLBars will not link the returned helperStream.
        // We subscribe the morph to the helperStream here, and also subscribe
        // the helperStream to any params.
        var addedDependency = false;
        for (var i = 0, l = params.length; i < l; i++) {
          addedDependency = true;
          helperStream.addDependency(params[i]);
        }
        for (var key in hash) {
          addedDependency = true;
          helperStream.addDependency(hash[key]);
        }
        if (addedDependency) {
          _emberHtmlbarsUtilsSubscribe.default(morph, env, scope, helperStream);
        }
      }

      return { link: true, value: helperStream };
    }

    // Built-in helpers are not linkable. They must run on every rerender.
    return { value: helperStream.value() };
  }
});
enifed('ember-htmlbars/hooks/link-render-node', ['exports', 'ember-htmlbars/utils/subscribe', 'ember-runtime/utils', 'ember-metal/streams/utils', 'ember-htmlbars/system/lookup-helper', 'ember-htmlbars/keywords/closure-component'], function (exports, _emberHtmlbarsUtilsSubscribe, _emberRuntimeUtils, _emberMetalStreamsUtils, _emberHtmlbarsSystemLookupHelper, _emberHtmlbarsKeywordsClosureComponent) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = linkRenderNode;
  exports.linkParamsFor = linkParamsFor;

  function linkRenderNode(renderNode, env, scope, path, params, hash) {
    if (renderNode.streamUnsubscribers) {
      return true;
    }

    var keyword = env.hooks.keywords[path];
    if (keyword && keyword.link) {
      keyword.link(renderNode.getState(), params, hash);
    } else if (path === 'unbound') {
      return true;
    } else {
      linkParamsFor(path, params);
    }

    // If there is a dot in the path, we need to subscribe to the arguments in the
    // closure component as well.

    if (_emberHtmlbarsSystemLookupHelper.CONTAINS_DOT_CACHE.get(path)) {
      var stream = env.hooks.get(env, scope, path);
      var componentCell = stream.value();

      if (_emberHtmlbarsKeywordsClosureComponent.isComponentCell(componentCell)) {
        var closureAttrs = _emberHtmlbarsKeywordsClosureComponent.mergeInNewHash(componentCell[_emberHtmlbarsKeywordsClosureComponent.COMPONENT_HASH], hash);

        for (var key in closureAttrs) {
          _emberHtmlbarsUtilsSubscribe.default(renderNode, env, scope, closureAttrs[key]);
        }
      }
    }

    if (params && params.length) {
      for (var i = 0; i < params.length; i++) {
        _emberHtmlbarsUtilsSubscribe.default(renderNode, env, scope, params[i]);
      }
    }

    if (hash) {
      for (var key in hash) {
        _emberHtmlbarsUtilsSubscribe.default(renderNode, env, scope, hash[key]);
      }
    }

    // The params and hash can be reused. They don't need to be
    // recomputed on subsequent re-renders because they are
    // streams.
    return true;
  }

  function linkParamsFor(path, params) {
    switch (path) {
      case 'unless':
      case 'if':
        params[0] = shouldDisplay(params[0], toBool);break;
      case 'each':
        params[0] = eachParam(params[0]);break;
      case 'with':
        params[0] = shouldDisplay(params[0], identity);break;
    }
  }

  function eachParam(list) {
    var listChange = getKey(list, '[]');

    var stream = _emberMetalStreamsUtils.chain(list, function () {
      _emberMetalStreamsUtils.read(listChange);
      return _emberMetalStreamsUtils.read(list);
    }, 'each');

    stream.addDependency(listChange);
    return stream;
  }

  function shouldDisplay(predicate, coercer) {
    var length = getKey(predicate, 'length');
    var isTruthy = getKey(predicate, 'isTruthy');

    var stream = _emberMetalStreamsUtils.chain(predicate, function () {
      var predicateVal = _emberMetalStreamsUtils.read(predicate);
      var lengthVal = _emberMetalStreamsUtils.read(length);
      var isTruthyVal = _emberMetalStreamsUtils.read(isTruthy);

      if (_emberRuntimeUtils.isArray(predicateVal)) {
        return lengthVal > 0 ? coercer(predicateVal) : false;
      }

      if (typeof isTruthyVal === 'boolean') {
        return isTruthyVal ? coercer(predicateVal) : false;
      }

      return coercer(predicateVal);
    }, 'ShouldDisplay');

    _emberMetalStreamsUtils.addDependency(stream, length);
    _emberMetalStreamsUtils.addDependency(stream, isTruthy);

    return stream;
  }

  function toBool(value) {
    return !!value;
  }

  function identity(value) {
    return value;
  }

  function getKey(obj, key) {
    if (_emberMetalStreamsUtils.isStream(obj)) {
      return obj.getKey(key);
    } else {
      return obj && obj[key];
    }
  }
});
enifed('ember-htmlbars/hooks/lookup-helper', ['exports', 'ember-htmlbars/system/lookup-helper'], function (exports, _emberHtmlbarsSystemLookupHelper) {
  'use strict';

  exports.default = lookupHelperHook;

  function lookupHelperHook(env, scope, helperName) {
    return _emberHtmlbarsSystemLookupHelper.default(helperName, scope.getSelf(), env);
  }
});
enifed('ember-htmlbars/hooks/subexpr', ['exports', 'ember-htmlbars/system/lookup-helper', 'ember-htmlbars/system/invoke-helper', 'ember-metal/streams/utils', 'ember-htmlbars/hooks/link-render-node'], function (exports, _emberHtmlbarsSystemLookupHelper, _emberHtmlbarsSystemInvokeHelper, _emberMetalStreamsUtils, _emberHtmlbarsHooksLinkRenderNode) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = subexpr;
  exports.labelForSubexpr = labelForSubexpr;

  function subexpr(env, scope, helperName, params, hash) {
    // TODO: Keywords and helper invocation should be integrated into
    // the subexpr hook upstream in HTMLBars.
    var keyword = env.hooks.keywords[helperName];
    if (keyword) {
      return keyword(null, env, scope, params, hash, null, null);
    }

    _emberHtmlbarsHooksLinkRenderNode.linkParamsFor(helperName, params);

    var label = labelForSubexpr(params, hash, helperName);
    var helper = _emberHtmlbarsSystemLookupHelper.default(helperName, scope.getSelf(), env);

    var helperStream = _emberHtmlbarsSystemInvokeHelper.buildHelperStream(helper, params, hash, null, env, scope, label);

    for (var i = 0, l = params.length; i < l; i++) {
      helperStream.addDependency(params[i]);
    }

    for (var key in hash) {
      helperStream.addDependency(hash[key]);
    }

    return helperStream;
  }

  function labelForSubexpr(params, hash, helperName) {
    var paramsLabels = labelsForParams(params);
    var hashLabels = labelsForHash(hash);
    var label = '(' + helperName;

    if (paramsLabels) {
      label += ' ' + paramsLabels;
    }
    if (hashLabels) {
      label += ' ' + hashLabels;
    }

    return label + ')';
  }

  function labelsForParams(params) {
    return _emberMetalStreamsUtils.labelsFor(params).join(' ');
  }

  function labelsForHash(hash) {
    var out = [];

    for (var prop in hash) {
      out.push(prop + '=' + _emberMetalStreamsUtils.labelFor(hash[prop]));
    }

    return out.join(' ');
  }
});
enifed('ember-htmlbars/hooks/update-self', ['exports', 'ember-metal/debug', 'ember-metal/property_get'], function (exports, _emberMetalDebug, _emberMetalProperty_get) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = updateSelf;

  function updateSelf(env, scope, _self) {
    var self = _self;

    if (self && self.hasBoundController) {
      var _self2 = self;
      var controller = _self2.controller;

      self = self.self;

      scope.updateLocal('controller', controller || self);
    }

    _emberMetalDebug.assert('BUG: scope.attrs and self.isView should not both be true', !(scope.attrs && self.isView));

    if (self && self.isView) {
      scope.updateLocal('view', self);
      scope.updateSelf(_emberMetalProperty_get.get(self, 'context'), '');
      return;
    }

    scope.updateSelf(self);
  }
});
enifed("ember-htmlbars/hooks/will-cleanup-tree", ["exports"], function (exports) {
  "use strict";

  exports.default = willCleanupTree;

  function willCleanupTree(env) {
    var view = env.view;

    // When we go to clean up the render node and all of its children, we may
    // encounter views/components associated with those nodes along the way. In
    // those cases, we need to sever the link between the
    // existing view hierarchy and those views.
    //
    // However, we do *not* need to remove the child views of child views, since
    // severing the connection to their parent effectively severs them from the
    // view graph.
    //
    // For example, imagine the following view graph:
    //
    //    A
    //   / \
    //  B  C
    //    / \
    //   D  E
    //
    // If we are cleaning up the node for view C, we need to remove that view
    // from A's child views. However, we do not need to remove D and E from C's
    // child views, since removing C transitively removes D and E as well.
    //
    // To accomplish this, we track the nearest view to this render node on the
    // owner view, the root-most view in the graph (A in the example above). If
    // we detect a view that is a direct child of that view, we remove it from
    // the `childViews` array. Other parent/child view relationships are
    // untouched.  This view is then cleared once cleanup is complete in
    // `didCleanupTree`.
    view.ownerView._destroyingSubtreeForView = view;
  }
});
enifed('ember-htmlbars/index', ['exports', 'ember-metal/core', 'ember-template-compiler', 'ember-htmlbars/system/make_bound_helper', 'ember-htmlbars/helpers', 'ember-htmlbars/helpers/if_unless', 'ember-htmlbars/helpers/with', 'ember-htmlbars/helpers/loc', 'ember-htmlbars/helpers/log', 'ember-htmlbars/helpers/each', 'ember-htmlbars/helpers/each-in', 'ember-htmlbars/helpers/-normalize-class', 'ember-htmlbars/helpers/concat', 'ember-htmlbars/helpers/-join-classes', 'ember-htmlbars/helpers/-html-safe', 'ember-htmlbars/helpers/hash', 'ember-htmlbars/system/dom-helper', 'ember-htmlbars/helper', 'ember-htmlbars/template_registry', 'ember-htmlbars/system/bootstrap', 'ember-htmlbars/compat'], function (exports, _emberMetalCore, _emberTemplateCompiler, _emberHtmlbarsSystemMake_bound_helper, _emberHtmlbarsHelpers, _emberHtmlbarsHelpersIf_unless, _emberHtmlbarsHelpersWith, _emberHtmlbarsHelpersLoc, _emberHtmlbarsHelpersLog, _emberHtmlbarsHelpersEach, _emberHtmlbarsHelpersEachIn, _emberHtmlbarsHelpersNormalizeClass, _emberHtmlbarsHelpersConcat, _emberHtmlbarsHelpersJoinClasses, _emberHtmlbarsHelpersHtmlSafe, _emberHtmlbarsHelpersHash, _emberHtmlbarsSystemDomHelper, _emberHtmlbarsHelper, _emberHtmlbarsTemplate_registry, _emberHtmlbarsSystemBootstrap, _emberHtmlbarsCompat) {
  /**
    Ember templates are executed by [HTMLBars](https://github.com/tildeio/htmlbars),
    an HTML-friendly version of [Handlebars](http://handlebarsjs.com/). Any valid Handlebars syntax is valid in an Ember template.

    ### Showing a property

    Templates manage the flow of an application's UI, and display state (through
    the DOM) to a user. For example, given a component with the property "name",
    that component's template can use the name in several ways:

    ```javascript
    // app/components/person.js
    export default Ember.Component.extend({
      name: 'Jill'
    });
    ```

    ```handlebars
    {{! app/components/person.hbs }}
    {{name}}
    <div>{{name}}</div>
    <span data-name={{name}}></span>
    ```

    Any time the "name" property on the component changes, the DOM will be
    updated.

    Properties can be chained as well:

    ```handlebars
    {{aUserModel.name}}
    <div>{{listOfUsers.firstObject.name}}</div>
    ```

    ### Using Ember helpers

    When content is passed in mustaches `{{}}`, Ember will first try to find a helper
    or component with that name. For example, the `if` helper:

    ```handlebars
    {{if name "I have a name" "I have no name"}}
    <span data-has-name={{if name true}}></span>
    ```

    The returned value is placed where the `{{}}` is called. The above style is
    called "inline". A second style of helper usage is called "block". For example:

    ```handlebars
    {{#if name}}
      I have a name
    {{else}}
      I have no name
    {{/if}}
    ```

    The block form of helpers allows you to control how the UI is created based
    on the values of properties.

    A third form of helper is called "nested". For example here the concat
    helper will add " Doe" to a displayed name if the person has no last name:

    ```handlebars
    <span data-name={{concat firstName (
     if lastName (concat " " lastName) "Doe"
    )}}></span>
    ```

    Ember's built-in helpers are described under the [Ember.Templates.helpers](/api/classes/Ember.Templates.helpers.html)
    namespace. Documentation on creating custom helpers can be found under
    [Ember.Helper](/api/classes/Ember.Helper.html).

    ### Invoking a Component

    Ember components represent state to the UI of an application. Further
    reading on components can be found under [Ember.Component](/api/classes/Ember.Component.html).

    @module ember
    @submodule ember-templates
    @main ember-templates
    @public
  */

  /**

    [HTMLBars](https://github.com/tildeio/htmlbars) is a [Handlebars](http://handlebarsjs.com/)
    compatible templating engine used by Ember.js. The classes and namespaces
    covered by this documentation attempt to focus on APIs for interacting
    with HTMLBars itself. For more general guidance on Ember.js templates and
    helpers, please see the [ember-templates](/api/modules/ember-templates.html)
    package.

    @module ember
    @submodule ember-htmlbars
    @main ember-htmlbars
    @public
  */
  'use strict';

  _emberHtmlbarsHelpers.registerHelper('if', _emberHtmlbarsHelpersIf_unless.ifHelper);
  _emberHtmlbarsHelpers.registerHelper('unless', _emberHtmlbarsHelpersIf_unless.unlessHelper);
  _emberHtmlbarsHelpers.registerHelper('with', _emberHtmlbarsHelpersWith.default);
  _emberHtmlbarsHelpers.registerHelper('loc', _emberHtmlbarsHelpersLoc.default);
  _emberHtmlbarsHelpers.registerHelper('log', _emberHtmlbarsHelpersLog.default);
  _emberHtmlbarsHelpers.registerHelper('each', _emberHtmlbarsHelpersEach.default);
  _emberHtmlbarsHelpers.registerHelper('each-in', _emberHtmlbarsHelpersEachIn.default);
  _emberHtmlbarsHelpers.registerHelper('-normalize-class', _emberHtmlbarsHelpersNormalizeClass.default);
  _emberHtmlbarsHelpers.registerHelper('concat', _emberHtmlbarsHelpersConcat.default);
  _emberHtmlbarsHelpers.registerHelper('-join-classes', _emberHtmlbarsHelpersJoinClasses.default);
  _emberHtmlbarsHelpers.registerHelper('-html-safe', _emberHtmlbarsHelpersHtmlSafe.default);
  _emberHtmlbarsHelpers.registerHelper('hash', _emberHtmlbarsHelpersHash.default);

  _emberMetalCore.default.HTMLBars = {
    template: _emberTemplateCompiler.template,
    compile: _emberTemplateCompiler.compile,
    precompile: _emberTemplateCompiler.precompile,
    makeBoundHelper: _emberHtmlbarsSystemMake_bound_helper.default,
    registerPlugin: _emberTemplateCompiler.registerPlugin,
    DOMHelper: _emberHtmlbarsSystemDomHelper.default
  };

  _emberHtmlbarsHelper.default.helper = _emberHtmlbarsHelper.helper;
  _emberMetalCore.default.Helper = _emberHtmlbarsHelper.default;

  /**
    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 Object
    @private
  */
  Object.defineProperty(_emberMetalCore.default, 'TEMPLATES', {
    configurable: false,
    get: _emberHtmlbarsTemplate_registry.getTemplates,
    set: _emberHtmlbarsTemplate_registry.setTemplates
  });
});

// Importing adds template bootstrapping
// initializer to enable embedded templates.

// Importing ember-htmlbars/compat updates the
// Ember.Handlebars global if htmlbars is enabled.
enifed('ember-htmlbars/keywords', ['exports', 'htmlbars-runtime'], function (exports, _htmlbarsRuntime) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.registerKeyword = registerKeyword;

  /**
   @private
   @property helpers
  */
  var keywords = Object.create(_htmlbarsRuntime.hooks.keywords);

  /**
  @module ember
  @submodule ember-htmlbars
  */

  /**
    @private
    @method _registerHelper
    @for Ember.HTMLBars
    @param {String} name
    @param {Object|Function} keyword The keyword to add.
  */

  function registerKeyword(name, keyword) {
    keywords[name] = keyword;
  }

  exports.default = keywords;
});
enifed('ember-htmlbars/keywords/closure-component', ['exports', 'ember-metal/debug', 'ember-metal/is_none', 'ember-metal/symbol', 'ember-metal/streams/stream', 'ember-metal/empty_object', 'ember-metal/streams/utils', 'ember-htmlbars/hooks/subexpr', 'ember-metal/assign', 'ember-htmlbars/utils/extract-positional-params', 'ember-htmlbars/utils/lookup-component'], function (exports, _emberMetalDebug, _emberMetalIs_none, _emberMetalSymbol, _emberMetalStreamsStream, _emberMetalEmpty_object, _emberMetalStreamsUtils, _emberHtmlbarsHooksSubexpr, _emberMetalAssign, _emberHtmlbarsUtilsExtractPositionalParams, _emberHtmlbarsUtilsLookupComponent) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  exports.default = closureComponent;
  exports.isComponentCell = isComponentCell;
  exports.processPositionalParamsFromCell = processPositionalParamsFromCell;
  exports.mergeInNewHash = mergeInNewHash;
  var COMPONENT_REFERENCE = _emberMetalSymbol.default('COMPONENT_REFERENCE');
  exports.COMPONENT_REFERENCE = COMPONENT_REFERENCE;
  var COMPONENT_CELL = _emberMetalSymbol.default('COMPONENT_CELL');
  exports.COMPONENT_CELL = COMPONENT_CELL;
  var COMPONENT_PATH = _emberMetalSymbol.default('COMPONENT_PATH');
  exports.COMPONENT_PATH = COMPONENT_PATH;
  var COMPONENT_POSITIONAL_PARAMS = _emberMetalSymbol.default('COMPONENT_POSITIONAL_PARAMS');
  exports.COMPONENT_POSITIONAL_PARAMS = COMPONENT_POSITIONAL_PARAMS;
  var COMPONENT_HASH = _emberMetalSymbol.default('COMPONENT_HASH');

  exports.COMPONENT_HASH = COMPONENT_HASH;
  var ClosureComponentStream = _emberMetalStreamsStream.default.extend({
    init: function (env, path, params, hash) {
      this._env = env;
      this._path = path;
      this._params = params;
      this._hash = hash;
      this.label = _emberHtmlbarsHooksSubexpr.labelForSubexpr([path].concat(params), hash, 'component');
      this[COMPONENT_REFERENCE] = true;
    },
    compute: function () {
      return createClosureComponentCell(this._env, this._path, this._params, this._hash, this.label);
    }
  });

  function closureComponent(env, _ref3, hash) {
    var path = _ref3[0];

    var params = _ref3.slice(1);

    var s = new ClosureComponentStream(env, path, params, hash);

    s.addDependency(path);

    // FIXME: If the stream invalidates on every params or hash change, then
    // the {{component helper will be forced to re-render the whole component
    // each time. Instead, these dependencies should not be required and the
    // element component keyword should add the params and hash as dependencies.
    params.forEach(function (item) {
      return s.addDependency(item);
    });
    Object.keys(hash).forEach(function (key) {
      return s.addDependency(hash[key]);
    });

    return s;
  }

  function createClosureComponentCell(env, originalComponentPath, params, hash, label) {
    var componentPath = _emberMetalStreamsUtils.read(originalComponentPath);

    _emberMetalDebug.assert('Component path cannot be null in ' + label, !_emberMetalIs_none.default(componentPath));

    var newHash = _emberMetalAssign.default(new _emberMetalEmpty_object.default(), hash);

    if (isComponentCell(componentPath)) {
      return createNestedClosureComponentCell(componentPath, params, newHash);
    } else {
      _emberMetalDebug.assert('The component helper cannot be used without a valid component name. You used "' + componentPath + '" via ' + label, isValidComponentPath(env, componentPath));
      return createNewClosureComponentCell(env, componentPath, params, newHash);
    }
  }

  function isValidComponentPath(env, path) {
    var result = _emberHtmlbarsUtilsLookupComponent.default(env.owner, path);

    return !!(result.component || result.layout);
  }

  function isComponentCell(component) {
    return component && component[COMPONENT_CELL];
  }

  function createNestedClosureComponentCell(componentCell, params, hash) {
    var _ref;

    // This needs to be done in each nesting level to avoid raising assertions.
    processPositionalParamsFromCell(componentCell, params, hash);

    return _ref = {}, _ref[COMPONENT_PATH] = componentCell[COMPONENT_PATH], _ref[COMPONENT_HASH] = mergeInNewHash(componentCell[COMPONENT_HASH], hash), _ref[COMPONENT_POSITIONAL_PARAMS] = componentCell[COMPONENT_POSITIONAL_PARAMS], _ref[COMPONENT_CELL] = true, _ref;
  }

  function processPositionalParamsFromCell(componentCell, params, hash) {
    var positionalParams = componentCell[COMPONENT_POSITIONAL_PARAMS];

    _emberHtmlbarsUtilsExtractPositionalParams.processPositionalParams(null, positionalParams, params, hash);
  }

  function createNewClosureComponentCell(env, componentPath, params, hash) {
    var _ref2;

    var positionalParams = getPositionalParams(env.owner, componentPath);

    // This needs to be done in each nesting level to avoid raising assertions.
    _emberHtmlbarsUtilsExtractPositionalParams.processPositionalParams(null, positionalParams, params, hash);

    return _ref2 = {}, _ref2[COMPONENT_PATH] = componentPath, _ref2[COMPONENT_HASH] = hash, _ref2[COMPONENT_POSITIONAL_PARAMS] = positionalParams, _ref2[COMPONENT_CELL] = true, _ref2;
  }

  /*
   Returns the positional parameters for component `componentPath`.
   If it has no positional parameters, it returns the empty array.
   */
  function getPositionalParams(container, componentPath) {
    if (!componentPath) {
      return [];
    }
    var result = _emberHtmlbarsUtilsLookupComponent.default(container, componentPath);
    var component = result.component;

    if (component && component.positionalParams) {
      return component.positionalParams;
    } else {
      return [];
    }
  }

  function mergeInNewHash(original, updates) {
    return _emberMetalAssign.default({}, original, updates);
  }
});
enifed('ember-htmlbars/keywords/component', ['exports', 'htmlbars-runtime/hooks', 'ember-htmlbars/keywords/closure-component', 'ember-metal/empty_object', 'ember-metal/assign'], function (exports, _htmlbarsRuntimeHooks, _emberHtmlbarsKeywordsClosureComponent, _emberMetalEmpty_object, _emberMetalAssign) {
  /**
    @module ember
    @submodule ember-templates
    @public
  */
  'use strict';

  /**
    The `{{component}}` helper lets you add instances of `Ember.Component` to a
    template. See [Ember.Component](/api/classes/Ember.Component.html) for
    additional information on how a `Component` functions.
    `{{component}}`'s primary use is for cases where you want to dynamically
    change which type of component is rendered as the state of your application
    changes. The provided block will be applied as the template for the component.
    Given an empty `<body>` the following template:

    ```handlebars
    {{! application.hbs }}
    {{component infographicComponentName}}
    ```

    And the following application code:

    ```javascript
    export default Ember.Controller.extend({
      infographicComponentName: computed('isMarketOpen', {
        get() {
          if (this.get('isMarketOpen')) {
            return 'live-updating-chart';
          } else {
            return 'market-close-summary';
          }
        }
      })
    });
    ```

    The `live-updating-chart` component will be appended when `isMarketOpen` is
    `true`, and the `market-close-summary` component will be appended when
    `isMarketOpen` is `false`. If the value changes while the app is running,
    the component will be automatically swapped out accordingly.
    Note: You should not use this helper when you are consistently rendering the same
    component. In that case, use standard component syntax, for example:

    ```handlebars
    {{! application.hbs }}
    {{live-updating-chart}}
    ```

    ## Nested Usage

    The `component` helper can be used to package a component path with initial attrs.
    The included attrs can then be merged during the final invocation.

    For example, given a `person-form` component with the following template:

    ```handlebars
    {{yield (hash
        nameInput=(component "my-input-component" value=model.name placeholder="First Name"))}}
    ```

    The following snippet:

    ```
    {{#person-form as |form|}}
      {{component form.nameInput placeholder="Username"}}
    {{/person-form}}
    ```

    would output an input whose value is already bound to `model.name` and `placeholder`
    is "Username".

    @method component
    @since 1.11.0
    @for Ember.Templates.helpers
    @public
  */

  exports.default = function (morph, env, scope, params, hash, template, inverse, visitor) {
    if (!morph) {
      return _emberHtmlbarsKeywordsClosureComponent.default(env, params, hash);
    }

    var newHash = _emberMetalAssign.default(new _emberMetalEmpty_object.default(), hash);

    _htmlbarsRuntimeHooks.keyword('@element_component', morph, env, scope, params, newHash, template, inverse, visitor);
    return true;
  };
});
enifed('ember-htmlbars/keywords/debugger', ['exports', 'ember-metal/debug'], function (exports, _emberMetalDebug) {
  /*jshint debug:true*/

  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = debuggerKeyword;

  /**
    Execute the `debugger` statement in the current template's context.

    ```handlebars
    {{debugger}}
    ```

    When using the debugger helper you will have access to a `get` function. This
    function retrieves values available in the context of the template.
    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 attempt to retrieve this value:

    ```
    > get('foo')
    ```

    `get` is also aware of keywords. So in this situation

    ```handlebars
    {{#each items as |item|}}
      {{debugger}}
    {{/each}}
    ```

    You'll be able to get values from the current item:

    ```
    > get('item.name')
    ```

    You can also access the context of the view to make sure it is the object that
    you expect:

    ```
    > context
    ```

    @method debugger
    @for Ember.Templates.helpers
    @public
  */

  function debuggerKeyword(morph, env, scope) {
    /* jshint unused: false, debug: true */

    var view = env.hooks.getValue(scope.getLocal('view'));
    var context = env.hooks.getValue(scope.getSelf());

    function get(path) {
      return env.hooks.getValue(env.hooks.get(env, scope, path));
    }

    _emberMetalDebug.info('Use `view`, `context`, and `get(<path>)` to debug this template.');

    debugger;

    return true;
  }
});
enifed('ember-htmlbars/keywords/element-component', ['exports', 'ember-metal/assign', 'ember-htmlbars/keywords/closure-component', 'ember-htmlbars/utils/lookup-component', 'ember-htmlbars/utils/extract-positional-params'], function (exports, _emberMetalAssign, _emberHtmlbarsKeywordsClosureComponent, _emberHtmlbarsUtilsLookupComponent, _emberHtmlbarsUtilsExtractPositionalParams) {
  'use strict';

  exports.default = {
    setupState: function (lastState, env, scope, params, hash) {
      var componentPath = getComponentPath(params[0], env);
      return _emberMetalAssign.default({}, lastState, {
        componentPath: componentPath,
        isComponentHelper: true
      });
    },

    render: function (morph) {
      var state = morph.getState();

      if (state.manager) {
        state.manager.destroy();
      }

      // Force the component hook to treat this as a first-time render,
      // because normal components (`<foo-bar>`) cannot change at runtime,
      // but the `{{component}}` helper can.
      state.manager = null;

      for (var _len = arguments.length, rest = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        rest[_key - 1] = arguments[_key];
      }

      render.apply(undefined, [morph].concat(rest));
    },

    rerender: render
  };

  function getComponentPath(param, env) {
    var path = env.hooks.getValue(param);
    if (_emberHtmlbarsKeywordsClosureComponent.isComponentCell(path)) {
      path = path[_emberHtmlbarsKeywordsClosureComponent.COMPONENT_PATH];
    }
    return path;
  }

  function render(morph, env, scope, _ref, hash, template, inverse, visitor) {
    var path = _ref[0];

    var params = _ref.slice(1);

    var isRerender = arguments.length <= 8 || arguments[8] === undefined ? false : arguments[8];

    var _morph$getState = morph.getState();

    var componentPath = _morph$getState.componentPath;

    // If the value passed to the {{component}} helper is undefined or null,
    // don't create a new ComponentNode.
    if (componentPath === undefined || componentPath === null) {
      return;
    }

    path = env.hooks.getValue(path);

    if (isRerender) {
      var result = _emberHtmlbarsUtilsLookupComponent.default(env.owner, componentPath);
      var component = result.component;

      _emberHtmlbarsUtilsExtractPositionalParams.default(null, component, params, hash);
    }

    if (_emberHtmlbarsKeywordsClosureComponent.isComponentCell(path)) {
      var closureComponent = env.hooks.getValue(path);

      // This needs to be done in each nesting level to avoid raising assertions
      _emberHtmlbarsKeywordsClosureComponent.processPositionalParamsFromCell(closureComponent, params, hash);
      params = [];
      hash = _emberHtmlbarsKeywordsClosureComponent.mergeInNewHash(closureComponent[_emberHtmlbarsKeywordsClosureComponent.COMPONENT_HASH], hash);
    }

    var templates = { default: template, inverse: inverse };
    env.hooks.component(morph, env, scope, componentPath, params, hash, templates, visitor);
  }
});
enifed('ember-htmlbars/keywords/get', ['exports', 'ember-metal/debug', 'ember-metal/streams/stream', 'ember-metal/streams/utils', 'ember-htmlbars/utils/subscribe', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/observer'], function (exports, _emberMetalDebug, _emberMetalStreamsStream, _emberMetalStreamsUtils, _emberHtmlbarsUtilsSubscribe, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalObserver) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  function labelFor(source, key) {
    var sourceLabel = source.label ? source.label : '';
    var keyLabel = key.label ? key.label : '';
    return '(get ' + sourceLabel + ' ' + keyLabel + ')';
  }

  var DynamicKeyStream = _emberMetalStreamsStream.default.extend({
    init: function (source, keySource) {
      // Used to get the original path for debugging purposes.
      var label = labelFor(source, keySource);

      this.label = label;
      this.path = label;
      this.sourceDep = this.addMutableDependency(source);
      this.keyDep = this.addMutableDependency(keySource);
      this.observedObject = null;
      this.observedKey = null;
    },

    key: function () {
      var key = this.keyDep.getValue();
      if (typeof key === 'string') {
        return key;
      }
    },

    compute: function () {
      var object = this.sourceDep.getValue();
      var key = this.key();
      if (object && key) {
        return _emberMetalProperty_get.get(object, key);
      }
    },

    setValue: function (value) {
      var object = this.sourceDep.getValue();
      var key = this.key();
      if (object) {
        _emberMetalProperty_set.set(object, key, value);
      }
    },

    _super$revalidate: _emberMetalStreamsStream.default.prototype.revalidate,

    revalidate: function (value) {
      this._super$revalidate(value);

      var object = this.sourceDep.getValue();
      var key = this.key();
      if (object !== this.observedObject || key !== this.observedKey) {
        this._clearObservedObject();

        if (object && typeof object === 'object' && key) {
          _emberMetalObserver.addObserver(object, key, this, this.notify);
          this.observedObject = object;
          this.observedKey = key;
        }
      }
    },

    _clearObservedObject: function () {
      if (this.observedObject) {
        _emberMetalObserver.removeObserver(this.observedObject, this.observedKey, this, this.notify);
        this.observedObject = null;
        this.observedKey = null;
      }
    }
  });

  var buildStream = function buildStream(params) {
    var objRef = params[0];
    var pathRef = params[1];

    _emberMetalDebug.assert('The first argument to {{get}} must be a stream', _emberMetalStreamsUtils.isStream(objRef));
    _emberMetalDebug.assert('{{get}} requires at least two arguments', params.length > 1);

    var stream = buildDynamicKeyStream(objRef, pathRef);

    return stream;
  };

  function buildDynamicKeyStream(source, keySource) {
    if (!_emberMetalStreamsUtils.isStream(keySource)) {
      return source.get(keySource);
    } else {
      return new DynamicKeyStream(source, keySource);
    }
  }

  /**
    Dynamically look up a property on an object. The second argument to `{{get}}`
    should have a string value, although it can be bound.

    For example, these two usages are equivilent:

    ```handlebars
    {{person.height}}
    {{get person "height"}}
    ```

    If there were several facts about a person, the `{{get}}` helper can dynamically
    pick one:

    ```handlebars
    {{get person factName}}
    ```

    For a more complex example, this template would allow the user to switch
    between showing the user's height and weight with a click:

    ```handlebars
    {{get person factName}}
    <button {{action (mut factName) "height"}}>Show height</button>
    <button {{action (mut factName) "weight"}}>Show weight</button>
    ```

    The `{{get}}` helper can also respect mutable values itself. For example:

    ```handlebars
    {{input value=(mut (get person factName)) type="text"}}
    <button {{action (mut factName) "height"}}>Show height</button>
    <button {{action (mut factName) "weight"}}>Show weight</button>
    ```

    Would allow the user to swap what fact is being displayed, and also edit
    that fact via a two-way mutable binding.

    @public
    @method get
    @for Ember.Templates.helpers
    @since 2.1.0
  */
  function getKeyword(morph, env, scope, params, hash, template, inverse, visitor) {
    if (morph === null) {
      return buildStream(params);
    } else {
      var stream = undefined;
      if (morph.linkedResult) {
        stream = morph.linkedResult;
      } else {
        stream = buildStream(params);

        _emberHtmlbarsUtilsSubscribe.default(morph, env, scope, stream);
        env.hooks.linkRenderNode(morph, env, scope, null, params, hash);

        morph.linkedResult = stream;
      }
      env.hooks.range(morph, env, scope, null, stream, visitor);
    }

    return true;
  }

  exports.default = getKeyword;
});
enifed('ember-htmlbars/keywords/input', ['exports', 'ember-metal/debug', 'ember-metal/assign'], function (exports, _emberMetalDebug, _emberMetalAssign) {
  /**
  @module ember
  @submodule ember-templates
  */
  'use strict';

  /**
    The `{{input}}` helper lets you create an HTML `<input />` component.
    It causes an `Ember.TextField` component to be rendered.  For more info,
    see the [Ember.TextField](/api/classes/Ember.TextField.html) docs and
    the [templates guide](http://emberjs.com/guides/templates/input-helpers/).

    ```handlebars
    {{input value="987"}}
    ```

    renders as:

    ```HTML
    <input type="text" value="987" />
    ```

    ### Text field

    If no `type` option is specified, a default of type 'text' is used.

    Many of the standard HTML attributes may be passed to this 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).


    A very common use of this helper is to bind the `value` of an input to an Object's attribute:

    ```handlebars
    Search:
    {{input value=searchWord}}
    ```

    In this example, the inital value in the `<input />` will be set to the value of `searchWord`.
    If the user changes the text, the value of `searchWord` will also be updated.

    ### Actions
    The helper can send multiple actions based on user events.
    The action property defines the action which is sent 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`
    * `key-up`


    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-out="alertMessage"}}
    ```

    See more about [Text Support Actions](/api/classes/Ember.TextField.html)


    ### Extending `Ember.TextField`

    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`. Expect isolated component semantics, not
    legacy 1.x view semantics (like `controller` being present).

    See more about [Ember components](/api/classes/Ember.Component.html)


    ### Checkbox

    Checkboxes are special forms of the `{{input}}` helper.  To create a `<checkbox />`:

    ```handlebars
    Emberize Everything:
    {{input type="checkbox" name="isEmberized" checked=isEmberized}}
    ```

    This will bind checked state of this checkbox to the value of `isEmberized`  -- if either one changes,
    it will be reflected in the other.


    The following HTML attributes can be set via the helper:

    * `checked`
    * `disabled`
    * `tabindex`
    * `indeterminate`
    * `name`
    * `autofocus`
    * `form`


    ### Extending `Ember.Checkbox`

    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.Templates.helpers
    @param {Hash} options
    @public
  */
  exports.default = {
    setupState: function (lastState, env, scope, params, hash) {
      var type = env.hooks.getValue(hash.type);
      var componentName = componentNameMap[type] || defaultComponentName;

      _emberMetalDebug.assert('{{input type=\'checkbox\'}} does not support setting `value=someBooleanValue`; ' + 'you must use `checked=someBooleanValue` instead.', !(type === 'checkbox' && hash.hasOwnProperty('value')));

      return _emberMetalAssign.default({}, lastState, { componentName: componentName });
    },

    render: function (morph, env, scope, params, hash, template, inverse, visitor) {
      env.hooks.component(morph, env, scope, morph.getState().componentName, params, hash, { default: template, inverse: inverse }, visitor);
    },

    rerender: function () {
      this.render.apply(this, arguments);
    }
  };

  var defaultComponentName = '-text-field';

  var componentNameMap = {
    'checkbox': '-checkbox'
  };
});
enifed('ember-htmlbars/keywords/mut', ['exports', 'ember-metal/debug', 'ember-metal/symbol', 'ember-metal/streams/proxy-stream', 'ember-metal/streams/stream', 'ember-metal/streams/utils', 'ember-views/compat/attrs-proxy', 'ember-routing-htmlbars/keywords/closure-action'], function (exports, _emberMetalDebug, _emberMetalSymbol, _emberMetalStreamsProxyStream, _emberMetalStreamsStream, _emberMetalStreamsUtils, _emberViewsCompatAttrsProxy, _emberRoutingHtmlbarsKeywordsClosureAction) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  var _ProxyStream$extend;

  exports.default = mut;
  exports.privateMut = privateMut;
  var MUTABLE_REFERENCE = _emberMetalSymbol.default('MUTABLE_REFERENCE');

  exports.MUTABLE_REFERENCE = MUTABLE_REFERENCE;
  var MutStream = _emberMetalStreamsProxyStream.default.extend((_ProxyStream$extend = {
    init: function (stream) {
      this.label = '(mut ' + stream.label + ')';
      this.path = stream.path;
      this.sourceDep = this.addMutableDependency(stream);
      this[MUTABLE_REFERENCE] = true;
    },

    cell: function () {
      var source = this;
      var value = source.value();

      if (value && value[_emberRoutingHtmlbarsKeywordsClosureAction.ACTION]) {
        return value;
      }

      var val = {
        value: value,
        update: function (val) {
          source.setValue(val);
        }
      };

      val[_emberViewsCompatAttrsProxy.MUTABLE_CELL] = true;
      return val;
    }
  }, _ProxyStream$extend[_emberRoutingHtmlbarsKeywordsClosureAction.INVOKE] = function (val) {
    this.setValue(val);
  }, _ProxyStream$extend));

  /**
    The `mut` helper lets you __clearly specify__ that a child `Component` can update the
    (mutable) value passed to it, which will __change the value of the parent component__.

    This is very helpful for passing mutable values to a `Component` of any size, but
    critical to understanding the logic of a large/complex `Component`.

    To specify that a parameter is mutable, when invoking the child `Component`:

    ```handlebars
    {{my-child childClickCount=(mut totalClicks)}}
    ```

    The child `Component` can then modify the parent's value as needed:

    ```javascript
    // my-child.js
    export default Component.extend({
      click() {
        this.get('childClickCount').update(this.get('childClickCount').value + 1);
      }
    });
    ```

    Additionally, the `mut` helper can be combined with the `action` helper to
    mutate a value. For example:

    ```handlebars
    {{my-child childClickCount=totalClicks click-count-change=(action (mut totalClicks))}}
    ```

    The child `Component` would invoke the action with the new click value:

    ```javascript
    // my-child.js
    export default Component.extend({
      click() {
        this.get('clickCountChange')(this.get('childClickCount') + 1);
      }
    });
    ```

    The `mut` helper changes the `totalClicks` value to what was provided as the action argument.

    See a [2.0 blog post](http://emberjs.com/blog/2015/05/10/run-up-to-two-oh.html#toc_the-code-mut-code-helper) for
    additional information on using `{{mut}}`.

    @public
    @method mut
    @param {Object} [attr] the "two-way" attribute that can be modified.
    @for Ember.Templates.helpers
    @public
  */

  function mut(morph, env, scope, originalParams, hash, template, inverse) {
    // If `morph` is `null` the keyword is being invoked as a subexpression.
    if (morph === null) {
      var valueStream = originalParams[0];
      return mutParam(env.hooks.getValue, valueStream);
    }

    return true;
  }

  function privateMut(morph, env, scope, originalParams, hash, template, inverse) {
    // If `morph` is `null` the keyword is being invoked as a subexpression.
    if (morph === null) {
      var valueStream = originalParams[0];
      return mutParam(env.hooks.getValue, valueStream, true);
    }

    return true;
  }

  var LiteralStream = _emberMetalStreamsStream.default.extend({
    init: function (literal) {
      this.literal = literal;
      this.label = '(literal ' + literal + ')';
    },

    compute: function () {
      return this.literal;
    },

    setValue: function (val) {
      this.literal = val;
      this.notify();
    }
  });

  function mutParam(read, stream, internal) {
    if (internal) {
      if (!_emberMetalStreamsUtils.isStream(stream)) {
        var literal = stream;
        stream = new LiteralStream(literal);
      }
    } else {
      _emberMetalDebug.assert('You can only pass a path to mut', _emberMetalStreamsUtils.isStream(stream));
    }

    if (stream[MUTABLE_REFERENCE]) {
      return stream;
    }

    return new MutStream(stream);
  }
});
enifed('ember-htmlbars/keywords/outlet', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-htmlbars/node-managers/view-node-manager', 'ember-htmlbars/templates/top-level-view', 'ember-metal/features'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberHtmlbarsNodeManagersViewNodeManager, _emberHtmlbarsTemplatesTopLevelView, _emberMetalFeatures) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  _emberHtmlbarsTemplatesTopLevelView.default.meta.revision = 'Ember@2.6.2';

  /**
    The `{{outlet}}` helper lets you specify where a child route will render in
    your template. An important use of the `{{outlet}}` helper is in your
    application's `application.hbs` file:

    ```handlebars
    {{! app/templates/application.hbs }}

    <!-- header content goes here, and will always display -->
    {{my-header}}

    <div class="my-dynamic-content">
      <!-- this content will change based on the current route, which depends on the current URL -->
      {{outlet}}
    </div>

    <!-- footer content goes here, and will always display -->
    {{my-footer}}
    ```

    See [templates guide](http://emberjs.com/guides/templates/the-application-template/) for
    additional information on using `{{outlet}}` in `application.hbs`.

    You may also specify a name for the `{{outlet}}`, which is useful when using more than one
    `{{outlet}}` in a template:

    ```handlebars
    {{outlet "menu"}}
    {{outlet "sidebar"}}
    {{outlet "main"}}
    ```

    Your routes can then render into a specific one of these `outlet`s by specifying the `outlet`
    attribute in your `renderTemplate` function:

    ```javascript
    // app/routes/menu.js

    export default Ember.Route.extend({
      renderTemplate() {
        this.render({ outlet: 'menu' });
      }
    });
    ```

    See the [routing guide](http://emberjs.com/guides/routing/rendering-a-template/) for more
    information on how your `route` interacts with the `{{outlet}}` helper.

    Note: Your content __will not render__ if there isn't an `{{outlet}}` for it.

    @public
    @method outlet
    @param {String} [name]
    @for Ember.Templates.helpers
    @public
  */
  exports.default = {
    willRender: function (renderNode, env) {
      env.view.ownerView._outlets.push(renderNode);
    },

    setupState: function (state, env, scope, params, hash) {
      var outletState = env.outletState;
      var read = env.hooks.getValue;
      var outletName = read(params[0]) || 'main';
      var selectedOutletState = outletState[outletName];

      return {
        outletState: selectedOutletState,
        hasParentOutlet: env.hasParentOutlet,
        manager: state.manager
      };
    },

    childEnv: function (state, env) {
      var outletState = state.outletState;
      var toRender = outletState && outletState.render;
      var meta = toRender && toRender.template && toRender.template.meta;

      return env.childWithOutletState(outletState && outletState.outlets, true, meta);
    },

    isStable: function (lastState, nextState) {
      return isStable(lastState.outletState, nextState.outletState);
    },

    isEmpty: function (state) {
      return isEmpty(state.outletState);
    },

    render: function (renderNode, env, scope, params, hash, template, inverse, visitor) {
      var state = renderNode.getState();
      var parentView = env.view;
      var outletState = state.outletState;
      var toRender = outletState.render;
      var namespace = env.owner.lookup('application:main');
      var LOG_VIEW_LOOKUPS = _emberMetalProperty_get.get(namespace, 'LOG_VIEW_LOOKUPS');

      var ViewClass = outletState.render.ViewClass;

      if (!state.hasParentOutlet && !ViewClass) {
        ViewClass = env.owner._lookupFactory('view:toplevel');
      }

      var Component;

      var options;
      var attrs = {};
      if (Component) {
        options = {
          component: Component
        };
        attrs = toRender.attrs;
      } else {
        options = {
          component: ViewClass,
          self: toRender.controller,
          createOptions: {
            controller: toRender.controller
          }
        };

        template = template || toRender.template && toRender.template.raw;

        if (LOG_VIEW_LOOKUPS && ViewClass) {
          _emberMetalDebug.info('Rendering ' + toRender.name + ' with ' + ViewClass, { fullName: 'view:' + toRender.name });
        }
      }

      if (state.manager) {
        state.manager.destroy();
        state.manager = null;
      }

      var nodeManager = _emberHtmlbarsNodeManagersViewNodeManager.default.create(renderNode, env, attrs, options, parentView, null, null, template);
      state.manager = nodeManager;

      nodeManager.render(env, hash, visitor);
    }
  };

  function isEmpty(outletState) {
    return !outletState || !outletState.render.ViewClass && !outletState.render.template;
  }

  function isStable(a, b) {
    if (!a && !b) {
      return true;
    }
    if (!a || !b) {
      return false;
    }
    a = a.render;
    b = b.render;
    for (var key in a) {
      if (a.hasOwnProperty(key)) {
        // Name is only here for logging & debugging. If two different
        // names result in otherwise identical states, they're still
        // identical.
        if (a[key] !== b[key] && key !== 'name') {
          return false;
        }
      }
    }
    return true;
  }
});
enifed('ember-htmlbars/keywords/partial', ['exports', 'ember-views/system/lookup_partial', 'htmlbars-runtime'], function (exports, _emberViewsSystemLookup_partial, _htmlbarsRuntime) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  /**
    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.


    @method partial
    @for Ember.Templates.helpers
    @param {String} partialName The name of the template to render minus the leading underscore.
    @public
  */

  exports.default = {
    setupState: function (state, env, scope, params, hash) {
      return { partialName: env.hooks.getValue(params[0]) };
    },

    render: function (renderNode, env, scope, params, hash, template, inverse, visitor) {
      var state = renderNode.getState();
      if (!state.partialName) {
        return true;
      }
      var found = _emberViewsSystemLookup_partial.default(env, state.partialName);
      if (!found) {
        return true;
      }

      _htmlbarsRuntime.internal.hostBlock(renderNode, env, scope, found.raw, null, null, visitor, function (options) {
        options.templates.template.yield();
      });
    }
  };
});
enifed('ember-htmlbars/keywords/readonly', ['exports', 'ember-htmlbars/keywords/mut'], function (exports, _emberHtmlbarsKeywordsMut) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  exports.default = readonly;

  function readonly(morph, env, scope, originalParams, hash, template, inverse) {
    // If `morph` is `null` the keyword is being invoked as a subexpression.
    if (morph === null) {
      var stream = originalParams[0];
      if (stream && stream[_emberHtmlbarsKeywordsMut.MUTABLE_REFERENCE]) {
        return stream.sourceDep.dependee;
      }
      return stream;
    }

    return true;
  }
});
enifed('ember-htmlbars/keywords/textarea', ['exports'], function (exports) {
  /**
  @module ember
  @submodule ember-templates
  */

  /**
    `{{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`. Expect isolated component semantics, not
    legacy 1.x view semantics (like `controller` being present).

    See more about [Ember components](/api/classes/Ember.Component.html)

    @method textarea
    @for Ember.Templates.helpers
    @param {Hash} options
    @public
  */
  'use strict';

  exports.default = textarea;

  function textarea(morph, env, scope, originalParams, hash, template, inverse, visitor) {
    env.hooks.component(morph, env, scope, '-text-area', originalParams, hash, { default: template, inverse: inverse }, visitor);
    return true;
  }
});
enifed('ember-htmlbars/keywords/unbound', ['exports', 'ember-metal/debug', 'ember-metal/streams/stream', 'ember-metal/streams/utils'], function (exports, _emberMetalDebug, _emberMetalStreamsStream, _emberMetalStreamsUtils) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  exports.default = unbound;

  /**
    The `{{unbound}}` helper disconnects the one-way binding of a property,
    essentially freezing its value at the moment of rendering. For example,
    in this example the display of the variable `name` will not change even
    if it is set with a new value:

    ```handlebars
    {{unbound name}}
    ```

    Like any helper, the `unbound` helper can accept a nested helper expression.
    This allows for custom helpers to be rendered unbound:

    ```handlebars
    {{unbound (some-custom-helper)}}
    {{unbound (capitalize name)}}
    {{! You can use any helper, including unbound, in a nested expression }}
    {{capitalize (unbound name)}}
    ```

    The `unbound` helper only accepts a single argument, and it return an
    unbound value.

    @method unbound
    @for Ember.Templates.helpers
    @public
  */

  var VolatileStream = _emberMetalStreamsStream.default.extend({
    init: function (source) {
      this.label = '(volatile ' + source.label + ')';
      this.source = source;
      this.addDependency(source);
    },

    value: function () {
      return _emberMetalStreamsUtils.read(this.source);
    },

    notify: function () {}
  });

  function unbound(morph, env, scope, params, hash, template, inverse, visitor) {
    _emberMetalDebug.assert('unbound helper cannot be called with multiple params or hash params', params.length === 1 && Object.keys(hash).length === 0);
    _emberMetalDebug.assert('unbound helper cannot be called as a block', !template);

    if (morph === null) {
      return new VolatileStream(params[0]);
    }

    var stream = undefined;
    if (morph.linkedResult) {
      stream = morph.linkedResult;
    } else {
      stream = new VolatileStream(params[0]);
      morph.linkedResult = stream;
    }
    env.hooks.range(morph, env, scope, null, stream, visitor);
    return true;
  }
});
enifed('ember-htmlbars/keywords/view', ['exports', 'ember-views/streams/utils', 'ember-views/views/view', 'ember-htmlbars/node-managers/view-node-manager'], function (exports, _emberViewsStreamsUtils, _emberViewsViewsView, _emberHtmlbarsNodeManagersViewNodeManager) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  /**
    `{{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 "custom"}}{{! will look up App.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.

    ```javascript
    var App = Ember.Application.create();
    App.WithTemplateDefinedView = Ember.View.extend({
      templateName: 'defined-template'
    });
    ```

    ```handlebars
    {{! application.hbs }}
    {{view 'with-template-defined'}}
    ```

    ```handlebars
    {{! defined-template.hbs }}
    Some content for the defined template view.
    ```

    ### `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.Templates.helpers
    @public
    @deprecated
  */

  exports.default = {
    setupState: function (state, env, scope, params, hash) {
      var read = env.hooks.getValue;
      var targetObject = read(scope.getSelf());
      var viewClassOrInstance = state.viewClassOrInstance;
      if (!viewClassOrInstance) {
        viewClassOrInstance = getView(read(params[0]), env.owner);
      }

      // if parentView exists, use its controller (the default
      // behavior), otherwise use `scope.self` as the controller
      var controller = scope.hasLocal('view') ? null : read(scope.getSelf());

      return {
        manager: state.manager,
        parentView: env.view,
        controller: controller,
        targetObject: targetObject,
        viewClassOrInstance: viewClassOrInstance
      };
    },

    rerender: function (morph, env, scope, params, hash, template, inverse, visitor) {
      // If the hash is empty, the component cannot have extracted a part
      // of a mutable param and used it in its layout, because there are
      // no params at all.
      if (Object.keys(hash).length) {
        return morph.getState().manager.rerender(env, hash, visitor, true);
      }
    },

    render: function (node, env, scope, params, hash, template, inverse, visitor) {
      if (hash.tag) {
        hash = swapKey(hash, 'tag', 'tagName');
      }

      if (hash.classNameBindings) {
        hash.classNameBindings = hash.classNameBindings.split(' ');
      }

      var state = node.getState();
      var parentView = state.parentView;

      var options = {
        component: state.viewClassOrInstance,
        layout: null
      };

      options.createOptions = {};
      if (state.controller) {
        // Use `_controller` to avoid stomping on a CP
        // that exists in the target view/component
        options.createOptions._controller = state.controller;
      }

      if (state.targetObject) {
        // Use `_targetObject` to avoid stomping on a CP
        // that exists in the target view/component
        options.createOptions._targetObject = state.targetObject;
      }

      if (state.manager) {
        state.manager.destroy();
        state.manager = null;
      }

      var nodeManager = _emberHtmlbarsNodeManagersViewNodeManager.default.create(node, env, hash, options, parentView, null, scope, template);
      state.manager = nodeManager;

      nodeManager.render(env, hash, visitor);
    }
  };

  function getView(viewPath, owner) {
    var viewClassOrInstance;

    if (!viewPath) {
      if (owner) {
        viewClassOrInstance = owner._lookupFactory('view:toplevel');
      } else {
        viewClassOrInstance = _emberViewsViewsView.default;
      }
    } else {
      viewClassOrInstance = _emberViewsStreamsUtils.readViewFactory(viewPath, owner);
    }

    return viewClassOrInstance;
  }

  function swapKey(hash, original, update) {
    var newHash = {};

    for (var prop in hash) {
      if (prop === original) {
        newHash[update] = hash[prop];
      } else {
        newHash[prop] = hash[prop];
      }
    }

    return newHash;
  }
});
enifed('ember-htmlbars/keywords/with', ['exports', 'ember-metal/debug', 'htmlbars-runtime'], function (exports, _emberMetalDebug, _htmlbarsRuntime) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  exports.default = {
    isStable: function () {
      return true;
    },

    isEmpty: function (state) {
      return false;
    },

    render: function (morph, env, scope, params, hash, template, inverse, visitor) {
      _emberMetalDebug.assert('{{#with foo}} must be called with a single argument or the use the ' + '{{#with foo as |bar|}} syntax', params.length === 1);

      _emberMetalDebug.assert('The {{#with}} helper must be called with a block', !!template);

      _htmlbarsRuntime.internal.continueBlock(morph, env, scope, 'with', params, hash, template, inverse, visitor);
    },

    rerender: function (morph, env, scope, params, hash, template, inverse, visitor) {
      _htmlbarsRuntime.internal.continueBlock(morph, env, scope, 'with', params, hash, template, inverse, visitor);
    }
  };
});
enifed('ember-htmlbars/keywords/yield', ['exports'], function (exports) {
  'use strict';

  exports.default = yieldKeyword;

  function yieldKeyword(morph, env, scope, params, hash, template, inverse, visitor) {
    var to = env.hooks.getValue(hash.to) || 'default';
    var block = scope.getBlock(to);

    if (block) {
      block.invoke(env, params, hash.self, morph, scope, visitor);
    }

    return true;
  }
});
enifed('ember-htmlbars/morphs/attr-morph', ['exports', 'ember-metal/debug', 'dom-helper', 'ember-metal/is_none'], function (exports, _emberMetalDebug, _domHelper, _emberMetalIs_none) {
  'use strict';

  var HTMLBarsAttrMorph = _domHelper.default.prototype.AttrMorphClass;

  var styleWarning = '' + 'Binding style attributes may introduce cross-site scripting vulnerabilities; ' + 'please ensure that values being bound are properly escaped. For more information, ' + 'including how to disable this warning, see ' + 'http://emberjs.com/deprecations/v1.x/#toc_binding-style-attributes.';

  exports.styleWarning = styleWarning;
  var proto = HTMLBarsAttrMorph.prototype;

  proto.didInit = function () {
    this.streamUnsubscribers = null;

    _emberMetalDebug.debugSeal(this);
  };

  function deprecateEscapedStyle(morph, value) {
    _emberMetalDebug.warn(styleWarning, (function (name, value, escaped) {
      // SafeString
      if (_emberMetalIs_none.default(value) || value && value.toHTML) {
        return true;
      }

      if (name !== 'style') {
        return true;
      }

      return !escaped;
    })(morph.attrName, value, morph.escaped), { id: 'ember-htmlbars.style-xss-warning' });
  }

  proto.willSetContent = function (value) {
    deprecateEscapedStyle(this, value);
  };

  exports.default = HTMLBarsAttrMorph;
});
enifed('ember-htmlbars/morphs/morph', ['exports', 'dom-helper', 'ember-metal/debug'], function (exports, _domHelper, _emberMetalDebug) {
  'use strict';

  var HTMLBarsMorph = _domHelper.default.prototype.MorphClass;
  var guid = 1;

  function EmberMorph(DOMHelper, contextualElement) {
    this.HTMLBarsMorph$constructor(DOMHelper, contextualElement);

    this.emberView = null;
    this.emberToDestroy = null;
    this.streamUnsubscribers = null;
    this.guid = guid++;

    // A component can become dirty either because one of its
    // attributes changed, or because it was re-rendered. If any part
    // of the component's template changes through observation, it has
    // re-rendered from the perpsective of the programming model. This
    // flag is set to true whenever a component becomes dirty because
    // one of its attributes changed, which also triggers the attribute
    // update flag (didUpdateAttrs).
    this.shouldReceiveAttrs = false;

    _emberMetalDebug.debugSeal(this);
  }

  var proto = EmberMorph.prototype = Object.create(HTMLBarsMorph.prototype);
  proto.HTMLBarsMorph$constructor = HTMLBarsMorph;
  proto.HTMLBarsMorph$clear = HTMLBarsMorph.prototype.clear;

  proto.addDestruction = function (toDestroy) {
    this.emberToDestroy = this.emberToDestroy || [];
    this.emberToDestroy.push(toDestroy);
  };

  proto.cleanup = function () {
    var view = this.emberView;

    if (view) {
      var parentView = view.parentView;

      if (parentView && view.ownerView._destroyingSubtreeForView === parentView) {
        parentView.removeChild(view);
      }
    }

    var toDestroy = this.emberToDestroy;

    if (toDestroy) {
      for (var i = 0, l = toDestroy.length; i < l; i++) {
        toDestroy[i].destroy();
      }

      this.emberToDestroy = null;
    }
  };

  proto.didRender = function (env, scope) {
    env.renderedNodes.add(this);
  };

  exports.default = EmberMorph;
});
enifed('ember-htmlbars/node-managers/component-node-manager', ['exports', 'ember-metal/debug', 'ember-views/system/build-component-template', 'ember-htmlbars/hooks/get-cell-or-value', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-views/compat/attrs-proxy', 'ember-htmlbars/system/instrumentation-support', 'ember-views/components/component', 'ember-htmlbars/glimmer-component', 'ember-htmlbars/utils/extract-positional-params', 'ember-metal/symbol', 'container/owner', 'ember-htmlbars/hooks/get-value'], function (exports, _emberMetalDebug, _emberViewsSystemBuildComponentTemplate, _emberHtmlbarsHooksGetCellOrValue, _emberMetalProperty_get, _emberMetalProperty_set, _emberViewsCompatAttrsProxy, _emberHtmlbarsSystemInstrumentationSupport, _emberViewsComponentsComponent, _emberHtmlbarsGlimmerComponent, _emberHtmlbarsUtilsExtractPositionalParams, _emberMetalSymbol, _containerOwner, _emberHtmlbarsHooksGetValue) {
  'use strict';

  exports.createComponent = createComponent;
  exports.takeLegacySnapshot = takeLegacySnapshot;

  // These symbols will be used to limit link-to's public API surface area.
  var HAS_BLOCK = _emberMetalSymbol.default('HAS_BLOCK');

  exports.HAS_BLOCK = HAS_BLOCK;
  // In theory this should come through the env, but it should
  // be safe to import this until we make the hook system public
  // and it gets actively used in addons or other downstream
  // libraries.

  function ComponentNodeManager(component, isAngleBracket, scope, renderNode, attrs, block, expectElement) {
    this.component = component;
    this.isAngleBracket = isAngleBracket;
    this.scope = scope;
    this.renderNode = renderNode;
    this.attrs = attrs;
    this.block = block;
    this.expectElement = expectElement;
  }

  exports.default = ComponentNodeManager;

  ComponentNodeManager.create = function ComponentNodeManager_create(renderNode, env, options) {
    var _createOptions;

    var tagName = options.tagName;
    var params = options.params;
    var _options$attrs = options.attrs;
    var attrs = _options$attrs === undefined ? {} : _options$attrs;
    var parentView = options.parentView;
    var parentScope = options.parentScope;
    var isAngleBracket = options.isAngleBracket;
    var component = options.component;
    var layout = options.layout;
    var templates = options.templates;

    component = component || (isAngleBracket ? _emberHtmlbarsGlimmerComponent.default : _emberViewsComponentsComponent.default);

    var createOptions = (_createOptions = {
      parentView: parentView
    }, _createOptions[HAS_BLOCK] = !!templates.default, _createOptions);

    configureTagName(attrs, tagName, component, isAngleBracket, createOptions);

    // Map passed attributes (e.g. <my-component id="foo">) to component
    // properties ({ id: "foo" }).
    configureCreateOptions(attrs, createOptions);

    // If there is a controller on the scope, pluck it off and save it on the
    // component. This allows the component to target actions sent via
    // `sendAction` correctly.
    if (parentScope.hasLocal('controller')) {
      createOptions._controller = _emberHtmlbarsHooksGetValue.default(parentScope.getLocal('controller'));
    } else {
      createOptions._targetObject = _emberHtmlbarsHooksGetValue.default(parentScope.getSelf());
    }

    _emberHtmlbarsUtilsExtractPositionalParams.default(renderNode, component, params, attrs);

    // Instantiate the component
    component = createComponent(component, isAngleBracket, createOptions, renderNode, env, attrs);

    // If the component specifies its layout via the `layout` property
    // instead of using the template looked up in the container, get it
    // now that we have the component instance.
    if (!layout) {
      layout = _emberMetalProperty_get.get(component, 'layout');
    }

    _emberMetalDebug.runInDebug(function () {
      if (isAngleBracket) {
        _emberMetalDebug.assert('You cannot invoke the \'' + tagName + '\' component with angle brackets, because it\'s a subclass of Component. Please upgrade to GlimmerComponent. Alternatively, you can invoke as \'{{' + tagName + '}}\'.', component.isGlimmerComponent);
      } else {
        _emberMetalDebug.assert('You cannot invoke the \'' + tagName + '\' component with curly braces, because it\'s a subclass of GlimmerComponent. Please invoke it as \'<' + tagName + '>\' instead.', !component.isGlimmerComponent);
      }

      if (!layout) {
        return;
      }

      var fragmentReason = layout.meta.fragmentReason;
      if (isAngleBracket && fragmentReason) {
        switch (fragmentReason.name) {
          case 'missing-wrapper':
            _emberMetalDebug.assert('The <' + tagName + '> template must have a single top-level element because it is a GlimmerComponent.');
            break;
          case 'modifiers':
            var modifiers = fragmentReason.modifiers.map(function (m) {
              return '{{' + m + ' ...}}';
            });
            _emberMetalDebug.assert('You cannot use ' + modifiers.join(', ') + ' in the top-level element of the <' + tagName + '> template because it is a GlimmerComponent.');
            break;
          case 'triple-curlies':
            _emberMetalDebug.assert('You cannot use triple curlies (e.g. style={{{ ... }}}) in the top-level element of the <' + tagName + '> template because it is a GlimmerComponent.');
            break;
        }
      }
    });

    var results = _emberViewsSystemBuildComponentTemplate.default({ layout: layout, component: component, isAngleBracket: isAngleBracket }, attrs, { templates: templates, scope: parentScope });

    return new ComponentNodeManager(component, isAngleBracket, parentScope, renderNode, attrs, results.block, results.createdElement);
  };

  function configureTagName(attrs, tagName, component, isAngleBracket, createOptions) {
    if (isAngleBracket) {
      createOptions.tagName = tagName;
    } else if (attrs.tagName) {
      createOptions.tagName = _emberHtmlbarsHooksGetValue.default(attrs.tagName);
    }
  }

  function configureCreateOptions(attrs, createOptions) {
    // Some attrs are special and need to be set as properties on the component
    // instance. Make sure we use getValue() to get them from `attrs` since
    // they are still streams.
    if (attrs.id) {
      createOptions.elementId = _emberHtmlbarsHooksGetValue.default(attrs.id);
    }
    if (attrs._defaultTagName) {
      createOptions._defaultTagName = _emberHtmlbarsHooksGetValue.default(attrs._defaultTagName);
    }
    if (attrs.viewName) {
      createOptions.viewName = _emberHtmlbarsHooksGetValue.default(attrs.viewName);
    }
  }

  ComponentNodeManager.prototype.render = function ComponentNodeManager_render(_env, visitor) {
    var component = this.component;

    return _emberHtmlbarsSystemInstrumentationSupport.instrument(component, function ComponentNodeManager_render_instrument() {
      var meta = this.block && this.block.template.meta;
      var env = _env.childWithView(component, meta);

      env.renderer.componentWillRender(component);
      env.renderedViews.push(component.elementId);

      if (this.block) {
        this.block.invoke(env, [], undefined, this.renderNode, this.scope, visitor);
      }

      var element = undefined;
      if (this.expectElement || component.isGlimmerComponent) {
        // This code assumes that Glimmer components are never fragments. When
        // Glimmer components gain fragment powers, we will need to communicate
        // whether the layout produced a single top-level node or fragment
        // somehow (either via static information on the template/component, or
        // dynamically as the layout is being rendered).
        element = this.renderNode.firstNode;

        // Glimmer components may have whitespace or boundary nodes around the
        // top-level element.
        if (element && element.nodeType !== 1) {
          element = nextElementSibling(element);
        }
      }

      // In environments like FastBoot, disable any hooks that would cause the component
      // to access the DOM directly.
      if (env.destinedForDOM) {
        env.renderer.didCreateElement(component, element);
        env.renderer.willInsertElement(component, element);

        env.lifecycleHooks.push({ type: 'didInsertElement', view: component });
      }
    }, this);
  };

  function nextElementSibling(node) {
    var current = node;

    while (current) {
      if (current.nodeType === 1) {
        return current;
      }
      current = node.nextSibling;
    }
  }

  ComponentNodeManager.prototype.rerender = function ComponentNodeManager_rerender(_env, attrs, visitor) {
    var component = this.component;

    return _emberHtmlbarsSystemInstrumentationSupport.instrument(component, function ComponentNodeManager_rerender_instrument() {
      var env = _env.childWithView(component);

      var snapshot = takeSnapshot(attrs);

      if (component._renderNode.shouldReceiveAttrs) {
        if (component._propagateAttrsToThis) {
          component._propagateAttrsToThis(takeLegacySnapshot(attrs));
        }

        env.renderer.componentUpdateAttrs(component, snapshot);
        component._renderNode.shouldReceiveAttrs = false;
      }

      // Notify component that it has become dirty and is about to change.
      env.renderer.componentWillUpdate(component, snapshot);
      env.renderer.componentWillRender(component);

      env.renderedViews.push(component.elementId);

      if (this.block) {
        this.block.invoke(env, [], undefined, this.renderNode, this.scope, visitor);
      }

      env.lifecycleHooks.push({ type: 'didUpdate', view: component });

      return env;
    }, this);
  };

  ComponentNodeManager.prototype.destroy = function ComponentNodeManager_destroy() {
    var component = this.component;

    // Clear component's render node. Normally this gets cleared
    // during view destruction, but in this case we're re-assigning the
    // node to a different view and it will get cleaned up automatically.
    component._renderNode = null;
    component.destroy();
  };

  function createComponent(_component, isAngleBracket, props, renderNode, env) {
    var attrs = arguments.length <= 5 || arguments[5] === undefined ? {} : arguments[5];

    if (!isAngleBracket) {
      _emberMetalDebug.assert('controller= is no longer supported', !('controller' in attrs));

      snapshotAndUpdateTarget(attrs, props);
    } else {
      props.attrs = takeSnapshot(attrs);

      props._isAngleBracket = true;
    }

    _containerOwner.setOwner(props, env.owner);
    props.renderer = props.parentView ? props.parentView.renderer : env.owner.lookup('renderer:-dom');
    props._viewRegistry = props.parentView ? props.parentView._viewRegistry : env.owner.lookup('-view-registry:main');

    var component = _component.create(props);

    if (props.parentView) {
      props.parentView.appendChild(component);

      if (props.viewName) {
        _emberMetalProperty_set.set(props.parentView, props.viewName, component);
      }
    }

    component._renderNode = renderNode;
    renderNode.emberView = component;
    renderNode.buildChildEnv = buildChildEnv;
    return component;
  }

  function takeSnapshot(attrs) {
    var hash = {};

    for (var prop in attrs) {
      hash[prop] = _emberHtmlbarsHooksGetCellOrValue.default(attrs[prop]);
    }

    return hash;
  }

  function takeLegacySnapshot(attrs) {
    var hash = {};

    for (var prop in attrs) {
      hash[prop] = _emberHtmlbarsHooksGetValue.default(attrs[prop]);
    }

    return hash;
  }

  function snapshotAndUpdateTarget(rawAttrs, target) {
    var attrs = {};

    for (var prop in rawAttrs) {
      var value = _emberHtmlbarsHooksGetCellOrValue.default(rawAttrs[prop]);
      attrs[prop] = value;

      // when `attrs` is an actual value being set in the
      // attrs hash (`{{foo-bar attrs="blah"}}`) we cannot
      // set `"blah"` to the root of the target because
      // that would replace all attrs with `attrs.attrs`
      if (prop === 'attrs') {
        _emberMetalDebug.warn('Invoking a component with a hash attribute named `attrs` is not supported. Please refactor usage of ' + target + ' to avoid passing `attrs` as a hash parameter.', false, { id: 'ember-htmlbars.component-unsupported-attrs' });
        continue;
      }

      if (value && value[_emberViewsCompatAttrsProxy.MUTABLE_CELL]) {
        value = value.value;
      }

      target[prop] = value;
    }

    return target.attrs = attrs;
  }

  function buildChildEnv(state, env) {
    return env.childWithView(this.emberView);
  }
});
enifed('ember-htmlbars/node-managers/view-node-manager', ['exports', 'ember-metal/assign', 'ember-metal/debug', 'ember-views/system/build-component-template', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/set_properties', 'ember-views/views/view', 'ember-views/compat/attrs-proxy', 'ember-htmlbars/hooks/get-cell-or-value', 'ember-htmlbars/system/instrumentation-support', 'ember-htmlbars/node-managers/component-node-manager', 'container/owner', 'ember-htmlbars/hooks/get-value'], function (exports, _emberMetalAssign, _emberMetalDebug, _emberViewsSystemBuildComponentTemplate, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalSet_properties, _emberViewsViewsView, _emberViewsCompatAttrsProxy, _emberHtmlbarsHooksGetCellOrValue, _emberHtmlbarsSystemInstrumentationSupport, _emberHtmlbarsNodeManagersComponentNodeManager, _containerOwner, _emberHtmlbarsHooksGetValue) {
  'use strict';

  exports.createOrUpdateComponent = createOrUpdateComponent;

  function ViewNodeManager(component, scope, renderNode, block, expectElement) {
    this.component = component;
    this.scope = scope;
    this.renderNode = renderNode;
    this.block = block;
    this.expectElement = expectElement;
  }

  exports.default = ViewNodeManager;

  ViewNodeManager.create = function ViewNodeManager_create(renderNode, env, attrs, found, parentView, path, contentScope, contentTemplate) {
    _emberMetalDebug.assert('HTMLBars error: Could not find component named "' + path + '" (no component or template with that name was found)', !!(function () {
      if (path) {
        return found.component || found.layout;
      } else {
        return found.component || found.layout || contentTemplate;
      }
    })());

    var component;
    var componentInfo = { layout: found.layout };

    if (found.component) {
      var options = { parentView: parentView };

      if (attrs && attrs.id) {
        options.elementId = _emberHtmlbarsHooksGetValue.default(attrs.id);
      }
      if (attrs && attrs.tagName) {
        options.tagName = _emberHtmlbarsHooksGetValue.default(attrs.tagName);
      }
      if (attrs && attrs._defaultTagName) {
        options._defaultTagName = _emberHtmlbarsHooksGetValue.default(attrs._defaultTagName);
      }
      if (attrs && attrs.viewName) {
        options.viewName = _emberHtmlbarsHooksGetValue.default(attrs.viewName);
      }

      if (found.component.create && contentScope) {
        var _self = contentScope.getSelf();
        if (_self) {
          options._context = _emberHtmlbarsHooksGetValue.default(contentScope.getSelf());
        }
      }

      if (found.self) {
        options._context = _emberHtmlbarsHooksGetValue.default(found.self);
      }

      component = componentInfo.component = createOrUpdateComponent(found.component, options, found.createOptions, renderNode, env, attrs);

      var layout = _emberMetalProperty_get.get(component, 'layout');
      if (layout) {
        componentInfo.layout = layout;
      } else {
        componentInfo.layout = getTemplate(component) || componentInfo.layout;
      }

      renderNode.emberView = component;
    }

    _emberMetalDebug.assert('BUG: ViewNodeManager.create can take a scope or a self, but not both', !(contentScope && found.self));

    var results = _emberViewsSystemBuildComponentTemplate.default(componentInfo, attrs, {
      templates: { default: contentTemplate },
      scope: contentScope,
      self: found.self
    });

    return new ViewNodeManager(component, contentScope, renderNode, results.block, results.createdElement);
  };

  ViewNodeManager.prototype.render = function ViewNodeManager_render(env, attrs, visitor) {
    var component = this.component;

    return _emberHtmlbarsSystemInstrumentationSupport.instrument(component, function ViewNodeManager_render_instrument() {
      var newEnv = env;
      if (component) {
        newEnv = env.childWithView(component);
      } else {
        var meta = this.block && this.block.template.meta;

        newEnv = env.childWithMeta(meta);
      }

      if (component) {
        env.renderer.willRender(component);
        env.renderedViews.push(component.elementId);
      }

      if (this.block) {
        this.block.invoke(newEnv, [], undefined, this.renderNode, this.scope, visitor);
      }

      if (component) {
        var element = this.expectElement && this.renderNode.firstNode;

        // In environments like FastBoot, disable any hooks that would cause the component
        // to access the DOM directly.
        if (env.destinedForDOM) {
          env.renderer.didCreateElement(component, element);
          env.renderer.willInsertElement(component, element);
          env.lifecycleHooks.push({ type: 'didInsertElement', view: component });
        }
      }
    }, this);
  };

  ViewNodeManager.prototype.rerender = function ViewNodeManager_rerender(env, attrs, visitor) {
    var component = this.component;

    return _emberHtmlbarsSystemInstrumentationSupport.instrument(component, function ViewNodeManager_rerender_instrument() {
      var newEnv = env;
      if (component) {
        newEnv = env.childWithView(component);

        var snapshot = takeSnapshot(attrs);

        // Notify component that it has become dirty and is about to change.
        env.renderer.willUpdate(component, snapshot);

        if (component._renderNode.shouldReceiveAttrs) {
          if (component._propagateAttrsToThis) {
            component._propagateAttrsToThis(_emberHtmlbarsNodeManagersComponentNodeManager.takeLegacySnapshot(attrs));
          }

          env.renderer.componentUpdateAttrs(component, snapshot);
          component._renderNode.shouldReceiveAttrs = false;
        }

        env.renderer.willRender(component);

        env.renderedViews.push(component.elementId);
      } else {
        var meta = this.block && this.block.template.meta;

        newEnv = env.childWithMeta(meta);
      }

      if (this.block) {
        this.block.invoke(newEnv, [], undefined, this.renderNode, this.scope, visitor);
      }

      return newEnv;
    }, this);
  };

  ViewNodeManager.prototype.destroy = function ViewNodeManager_destroy() {
    if (this.component) {
      this.component.destroy();
      this.component = null;
    }
  };

  function getTemplate(componentOrView) {
    if (!componentOrView.isComponent) {
      return _emberMetalProperty_get.get(componentOrView, 'template');
    }

    return null;
  }

  function createOrUpdateComponent(component, options, createOptions, renderNode, env) {
    var attrs = arguments.length <= 5 || arguments[5] === undefined ? {} : arguments[5];

    var snapshot = takeSnapshot(attrs);
    var props = _emberMetalAssign.default({}, options);
    var defaultController = _emberViewsViewsView.default.proto().controller;
    var hasSuppliedController = 'controller' in attrs || 'controller' in props;

    if (!props.ownerView && options.parentView) {
      props.ownerView = options.parentView.ownerView;
    }

    props.attrs = snapshot;
    if (component.create) {
      var proto = component.proto();

      if (createOptions) {
        _emberMetalAssign.default(props, createOptions);
      }

      mergeBindings(props, snapshot);

      var owner = env.owner;

      _containerOwner.setOwner(props, owner);
      props.renderer = options.parentView ? options.parentView.renderer : owner && owner.lookup('renderer:-dom');
      props._viewRegistry = options.parentView ? options.parentView._viewRegistry : owner && owner.lookup('-view-registry:main');

      if (proto.controller !== defaultController || hasSuppliedController) {
        delete props._context;
      }

      component = component.create(props);
    } else {
      env.renderer.componentUpdateAttrs(component, snapshot);
      _emberMetalSet_properties.default(component, props);

      if (component._propagateAttrsToThis) {
        component._propagateAttrsToThis(_emberHtmlbarsNodeManagersComponentNodeManager.takeLegacySnapshot(attrs));
      }
    }

    if (options.parentView) {
      options.parentView.appendChild(component);

      if (options.viewName) {
        _emberMetalProperty_set.set(options.parentView, options.viewName, component);
      }
    }

    component._renderNode = renderNode;

    renderNode.emberView = component;
    return component;
  }

  function takeSnapshot(attrs) {
    var hash = {};

    for (var prop in attrs) {
      hash[prop] = _emberHtmlbarsHooksGetCellOrValue.default(attrs[prop]);
    }

    return hash;
  }

  function mergeBindings(target, attrs) {
    for (var prop in attrs) {
      if (!attrs.hasOwnProperty(prop)) {
        continue;
      }
      // when `attrs` is an actual value being set in the
      // attrs hash (`{{foo-bar attrs="blah"}}`) we cannot
      // set `"blah"` to the root of the target because
      // that would replace all attrs with `attrs.attrs`
      if (prop === 'attrs') {
        _emberMetalDebug.warn('Invoking a component with a hash attribute named `attrs` is not supported. Please refactor usage of ' + target + ' to avoid passing `attrs` as a hash parameter.', false, { id: 'ember-htmlbars.view-unsupported-attrs' });
        continue;
      }
      var value = attrs[prop];

      if (value && value[_emberViewsCompatAttrsProxy.MUTABLE_CELL]) {
        target[prop] = value.value;
      } else {
        target[prop] = value;
      }
    }

    return target;
  }
});

// In theory this should come through the env, but it should
// be safe to import this until we make the hook system public
// and it gets actively used in addons or other downstream
// libraries.
enifed('ember-htmlbars/streams/built-in-helper', ['exports', 'ember-metal/streams/stream', 'ember-htmlbars/streams/utils'], function (exports, _emberMetalStreamsStream, _emberHtmlbarsStreamsUtils) {
  'use strict';

  var BuiltInHelperStream = _emberMetalStreamsStream.default.extend({
    init: function (helper, params, hash, templates, env, scope, label) {
      this.helper = helper;
      this.params = params;
      this.templates = templates;
      this.env = env;
      this.scope = scope;
      this.hash = hash;
      this.label = label;
    },

    compute: function () {
      return this.helper(_emberHtmlbarsStreamsUtils.getArrayValues(this.params), _emberHtmlbarsStreamsUtils.getHashValues(this.hash), this.templates, this.env, this.scope);
    }
  });

  exports.default = BuiltInHelperStream;
});
enifed('ember-htmlbars/streams/helper-factory', ['exports', 'ember-metal/streams/stream', 'ember-htmlbars/streams/utils'], function (exports, _emberMetalStreamsStream, _emberHtmlbarsStreamsUtils) {
  'use strict';

  var HelperFactoryStream = _emberMetalStreamsStream.default.extend({
    init: function (helperFactory, params, hash, label) {
      this.helperFactory = helperFactory;
      this.params = params;
      this.hash = hash;
      this.linkable = true;
      this.helper = null;
      this.label = label;
    },

    compute: function () {
      if (!this.helper) {
        this.helper = this.helperFactory.create({ _stream: this });
      }
      return this.helper.compute(_emberHtmlbarsStreamsUtils.getArrayValues(this.params), _emberHtmlbarsStreamsUtils.getHashValues(this.hash));
    },

    deactivate: function () {
      this.super$deactivate();
      if (this.helper) {
        this.helper.destroy();
        this.helper = null;
      }
    },
    super$deactivate: _emberMetalStreamsStream.default.prototype.deactivate
  });

  exports.default = HelperFactoryStream;
});
enifed('ember-htmlbars/streams/helper-instance', ['exports', 'ember-metal/streams/stream', 'ember-htmlbars/streams/utils'], function (exports, _emberMetalStreamsStream, _emberHtmlbarsStreamsUtils) {
  'use strict';

  var HelperInstanceStream = _emberMetalStreamsStream.default.extend({
    init: function (helper, params, hash, label) {
      this.helper = helper;
      this.params = params;
      this.hash = hash;
      this.linkable = true;
      this.label = label;
    },

    compute: function () {
      return this.helper.compute(_emberHtmlbarsStreamsUtils.getArrayValues(this.params), _emberHtmlbarsStreamsUtils.getHashValues(this.hash));
    }
  });

  exports.default = HelperInstanceStream;
});
enifed('ember-htmlbars/streams/utils', ['exports', 'ember-htmlbars/hooks/get-value'], function (exports, _emberHtmlbarsHooksGetValue) {
  'use strict';

  exports.getArrayValues = getArrayValues;
  exports.getHashValues = getHashValues;

  // We don't want to leak mutable cells into helpers, which
  // are pure functions that can only work with values.

  function getArrayValues(params) {
    var l = params.length;
    var out = new Array(l);

    for (var i = 0; i < l; i++) {
      out[i] = _emberHtmlbarsHooksGetValue.default(params[i]);
    }

    return out;
  }

  function getHashValues(hash) {
    var out = {};

    for (var prop in hash) {
      out[prop] = _emberHtmlbarsHooksGetValue.default(hash[prop]);
    }

    return out;
  }
});
enifed('ember-htmlbars/system/append-templated-view', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-views/views/view'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberViewsViewsView) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = appendTemplatedView;

  function appendTemplatedView(parentView, morph, viewClassOrInstance, props) {
    var viewProto;
    if (_emberViewsViewsView.default.detectInstance(viewClassOrInstance)) {
      viewProto = viewClassOrInstance;
    } else {
      viewProto = viewClassOrInstance.proto();
    }

    _emberMetalDebug.assert('You cannot provide a template block if you also specified a templateName', !props.template || !_emberMetalProperty_get.get(props, 'templateName') && !_emberMetalProperty_get.get(viewProto, 'templateName'));

    // We only want to override the `_context` computed property if there is
    // no specified controller. See View#_context for more information.
    var noControllerInProto = !viewProto.controller;
    if (viewProto.controller && viewProto.controller.isDescriptor) {
      noControllerInProto = true;
    }
    if (noControllerInProto && !viewProto.controllerBinding && !props.controller && !props.controllerBinding) {
      props._context = _emberMetalProperty_get.get(parentView, 'context'); // TODO: is this right?!
    }

    props._morph = morph;

    return parentView.appendChild(viewClassOrInstance, props);
  }
});
enifed('ember-htmlbars/system/bootstrap', ['exports', 'ember-views/component_lookup', 'ember-views/system/jquery', 'ember-metal/error', 'ember-runtime/system/lazy_load', 'ember-template-compiler/system/compile', 'ember-metal/environment', 'ember-htmlbars/template_registry'], function (exports, _emberViewsComponent_lookup, _emberViewsSystemJquery, _emberMetalError, _emberRuntimeSystemLazy_load, _emberTemplateCompilerSystemCompile, _emberMetalEnvironment, _emberHtmlbarsTemplate_registry) {
  /*globals Handlebars */

  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  /**
  @module ember
  @submodule ember-htmlbars
  */

  /**
    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 a jQuery DOM-ready callback.

    Script tags with `text/x-handlebars` will be compiled
    with Ember's template compiler 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.HTMLBars
    @static
    @param ctx
  */
  function bootstrap(ctx) {
    var selectors = 'script[type="text/x-handlebars"], script[type="text/x-raw-handlebars"]';

    _emberViewsSystemJquery.default(selectors, ctx).each(function () {
      // Get a reference to the script tag.
      var script = _emberViewsSystemJquery.default(this);

      // 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.
      var templateName = script.attr('data-template-name') || script.attr('id') || 'application';
      var template, compile;

      if (script.attr('type') === 'text/x-raw-handlebars') {
        compile = _emberViewsSystemJquery.default.proxy(Handlebars.compile, Handlebars);
        template = compile(script.html());
      } else {
        template = _emberTemplateCompilerSystemCompile.default(script.html(), {
          moduleName: templateName
        });
      }

      // Check if template of same name already exists.
      if (_emberHtmlbarsTemplate_registry.has(templateName)) {
        throw new _emberMetalError.default('Template named "' + templateName + '" already exists.');
      }

      // For templates which have a name, we save them and then remove them from the DOM.
      _emberHtmlbarsTemplate_registry.set(templateName, template);

      // Remove script tag from DOM.
      script.remove();
    });
  }

  function _bootstrap() {
    bootstrap(_emberViewsSystemJquery.default(document));
  }

  function registerComponentLookup(app) {
    app.register('component-lookup:main', _emberViewsComponent_lookup.default);
  }

  /*
    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.
  */

  _emberRuntimeSystemLazy_load.onLoad('Ember.Application', function (Application) {
    Application.initializer({
      name: 'domTemplates',
      initialize: _emberMetalEnvironment.default.hasDOM ? _bootstrap : function () {}
    });

    Application.instanceInitializer({
      name: 'registerComponentLookup',
      initialize: registerComponentLookup
    });
  });

  exports.default = bootstrap;
});
enifed('ember-htmlbars/system/dom-helper', ['exports', 'dom-helper', 'ember-htmlbars/morphs/morph', 'ember-htmlbars/morphs/attr-morph'], function (exports, _domHelper, _emberHtmlbarsMorphsMorph, _emberHtmlbarsMorphsAttrMorph) {
  'use strict';

  function EmberDOMHelper(_document) {
    _domHelper.default.call(this, _document);
  }

  var proto = EmberDOMHelper.prototype = Object.create(_domHelper.default.prototype);
  proto.MorphClass = _emberHtmlbarsMorphsMorph.default;
  proto.AttrMorphClass = _emberHtmlbarsMorphsAttrMorph.default;

  exports.default = EmberDOMHelper;
});
enifed('ember-htmlbars/system/instrumentation-support', ['exports', 'ember-metal/instrumentation'], function (exports, _emberMetalInstrumentation) {
  'use strict';

  exports.instrument = instrument;

  /**
    Provides instrumentation for node managers.

    Wrap your node manager's render and re-render methods
    with this function.

    @param {Object} component Component or View instance (optional).
    @param {Function} callback The function to instrument.
    @param {Object} context The context to call the function with.
    @return {Object} Return value from the invoked callback.
    @private
  */

  function instrument(component, callback, context) {
    var instrumentName, val, details, end;
    // Only instrument if there's at least one subscriber.
    if (_emberMetalInstrumentation.subscribers.length) {
      if (component) {
        instrumentName = component.instrumentName;
      } else {
        instrumentName = 'node';
      }
      details = {};
      if (component) {
        component.instrumentDetails(details);
      }
      end = _emberMetalInstrumentation._instrumentStart('render.' + instrumentName, function viewInstrumentDetails() {
        return details;
      });
      val = callback.call(context);
      if (end) {
        end();
      }
      return val;
    } else {
      return callback.call(context);
    }
  }
});
enifed('ember-htmlbars/system/invoke-helper', ['exports', 'ember-metal/debug', 'ember-htmlbars/streams/helper-instance', 'ember-htmlbars/streams/helper-factory', 'ember-htmlbars/streams/built-in-helper'], function (exports, _emberMetalDebug, _emberHtmlbarsStreamsHelperInstance, _emberHtmlbarsStreamsHelperFactory, _emberHtmlbarsStreamsBuiltInHelper) {
  'use strict';

  exports.buildHelperStream = buildHelperStream;

  function buildHelperStream(helper, params, hash, templates, env, scope, label) {
    var isAnyKindOfHelper = helper.isHelperInstance || helper.isHelperFactory;
    _emberMetalDebug.assert('Helpers may not be used in the block form, for example {{#my-helper}}{{/my-helper}}. Please use a component, or alternatively use the helper in combination with a built-in Ember helper, for example {{#if (my-helper)}}{{/if}}.', !(isAnyKindOfHelper && templates && templates.template && templates.template.meta));
    _emberMetalDebug.assert('Helpers may not be used in the element form, for example <div {{my-helper}}>.', !(isAnyKindOfHelper && templates && templates.element));
    if (helper.isHelperFactory) {
      return new _emberHtmlbarsStreamsHelperFactory.default(helper, params, hash, label);
    } else if (helper.isHelperInstance) {
      return new _emberHtmlbarsStreamsHelperInstance.default(helper, params, hash, label);
    } else {
      templates = templates || { template: {}, inverse: {} };
      return new _emberHtmlbarsStreamsBuiltInHelper.default(helper, params, hash, templates, env, scope, label);
    }
  }
});
enifed('ember-htmlbars/system/lookup-helper', ['exports', 'ember-metal/debug', 'ember-metal/cache'], function (exports, _emberMetalDebug, _emberMetalCache) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.validateLazyHelperName = validateLazyHelperName;
  exports.findHelper = findHelper;
  exports.default = lookupHelper;
  var CONTAINS_DASH_CACHE = new _emberMetalCache.default(1000, function (key) {
    return key.indexOf('-') !== -1;
  });

  exports.CONTAINS_DASH_CACHE = CONTAINS_DASH_CACHE;
  var CONTAINS_DOT_CACHE = new _emberMetalCache.default(1000, function (key) {
    return key.indexOf('.') !== -1;
  });

  exports.CONTAINS_DOT_CACHE = CONTAINS_DOT_CACHE;

  function validateLazyHelperName(helperName, container, keywords) {
    return container && !(helperName in keywords);
  }

  /**
    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 {String} name The name of the helper to lookup.
    @return {Helper}
  */
  function _findHelper(name, view, env, options) {
    var helper = env.helpers[name];

    if (!helper) {
      var owner = env.owner;
      if (validateLazyHelperName(name, owner, env.hooks.keywords)) {
        var helperName = 'helper:' + name;
        // See https://github.com/emberjs/ember.js/issues/13071
        // See https://bugs.chromium.org/p/v8/issues/detail?id=4839
        var registered = owner.hasRegistration(helperName, options);
        if (registered) {
          helper = owner._lookupFactory(helperName, options);
          _emberMetalDebug.assert('Expected to find an Ember.Helper with the name ' + helperName + ', but found an object of type ' + typeof helper + ' instead.', helper.isHelperFactory || helper.isHelperInstance);
        }
      }
    }

    return helper;
  }

  function findHelper(name, view, env) {
    var options = {};
    var moduleName = env.meta && env.meta.moduleName;
    if (moduleName) {
      options.source = 'template:' + moduleName;
    }

    var localHelper = _findHelper(name, view, env, options);

    // Local match found, use it.
    if (localHelper) {
      return localHelper;
    }

    // Fall back to global.
    return _findHelper(name, view, env);
  }

  function lookupHelper(name, view, env) {
    var helper = findHelper(name, view, env);

    _emberMetalDebug.assert('A helper named \'' + name + '\' could not be found', !!helper);

    return helper;
  }
});
enifed('ember-htmlbars/system/make_bound_helper', ['exports', 'ember-metal/debug', 'ember-htmlbars/helper'], function (exports, _emberMetalDebug, _emberHtmlbarsHelper) {
  /**
  @module ember
  @submodule ember-htmlbars
  */
  'use strict';

  exports.default = makeBoundHelper;

  /**
    Create a bound helper. Accepts a function that receives the ordered and hash parameters
    from the template. If a bound property was provided in the template, it will be resolved to its
    value and any changes to the bound property cause the helper function to be re-run with the updated
    values.

    * `params` - An array of resolved ordered parameters.
    * `hash` - An object containing the hash parameters.

    For example:

    * With an unquoted ordered parameter:

      ```javascript
      {{x-capitalize foo}}
      ```

      Assuming `foo` was set to `"bar"`, the bound helper would receive `["bar"]` as its first argument, and
      an empty hash as its second.

    * With a quoted ordered parameter:

      ```javascript
      {{x-capitalize "foo"}}
      ```

      The bound helper would receive `["foo"]` as its first argument, and an empty hash as its second.

    * With an unquoted hash parameter:

      ```javascript
      {{x-repeat "foo" count=repeatCount}}
      ```

      Assuming that `repeatCount` resolved to 2, the bound helper would receive `["foo"]` as its first argument,
      and { count: 2 } as its second.

    @private
    @method makeBoundHelper
    @for Ember.HTMLBars
    @param {Function} fn
    @since 1.10.0
  */

  function makeBoundHelper(fn) {
    _emberMetalDebug.deprecate('Using `Ember.HTMLBars.makeBoundHelper` is deprecated. Please refactor to use `Ember.Helper` or `Ember.Helper.helper`.', false, { id: 'ember-htmlbars.make-bound-helper', until: '3.0.0' });
    return _emberHtmlbarsHelper.helper(fn);
  }
});
enifed('ember-htmlbars/system/render-env', ['exports', 'ember-htmlbars/env', 'ember-metal-views', 'container/owner'], function (exports, _emberHtmlbarsEnv, _emberMetalViews, _containerOwner) {
  'use strict';

  exports.default = RenderEnv;

  function RenderEnv(options) {
    this.lifecycleHooks = options.lifecycleHooks || [];
    this.renderedViews = options.renderedViews || [];
    this.renderedNodes = options.renderedNodes || new _emberMetalViews.MorphSet();
    this.hasParentOutlet = options.hasParentOutlet || false;

    this.view = options.view;
    this.outletState = options.outletState;
    this.owner = options.owner;
    this.renderer = options.renderer;
    this.dom = options.dom;
    this.meta = options.meta;

    this.hooks = _emberHtmlbarsEnv.default.hooks;
    this.helpers = _emberHtmlbarsEnv.default.helpers;
    this.useFragmentCache = _emberHtmlbarsEnv.default.useFragmentCache;
    this.destinedForDOM = this.renderer._destinedForDOM;
  }

  RenderEnv.build = function (view, meta) {
    return new RenderEnv({
      view: view,
      outletState: view.outletState,
      owner: _containerOwner.getOwner(view),
      renderer: view.renderer,
      dom: view.renderer._dom,
      meta: meta
    });
  };

  RenderEnv.prototype.childWithMeta = function (meta) {
    return new RenderEnv({
      view: this.view,
      outletState: this.outletState,
      owner: this.owner,
      renderer: this.renderer,
      dom: this.dom,
      lifecycleHooks: this.lifecycleHooks,
      renderedViews: this.renderedViews,
      renderedNodes: this.renderedNodes,
      hasParentOutlet: this.hasParentOutlet,
      meta: meta
    });
  };

  RenderEnv.prototype.childWithView = function (view) {
    var meta = arguments.length <= 1 || arguments[1] === undefined ? this.meta : arguments[1];

    return new RenderEnv({
      view: view,
      outletState: this.outletState,
      owner: this.owner,
      renderer: this.renderer,
      dom: this.dom,
      lifecycleHooks: this.lifecycleHooks,
      renderedViews: this.renderedViews,
      renderedNodes: this.renderedNodes,
      hasParentOutlet: this.hasParentOutlet,
      meta: meta
    });
  };

  RenderEnv.prototype.childWithOutletState = function (outletState) {
    var hasParentOutlet = arguments.length <= 1 || arguments[1] === undefined ? this.hasParentOutlet : arguments[1];
    var meta = arguments.length <= 2 || arguments[2] === undefined ? this.meta : arguments[2];

    return new RenderEnv({
      view: this.view,
      outletState: outletState,
      owner: this.owner,
      renderer: this.renderer,
      dom: this.dom,
      lifecycleHooks: this.lifecycleHooks,
      renderedViews: this.renderedViews,
      renderedNodes: this.renderedNodes,
      hasParentOutlet: hasParentOutlet,
      meta: meta
    });
  };
});
enifed('ember-htmlbars/system/render-view', ['exports', 'ember-htmlbars/node-managers/view-node-manager', 'ember-htmlbars/system/render-env'], function (exports, _emberHtmlbarsNodeManagersViewNodeManager, _emberHtmlbarsSystemRenderEnv) {
  'use strict';

  exports.renderHTMLBarsBlock = renderHTMLBarsBlock;

  // This function only gets called once per render of a "root view" (`appendTo`). Otherwise,
  // HTMLBars propagates the existing env and renders templates for a given render node.

  function renderHTMLBarsBlock(view, block, renderNode) {
    var meta = block && block.template && block.template.meta;
    var env = _emberHtmlbarsSystemRenderEnv.default.build(view, meta);

    view.env = env;
    _emberHtmlbarsNodeManagersViewNodeManager.createOrUpdateComponent(view, {}, null, renderNode, env);
    var nodeManager = new _emberHtmlbarsNodeManagersViewNodeManager.default(view, null, renderNode, block, view.tagName !== '');

    nodeManager.render(env, {});
  }
});
enifed("ember-htmlbars/template_registry", ["exports"], function (exports) {
  // STATE within a module is frowned apon, this exists
  // to support Ember.TEMPLATES but shield ember internals from this legacy
  // global API.
  "use strict";

  exports.setTemplates = setTemplates;
  exports.getTemplates = getTemplates;
  exports.get = get;
  exports.has = has;
  exports.set = set;
  var TEMPLATES = {};

  function setTemplates(templates) {
    TEMPLATES = templates;
  }

  function getTemplates() {
    return TEMPLATES;
  }

  function get(name) {
    if (TEMPLATES.hasOwnProperty(name)) {
      return TEMPLATES[name];
    }
  }

  function has(name) {
    return TEMPLATES.hasOwnProperty(name);
  }

  function set(name, template) {
    return TEMPLATES[name] = template;
  }
});
enifed("ember-htmlbars/templates/component", ["exports", "ember-template-compiler/system/template"], function (exports, _emberTemplateCompilerSystemTemplate) {
  "use strict";

  exports.default = _emberTemplateCompilerSystemTemplate.default((function () {
    return {
      meta: {},
      isEmpty: false,
      arity: 0,
      cachedFragment: null,
      hasRendered: false,
      buildFragment: function buildFragment(dom) {
        var el0 = dom.createDocumentFragment();
        var el1 = dom.createComment("");
        dom.appendChild(el0, el1);
        return el0;
      },
      buildRenderNodes: function buildRenderNodes(dom, fragment, contextualElement) {
        var morphs = new Array(1);
        morphs[0] = dom.createMorphAt(fragment, 0, 0, contextualElement);
        dom.insertBoundary(fragment, 0);
        dom.insertBoundary(fragment, null);
        return morphs;
      },
      statements: [["content", "yield", ["loc", [null, [1, 0], [1, 9]]]]],
      locals: [],
      templates: []
    };
  })());
});
enifed("ember-htmlbars/templates/empty", ["exports", "ember-template-compiler/system/template"], function (exports, _emberTemplateCompilerSystemTemplate) {
  "use strict";

  exports.default = _emberTemplateCompilerSystemTemplate.default((function () {
    return {
      meta: {},
      isEmpty: true,
      arity: 0,
      cachedFragment: null,
      hasRendered: false,
      buildFragment: function buildFragment(dom) {
        var el0 = dom.createDocumentFragment();
        return el0;
      },
      buildRenderNodes: function buildRenderNodes() {
        return [];
      },
      statements: [],
      locals: [],
      templates: []
    };
  })());
});
enifed("ember-htmlbars/templates/link-to", ["exports", "ember-template-compiler/system/template"], function (exports, _emberTemplateCompilerSystemTemplate) {
  "use strict";

  exports.default = _emberTemplateCompilerSystemTemplate.default((function () {
    var child0 = (function () {
      return {
        meta: {},
        isEmpty: false,
        arity: 0,
        cachedFragment: null,
        hasRendered: false,
        buildFragment: function buildFragment(dom) {
          var el0 = dom.createDocumentFragment();
          var el1 = dom.createComment("");
          dom.appendChild(el0, el1);
          return el0;
        },
        buildRenderNodes: function buildRenderNodes(dom, fragment, contextualElement) {
          var morphs = new Array(1);
          morphs[0] = dom.createMorphAt(fragment, 0, 0, contextualElement);
          dom.insertBoundary(fragment, 0);
          dom.insertBoundary(fragment, null);
          return morphs;
        },
        statements: [["content", "linkTitle", ["loc", [null, [1, 17], [1, 30]]]]],
        locals: [],
        templates: []
      };
    })();
    var child1 = (function () {
      return {
        meta: {},
        isEmpty: false,
        arity: 0,
        cachedFragment: null,
        hasRendered: false,
        buildFragment: function buildFragment(dom) {
          var el0 = dom.createDocumentFragment();
          var el1 = dom.createComment("");
          dom.appendChild(el0, el1);
          return el0;
        },
        buildRenderNodes: function buildRenderNodes(dom, fragment, contextualElement) {
          var morphs = new Array(1);
          morphs[0] = dom.createMorphAt(fragment, 0, 0, contextualElement);
          dom.insertBoundary(fragment, 0);
          dom.insertBoundary(fragment, null);
          return morphs;
        },
        statements: [["content", "yield", ["loc", [null, [1, 38], [1, 47]]]]],
        locals: [],
        templates: []
      };
    })();
    return {
      meta: {},
      isEmpty: false,
      arity: 0,
      cachedFragment: null,
      hasRendered: false,
      buildFragment: function buildFragment(dom) {
        var el0 = dom.createDocumentFragment();
        var el1 = dom.createComment("");
        dom.appendChild(el0, el1);
        return el0;
      },
      buildRenderNodes: function buildRenderNodes(dom, fragment, contextualElement) {
        var morphs = new Array(1);
        morphs[0] = dom.createMorphAt(fragment, 0, 0, contextualElement);
        dom.insertBoundary(fragment, 0);
        dom.insertBoundary(fragment, null);
        return morphs;
      },
      statements: [["block", "if", [["get", "linkTitle", ["loc", [null, [1, 6], [1, 15]]]]], [], 0, 1, ["loc", [null, [1, 0], [1, 54]]]]],
      locals: [],
      templates: [child0, child1]
    };
  })());
});
enifed("ember-htmlbars/templates/top-level-view", ["exports", "ember-template-compiler/system/template"], function (exports, _emberTemplateCompilerSystemTemplate) {
  "use strict";

  exports.default = _emberTemplateCompilerSystemTemplate.default((function () {
    return {
      meta: {},
      isEmpty: false,
      arity: 0,
      cachedFragment: null,
      hasRendered: false,
      buildFragment: function buildFragment(dom) {
        var el0 = dom.createDocumentFragment();
        var el1 = dom.createComment("");
        dom.appendChild(el0, el1);
        return el0;
      },
      buildRenderNodes: function buildRenderNodes(dom, fragment, contextualElement) {
        var morphs = new Array(1);
        morphs[0] = dom.createMorphAt(fragment, 0, 0, contextualElement);
        dom.insertBoundary(fragment, 0);
        dom.insertBoundary(fragment, null);
        return morphs;
      },
      statements: [["content", "outlet", ["loc", [null, [1, 0], [1, 10]]]]],
      locals: [],
      templates: []
    };
  })());
});
enifed('ember-htmlbars/utils/decode-each-key', ['exports', 'ember-metal/property_get', 'ember-metal/utils'], function (exports, _emberMetalProperty_get, _emberMetalUtils) {
  'use strict';

  exports.default = decodeEachKey;

  function identity(item) {
    var key = undefined;
    var type = typeof item;

    if (type === 'string' || type === 'number') {
      key = item;
    } else {
      key = _emberMetalUtils.guidFor(item);
    }

    return key;
  }

  function decodeEachKey(item, keyPath, index) {
    var key;

    switch (keyPath) {
      case '@index':
        key = index;
        break;
      case '@identity':
        key = identity(item);
        break;
      default:
        if (keyPath) {
          key = _emberMetalProperty_get.get(item, keyPath);
        } else {
          key = identity(item);
        }
    }

    if (typeof key === 'number') {
      key = String(key);
    }

    return key;
  }
});
enifed('ember-htmlbars/utils/extract-positional-params', ['exports', 'ember-metal/debug', 'ember-metal/streams/stream', 'ember-metal/streams/utils'], function (exports, _emberMetalDebug, _emberMetalStreamsStream, _emberMetalStreamsUtils) {
  'use strict';

  exports.default = extractPositionalParams;
  exports.processPositionalParams = processPositionalParams;

  function extractPositionalParams(renderNode, component, params, attrs) {
    var raiseAssertions = arguments.length <= 4 || arguments[4] === undefined ? true : arguments[4];

    var positionalParams = component.positionalParams;

    if (positionalParams) {
      processPositionalParams(renderNode, positionalParams, params, attrs, raiseAssertions);
    }
  }

  function processPositionalParams(renderNode, positionalParams, params, attrs) {
    var raiseAssertions = arguments.length <= 4 || arguments[4] === undefined ? true : arguments[4];

    var isRest = typeof positionalParams === 'string';

    if (isRest) {
      processRestPositionalParameters(renderNode, positionalParams, params, attrs, raiseAssertions);
    } else {
      processNamedPositionalParameters(renderNode, positionalParams, params, attrs, raiseAssertions);
    }
  }

  function processNamedPositionalParameters(renderNode, positionalParams, params, attrs, raiseAssertions) {
    var limit = Math.min(params.length, positionalParams.length);

    for (var i = 0; i < limit; i++) {
      var param = params[i];

      _emberMetalDebug.assert('You cannot specify both a positional param (at position ' + i + ') and the hash argument `' + positionalParams[i] + '`.', !(positionalParams[i] in attrs && raiseAssertions));

      attrs[positionalParams[i]] = param;
    }
  }

  function processRestPositionalParameters(renderNode, positionalParamsName, params, attrs, raiseAssertions) {
    var nameInAttrs = (positionalParamsName in attrs);

    // when no params are used, do not override the specified `attrs.stringParamName` value
    if (params.length === 0 && nameInAttrs) {
      return;
    }

    // If there is already an attribute for that variable, do nothing
    _emberMetalDebug.assert('You cannot specify positional parameters and the hash argument `' + positionalParamsName + '`.', !(nameInAttrs && raiseAssertions));

    var paramsStream = new _emberMetalStreamsStream.Stream(function () {
      return _emberMetalStreamsUtils.readArray(params.slice(0));
    }, 'params');

    attrs[positionalParamsName] = paramsStream;

    for (var i = 0; i < params.length; i++) {
      var param = params[i];
      paramsStream.addDependency(param);
    }
  }
});
enifed('ember-htmlbars/utils/is-component', ['exports', 'ember-metal/features', 'ember-htmlbars/system/lookup-helper', 'ember-htmlbars/keywords/closure-component', 'ember-metal/streams/utils'], function (exports, _emberMetalFeatures, _emberHtmlbarsSystemLookupHelper, _emberHtmlbarsKeywordsClosureComponent, _emberMetalStreamsUtils) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  exports.default = isComponent;

  function hasComponentOrTemplate(owner, path, options) {
    return owner.hasRegistration('component:' + path, options) || owner.hasRegistration('template:components/' + path, options);
  }

  /*
   Given a path name, returns whether or not a component with that
   name was found in the container.
  */

  function isComponent(env, scope, path) {
    var owner = env.owner;
    if (!owner) {
      return false;
    }
    if (typeof path === 'string') {
      if (_emberHtmlbarsSystemLookupHelper.CONTAINS_DOT_CACHE.get(path)) {
        var stream = env.hooks.get(env, scope, path);
        if (_emberMetalStreamsUtils.isStream(stream)) {
          var cell = stream.value();
          if (_emberHtmlbarsKeywordsClosureComponent.isComponentCell(cell)) {
            return true;
          }
        }
      }
      if (!_emberHtmlbarsSystemLookupHelper.CONTAINS_DASH_CACHE.get(path)) {
        return false;
      }

      if (hasComponentOrTemplate(owner, path)) {
        return true; // global component found
      } else {
          var moduleName = env.meta && env.meta.moduleName;

          if (!moduleName) {
            // Without a source moduleName, we can not perform local lookups.
            return false;
          }

          var options = { source: 'template:' + moduleName };

          return hasComponentOrTemplate(owner, path, options);
        }
    }
  }
});
enifed('ember-htmlbars/utils/lookup-component', ['exports', 'ember-metal/features'], function (exports, _emberMetalFeatures) {
  'use strict';

  exports.default = lookupComponent;

  function lookupComponentPair(componentLookup, owner, name, options) {
    return {
      component: componentLookup.componentFor(name, owner, options),
      layout: componentLookup.layoutFor(name, owner, options)
    };
  }

  function lookupComponent(owner, name, options) {
    var componentLookup = owner.lookup('component-lookup:main');

    var source = options && options.source;

    if (source) {
      var localResult = lookupComponentPair(componentLookup, owner, name, options);

      if (localResult.component || localResult.layout) {
        return localResult;
      }
    }

    return lookupComponentPair(componentLookup, owner, name);
  }
});
enifed('ember-htmlbars/utils/new-stream', ['exports', 'ember-metal/streams/proxy-stream', 'ember-htmlbars/utils/subscribe'], function (exports, _emberMetalStreamsProxyStream, _emberHtmlbarsUtilsSubscribe) {
  'use strict';

  exports.default = newStream;

  function newStream(scope, key, newValue, renderNode, isSelf) {
    var stream = new _emberMetalStreamsProxyStream.default(newValue, isSelf ? '' : key);
    if (renderNode) {
      _emberHtmlbarsUtilsSubscribe.default(renderNode, scope, stream);
    }
    scope[key] = stream;
  }
});
enifed("ember-htmlbars/utils/normalize-self", ["exports"], function (exports) {
  "use strict";

  exports.default = normalizeSelf;

  function normalizeSelf(self) {
    if (self === undefined) {
      return null;
    } else {
      return self;
    }
  }
});
enifed('ember-htmlbars/utils/string', ['exports', 'ember-metal/core', 'ember-runtime/system/string', 'htmlbars-util'], function (exports, _emberMetalCore, _emberRuntimeSystemString, _htmlbarsUtil) {
  /**
  @module ember
  @submodule ember-htmlbars
  */

  'use strict';

  /**
    Mark a string as safe for unescaped output with Ember templates. If you
    return HTML from a helper, use this function to
    ensure Ember's rendering layer 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.
    @public
  */
  function htmlSafe(str) {
    if (str === null || str === undefined) {
      str = '';
    } else if (typeof str !== 'string') {
      str = '' + str;
    }
    return new _htmlbarsUtil.SafeString(str);
  }

  _emberRuntimeSystemString.default.htmlSafe = htmlSafe;
  if (_emberMetalCore.default.EXTEND_PROTOTYPES === true || _emberMetalCore.default.EXTEND_PROTOTYPES.String) {
    String.prototype.htmlSafe = function () {
      return htmlSafe(this);
    };
  }

  exports.SafeString = _htmlbarsUtil.SafeString;
  exports.htmlSafe = htmlSafe;
  exports.escapeExpression = _htmlbarsUtil.escapeExpression;
});
enifed('ember-htmlbars/utils/subscribe', ['exports', 'ember-metal/streams/utils'], function (exports, _emberMetalStreamsUtils) {
  'use strict';

  exports.default = subscribe;

  function subscribe(node, env, scope, stream) {
    if (!_emberMetalStreamsUtils.isStream(stream)) {
      return;
    }
    var component = scope.getComponent();
    var unsubscribers = node.streamUnsubscribers = node.streamUnsubscribers || [];

    unsubscribers.push(stream.subscribe(function () {
      node.isDirty = true;

      // Whenever a render node directly inside a component becomes
      // dirty, we want to invoke the willRenderElement and
      // didRenderElement lifecycle hooks. From the perspective of the
      // programming model, whenever anything in the DOM changes, a
      // "re-render" has occured.
      if (component && component._renderNode) {
        component._renderNode.isDirty = true;
      }

      if (node.getState().manager) {
        node.shouldReceiveAttrs = true;
      }

      node.ownerNode.emberView.scheduleRevalidate(node, _emberMetalStreamsUtils.labelFor(stream));
    }));
  }
});
enifed('ember-htmlbars/utils/update-scope', ['exports', 'ember-metal/streams/proxy-stream', 'ember-htmlbars/utils/subscribe'], function (exports, _emberMetalStreamsProxyStream, _emberHtmlbarsUtilsSubscribe) {
  'use strict';

  exports.default = updateScope;

  function updateScope(scope, key, newValue, renderNode, isSelf) {
    var existing = scope[key];

    if (existing) {
      existing.setSource(newValue);
    } else {
      var stream = new _emberMetalStreamsProxyStream.default(newValue, isSelf ? null : key);
      if (renderNode) {
        _emberHtmlbarsUtilsSubscribe.default(renderNode, scope, stream);
      }
      scope[key] = stream;
    }
  }
});
enifed('ember-metal-views/htmlbars-renderer', ['exports', 'ember-metal/run_loop', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/assign', 'ember-metal/set_properties', 'ember-views/system/build-component-template', 'ember-metal/environment', 'htmlbars-runtime'], function (exports, _emberMetalRun_loop, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalAssign, _emberMetalSet_properties, _emberViewsSystemBuildComponentTemplate, _emberMetalEnvironment, _htmlbarsRuntime) {
  'use strict';

  exports.Renderer = Renderer;
  exports.MorphSet = MorphSet;

  function Renderer(domHelper) {
    var _ref = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

    var destinedForDOM = _ref.destinedForDOM;

    this._dom = domHelper;

    // This flag indicates whether the resulting rendered element will be
    // inserted into the DOM. This should be set to `false` if the rendered
    // element is going to be serialized to HTML without being inserted into
    // the DOM (e.g., in FastBoot mode). By default, this flag is the same
    // as whether we are running in an environment with DOM, but may be
    // overridden.
    this._destinedForDOM = destinedForDOM === undefined ? _emberMetalEnvironment.default.hasDOM : destinedForDOM;
  }

  Renderer.prototype.prerenderTopLevelView = function Renderer_prerenderTopLevelView(view, renderNode) {
    if (view._state === 'inDOM') {
      throw new Error('You cannot insert a View that has already been rendered');
    }
    view.ownerView = renderNode.emberView = view;
    view._renderNode = renderNode;

    var layout = _emberMetalProperty_get.get(view, 'layout');
    var template = _emberMetalProperty_get.get(view, 'template');

    var componentInfo = { component: view, layout: layout };

    var block = _emberViewsSystemBuildComponentTemplate.default(componentInfo, {}, {
      self: view,
      templates: template ? { default: template.raw } : undefined
    }).block;

    view.renderBlock(block, renderNode);
    view.lastResult = renderNode.lastResult;
    this.clearRenderedViews(view.env);
  };

  Renderer.prototype.renderTopLevelView = function Renderer_renderTopLevelView(view, renderNode) {
    // Check to see if insertion has been canceled.
    if (view._willInsert) {
      view._willInsert = false;
      this.prerenderTopLevelView(view, renderNode);
      this.dispatchLifecycleHooks(view.env);
    }
  };

  Renderer.prototype.revalidateTopLevelView = function Renderer_revalidateTopLevelView(view) {
    // This guard prevents revalidation on an already-destroyed view.
    if (view._renderNode.lastResult) {
      view._renderNode.lastResult.revalidate(view.env);
      // supports createElement, which operates without moving the view into
      // the inDOM state.
      if (view._state === 'inDOM') {
        this.dispatchLifecycleHooks(view.env);
      }
      this.clearRenderedViews(view.env);
    }
  };

  Renderer.prototype.dispatchLifecycleHooks = function Renderer_dispatchLifecycleHooks(env) {
    var ownerView = env.view;

    var lifecycleHooks = env.lifecycleHooks;
    var i, hook;

    for (i = 0; i < lifecycleHooks.length; i++) {
      hook = lifecycleHooks[i];
      ownerView._dispatching = hook.type;

      switch (hook.type) {
        case 'didInsertElement':
          this.didInsertElement(hook.view);break;
        case 'didUpdate':
          this.didUpdate(hook.view);break;
      }

      this.didRender(hook.view);
    }

    ownerView._dispatching = null;
    env.lifecycleHooks.length = 0;
  };

  Renderer.prototype.ensureViewNotRendering = function Renderer_ensureViewNotRendering(view) {
    var env = view.ownerView.env;
    if (env && env.renderedViews.indexOf(view.elementId) !== -1) {
      throw new Error('Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.');
    }
  };

  function MorphSet() {
    this.morphs = [];
  }

  MorphSet.prototype.add = function (morph) {
    this.morphs.push(morph);
    morph.seen = true;
  };

  MorphSet.prototype.has = function (morph) {
    return morph.seen;
  };

  MorphSet.prototype.clear = function () {
    var morphs = this.morphs;
    for (var i = 0, l = morphs.length; i < l; i++) {
      morphs[i].seen = false;
    }

    this.morphs = [];
  };

  Renderer.prototype.clearRenderedViews = function Renderer_clearRenderedViews(env) {
    env.renderedNodes.clear();
    env.renderedViews.length = 0;
  };

  // This entry point is called from top-level `view.appendTo`.
  Renderer.prototype.appendTo = function Renderer_appendTo(view, target) {
    var morph = this._dom.appendMorph(target);
    morph.ownerNode = morph;
    view._willInsert = true;
    _emberMetalRun_loop.default.schedule('render', this, this.renderTopLevelView, view, morph);
  };

  Renderer.prototype.replaceIn = function Renderer_replaceIn(view, target) {
    var morph = this._dom.replaceContentWithMorph(target);
    morph.ownerNode = morph;
    view._willInsert = true;
    _emberMetalRun_loop.default.scheduleOnce('render', this, this.renderTopLevelView, view, morph);
  };

  Renderer.prototype.createElement = function Renderer_createElement(view) {
    var morph = this._dom.createFragmentMorph();
    morph.ownerNode = morph;
    this.prerenderTopLevelView(view, morph);
  };

  Renderer.prototype.didCreateElement = function (view, element) {
    if (element) {
      view.element = element;
    }

    if (view._transitionTo) {
      view._transitionTo('hasElement');
    }
  }; // hasElement

  Renderer.prototype.willInsertElement = function (view) {
    if (view.trigger) {
      view.trigger('willInsertElement');
    }
  }; // Will place into DOM.

  Renderer.prototype.setAttrs = function (view, attrs) {
    _emberMetalProperty_set.set(view, 'attrs', attrs);
  }; // Set attrs the first time.

  Renderer.prototype.componentInitAttrs = function (component, attrs) {
    component.trigger('didInitAttrs', { attrs: attrs });
    component.trigger('didReceiveAttrs', { newAttrs: attrs });
  }; // Set attrs the first time.

  Renderer.prototype.didInsertElement = function (view) {
    if (view._transitionTo) {
      view._transitionTo('inDOM');
    }

    if (view.trigger) {
      view.trigger('didInsertElement');
    }
  }; // inDOM // Placed into DOM.

  Renderer.prototype.didUpdate = function (view) {
    if (view.trigger) {
      view.trigger('didUpdate');
    }
  };

  Renderer.prototype.didRender = function (view) {
    if (view.trigger) {
      view.trigger('didRender');
    }
  };

  Renderer.prototype.updateAttrs = function (view, attrs) {
    this.setAttrs(view, attrs);
  }; // Setting new attrs.

  Renderer.prototype.componentUpdateAttrs = function (component, newAttrs) {
    var oldAttrs = null;

    if (component.attrs) {
      oldAttrs = _emberMetalAssign.default({}, component.attrs);
      _emberMetalSet_properties.default(component.attrs, newAttrs);
    } else {
      _emberMetalProperty_set.set(component, 'attrs', newAttrs);
    }

    component.trigger('didUpdateAttrs', { oldAttrs: oldAttrs, newAttrs: newAttrs });
    component.trigger('didReceiveAttrs', { oldAttrs: oldAttrs, newAttrs: newAttrs });
  };

  Renderer.prototype.willUpdate = function (view, attrs) {
    if (view._willUpdate) {
      view._willUpdate(attrs);
    }
  };

  Renderer.prototype.componentWillUpdate = function (component) {
    component.trigger('willUpdate');
  };

  Renderer.prototype.willRender = function (view) {
    if (view._willRender) {
      view._willRender();
    }
  };

  Renderer.prototype.componentWillRender = function (component) {
    component.trigger('willRender');
  };

  Renderer.prototype.rerender = function (view) {
    var renderNode = view._renderNode;

    renderNode.isDirty = true;
    _htmlbarsRuntime.internal.visitChildren(renderNode.childNodes, function (node) {
      if (node.getState().manager) {
        node.shouldReceiveAttrs = true;
      }
      node.isDirty = true;
    });

    renderNode.ownerNode.emberView.scheduleRevalidate(renderNode, view.toString(), 'rerendering');
  };

  Renderer.prototype.remove = function (view, shouldDestroy) {
    this.willDestroyElement(view);

    view._willRemoveElement = true;
    _emberMetalRun_loop.default.schedule('render', this, this.renderElementRemoval, view);
  };

  Renderer.prototype.renderElementRemoval = function Renderer_renderElementRemoval(view) {
    // Use the _willRemoveElement flag to avoid mulitple removal attempts in
    // case many have been scheduled. This should be more performant than using
    // `scheduleOnce`.
    if (view._willRemoveElement) {
      view._willRemoveElement = false;

      if (view._renderNode && view.element && view.element.parentNode) {
        view._renderNode.clear();
      }
      this.didDestroyElement(view);
    }
  };

  Renderer.prototype.willRemoveElement = function () /*view*/{};

  Renderer.prototype.willDestroyElement = function (view) {
    if (view._willDestroyElement) {
      view._willDestroyElement();
    }
    if (view.trigger) {
      view.trigger('willDestroyElement');
      view.trigger('willClearRender');
    }

    if (view._transitionTo) {
      view._transitionTo('destroying');
    }
  };

  Renderer.prototype.didDestroyElement = function (view) {
    view.element = null;

    // Views that are being destroyed should never go back to the preRender state.
    // However if we're just destroying an element on a view (as is the case when
    // using View#remove) then the view should go to a preRender state so that
    // it can be rendered again later.
    if (view._state !== 'destroying' && view._transitionTo) {
      view._transitionTo('preRender');
    }

    if (view.trigger) {
      view.trigger('didDestroyElement');
    }
  }; // Element destroyed so view.destroy shouldn't try to remove it removedFromDOM

  var InertRenderer = {
    create: function (_ref2) {
      var dom = _ref2.dom;

      return new Renderer(dom, { destinedForDOM: false });
    }
  };

  exports.InertRenderer = InertRenderer;
  var InteractiveRenderer = {
    create: function (_ref3) {
      var dom = _ref3.dom;

      return new Renderer(dom, { destinedForDOM: true });
    }
  };
  exports.InteractiveRenderer = InteractiveRenderer;
});
enifed('ember-metal-views/index', ['exports', 'ember-metal-views/htmlbars-renderer'], function (exports, _emberMetalViewsHtmlbarsRenderer) {
  'use strict';

  function _interopExportWildcard(obj, defaults) { var newObj = defaults({}, obj); delete newObj['default']; return newObj; }

  function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }

  _defaults(exports, _interopExportWildcard(_emberMetalViewsHtmlbarsRenderer, _defaults));
});
enifed('ember-metal/alias', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/error', 'ember-metal/properties', 'ember-metal/computed', 'ember-metal/utils', 'ember-metal/meta', 'ember-metal/dependent_keys'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalError, _emberMetalProperties, _emberMetalComputed, _emberMetalUtils, _emberMetalMeta, _emberMetalDependent_keys) {
  'use strict';

  exports.default = alias;
  exports.AliasedProperty = AliasedProperty;

  function alias(altKey) {
    return new AliasedProperty(altKey);
  }

  function AliasedProperty(altKey) {
    this.isDescriptor = true;
    this.altKey = altKey;
    this._dependentKeys = [altKey];
  }

  AliasedProperty.prototype = Object.create(_emberMetalProperties.Descriptor.prototype);

  AliasedProperty.prototype.get = function AliasedProperty_get(obj, keyName) {
    return _emberMetalProperty_get.get(obj, this.altKey);
  };

  AliasedProperty.prototype.set = function AliasedProperty_set(obj, keyName, value) {
    return _emberMetalProperty_set.set(obj, this.altKey, value);
  };

  AliasedProperty.prototype.willWatch = function (obj, keyName) {
    _emberMetalDependent_keys.addDependentKeys(this, obj, keyName, _emberMetalMeta.meta(obj));
  };

  AliasedProperty.prototype.didUnwatch = function (obj, keyName) {
    _emberMetalDependent_keys.removeDependentKeys(this, obj, keyName, _emberMetalMeta.meta(obj));
  };

  AliasedProperty.prototype.setup = function (obj, keyName) {
    _emberMetalDebug.assert('Setting alias \'' + keyName + '\' on self', this.altKey !== keyName);
    var m = _emberMetalMeta.meta(obj);
    if (m.peekWatching(keyName)) {
      _emberMetalDependent_keys.addDependentKeys(this, obj, keyName, m);
    }
  };

  AliasedProperty.prototype.teardown = function (obj, keyName) {
    var m = _emberMetalMeta.meta(obj);
    if (m.peekWatching(keyName)) {
      _emberMetalDependent_keys.removeDependentKeys(this, obj, keyName, m);
    }
  };

  AliasedProperty.prototype.readOnly = function () {
    this.set = AliasedProperty_readOnlySet;
    return this;
  };

  function AliasedProperty_readOnlySet(obj, keyName, value) {
    throw new _emberMetalError.default('Cannot set read-only property \'' + keyName + '\' on object: ' + _emberMetalUtils.inspect(obj));
  }

  AliasedProperty.prototype.oneWay = function () {
    this.set = AliasedProperty_oneWaySet;
    return this;
  };

  function AliasedProperty_oneWaySet(obj, keyName, value) {
    _emberMetalProperties.defineProperty(obj, keyName, null);
    return _emberMetalProperty_set.set(obj, keyName, value);
  }

  // Backwards compatibility with Ember Data.
  AliasedProperty.prototype._meta = undefined;
  AliasedProperty.prototype.meta = _emberMetalComputed.ComputedProperty.prototype.meta;
});
enifed("ember-metal/assign", ["exports"], function (exports) {
  /**
    Copy properties from a source object to a target object.

    ```javascript
    var a = {first: 'Yehuda'};
    var b = {last: 'Katz'};
    var c = {company: 'Tilde Inc.'};
    Ember.assign(a, b, c); // a === {first: 'Yehuda', last: 'Katz', company: 'Tilde Inc.'}, b === {last: 'Katz'}, c === {company: 'Tilde Inc.'}
    ```

    @method assign
    @for Ember
    @param {Object} original The object to assign into
    @param {Object} ...args The objects to copy properties from
    @return {Object}
    @public
  */
  "use strict";

  exports.default = assign;

  function assign(original) {
    for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }

    for (var i = 0, l = args.length; i < l; i++) {
      var arg = args[i];
      if (!arg) {
        continue;
      }

      var updates = Object.keys(arg);

      for (var _i = 0, _l = updates.length; _i < _l; _i++) {
        var prop = updates[_i];
        original[prop] = arg[prop];
      }
    }

    return original;
  }
});
enifed('ember-metal/binding', ['exports', 'ember-metal/core', 'ember-metal/logger', 'ember-metal/run_loop', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/utils', 'ember-metal/events', 'ember-metal/observer', 'ember-metal/path_cache'], function (exports, _emberMetalCore, _emberMetalLogger, _emberMetalRun_loop, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalUtils, _emberMetalEvents, _emberMetalObserver, _emberMetalPath_cache) {
  'use strict';

  exports.bind = bind;

  // ES6TODO: where is Ember.lookup defined?
  /**
  @module ember
  @submodule 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
    @public
  */
  _emberMetalCore.default.LOG_BINDINGS = false || !!_emberMetalCore.default.ENV.LOG_BINDINGS;

  // ..........................................................
  // BINDING
  //

  function Binding(toPath, fromPath) {
    // Configuration
    this._from = fromPath;
    this._to = toPath;
    this._oneWay = undefined;

    // State
    this._direction = undefined;
    this._readyToSync = undefined;
    this._fromObj = undefined;
    this._fromPath = undefined;
    this._toObj = undefined;
  }

  /**
    @class Binding
    @namespace Ember
    @public
  */

  Binding.prototype = {
    /**
      This copies the Binding so it can be connected to another object.
       @method copy
      @return {Ember.Binding} `this`
      @public
    */
    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`
      @public
    */
    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`
      @public
    */
    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`
      @public
    */
    oneWay: function () {
      this._oneWay = true;
      return this;
    },

    /**
      @method toString
      @return {String} string representation of binding
      @public
    */
    toString: function () {
      var oneWay = this._oneWay ? '[oneWay]' : '';
      return 'Ember.Binding<' + _emberMetalUtils.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`
      @public
    */
    connect: function (obj) {
      _emberMetalDebug.assert('Must pass a valid object to Ember.Binding.connect()', !!obj);

      var fromObj = undefined,
          fromPath = undefined;

      // If the binding's "from" path could be interpreted as a global, verify
      // whether the path refers to a global or not by consulting `Ember.lookup`.
      if (_emberMetalPath_cache.isGlobalPath(this._from)) {
        var _name = _emberMetalPath_cache.getFirstKey(this._from);
        var possibleGlobal = _emberMetalCore.default.lookup[_name];

        if (possibleGlobal) {
          fromObj = possibleGlobal;
          fromPath = _emberMetalPath_cache.getTailPath(this._from);
        }
      }

      if (fromObj === undefined) {
        fromObj = obj;
        fromPath = this._from;
      }

      _emberMetalProperty_set.trySet(obj, this._to, _emberMetalProperty_get.get(fromObj, fromPath));

      // Add an observer on the object to be notified when the binding should be updated.
      _emberMetalObserver.addObserver(fromObj, fromPath, this, 'fromDidChange');

      // If the binding is a two-way binding, also set up an observer on the target.
      if (!this._oneWay) {
        _emberMetalObserver.addObserver(obj, this._to, this, 'toDidChange');
      }

      _emberMetalEvents.addListener(obj, 'willDestroy', this, 'disconnect');

      this._readyToSync = true;
      this._fromObj = fromObj;
      this._fromPath = fromPath;
      this._toObj = obj;

      return this;
    },

    /**
      Disconnects the binding instance. Changes will no longer be relayed. You
      will not usually need to call this method.
       @method disconnect
      @return {Ember.Binding} `this`
      @public
    */
    disconnect: function () {
      _emberMetalDebug.assert('Must pass a valid object to Ember.Binding.disconnect()', !!this._toObj);

      // Remove an observer on the object so we're no longer notified of
      // changes that should update bindings.
      _emberMetalObserver.removeObserver(this._fromObj, this._fromPath, this, 'fromDidChange');

      // If the binding is two-way, remove the observer from the target as well.
      if (!this._oneWay) {
        _emberMetalObserver.removeObserver(this._toObj, this._to, this, 'toDidChange');
      }

      this._readyToSync = false; // Disable scheduled syncs...
      return this;
    },

    // ..........................................................
    // PRIVATE
    //

    /* Called when the from side changes. */
    fromDidChange: function (target) {
      this._scheduleSync('fwd');
    },

    /* Called when the to side changes. */
    toDidChange: function (target) {
      this._scheduleSync('back');
    },

    _scheduleSync: function (dir) {
      var existingDir = this._direction;

      // If we haven't scheduled the binding yet, schedule it.
      if (existingDir === undefined) {
        _emberMetalRun_loop.default.schedule('sync', this, '_sync');
        this._direction = 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') {
        this._direction = 'fwd';
      }
    },

    _sync: function () {
      var log = _emberMetalCore.default.LOG_BINDINGS;

      var toObj = this._toObj;

      // Don't synchronize destroyed objects or disconnected bindings.
      if (toObj.isDestroyed || !this._readyToSync) {
        return;
      }

      // Get the direction of the binding for the object we are
      // synchronizing from.
      var direction = this._direction;

      var fromObj = this._fromObj;
      var fromPath = this._fromPath;

      this._direction = undefined;

      // If we're synchronizing from the remote object...
      if (direction === 'fwd') {
        var fromValue = _emberMetalProperty_get.get(fromObj, fromPath);
        if (log) {
          _emberMetalLogger.default.log(' ', this.toString(), '->', fromValue, fromObj);
        }
        if (this._oneWay) {
          _emberMetalProperty_set.trySet(toObj, this._to, fromValue);
        } else {
          _emberMetalObserver._suspendObserver(toObj, this._to, this, 'toDidChange', function () {
            _emberMetalProperty_set.trySet(toObj, this._to, fromValue);
          });
        }
        // If we're synchronizing *to* the remote object.
      } else if (direction === 'back') {
          var toValue = _emberMetalProperty_get.get(toObj, this._to);
          if (log) {
            _emberMetalLogger.default.log(' ', this.toString(), '<-', toValue, toObj);
          }
          _emberMetalObserver._suspendObserver(fromObj, fromPath, this, 'fromDidChange', function () {
            _emberMetalProperty_set.trySet(fromObj, 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 (from) {
      var C = this;
      return new C(undefined, from);
    },

    /*
      See `Ember.Binding.to`.
       @method to
      @static
    */
    to: function (to) {
      var C = this;
      return new C(to, undefined);
    }
  });
  /**
    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 instance 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("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.

    This also allows you to bind between objects using the paths you declare in
    `from` and `to`:

    ```javascript
    // Example 1
    binding = Ember.Binding.from("App.someObject.value").to("value");
    binding.connect(this);

    // Example 2
    binding = Ember.Binding.from("parentView.value").to("App.someObject.value");
    binding.connect(this);
    ```

    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
    @public
  */
  // 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
    @public
  */

  function bind(obj, to, from) {
    return new Binding(to, from).connect(obj);
  }

  exports.Binding = Binding;
});
// Ember.LOG_BINDINGS
enifed('ember-metal/cache', ['exports', 'ember-metal/empty_object'], function (exports, _emberMetalEmpty_object) {
  'use strict';

  exports.default = Cache;

  function Cache(limit, func) {
    this.store = new _emberMetalEmpty_object.default();
    this.size = 0;
    this.misses = 0;
    this.hits = 0;
    this.limit = limit;
    this.func = func;
  }

  var UNDEFINED = function () {};

  Cache.prototype = {
    set: function (key, value) {
      if (this.limit > this.size) {
        this.size++;
        if (value === undefined) {
          this.store[key] = UNDEFINED;
        } else {
          this.store[key] = value;
        }
      }

      return value;
    },

    get: function (key) {
      var value = this.store[key];

      if (value === undefined) {
        this.misses++;
        value = this.set(key, this.func(key));
      } else if (value === UNDEFINED) {
        this.hits++;
        value = undefined;
      } else {
        this.hits++;
        // nothing to translate
      }

      return value;
    },

    purge: function () {
      this.store = new _emberMetalEmpty_object.default();
      this.size = 0;
      this.hits = 0;
      this.misses = 0;
    }
  };
});
enifed('ember-metal/chains', ['exports', 'ember-metal/property_get', 'ember-metal/meta', 'ember-metal/watch_key', 'ember-metal/empty_object'], function (exports, _emberMetalProperty_get, _emberMetalMeta, _emberMetalWatch_key, _emberMetalEmpty_object) {
  'use strict';

  exports.finishChains = finishChains;

  var FIRST_KEY = /^([^\.]+)/;

  function firstKey(path) {
    return path.match(FIRST_KEY)[0];
  }

  function isObject(obj) {
    return obj && typeof obj === 'object';
  }

  function isVolatile(obj) {
    return !(isObject(obj) && obj.isDescriptor && obj._volatile === false);
  }

  function ChainWatchers() {
    // chain nodes that reference a key in this obj by key
    // we only create ChainWatchers when we are going to add them
    // so create this upfront
    this.chains = new _emberMetalEmpty_object.default();
  }

  ChainWatchers.prototype = {
    add: function (key, node) {
      var nodes = this.chains[key];
      if (nodes === undefined) {
        this.chains[key] = [node];
      } else {
        nodes.push(node);
      }
    },

    remove: function (key, node) {
      var nodes = this.chains[key];
      if (nodes) {
        for (var i = 0, l = nodes.length; i < l; i++) {
          if (nodes[i] === node) {
            nodes.splice(i, 1);
            break;
          }
        }
      }
    },

    has: function (key, node) {
      var nodes = this.chains[key];
      if (nodes) {
        for (var i = 0, l = nodes.length; i < l; i++) {
          if (nodes[i] === node) {
            return true;
          }
        }
      }
      return false;
    },

    revalidateAll: function () {
      for (var key in this.chains) {
        this.notify(key, true, undefined);
      }
    },

    revalidate: function (key) {
      this.notify(key, true, undefined);
    },

    // key: the string key that is part of a path changed
    // revalidate: boolean; the chains that are watching this value should revalidate
    // callback: function that will be called with the object and path that
    //           will be/are invalidated by this key change, depending on
    //           whether the revalidate flag is passed
    notify: function (key, revalidate, callback) {
      var nodes = this.chains[key];
      if (nodes === undefined || nodes.length === 0) {
        return;
      }

      var affected = undefined;

      if (callback) {
        affected = [];
      }

      for (var i = 0, l = nodes.length; i < l; i++) {
        nodes[i].notify(revalidate, affected);
      }

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

      // we gather callbacks so we don't notify them during revalidation
      for (var i = 0, l = affected.length; i < l; i += 2) {
        var obj = affected[i];
        var path = affected[i + 1];
        callback(obj, path);
      }
    }
  };

  function makeChainWatcher() {
    return new ChainWatchers();
  }

  function addChainWatcher(obj, keyName, node) {
    if (!isObject(obj)) {
      return;
    }

    var m = _emberMetalMeta.meta(obj);
    m.writableChainWatchers(makeChainWatcher).add(keyName, node);
    _emberMetalWatch_key.watchKey(obj, keyName, m);
  }

  function removeChainWatcher(obj, keyName, node) {
    if (!isObject(obj)) {
      return;
    }

    var m = _emberMetalMeta.peekMeta(obj);

    if (!m || !m.readableChainWatchers()) {
      return;
    }

    // make meta writable
    m = _emberMetalMeta.meta(obj);

    m.readableChainWatchers().remove(keyName, node);

    _emberMetalWatch_key.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._chains = undefined;
    this._object = undefined;
    this.count = 0;

    this._value = value;
    this._paths = {};
    if (this._watching) {
      this._object = parent.value();
      if (this._object) {
        addChainWatcher(this._object, this._key, this);
      }
    }
  }

  function lazyGet(obj, key) {
    if (!obj) {
      return;
    }

    var meta = _emberMetalMeta.peekMeta(obj);

    // check if object meant only to be a prototype
    if (meta && meta.proto === obj) {
      return;
    }

    // Use `get` if the return value is an EachProxy or an uncacheable value.
    if (isVolatile(obj[key])) {
      return _emberMetalProperty_get.get(obj, key);
      // Otherwise attempt to get the cached value of the computed property
    } else {
        var cache = meta.readableCache();
        if (cache && key in cache) {
          return cache[key];
        }
      }
  }

  ChainNode.prototype = {
    value: function () {
      if (this._value === undefined && this._watching) {
        var obj = this._parent.value();
        this._value = lazyGet(obj, this._key);
      }
      return this._value;
    },

    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
    copy: function (obj) {
      var ret = new ChainNode(null, null, obj);
      var paths = this._paths;
      var path;

      for (path in paths) {
        // this check will also catch non-number vals.
        if (paths[path] <= 0) {
          continue;
        }
        ret.add(path);
      }
      return ret;
    },

    // called on the root node of a chain to setup watchers on the specified
    // path.
    add: function (path) {
      var paths = this._paths;
      paths[path] = (paths[path] || 0) + 1;

      var key = firstKey(path);
      var tail = path.slice(key.length + 1);

      this.chain(key, tail);
    },

    // called on the root node of a chain to teardown watcher on the specified
    // path
    remove: function (path) {
      var paths = this._paths;
      if (paths[path] > 0) {
        paths[path]--;
      }

      var key = firstKey(path);
      var tail = path.slice(key.length + 1);

      this.unchain(key, tail);
    },

    chain: function (key, path) {
      var chains = this._chains;
      var node;
      if (chains === undefined) {
        chains = this._chains = new _emberMetalEmpty_object.default();
      } else {
        node = chains[key];
      }

      if (node === undefined) {
        node = chains[key] = new ChainNode(this, key, undefined);
      }

      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);
      }
    },

    unchain: function (key, path) {
      var chains = this._chains;
      var node = chains[key];

      // unchain rest of path first...
      if (path && path.length > 1) {
        var nextKey = firstKey(path);
        var nextPath = path.slice(nextKey.length + 1);
        node.unchain(nextKey, nextPath);
      }

      // delete node if needed.
      node.count--;
      if (node.count <= 0) {
        chains[node._key] = undefined;
        node.destroy();
      }
    },

    notify: function (revalidate, affected) {
      if (revalidate && 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;
      }

      // then notify chains...
      var chains = this._chains;
      var node;
      if (chains) {
        for (var key in chains) {
          node = chains[key];
          if (node !== undefined) {
            node.notify(revalidate, affected);
          }
        }
      }

      if (affected && this._parent) {
        this._parent.populateAffected(this._key, 1, affected);
      }
    },

    populateAffected: function (path, depth, affected) {
      if (this._key) {
        path = this._key + '.' + path;
      }

      if (this._parent) {
        this._parent.populateAffected(path, depth + 1, affected);
      } else {
        if (depth > 1) {
          affected.push(this.value(), path);
        }
      }
    }
  };

  function finishChains(obj) {
    // We only create meta if we really have to
    var m = _emberMetalMeta.peekMeta(obj);
    if (m) {
      m = _emberMetalMeta.meta(obj);

      // finish any current chains node watchers that reference obj
      var chainWatchers = m.readableChainWatchers();
      if (chainWatchers) {
        chainWatchers.revalidateAll();
      }
      // ensure that if we have inherited any chains they have been
      // copied onto our own meta.
      if (m.readableChains()) {
        m.writableChains();
      }
    }
  }

  exports.removeChainWatcher = removeChainWatcher;
  exports.ChainNode = ChainNode;
});
enifed('ember-metal/computed', ['exports', 'ember-metal/debug', 'ember-metal/property_set', 'ember-metal/utils', 'ember-metal/meta', 'ember-metal/expand_properties', 'ember-metal/error', 'ember-metal/properties', 'ember-metal/property_events', 'ember-metal/dependent_keys'], function (exports, _emberMetalDebug, _emberMetalProperty_set, _emberMetalUtils, _emberMetalMeta, _emberMetalExpand_properties, _emberMetalError, _emberMetalProperties, _emberMetalProperty_events, _emberMetalDependent_keys) {
  'use strict';

  exports.default = computed;

  /**
  @module ember
  @submodule ember-metal
  */

  function UNDEFINED() {}

  var DEEP_EACH_REGEX = /\.@each\.[^.]+\./;

  /**
    A computed property transforms an object literal with object's accessor function(s) 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 depends on. This will force the cached
    result to be recomputed if the dependencies are modified.

    In the following example we declare a computed property - `fullName` - by calling
    `.Ember.computed()` with property dependencies (`firstName` and `lastName`) as leading arguments and getter accessor function. The `fullName` getter function
    will be called once (regardless of how many times it is accessed) as long
    as its dependencies have not changed. Once `firstName` or `lastName` are updated
    any future calls (or anything bound) to `fullName` will incorporate the new
    values.

    ```javascript
    let Person = Ember.Object.extend({
      // these will be supplied by `create`
      firstName: null,
      lastName: null,

      fullName: Ember.computed('firstName', 'lastName', function() {
        let firstName = this.get('firstName'),
            lastName  = this.get('lastName');

        return firstName + ' ' + lastName;
      })
    });

    let 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 by providing additional function (`set`) in hash argument.
    If you try to set a computed property, it will try to invoke setter accessor function with the key and
    value you want to set it to as arguments.

    ```javascript
    let Person = Ember.Object.extend({
      // these will be supplied by `create`
      firstName: null,
      lastName: null,

      fullName: Ember.computed('firstName', 'lastName', {
        get(key) {
          let firstName = this.get('firstName'),
              lastName  = this.get('lastName');

          return firstName + ' ' + lastName;
        },
        set(key, value) {
          let [firstName, lastName] = value.split(' ');

          this.set('firstName', firstName);
          this.set('lastName', lastName);

          return value;
        }
      })
    });

    let person = Person.create();

    person.set('fullName', 'Peter Wagenet');
    person.get('firstName'); // 'Peter'
    person.get('lastName');  // 'Wagenet'
    ```

    You can overwrite computed property with normal property (no longer computed), that won't change if dependencies change, if you set computed property and it won't have setter accessor function defined.

    You can also mark computed property as `.readOnly()` and block all attempts to set it.

    ```javascript
    let Person = Ember.Object.extend({
      // these will be supplied by `create`
      firstName: null,
      lastName: null,

      fullName: Ember.computed('firstName', 'lastName', {
        get(key) {
          let firstName = this.get('firstName');
          let lastName  = this.get('lastName');

          return firstName + ' ' + lastName;
        }
      }).readOnly()
    });

    let person = Person.create();
    person.set('fullName', 'Peter Wagenet'); // Uncaught Error: Cannot set read-only property "fullName" on object: <(...):emberXXX>
    ```

    Additional resources:
    - [New CP syntax RFC](https://github.com/emberjs/rfcs/blob/master/text/0011-improved-cp-syntax.md)
    - [New computed syntax explained in "Ember 1.12 released" ](http://emberjs.com/blog/2015/05/13/ember-1-12-released.html#toc_new-computed-syntax)

    @class ComputedProperty
    @namespace Ember
    @public
  */
  function ComputedProperty(config, opts) {
    this.isDescriptor = true;
    if (typeof config === 'function') {
      this._getter = config;
    } else {
      _emberMetalDebug.assert('Ember.computed expects a function or an object as last argument.', typeof config === 'object' && !Array.isArray(config));
      _emberMetalDebug.assert('Config object pased to a Ember.computed can only contain `get` or `set` keys.', (function () {
        var keys = Object.keys(config);
        for (var i = 0; i < keys.length; i++) {
          if (keys[i] !== 'get' && keys[i] !== 'set') {
            return false;
          }
        }
        return true;
      })());
      this._getter = config.get;
      this._setter = config.set;
    }
    _emberMetalDebug.assert('Computed properties must receive a getter or a setter, you passed none.', !!this._getter || !!this._setter);
    this._dependentKeys = undefined;
    this._suspended = undefined;
    this._meta = undefined;
    this._volatile = false;
    this._dependentKeys = opts && opts.dependentKeys;
    this._readOnly = false;
  }

  ComputedProperty.prototype = new _emberMetalProperties.Descriptor();

  var ComputedPropertyPrototype = ComputedProperty.prototype;

  /**
    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.

    It also does not automatically fire any change events. You must manually notify
    any changes if you want to observe this property.

    Dependency keys have no effect on volatile properties as they are for cache
    invalidation and notification when cached value is invalidated.

    ```javascript
    let outsideService = Ember.Object.extend({
      value: Ember.computed(function() {
        return OutsideService.getValue();
      }).volatile()
    }).create();
    ```

    @method volatile
    @return {Ember.ComputedProperty} this
    @chainable
    @public
  */
  ComputedPropertyPrototype.volatile = function () {
    this._volatile = true;
    return this;
  };

  /**
    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
    let Person = Ember.Object.extend({
      guid: Ember.computed(function() {
        return 'guid-guid-guid';
      }).readOnly()
    });

    let person = Person.create();

    person.set('guid', 'new-guid'); // will throw an exception
    ```

    @method readOnly
    @return {Ember.ComputedProperty} this
    @chainable
    @public
  */
  ComputedPropertyPrototype.readOnly = function () {
    this._readOnly = true;
    _emberMetalDebug.assert('Computed properties that define a setter using the new syntax cannot be read-only', !(this._readOnly && this._setter && this._setter !== this._getter));
    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
    let President = Ember.Object.extend({
      fullName: Ember.computed(function() {
        return this.get('firstName') + ' ' + this.get('lastName');

        // Tell Ember that this computed property depends on firstName
        // and lastName
      }).property('firstName', 'lastName')
    });

    let 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
    @public
  */
  ComputedPropertyPrototype.property = function () {
    var args;

    var addArg = function (property) {
      _emberMetalDebug.warn('Dependent keys containing @each only work one level deep. ' + 'You cannot use nested forms like todos.@each.owner.name or todos.@each.owner.@each.name. ' + 'Please create an intermediary computed property.', DEEP_EACH_REGEX.test(property) === false, { id: 'ember-metal.computed-deep-each' });
      args.push(property);
    };

    args = [];
    for (var i = 0, l = arguments.length; i < l; i++) {
      _emberMetalExpand_properties.default(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: Ember.computed(function() {
      let personId = this.get('personId');
      return App.Person.create({ id: personId });
    }).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 {Object} meta
    @chainable
    @public
  */
  ComputedPropertyPrototype.meta = function (meta) {
    if (arguments.length === 0) {
      return this._meta || {};
    } else {
      this._meta = meta;
      return this;
    }
  };

  // invalidate cache when CP key changes
  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._volatile || this._suspended === obj) {
      return;
    }

    // don't create objects just to invalidate
    var meta = _emberMetalMeta.peekMeta(obj);
    if (!meta || meta.source !== obj) {
      return;
    }

    var cache = meta.readableCache();
    if (cache && cache[keyName] !== undefined) {
      cache[keyName] = undefined;
      _emberMetalDependent_keys.removeDependentKeys(this, obj, keyName, meta);
    }
  };

  ComputedPropertyPrototype.get = function (obj, keyName) {
    if (this._volatile) {
      return this._getter.call(obj, keyName);
    }

    var meta = _emberMetalMeta.meta(obj);
    var cache = meta.writableCache();

    var result = cache[keyName];
    if (result === UNDEFINED) {
      return undefined;
    } else if (result !== undefined) {
      return result;
    }

    var ret = this._getter.call(obj, keyName);
    if (ret === undefined) {
      cache[keyName] = UNDEFINED;
    } else {
      cache[keyName] = ret;
    }

    var chainWatchers = meta.readableChainWatchers();
    if (chainWatchers) {
      chainWatchers.revalidate(keyName);
    }
    _emberMetalDependent_keys.addDependentKeys(this, obj, keyName, meta);

    return ret;
  };

  ComputedPropertyPrototype.set = function computedPropertySetEntry(obj, keyName, value) {
    if (this._readOnly) {
      this._throwReadOnlyError(obj, keyName);
    }

    if (!this._setter) {
      return this.clobberSet(obj, keyName, value);
    }

    if (this._volatile) {
      return this.volatileSet(obj, keyName, value);
    }

    return this.setWithSuspend(obj, keyName, value);
  };

  ComputedPropertyPrototype._throwReadOnlyError = function computedPropertyThrowReadOnlyError(obj, keyName) {
    throw new _emberMetalError.default('Cannot set read-only property "' + keyName + '" on object: ' + _emberMetalUtils.inspect(obj));
  };

  ComputedPropertyPrototype.clobberSet = function computedPropertyClobberSet(obj, keyName, value) {
    var cachedValue = cacheFor(obj, keyName);
    _emberMetalProperties.defineProperty(obj, keyName, null, cachedValue);
    _emberMetalProperty_set.set(obj, keyName, value);
    return value;
  };

  ComputedPropertyPrototype.volatileSet = function computedPropertyVolatileSet(obj, keyName, value) {
    return this._setter.call(obj, keyName, value);
  };

  ComputedPropertyPrototype.setWithSuspend = function computedPropertySetWithSuspend(obj, keyName, value) {
    var oldSuspended = this._suspended;
    this._suspended = obj;
    try {
      return this._set(obj, keyName, value);
    } finally {
      this._suspended = oldSuspended;
    }
  };

  ComputedPropertyPrototype._set = function computedPropertySet(obj, keyName, value) {
    // cache requires own meta
    var meta = _emberMetalMeta.meta(obj);
    // either there is a writable cache or we need one to update
    var cache = meta.writableCache();
    var hadCachedValue = false;
    var cachedValue = undefined;
    if (cache[keyName] !== undefined) {
      if (cache[keyName] !== UNDEFINED) {
        cachedValue = cache[keyName];
      }
      hadCachedValue = true;
    }

    var ret = this._setter.call(obj, keyName, value, cachedValue);

    // allows setter to return the same value that is cached already
    if (hadCachedValue && cachedValue === ret) {
      return ret;
    }

    var watched = meta.peekWatching(keyName);
    if (watched) {
      _emberMetalProperty_events.propertyWillChange(obj, keyName);
    }

    if (hadCachedValue) {
      cache[keyName] = undefined;
    }

    if (!hadCachedValue) {
      _emberMetalDependent_keys.addDependentKeys(this, obj, keyName, meta);
    }

    if (ret === undefined) {
      cache[keyName] = UNDEFINED;
    } else {
      cache[keyName] = ret;
    }

    if (watched) {
      _emberMetalProperty_events.propertyDidChange(obj, keyName);
    }

    return ret;
  };

  /* called before property is overridden */
  ComputedPropertyPrototype.teardown = function (obj, keyName) {
    if (this._volatile) {
      return;
    }
    var meta = _emberMetalMeta.meta(obj);
    var cache = meta.readableCache();
    if (cache && cache[keyName] !== undefined) {
      _emberMetalDependent_keys.removeDependentKeys(this, obj, keyName, meta);
      cache[keyName] = undefined;
    }
  };

  /**
    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()`.

    If you pass a function as an argument, it will be used as a getter. A computed
    property defined in this way might look like this:

    ```js
    let Person = Ember.Object.extend({
      init() {
        this._super(...arguments);

        this.firstName = 'Betty';
        this.lastName = 'Jones';
      },

      fullName: Ember.computed('firstName', 'lastName', function() {
        return `${this.get('firstName')} ${this.get('lastName')}`;
      })
    });

    let client = Person.create();

    client.get('fullName'); // 'Betty Jones'

    client.set('lastName', 'Fuller');
    client.get('fullName'); // 'Betty Fuller'
    ```

    You can pass a hash with two functions, `get` and `set`, as an
    argument to provide both a getter and setter:

    ```js
    let Person = Ember.Object.extend({
      init() {
        this._super(...arguments);

        this.firstName = 'Betty';
        this.lastName = 'Jones';
      },

      fullName: Ember.computed('firstName', 'lastName', {
        get(key) {
          return `${this.get('firstName')} ${this.get('lastName')}`;
        },
        set(key, value) {
          let [firstName, lastName] = value.split(/\s+/);
          this.setProperties({ firstName, lastName });
          return value;
        }
      });
    })

    let client = Person.create();
    client.get('firstName'); // 'Betty'

    client.set('fullName', 'Carroll Fuller');
    client.get('firstName'); // 'Carroll'
    ```

    The `set` function should accept two parameters, `key` and `value`. The value
    returned from `set` will be the new value of the property.

    _Note: This is the preferred way to define computed properties when writing third-party
    libraries that depend on or use Ember, since there is no guarantee that the user
    will have [prototype Extensions](http://emberjs.com/guides/configuring-ember/disabling-prototype-extensions/) enabled._

    The alternative syntax, with prototype extensions, might look like:

    ```js
    fullName: function() {
      return this.get('firstName') + ' ' + this.get('lastName');
    }.property('firstName', 'lastName')
    ```

    @class computed
    @namespace Ember
    @constructor
    @static
    @param {String} [dependentKeys*] Optional dependent keys that trigger this computed property.
    @param {Function} func The computed property function.
    @return {Ember.ComputedProperty} property descriptor instance
    @public
  */

  function computed(func) {
    var args;

    if (arguments.length > 1) {
      args = [].slice.call(arguments);
      func = args.pop();
    }

    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
    @public
  */
  function cacheFor(obj, key) {
    var meta = _emberMetalMeta.peekMeta(obj);
    var cache = meta && meta.source === obj && meta.readableCache();
    var 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;
});
enifed('ember-metal/computed_macros', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/computed', 'ember-metal/is_empty', 'ember-metal/is_none', 'ember-metal/alias', 'ember-metal/expand_properties'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalComputed, _emberMetalIs_empty, _emberMetalIs_none, _emberMetalAlias, _emberMetalExpand_properties) {
  'use strict';

  exports.empty = empty;
  exports.notEmpty = notEmpty;
  exports.none = none;
  exports.not = not;
  exports.bool = bool;
  exports.match = match;
  exports.equal = equal;
  exports.gt = gt;
  exports.gte = gte;
  exports.lt = lt;
  exports.lte = lte;
  exports.oneWay = oneWay;
  exports.readOnly = readOnly;
  exports.deprecatingAlias = deprecatingAlias;

  /**
  @module ember
  @submodule ember-metal
  */

  function getProperties(self, propertyNames) {
    var ret = {};
    for (var i = 0; i < propertyNames.length; i++) {
      ret[propertyNames[i]] = _emberMetalProperty_get.get(self, propertyNames[i]);
    }
    return ret;
  }

  function generateComputedWithProperties(macro) {
    return function () {
      var expandedProperties = [];
      var computedFunc = _emberMetalComputed.computed(function () {
        return macro.apply(this, [getProperties(this, expandedProperties)]);
      });

      function extractProperty(entry) {
        expandedProperties.push(entry);
      }

      for (var _len = arguments.length, properties = Array(_len), _key = 0; _key < _len; _key++) {
        properties[_key] = arguments[_key];
      }

      for (var i = 0; i < properties.length; i++) {
        _emberMetalExpand_properties.default(properties[i], extractProperty);
      }

      return computedFunc.property.apply(computedFunc, expandedProperties);
    };
  }

  /**
    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({
      isDone: Ember.computed.empty('todos')
    });

    var todoList = ToDoList.create({
      todos: ['Unit Test', 'Documentation', 'Release']
    });

    todoList.get('isDone'); // false
    todoList.get('todos').clear();
    todoList.get('isDone'); // true
    ```

    @since 1.6.0
    @method empty
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which negate
    the original value for property
    @public
  */

  function empty(dependentKey) {
    return _emberMetalComputed.computed(dependentKey + '.length', function () {
      return _emberMetalIs_empty.default(_emberMetalProperty_get.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.

    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 notEmpty
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which returns true if
    original value for property is not empty.
    @public
  */

  function notEmpty(dependentKey) {
    return _emberMetalComputed.computed(dependentKey + '.length', function () {
      return !_emberMetalIs_empty.default(_emberMetalProperty_get.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 none
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which
    returns true if original value for property is null or undefined.
    @public
  */

  function none(dependentKey) {
    return _emberMetalComputed.computed(dependentKey, function () {
      return _emberMetalIs_none.default(_emberMetalProperty_get.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 not
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which returns
    inverse of the original value for property
    @public
  */

  function not(dependentKey) {
    return _emberMetalComputed.computed(dependentKey, function () {
      return !_emberMetalProperty_get.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 bool
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which converts
    to boolean the original value for property
    @public
  */

  function bool(dependentKey) {
    return _emberMetalComputed.computed(dependentKey, function () {
      return !!_emberMetalProperty_get.get(this, dependentKey);
    });
  }

  /**
    A computed property which matches the original value for the
    dependent property against a given RegExp, returning `true`
    if the value 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 match
    @for Ember.computed
    @param {String} dependentKey
    @param {RegExp} regexp
    @return {Ember.ComputedProperty} computed property which match
    the original value for property against a given RegExp
    @public
  */

  function match(dependentKey, regexp) {
    return _emberMetalComputed.computed(dependentKey, function () {
      var value = _emberMetalProperty_get.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 equal
    @for Ember.computed
    @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.
    @public
  */

  function equal(dependentKey, value) {
    return _emberMetalComputed.computed(dependentKey, function () {
      return _emberMetalProperty_get.get(this, dependentKey) === value;
    });
  }

  /**
    A computed property that returns true if the provided 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 gt
    @for Ember.computed
    @param {String} dependentKey
    @param {Number} value
    @return {Ember.ComputedProperty} computed property which returns true if
    the original value for property is greater than given value.
    @public
  */

  function gt(dependentKey, value) {
    return _emberMetalComputed.computed(dependentKey, function () {
      return _emberMetalProperty_get.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 gte
    @for Ember.computed
    @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.
    @public
  */

  function gte(dependentKey, value) {
    return _emberMetalComputed.computed(dependentKey, function () {
      return _emberMetalProperty_get.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 lt
    @for Ember.computed
    @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.
    @public
  */

  function lt(dependentKey, value) {
    return _emberMetalComputed.computed(dependentKey, function () {
      return _emberMetalProperty_get.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 lte
    @for Ember.computed
    @param {String} dependentKey
    @param {Number} value
    @return {Ember.ComputedProperty} computed property which returns true if
    the original value for property is less or equal than given value.
    @public
  */

  function lte(dependentKey, value) {
    return _emberMetalComputed.computed(dependentKey, function () {
      return _emberMetalProperty_get.get(this, dependentKey) <= value;
    });
  }

  /**
    A computed property that performs a logical `and` on the
    original values for the provided dependent properties.

    You may pass in more than two properties and even use
    property brace expansion.  The computed property will
    returns the first falsy value or last truthy value
    just like JavaScript's `||` operator.

    Example

    ```javascript
    var Hamster = Ember.Object.extend({
      readyForCamp: Ember.computed.and('hasTent', 'hasBackpack'),
      readyForHike: Ember.computed.and('hasWalkingStick', 'hasBackpack')
    });

    var tomster = Hamster.create();

    tomster.get('readyForCamp'); // false
    tomster.set('hasTent', true);
    tomster.get('readyForCamp'); // false
    tomster.set('hasBackpack', true);
    tomster.get('readyForCamp'); // true
    tomster.set('hasBackpack', 'Yes');
    tomster.get('readyForCamp'); // 'Yes'
    tomster.set('hasWalkingStick', null);
    tomster.get('readyForHike'); // null
    ```

    @method and
    @for Ember.computed
    @param {String} dependentKey*
    @return {Ember.ComputedProperty} computed property which performs
    a logical `and` on the values of all the original values for properties.
    @public
  */
  var and = generateComputedWithProperties(function (properties) {
    var value;
    for (var key in properties) {
      value = properties[key];
      if (properties.hasOwnProperty(key) && !value) {
        return value;
      }
    }
    return value;
  });

  exports.and = and;
  /**
    A computed property which performs a logical `or` on the
    original values for the provided dependent properties.

    You may pass in more than two properties and even use
    property brace expansion.  The computed property will
    returns the first truthy value or last falsy value just
    like JavaScript's `||` operator.

    Example

    ```javascript
    var Hamster = Ember.Object.extend({
      readyForRain: Ember.computed.or('hasJacket', 'hasUmbrella'),
      readyForBeach: Ember.computed.or('{hasSunscreen,hasUmbrella}')
    });

    var tomster = Hamster.create();

    tomster.get('readyForRain'); // undefined
    tomster.set('hasUmbrella', true);
    tomster.get('readyForRain'); // true
    tomster.set('hasJacket', 'Yes');
    tomster.get('readyForRain'); // 'Yes'
    tomster.set('hasSunscreen', 'Check');
    tomster.get('readyForBeach'); // 'Check'
    ```

    @method or
    @for Ember.computed
    @param {String} dependentKey*
    @return {Ember.ComputedProperty} computed property which performs
    a logical `or` on the values of all the original values for properties.
    @public
  */
  var or = generateComputedWithProperties(function (properties) {
    var value;
    for (var key in properties) {
      value = properties[key];
      if (properties.hasOwnProperty(key) && value) {
        return value;
      }
    }
    return value;
  });

  exports.or = or;
  /**
    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 alias
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which creates an
    alias to the original value for property.
    @public
  */

  /**
    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 oneWay
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which creates a
    one way computed property to the original value for property.
    @public
  */

  function oneWay(dependentKey) {
    return _emberMetalAlias.default(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 reads
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which creates a
      one way computed property to the original value for property.
    @public
   */

  /**
    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 propagate 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 readOnly
    @for Ember.computed
    @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
    @public
  */

  function readOnly(dependentKey) {
    return _emberMetalAlias.default(dependentKey).readOnly();
  }

  /**
    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 deprecatingAlias
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computed property which creates an
    alias with a deprecation to the original value for property.
    @since 1.7.0
    @public
  */

  function deprecatingAlias(dependentKey, options) {
    return _emberMetalComputed.computed(dependentKey, {
      get: function (key) {
        _emberMetalDebug.deprecate('Usage of `' + key + '` is deprecated, use `' + dependentKey + '` instead.', false, options);
        return _emberMetalProperty_get.get(this, dependentKey);
      },
      set: function (key, value) {
        _emberMetalDebug.deprecate('Usage of `' + key + '` is deprecated, use `' + dependentKey + '` instead.', false, options);
        _emberMetalProperty_set.set(this, dependentKey, value);
        return value;
      }
    });
  }
});
enifed('ember-metal/core', ['exports', 'require'], function (exports, _require) {
  /*globals Ember:true,ENV,EmberENV */

  'use strict';

  /**
  @module ember
  @submodule ember-metal
  */

  /**
    This namespace contains all Ember methods and functions. Future versions of
    Ember may overwrite this namespace and therefore, you should avoid adding any
    new properties.

    At the heart of Ember is Ember-Runtime, a set of core functions that provide
    cross-platform compatibility and object property observing.  Ember-Runtime is
    small and performance-focused so you can use it alongside other
    cross-platform libraries such as jQuery. For more details, see
    [Ember-Runtime](http://emberjs.com/api/modules/ember-runtime.html).

    @class Ember
    @static
    @version 2.6.2
    @public
  */

  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 global = mainContext || {}; // jshint ignore:line
  Ember.imports = Ember.imports || global;
  Ember.lookup = Ember.lookup || global;
  var emExports = Ember.exports = Ember.exports || global;

  // aliases needed to keep minifiers from removing the global context
  emExports.Em = emExports.Ember = Ember;

  // Make sure these are set whether Ember was already defined or not

  Ember.isNamespace = true;

  Ember.toString = function () {
    return 'Ember';
  };

  // The debug functions are exported to globals with `require` to
  // prevent babel-plugin-filter-imports from removing them.
  var debugModule = _require.default('ember-metal/debug');
  Ember.assert = debugModule.assert;
  Ember.warn = debugModule.warn;
  Ember.debug = debugModule.debug;
  Ember.deprecate = debugModule.deprecate;
  Ember.deprecateFunc = debugModule.deprecateFunc;
  Ember.runInDebug = debugModule.runInDebug;

  /**
    The semantic version.

    @property VERSION
    @type String
    @default '2.6.2'
    @static
    @public
  */
  Ember.VERSION = '2.6.2';

  /**
    The hash of environment variables used to control various configuration
    settings. To specify your own or override default settings, add the
    desired properties to a global hash named `EmberENV` (or `ENV` for
    backwards compatibility with earlier versions of Ember). The `EmberENV`
    hash must be created before loading Ember.

    @property ENV
    @type Object
    @public
  */

  if (Ember.ENV) {
    // do nothing if Ember.ENV is already setup
    Ember.assert('Ember.ENV should be an object.', 'object' !== typeof Ember.ENV);
  } else if ('undefined' !== typeof EmberENV) {
    Ember.ENV = EmberENV;
  } else if ('undefined' !== typeof ENV) {
    Ember.ENV = ENV;
  } else {
    Ember.ENV = {};
  }

  // ENABLE_ALL_FEATURES was documented, but you can't actually enable non optional features.
  if (Ember.ENV.ENABLE_ALL_FEATURES) {
    Ember.ENV.ENABLE_OPTIONAL_FEATURES = Ember.ENV.ENABLE_ALL_FEATURES;
  }

  Ember.config = Ember.config || {};

  // ..........................................................
  // BOOTSTRAP
  //

  /**
    Determines whether Ember should add to `Array`, `Function`, and `String`
    native object prototypes, a few extra methods in order to provide a more
    friendly API.

    We generally recommend leaving this option set to true however, if you need
    to turn it off, you can add the configuration property
    `EXTEND_PROTOTYPES` to `EmberENV` and set it to `false`.

    Note, when disabled (the default configuration for Ember Addons), you will
    instead have to access all methods and functions from the Ember
    namespace.

    @property EXTEND_PROTOTYPES
    @type Boolean
    @default true
    @for Ember
    @public
  */
  Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES;

  if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') {
    Ember.EXTEND_PROTOTYPES = true;
  }

  /**
    The `LOG_STACKTRACE_ON_DEPRECATION` property, when true, tells Ember to log
    a full stack trace during deprecation warnings.

    @property LOG_STACKTRACE_ON_DEPRECATION
    @type Boolean
    @default true
    @public
  */
  Ember.LOG_STACKTRACE_ON_DEPRECATION = Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false;

  /**
    The `LOG_VERSION` property, when true, tells Ember to log versions of all
    dependent libraries in use.

    @property LOG_VERSION
    @type Boolean
    @default true
    @public
  */
  Ember.LOG_VERSION = Ember.ENV.LOG_VERSION === false ? false : true;

  /**
    An empty function useful for some operations. Always returns `this`.

    @method K
    @return {Object}
    @public
  */
  function K() {
    return this;
  }
  exports.K = K;

  Ember.K = K;
  //TODO: ES6 GLOBAL TODO

  exports.default = Ember;
});
enifed("ember-metal/debug", ["exports"], function (exports) {
  "use strict";

  exports.getDebugFunction = getDebugFunction;
  exports.setDebugFunction = setDebugFunction;
  exports.assert = assert;
  exports.info = info;
  exports.warn = warn;
  exports.debug = debug;
  exports.deprecate = deprecate;
  exports.deprecateFunc = deprecateFunc;
  exports.runInDebug = runInDebug;
  exports.debugSeal = debugSeal;
  var debugFunctions = {
    assert: function () {},
    info: function () {},
    warn: function () {},
    debug: function () {},
    deprecate: function () {},
    deprecateFunc: function () {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      return args[args.length - 1];
    },
    runInDebug: function () {},
    debugSeal: function () {}
  };

  exports.debugFunctions = debugFunctions;

  function getDebugFunction(name) {
    return debugFunctions[name];
  }

  function setDebugFunction(name, fn) {
    debugFunctions[name] = fn;
  }

  function assert() {
    return debugFunctions.assert.apply(undefined, arguments);
  }

  function info() {
    return debugFunctions.info.apply(undefined, arguments);
  }

  function warn() {
    return debugFunctions.warn.apply(undefined, arguments);
  }

  function debug() {
    return debugFunctions.debug.apply(undefined, arguments);
  }

  function deprecate() {
    return debugFunctions.deprecate.apply(undefined, arguments);
  }

  function deprecateFunc() {
    return debugFunctions.deprecateFunc.apply(undefined, arguments);
  }

  function runInDebug() {
    return debugFunctions.runInDebug.apply(undefined, arguments);
  }

  function debugSeal() {
    return debugFunctions.debugSeal.apply(undefined, arguments);
  }
});
enifed('ember-metal/dependent_keys', ['exports', 'ember-metal/watching'], function (exports, _emberMetalWatching) {
  'no use strict';
  // Remove "use strict"; from transpiled module until
  // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed

  exports.addDependentKeys = addDependentKeys;
  exports.removeDependentKeys = removeDependentKeys;

  /**
  @module ember
  @submodule ember-metal
  */

  // ..........................................................
  // DEPENDENT KEYS
  //

  function addDependentKeys(desc, obj, keyName, meta) {
    // the descriptor has a list of dependent keys, so
    // add all of its dependent keys.
    var idx, len, depKey;
    var depKeys = desc._dependentKeys;
    if (!depKeys) {
      return;
    }

    for (idx = 0, len = depKeys.length; idx < len; idx++) {
      depKey = depKeys[idx];
      // Increment the number of times depKey depends on keyName.
      meta.writeDeps(depKey, keyName, (meta.peekDeps(depKey, keyName) || 0) + 1);
      // Watch the depKey
      _emberMetalWatching.watch(obj, depKey, meta);
    }
  }

  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;
    var idx, len, depKey;
    if (!depKeys) {
      return;
    }

    for (idx = 0, len = depKeys.length; idx < len; idx++) {
      depKey = depKeys[idx];
      // Decrement the number of times depKey depends on keyName.
      meta.writeDeps(depKey, keyName, (meta.peekDeps(depKey, keyName) || 0) - 1);
      // Unwatch the depKey
      _emberMetalWatching.unwatch(obj, depKey, meta);
    }
  }
});
enifed('ember-metal/deprecate_property', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set) {
  /**
  @module ember
  @submodule ember-metal
  */

  'use strict';

  exports.deprecateProperty = deprecateProperty;

  /**
    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
    @since 1.7.0
  */

  function deprecateProperty(object, deprecatedKey, newKey, options) {
    function _deprecate() {
      _emberMetalDebug.deprecate('Usage of `' + deprecatedKey + '` is deprecated, use `' + newKey + '` instead.', false, options);
    }

    Object.defineProperty(object, deprecatedKey, {
      configurable: true,
      enumerable: false,
      set: function (value) {
        _deprecate();
        _emberMetalProperty_set.set(this, newKey, value);
      },
      get: function () {
        _deprecate();
        return _emberMetalProperty_get.get(this, newKey);
      }
    });
  }
});
enifed('ember-metal/dictionary', ['exports', 'ember-metal/empty_object'], function (exports, _emberMetalEmpty_object) {
  'use strict';

  exports.default = makeDictionary;

  // the delete is meant to hint at runtimes that this object should remain in
  // dictionary mode. This is clearly a runtime specific hack, but currently it
  // appears worthwhile in some usecases. Please note, these deletes do increase
  // the cost of creation dramatically over a plain Object.create. And as this
  // only makes sense for long-lived dictionaries that aren't instantiated often.

  function makeDictionary(parent) {
    var dict;
    if (parent === null) {
      dict = new _emberMetalEmpty_object.default();
    } else {
      dict = Object.create(parent);
    }
    dict['_dict'] = null;
    delete dict['_dict'];
    return dict;
  }
});
enifed("ember-metal/empty_object", ["exports"], function (exports) {
  // This exists because `Object.create(null)` is absurdly slow compared
  // to `new EmptyObject()`. In either case, you want a null prototype
  // when you're treating the object instances as arbitrary dictionaries
  // and don't want your keys colliding with build-in methods on the
  // default object prototype.

  "use strict";

  var proto = Object.create(null, {
    // without this, we will always still end up with (new
    // EmptyObject()).constructor === Object
    constructor: {
      value: undefined,
      enumerable: false,
      writable: true
    }
  });

  function EmptyObject() {}
  EmptyObject.prototype = proto;
  exports.default = EmptyObject;
});
enifed('ember-metal/environment', ['exports', 'ember-metal/core'], function (exports, _emberMetalCore) {
  'use strict';

  /*
    Ember can run in many different environments, including environments like
    Node.js where the DOM is unavailable. This object serves as an abstraction
    over the browser features that Ember relies on, so that code does not
    explode when trying to boot in an environment that doesn't have them.

    This is a private abstraction. In the future, we hope that other
    abstractions (like `Location`, `Renderer`, `dom-helper`) can fully abstract
    over the differences in environment.
  */
  var environment;

  // This code attempts to automatically detect an environment with DOM
  // by searching for window and document.createElement. An environment
  // with DOM may disable the DOM functionality of Ember explicitly by
  // defining a `disableBrowserEnvironment` ENV.
  var hasDOM = typeof window !== 'undefined' && typeof document !== 'undefined' && typeof document.createElement !== 'undefined' && !_emberMetalCore.default.ENV.disableBrowserEnvironment;

  if (hasDOM) {
    environment = {
      hasDOM: true,
      isChrome: !!window.chrome && !window.opera,
      isFirefox: typeof InstallTrigger !== 'undefined',
      isPhantom: !!window.callPhantom,
      location: window.location,
      history: window.history,
      userAgent: window.navigator.userAgent,
      global: window
    };
  } else {
    environment = {
      hasDOM: false,
      isChrome: false,
      isFirefox: false,
      isPhantom: false,
      location: null,
      history: null,
      userAgent: 'Lynx (textmode)',
      global: null
    };
  }

  exports.default = environment;
});
enifed('ember-metal/error', ['exports', 'ember-metal/core'], function (exports, _emberMetalCore) {
  'use strict';

  exports.default = EmberError;

  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
    @public
  */

  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, _emberMetalCore.default.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 = Object.create(Error.prototype);
});
enifed('ember-metal/events', ['exports', 'ember-metal/debug', 'ember-metal/utils', 'ember-metal/meta', 'ember-metal/meta_listeners'], function (exports, _emberMetalDebug, _emberMetalUtils, _emberMetalMeta, _emberMetalMeta_listeners) {
  'no use strict';
  // Remove "use strict"; from transpiled module until
  // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed

  /**
  @module ember
  @submodule ember-metal
  */
  exports.accumulateListeners = accumulateListeners;
  exports.addListener = addListener;
  exports.removeListener = removeListener;
  exports.suspendListener = suspendListener;
  exports.suspendListeners = suspendListeners;
  exports.watchedEvents = watchedEvents;
  exports.sendEvent = sendEvent;
  exports.hasListeners = hasListeners;
  exports.listenersFor = listenersFor;
  exports.on = on;

  /*
    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 accumulateListeners(obj, eventName, otherActions) {
    var meta = _emberMetalMeta.peekMeta(obj);
    if (!meta) {
      return;
    }
    var actions = meta.matchingListeners(eventName);
    var newActions = [];

    for (var i = actions.length - 3; i >= 0; i -= 3) {
      var target = actions[i];
      var method = actions[i + 1];
      var flags = actions[i + 2];
      var actionIndex = indexOf(otherActions, target, method);

      if (actionIndex === -1) {
        otherActions.push(target, method, flags);
        newActions.push(target, method, flags);
      }
    }

    return newActions;
  }

  /**
    Add an event listener

    @method addListener
    @for Ember
    @param obj
    @param {String} eventName
    @param {Object|Function} target 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
    @public
  */

  function addListener(obj, eventName, target, method, once) {
    _emberMetalDebug.assert('You must pass at least an object and event name to Ember.addListener', !!obj && !!eventName);

    _emberMetalDebug.deprecate('didInitAttrs called in ' + (obj && obj.toString && obj.toString()) + '.', eventName !== 'didInitAttrs', {
      id: 'ember-views.did-init-attrs',
      until: '3.0.0',
      url: 'http://emberjs.com/deprecations/v2.x#toc_ember-component-didinitattrs'
    });

    if (!method && 'function' === typeof target) {
      method = target;
      target = null;
    }

    var flags = 0;
    if (once) {
      flags |= _emberMetalMeta_listeners.ONCE;
    }

    _emberMetalMeta.meta(obj).addToListeners(eventName, target, method, flags);

    if ('function' === typeof obj.didAddListener) {
      obj.didAddListener(eventName, target, method);
    }
  }

  /**
    Remove an event listener

    Arguments should match those passed to `Ember.addListener`.

    @method removeListener
    @for Ember
    @param obj
    @param {String} eventName
    @param {Object|Function} target A target object or a function
    @param {Function|String} method A function or the name of a function to be called on `target`
    @public
  */

  function removeListener(obj, eventName, target, method) {
    _emberMetalDebug.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;
    }

    _emberMetalMeta.meta(obj).removeFromListeners(eventName, target, method, function () {
      if ('function' === typeof obj.didRemoveListener) {
        obj.didRemoveListener.apply(obj, arguments);
      }
    });
  }

  /**
    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} target 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) {
    return suspendListeners(obj, [eventName], target, method, callback);
  }

  /**
    Suspends multiple listeners during a callback.

    @method suspendListeners
    @for Ember

    @private
    @param obj
    @param {Array} eventNames Array of event names
    @param {Object|Function} target 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;
    }
    return _emberMetalMeta.meta(obj).suspendListeners(eventNames, target, method, callback);
  }

  /**
    Return a list of currently watched events

    @private
    @method watchedEvents
    @for Ember
    @param obj
  */

  function watchedEvents(obj) {
    return _emberMetalMeta.meta(obj).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
    @public
  */

  function sendEvent(obj, eventName, params, actions) {
    if (!actions) {
      var meta = _emberMetalMeta.peekMeta(obj);
      actions = meta && meta.matchingListeners(eventName);
    }

    if (!actions || actions.length === 0) {
      return;
    }

    for (var i = actions.length - 3; i >= 0; i -= 3) {
      // looping in reverse for once listeners
      var target = actions[i];
      var method = actions[i + 1];
      var flags = actions[i + 2];

      if (!method) {
        continue;
      }
      if (flags & _emberMetalMeta_listeners.SUSPENDED) {
        continue;
      }
      if (flags & _emberMetalMeta_listeners.ONCE) {
        removeListener(obj, eventName, target, method);
      }
      if (!target) {
        target = obj;
      }
      if ('string' === typeof method) {
        if (params) {
          _emberMetalUtils.applyStr(target, method, params);
        } else {
          target[method]();
        }
      } else {
        if (params) {
          method.apply(target, params);
        } else {
          method.call(target);
        }
      }
    }
    return true;
  }

  /**
    @private
    @method hasListeners
    @for Ember
    @param obj
    @param {String} eventName
  */

  function hasListeners(obj, eventName) {
    var meta = _emberMetalMeta.peekMeta(obj);
    if (!meta) {
      return false;
    }
    return meta.matchingListeners(eventName).length > 0;
  }

  /**
    @private
    @method listenersFor
    @for Ember
    @param obj
    @param {String} eventName
  */

  function listenersFor(obj, eventName) {
    var ret = [];
    var meta = _emberMetalMeta.peekMeta(obj);
    var actions = meta && meta.matchingListeners(eventName);

    if (!actions) {
      return ret;
    }

    for (var i = 0, l = actions.length; i < l; i += 3) {
      var target = actions[i];
      var method = actions[i + 1];
      ret.push([target, method]);
    }

    return ret;
  }

  /**
    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
    @public
  */

  function on() {
    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    var func = args.pop();
    var events = args;
    func.__ember_listens__ = events;
    return func;
  }
});
enifed('ember-metal/expand_properties', ['exports', 'ember-metal/debug'], function (exports, _emberMetalDebug) {
  'use strict';

  exports.default = expandProperties;

  /**
  @module ember
  @submodule ember-metal
  */

  var SPLIT_REGEX = /\{|\}/;
  var END_WITH_EACH_REGEX = /\.@each$/;

  /**
    Expands `pattern`, invoking `callback` for each expansion.

    The only pattern supported is brace-expansion, anything else will be passed
    once to `callback` directly.

    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.baz', 'bar.baz'
    Ember.expandProperties('foo.{bar,baz}.[]', echo)      //=> 'foo.bar.[]', 'foo.baz.[]'
    Ember.expandProperties('{foo,bar}.{spam,eggs}', echo) //=> 'foo.spam', 'foo.eggs', 'bar.spam', 'bar.eggs'
    Ember.expandProperties('{foo}.bar.{baz}')             //=> 'foo.bar.baz'
    ```

    @method expandProperties
    @for Ember
    @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.
  */

  function expandProperties(pattern, callback) {
    _emberMetalDebug.assert('A computed property key must be a string', typeof pattern === 'string');
    _emberMetalDebug.assert('Brace expanded properties cannot contain spaces, e.g. "user.{firstName, lastName}" should be "user.{firstName,lastName}"', pattern.indexOf(' ') === -1);

    var parts = pattern.split(SPLIT_REGEX);
    var properties = [parts];

    for (var i = 0; i < parts.length; i++) {
      var part = parts[i];
      if (part.indexOf(',') >= 0) {
        properties = duplicateAndReplace(properties, part.split(','), i);
      }
    }

    for (var i = 0; i < properties.length; i++) {
      callback(properties[i].join('').replace(END_WITH_EACH_REGEX, '.[]'));
    }
  }

  function duplicateAndReplace(properties, currentParts, index) {
    var all = [];

    properties.forEach(function (property) {
      currentParts.forEach(function (part) {
        var current = property.slice(0);
        current[index] = part;
        all.push(current);
      });
    });

    return all;
  }
});
enifed('ember-metal/features', ['exports', 'ember-metal/core', 'ember-metal/assign'], function (exports, _emberMetalCore, _emberMetalAssign) {
  'use strict';

  exports.default = isEnabled;

  /**
    The hash of enabled Canary features. Add to this, any canary features
    before creating your application.

    Alternatively (and recommended), you can also define `EmberENV.FEATURES`
    if you need to enable features flagged at runtime.

    @class FEATURES
    @namespace Ember
    @static
    @since 1.1.0
    @public
  */
  var KNOWN_FEATURES = {};exports.KNOWN_FEATURES = KNOWN_FEATURES;
  // jshint ignore:line
  var FEATURES = _emberMetalAssign.default(KNOWN_FEATURES, _emberMetalCore.default.ENV.FEATURES);

  exports.FEATURES = FEATURES;
  /**
    Determine whether the specified `feature` is enabled. Used by Ember's
    build tools to exclude experimental features from beta/stable builds.

    You can define the following configuration options:

    * `EmberENV.ENABLE_OPTIONAL_FEATURES` - enable any features that have not been explicitly
      enabled/disabled.

    @method isEnabled
    @param {String} feature The feature to check
    @return {Boolean}
    @for Ember.FEATURES
    @since 1.1.0
    @public
  */

  function isEnabled(feature) {
    var featureValue = FEATURES[feature];

    if (featureValue === true || featureValue === false || featureValue === undefined) {
      return featureValue;
    } else if (_emberMetalCore.default.ENV.ENABLE_OPTIONAL_FEATURES) {
      return true;
    } else {
      return false;
    }
  }
});
enifed('ember-metal/get_properties', ['exports', 'ember-metal/property_get'], function (exports, _emberMetalProperty_get) {
  'use strict';

  exports.default = getProperties;

  /**
    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
    @for Ember
    @param {Object} obj
    @param {String...|Array} list of keys to get
    @return {Object}
    @public
  */

  function getProperties(obj) {
    var ret = {};
    var propertyNames = arguments;
    var i = 1;

    if (arguments.length === 2 && Array.isArray(arguments[1])) {
      i = 0;
      propertyNames = arguments[1];
    }
    for (var len = propertyNames.length; i < len; i++) {
      ret[propertyNames[i]] = _emberMetalProperty_get.get(obj, propertyNames[i]);
    }
    return ret;
  }
});
enifed('ember-metal/index', ['exports', 'require', 'ember-metal/core', 'ember-metal/debug', 'ember-metal/features', 'ember-metal/assign', 'ember-metal/merge', 'ember-metal/instrumentation', 'ember-metal/utils', 'ember-metal/meta', 'ember-metal/error', 'ember-metal/cache', '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/alias', 'ember-metal/computed_macros', 'ember-metal/observer', 'ember-metal/mixin', 'ember-metal/binding', 'ember-metal/path_cache', 'ember-metal/run_loop', 'ember-metal/libraries', 'ember-metal/is_none', 'ember-metal/is_empty', 'ember-metal/is_blank', 'ember-metal/is_present', 'backburner'], function (exports, _require, _emberMetalCore, _emberMetalDebug, _emberMetalFeatures, _emberMetalAssign, _emberMetalMerge, _emberMetalInstrumentation, _emberMetalUtils, _emberMetalMeta, _emberMetalError, _emberMetalCache, _emberMetalLogger, _emberMetalProperty_get, _emberMetalEvents, _emberMetalObserver_set, _emberMetalProperty_events, _emberMetalProperties, _emberMetalProperty_set, _emberMetalMap, _emberMetalGet_properties, _emberMetalSet_properties, _emberMetalWatch_key, _emberMetalChains, _emberMetalWatch_path, _emberMetalWatching, _emberMetalExpand_properties, _emberMetalComputed, _emberMetalAlias, _emberMetalComputed_macros, _emberMetalObserver, _emberMetalMixin, _emberMetalBinding, _emberMetalPath_cache, _emberMetalRun_loop, _emberMetalLibraries, _emberMetalIs_none, _emberMetalIs_empty, _emberMetalIs_blank, _emberMetalIs_present, _backburner) {
  /**
  @module ember
  @submodule ember-metal
  */

  // BEGIN IMPORTS
  'use strict';

  _emberMetalComputed.computed.empty = _emberMetalComputed_macros.empty;
  _emberMetalComputed.computed.notEmpty = _emberMetalComputed_macros.notEmpty;
  _emberMetalComputed.computed.none = _emberMetalComputed_macros.none;
  _emberMetalComputed.computed.not = _emberMetalComputed_macros.not;
  _emberMetalComputed.computed.bool = _emberMetalComputed_macros.bool;
  _emberMetalComputed.computed.match = _emberMetalComputed_macros.match;
  _emberMetalComputed.computed.equal = _emberMetalComputed_macros.equal;
  _emberMetalComputed.computed.gt = _emberMetalComputed_macros.gt;
  _emberMetalComputed.computed.gte = _emberMetalComputed_macros.gte;
  _emberMetalComputed.computed.lt = _emberMetalComputed_macros.lt;
  _emberMetalComputed.computed.lte = _emberMetalComputed_macros.lte;
  _emberMetalComputed.computed.alias = _emberMetalAlias.default;
  _emberMetalComputed.computed.oneWay = _emberMetalComputed_macros.oneWay;
  _emberMetalComputed.computed.reads = _emberMetalComputed_macros.oneWay;
  _emberMetalComputed.computed.readOnly = _emberMetalComputed_macros.readOnly;
  _emberMetalComputed.computed.defaultTo = _emberMetalComputed_macros.defaultTo;
  _emberMetalComputed.computed.deprecatingAlias = _emberMetalComputed_macros.deprecatingAlias;
  _emberMetalComputed.computed.and = _emberMetalComputed_macros.and;
  _emberMetalComputed.computed.or = _emberMetalComputed_macros.or;
  _emberMetalComputed.computed.any = _emberMetalComputed_macros.any;

  // END IMPORTS

  // BEGIN EXPORTS
  var EmberInstrumentation = _emberMetalCore.default.Instrumentation = {};
  EmberInstrumentation.instrument = _emberMetalInstrumentation.instrument;
  EmberInstrumentation.subscribe = _emberMetalInstrumentation.subscribe;
  EmberInstrumentation.unsubscribe = _emberMetalInstrumentation.unsubscribe;
  EmberInstrumentation.reset = _emberMetalInstrumentation.reset;

  _emberMetalCore.default.instrument = _emberMetalInstrumentation.instrument;
  _emberMetalCore.default.subscribe = _emberMetalInstrumentation.subscribe;

  _emberMetalCore.default._Cache = _emberMetalCache.default;

  _emberMetalCore.default.generateGuid = _emberMetalUtils.generateGuid;
  _emberMetalCore.default.GUID_KEY = _emberMetalUtils.GUID_KEY;
  _emberMetalCore.default.platform = {
    defineProperty: true,
    hasPropertyAccessors: true
  };

  _emberMetalCore.default.Error = _emberMetalError.default;
  _emberMetalCore.default.guidFor = _emberMetalUtils.guidFor;
  _emberMetalCore.default.META_DESC = _emberMetalMeta.META_DESC;
  _emberMetalCore.default.meta = _emberMetalMeta.meta;
  _emberMetalCore.default.inspect = _emberMetalUtils.inspect;

  _emberMetalCore.default.tryCatchFinally = _emberMetalUtils.deprecatedTryCatchFinally;
  _emberMetalCore.default.makeArray = _emberMetalUtils.makeArray;
  _emberMetalCore.default.canInvoke = _emberMetalUtils.canInvoke;
  _emberMetalCore.default.tryInvoke = _emberMetalUtils.tryInvoke;
  _emberMetalCore.default.wrap = _emberMetalUtils.wrap;
  _emberMetalCore.default.apply = _emberMetalUtils.apply;
  _emberMetalCore.default.applyStr = _emberMetalUtils.applyStr;
  _emberMetalCore.default.uuid = _emberMetalUtils.uuid;

  _emberMetalCore.default.Logger = _emberMetalLogger.default;

  _emberMetalCore.default.get = _emberMetalProperty_get.get;
  _emberMetalCore.default.getWithDefault = _emberMetalProperty_get.getWithDefault;
  _emberMetalCore.default._getPath = _emberMetalProperty_get._getPath;

  _emberMetalCore.default.on = _emberMetalEvents.on;
  _emberMetalCore.default.addListener = _emberMetalEvents.addListener;
  _emberMetalCore.default.removeListener = _emberMetalEvents.removeListener;
  _emberMetalCore.default._suspendListener = _emberMetalEvents.suspendListener;
  _emberMetalCore.default._suspendListeners = _emberMetalEvents.suspendListeners;
  _emberMetalCore.default.sendEvent = _emberMetalEvents.sendEvent;
  _emberMetalCore.default.hasListeners = _emberMetalEvents.hasListeners;
  _emberMetalCore.default.watchedEvents = _emberMetalEvents.watchedEvents;
  _emberMetalCore.default.listenersFor = _emberMetalEvents.listenersFor;
  _emberMetalCore.default.accumulateListeners = _emberMetalEvents.accumulateListeners;

  _emberMetalCore.default._ObserverSet = _emberMetalObserver_set.default;

  _emberMetalCore.default.propertyWillChange = _emberMetalProperty_events.propertyWillChange;
  _emberMetalCore.default.propertyDidChange = _emberMetalProperty_events.propertyDidChange;
  _emberMetalCore.default.overrideChains = _emberMetalProperty_events.overrideChains;
  _emberMetalCore.default.beginPropertyChanges = _emberMetalProperty_events.beginPropertyChanges;
  _emberMetalCore.default.endPropertyChanges = _emberMetalProperty_events.endPropertyChanges;
  _emberMetalCore.default.changeProperties = _emberMetalProperty_events.changeProperties;

  _emberMetalCore.default.defineProperty = _emberMetalProperties.defineProperty;

  _emberMetalCore.default.set = _emberMetalProperty_set.set;
  _emberMetalCore.default.trySet = _emberMetalProperty_set.trySet;

  _emberMetalCore.default.OrderedSet = _emberMetalMap.OrderedSet;
  _emberMetalCore.default.Map = _emberMetalMap.Map;
  _emberMetalCore.default.MapWithDefault = _emberMetalMap.MapWithDefault;

  _emberMetalCore.default.getProperties = _emberMetalGet_properties.default;
  _emberMetalCore.default.setProperties = _emberMetalSet_properties.default;

  _emberMetalCore.default.watchKey = _emberMetalWatch_key.watchKey;
  _emberMetalCore.default.unwatchKey = _emberMetalWatch_key.unwatchKey;

  _emberMetalCore.default.removeChainWatcher = _emberMetalChains.removeChainWatcher;
  _emberMetalCore.default._ChainNode = _emberMetalChains.ChainNode;
  _emberMetalCore.default.finishChains = _emberMetalChains.finishChains;

  _emberMetalCore.default.watchPath = _emberMetalWatch_path.watchPath;
  _emberMetalCore.default.unwatchPath = _emberMetalWatch_path.unwatchPath;

  _emberMetalCore.default.watch = _emberMetalWatching.watch;
  _emberMetalCore.default.isWatching = _emberMetalWatching.isWatching;
  _emberMetalCore.default.unwatch = _emberMetalWatching.unwatch;
  _emberMetalCore.default.rewatch = _emberMetalWatching.rewatch;
  _emberMetalCore.default.destroy = _emberMetalWatching.destroy;

  _emberMetalCore.default.expandProperties = _emberMetalExpand_properties.default;

  _emberMetalCore.default.ComputedProperty = _emberMetalComputed.ComputedProperty;
  _emberMetalCore.default.computed = _emberMetalComputed.computed;
  _emberMetalCore.default.cacheFor = _emberMetalComputed.cacheFor;

  _emberMetalCore.default.addObserver = _emberMetalObserver.addObserver;
  _emberMetalCore.default.observersFor = _emberMetalObserver.observersFor;
  _emberMetalCore.default.removeObserver = _emberMetalObserver.removeObserver;
  _emberMetalCore.default._suspendObserver = _emberMetalObserver._suspendObserver;
  _emberMetalCore.default._suspendObservers = _emberMetalObserver._suspendObservers;

  _emberMetalCore.default.IS_BINDING = _emberMetalMixin.IS_BINDING;
  _emberMetalCore.default.required = _emberMetalMixin.required;
  _emberMetalCore.default.aliasMethod = _emberMetalMixin.aliasMethod;
  _emberMetalCore.default.observer = _emberMetalMixin.observer;
  _emberMetalCore.default.immediateObserver = _emberMetalMixin._immediateObserver;
  _emberMetalCore.default.mixin = _emberMetalMixin.mixin;
  _emberMetalCore.default.Mixin = _emberMetalMixin.Mixin;

  _emberMetalCore.default.bind = _emberMetalBinding.bind;
  _emberMetalCore.default.Binding = _emberMetalBinding.Binding;
  _emberMetalCore.default.isGlobalPath = _emberMetalPath_cache.isGlobalPath;

  _emberMetalCore.default.run = _emberMetalRun_loop.default;

  /**
  @class Backburner
  @for Ember
  @private
  */
  _emberMetalCore.default.Backburner = _backburner.default;
  // this is the new go forward, once Ember Data updates to using `_Backburner` we
  // can remove the non-underscored version.
  _emberMetalCore.default._Backburner = _backburner.default;

  _emberMetalCore.default.libraries = new _emberMetalLibraries.default();
  _emberMetalCore.default.libraries.registerCoreLibrary('Ember', _emberMetalCore.default.VERSION);

  _emberMetalCore.default.isNone = _emberMetalIs_none.default;
  _emberMetalCore.default.isEmpty = _emberMetalIs_empty.default;
  _emberMetalCore.default.isBlank = _emberMetalIs_blank.default;
  _emberMetalCore.default.isPresent = _emberMetalIs_present.default;

  _emberMetalCore.default.assign = Object.assign || _emberMetalAssign.default;
  _emberMetalCore.default.merge = _emberMetalMerge.default;

  _emberMetalCore.default.FEATURES = _emberMetalFeatures.FEATURES;
  _emberMetalCore.default.FEATURES.isEnabled = _emberMetalFeatures.default;

  /**
    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
    @public
  */
  _emberMetalCore.default.onerror = null;
  // END EXPORTS

  // do this for side-effects of updating Ember.assert, warn, etc when
  // ember-debug is present
  // This needs to be called before any deprecateFunc
  if (_require.has('ember-debug')) {
    _require.default('ember-debug');
  } else {
    _emberMetalCore.default.Debug = {};
    _emberMetalCore.default.Debug.registerDeprecationHandler = function () {};
    _emberMetalCore.default.Debug.registerWarnHandler = function () {};
  }

  _emberMetalCore.default.create = _emberMetalDebug.deprecateFunc('Ember.create is deprecated in favor of Object.create', { id: 'ember-metal.ember-create', until: '3.0.0' }, Object.create);
  _emberMetalCore.default.keys = _emberMetalDebug.deprecateFunc('Ember.keys is deprecated in favor of Object.keys', { id: 'ember-metal.ember.keys', until: '3.0.0' }, Object.keys);

  exports.default = _emberMetalCore.default;
});
enifed('ember-metal/injected_property', ['exports', 'ember-metal/debug', 'ember-metal/computed', 'ember-metal/alias', 'ember-metal/properties', 'container/owner'], function (exports, _emberMetalDebug, _emberMetalComputed, _emberMetalAlias, _emberMetalProperties, _containerOwner) {
  'use strict';

  /**
    Read-only property that returns the result of a container lookup.

    @class InjectedProperty
    @namespace Ember
    @constructor
    @param {String} type The container type the property will lookup
    @param {String} name (optional) The name the property will lookup, defaults
           to the property's name
    @private
  */
  function InjectedProperty(type, name) {
    this.type = type;
    this.name = name;

    this._super$Constructor(injectedPropertyGet);
    AliasedPropertyPrototype.oneWay.call(this);
  }

  function injectedPropertyGet(keyName) {
    var desc = this[keyName];
    var owner = _containerOwner.getOwner(this) || this.container; // fallback to `container` for backwards compat

    _emberMetalDebug.assert('InjectedProperties should be defined with the Ember.inject computed property macros.', desc && desc.isDescriptor && desc.type);
    _emberMetalDebug.assert('Attempting to lookup an injected property on an object without a container, ensure that the object was instantiated via a container.', owner);

    return owner.lookup(desc.type + ':' + (desc.name || keyName));
  }

  InjectedProperty.prototype = Object.create(_emberMetalProperties.Descriptor.prototype);

  var InjectedPropertyPrototype = InjectedProperty.prototype;
  var ComputedPropertyPrototype = _emberMetalComputed.ComputedProperty.prototype;
  var AliasedPropertyPrototype = _emberMetalAlias.AliasedProperty.prototype;

  InjectedPropertyPrototype._super$Constructor = _emberMetalComputed.ComputedProperty;

  InjectedPropertyPrototype.get = ComputedPropertyPrototype.get;
  InjectedPropertyPrototype.readOnly = ComputedPropertyPrototype.readOnly;

  InjectedPropertyPrototype.teardown = ComputedPropertyPrototype.teardown;

  exports.default = InjectedProperty;
});
enifed('ember-metal/instrumentation', ['exports', 'ember-metal/core', 'ember-metal/features'], function (exports, _emberMetalCore, _emberMetalFeatures) {
  'use strict';

  exports.instrument = instrument;
  exports._instrumentStart = _instrumentStart;
  exports.subscribe = subscribe;
  exports.unsubscribe = unsubscribe;
  exports.reset = reset;

  /**
    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
    @private
  */
  var subscribers = [];
  exports.subscribers = subscribers;
  var cache = {};

  var populateListeners = function (name) {
    var listeners = [];
    var 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.
    @private
  */

  function instrument(name, _payload, callback, binding) {
    if (arguments.length <= 3 && typeof _payload === 'function') {
      binding = callback;
      callback = _payload;
      _payload = undefined;
    }
    if (subscribers.length === 0) {
      return callback.call(binding);
    }
    var payload = _payload || {};
    var finalizer = _instrumentStart(name, function () {
      return payload;
    });

    if (finalizer) {
      return withFinalizer(callback, finalizer, payload, binding);
    } else {
      return callback.call(binding);
    }
  }

  var flaggedInstrument;

  exports.flaggedInstrument = flaggedInstrument = function (name, payload, callback) {
    return callback();
  };
  exports.flaggedInstrument = flaggedInstrument;

  function withFinalizer(callback, finalizer, payload, binding) {
    var result = undefined;
    try {
      result = callback.call(binding);
    } catch (e) {
      payload.exception = e;
      result = payload;
    } finally {
      finalizer();
      return result;
    }
  }

  // private for now

  function _instrumentStart(name, _payload) {
    var listeners = cache[name];

    if (!listeners) {
      listeners = populateListeners(name);
    }

    if (listeners.length === 0) {
      return;
    }

    var payload = _payload();

    var STRUCTURED_PROFILE = _emberMetalCore.default.STRUCTURED_PROFILE;
    var timeName;
    if (STRUCTURED_PROFILE) {
      timeName = name + ': ' + payload.object;
      console.time(timeName);
    }

    var l = listeners.length;
    var beforeValues = new Array(l);
    var i, listener;
    var timestamp = time();
    for (i = 0; i < l; i++) {
      listener = listeners[i];
      beforeValues[i] = listener.before(name, timestamp, payload);
    }

    return function _instrumentEnd() {
      var i, l, listener;
      var timestamp = time();
      for (i = 0, l = listeners.length; i < l; i++) {
        listener = listeners[i];
        if (typeof listener.after === 'function') {
          listener.after(name, timestamp, payload, beforeValues[i]);
        }
      }

      if (STRUCTURED_PROFILE) {
        console.timeEnd(timeName);
      }
    };
  }

  /**
    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}
    @private
  */

  function subscribe(pattern, object) {
    var paths = pattern.split('.');
    var path;
    var 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;
  }

  /**
    Unsubscribes from a particular event or instrumented block of code.

    @method unsubscribe
    @namespace Ember.Instrumentation

    @param {Object} [subscriber]
    @private
  */

  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 = {};
  }

  /**
    Resets `Ember.Instrumentation` by flushing list of subscribers.

    @method reset
    @namespace Ember.Instrumentation
    @private
  */

  function reset() {
    subscribers.length = 0;
    cache = {};
  }
});
enifed('ember-metal/is_blank', ['exports', 'ember-metal/is_empty'], function (exports, _emberMetalIs_empty) {
  'use strict';

  exports.default = isBlank;

  /**
    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
    @public
  */

  function isBlank(obj) {
    return _emberMetalIs_empty.default(obj) || typeof obj === 'string' && obj.match(/\S/) === null;
  }
});
enifed('ember-metal/is_empty', ['exports', 'ember-metal/property_get', 'ember-metal/is_none'], function (exports, _emberMetalProperty_get, _emberMetalIs_none) {
  'use strict';

  /**
    Verifies that a value is `null` or an empty string, empty array,
    or empty function.

    Constrains the rules on `Ember.isNone` by returning true 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({});              // false
    Ember.isEmpty('Adam Hawkins');  // false
    Ember.isEmpty([0,1,2]);         // false
    Ember.isEmpty('\n\t');          // false
    Ember.isEmpty('  ');            // false
    ```

    @method isEmpty
    @for Ember
    @param {Object} obj Value to test
    @return {Boolean}
    @public
  */
  function isEmpty(obj) {
    var none = _emberMetalIs_none.default(obj);
    if (none) {
      return none;
    }

    if (typeof obj.size === 'number') {
      return !obj.size;
    }

    var objectType = typeof obj;

    if (objectType === 'object') {
      var size = _emberMetalProperty_get.get(obj, 'size');
      if (typeof size === 'number') {
        return !size;
      }
    }

    if (typeof obj.length === 'number' && objectType !== 'function') {
      return !obj.length;
    }

    if (objectType === 'object') {
      var length = _emberMetalProperty_get.get(obj, 'length');
      if (typeof length === 'number') {
        return !length;
      }
    }

    return false;
  }

  exports.default = isEmpty;
});
enifed("ember-metal/is_none", ["exports"], function (exports) {
  /**
    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}
    @public
  */
  "use strict";

  exports.default = isNone;

  function isNone(obj) {
    return obj === null || obj === undefined;
  }
});
enifed('ember-metal/is_present', ['exports', 'ember-metal/is_blank'], function (exports, _emberMetalIs_blank) {
  'use strict';

  exports.default = isPresent;

  /**
    A value is present if it not `isBlank`.

    ```javascript
    Ember.isPresent();                // false
    Ember.isPresent(null);            // false
    Ember.isPresent(undefined);       // false
    Ember.isPresent('');              // false
    Ember.isPresent('  ');            // false
    Ember.isPresent('\n\t');          // false
    Ember.isPresent([]);              // false
    Ember.isPresent({ length: 0 })    // false
    Ember.isPresent(false);           // true
    Ember.isPresent(true);            // true
    Ember.isPresent('string');        // true
    Ember.isPresent(0);               // true
    Ember.isPresent(function() {})    // true
    Ember.isPresent({});              // true
    Ember.isPresent(false);           // true
    Ember.isPresent('\n\t Hello');    // true
    Ember.isPresent([1,2,3]);         // true
    ```

    @method isPresent
    @for Ember
    @param {Object} obj Value to test
    @return {Boolean}
    @since 1.8.0
    @public
  */

  function isPresent(obj) {
    return !_emberMetalIs_blank.default(obj);
  }
});
enifed('ember-metal/libraries', ['exports', 'ember-metal/debug', 'ember-metal/features'], function (exports, _emberMetalDebug, _emberMetalFeatures) {
  'use strict';

  /**
    Helper class that allows you to register your library with Ember.

    Singleton created at `Ember.libraries`.

    @class Libraries
    @constructor
    @private
  */
  function Libraries() {
    this._registry = [];
    this._coreLibIndex = 0;
  }

  Libraries.prototype = {
    constructor: Libraries,

    _getLibraryByName: function (name) {
      var libs = this._registry;
      var count = libs.length;

      for (var i = 0; i < count; i++) {
        if (libs[i].name === name) {
          return libs[i];
        }
      }
    },

    register: function (name, version, isCoreLibrary) {
      var index = this._registry.length;

      if (!this._getLibraryByName(name)) {
        if (isCoreLibrary) {
          index = this._coreLibIndex++;
        }
        this._registry.splice(index, 0, { name: name, version: version });
      } else {
        _emberMetalDebug.warn('Library "' + name + '" is already registered with Ember.', false, { id: 'ember-metal.libraries-register' });
      }
    },

    registerCoreLibrary: function (name, version) {
      this.register(name, version, true);
    },

    deRegister: function (name) {
      var lib = this._getLibraryByName(name);
      var index;

      if (lib) {
        index = this._registry.indexOf(lib);
        this._registry.splice(index, 1);
      }
    }
  };

  exports.default = Libraries;
});
enifed('ember-metal/logger', ['exports', 'ember-metal/core', 'ember-metal/error'], function (exports, _emberMetalCore, _emberMetalError) {
  'use strict';

  function K() {
    return this;
  }

  function consoleMethod(name) {
    var consoleObj, logToConsole;
    if (_emberMetalCore.default.imports.console) {
      consoleObj = _emberMetalCore.default.imports.console;
    } else if (typeof console !== 'undefined') {
      consoleObj = console;
    }

    var method = typeof consoleObj === 'object' ? consoleObj[name] : null;

    if (method) {
      // Older IE doesn't support bind, but Chrome needs it
      if (typeof method.bind === 'function') {
        logToConsole = method.bind(consoleObj);
        logToConsole.displayName = 'console.' + name;
        return logToConsole;
      } else 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 _emberMetalError.default('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
    @public
  */
  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
     @public
    */
    log: consoleMethod('log') || 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
     @public
    */
    warn: consoleMethod('warn') || 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
     @public
    */
    error: consoleMethod('error') || 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
     @public
    */
    info: consoleMethod('info') || 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
     @public
    */
    debug: consoleMethod('debug') || consoleMethod('info') || 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.
      Ember.Logger.assert(true === false, 'Something invalid'); // Throws an Assertion failed error with message.
      ```
      @method assert
     @for Ember.Logger
     @param {Boolean} bool Value to test
     @param {String} message Assertion message on failed
     @public
    */
    assert: consoleMethod('assert') || assertPolyfill
  };
});
// Ember.imports
enifed('ember-metal/map', ['exports', 'ember-metal/core', 'ember-metal/utils', 'ember-metal/empty_object'], function (exports, _emberMetalCore, _emberMetalUtils, _emberMetalEmpty_object) {
  /**
  @module ember
  @submodule 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 one exception:  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.
  */

  'use strict';

  function missingFunction(fn) {
    throw new TypeError(Object.prototype.toString.call(fn) + ' is not a function');
  }

  function missingNew(name) {
    throw new TypeError('Constructor ' + name + ' requires \'new\'');
  }

  function copyNull(obj) {
    var output = new _emberMetalEmpty_object.default();

    for (var prop in obj) {
      // hasOwnPropery is not needed because obj is new EmptyObject();
      output[prop] = obj[prop];
    }

    return output;
  }

  function copyMap(original, newObject) {
    var keys = original._keys.copy();
    var values = copyNull(original._values);

    newObject._keys = keys;
    newObject._values = values;
    newObject.size = original.size;

    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() {
    if (this instanceof OrderedSet) {
      this.clear();
      this._silenceRemoveDeprecation = false;
    } else {
      missingNew('OrderedSet');
    }
  }

  /**
    @method create
    @static
    @return {Ember.OrderedSet}
    @private
  */
  OrderedSet.create = function () {
    var Constructor = this;

    return new Constructor();
  };

  OrderedSet.prototype = {
    constructor: OrderedSet,
    /**
      @method clear
      @private
    */
    clear: function () {
      this.presenceSet = new _emberMetalEmpty_object.default();
      this.list = [];
      this.size = 0;
    },

    /**
      @method add
      @param obj
      @param guid (optional, and for internal use)
      @return {Ember.OrderedSet}
      @private
    */
    add: function (obj, _guid) {
      var guid = _guid || _emberMetalUtils.guidFor(obj);
      var presenceSet = this.presenceSet;
      var list = this.list;

      if (presenceSet[guid] !== true) {
        presenceSet[guid] = true;
        this.size = list.push(obj);
      }

      return this;
    },

    /**
      @since 1.8.0
      @method delete
      @param obj
      @param _guid (optional and for internal use only)
      @return {Boolean}
      @private
    */
    delete: function (obj, _guid) {
      var guid = _guid || _emberMetalUtils.guidFor(obj);
      var presenceSet = this.presenceSet;
      var list = this.list;

      if (presenceSet[guid] === true) {
        delete presenceSet[guid];
        var index = list.indexOf(obj);
        if (index > -1) {
          list.splice(index, 1);
        }
        this.size = list.length;
        return true;
      } else {
        return false;
      }
    },

    /**
      @method isEmpty
      @return {Boolean}
      @private
    */
    isEmpty: function () {
      return this.size === 0;
    },

    /**
      @method has
      @param obj
      @return {Boolean}
      @private
    */
    has: function (obj) {
      if (this.size === 0) {
        return false;
      }

      var guid = _emberMetalUtils.guidFor(obj);
      var presenceSet = this.presenceSet;

      return presenceSet[guid] === true;
    },

    /**
      @method forEach
      @param {Function} fn
      @param self
      @private
    */
    forEach: function (fn /*, ...thisArg*/) {
      if (typeof fn !== 'function') {
        missingFunction(fn);
      }

      if (this.size === 0) {
        return;
      }

      var list = this.list;
      var length = arguments.length;
      var i;

      if (length === 2) {
        for (i = 0; i < list.length; i++) {
          fn.call(arguments[1], list[i]);
        }
      } else {
        for (i = 0; i < list.length; i++) {
          fn(list[i]);
        }
      }
    },

    /**
      @method toArray
      @return {Array}
      @private
    */
    toArray: function () {
      return this.list.slice();
    },

    /**
      @method copy
      @return {Ember.OrderedSet}
      @private
    */
    copy: function () {
      var Constructor = this.constructor;
      var set = new Constructor();

      set._silenceRemoveDeprecation = this._silenceRemoveDeprecation;
      set.presenceSet = copyNull(this.presenceSet);
      set.list = this.toArray();
      set.size = this.size;

      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() {
    if (this instanceof this.constructor) {
      this._keys = OrderedSet.create();
      this._keys._silenceRemoveDeprecation = true;
      this._values = new _emberMetalEmpty_object.default();
      this.size = 0;
    } else {
      missingNew('OrderedSet');
    }
  }

  _emberMetalCore.default.Map = Map;

  /**
    @method create
    @static
    @private
  */
  Map.create = function () {
    var Constructor = this;
    return new Constructor();
  };

  Map.prototype = {
    constructor: Map,

    /**
      This property will change as the number of objects in the map changes.
       @since 1.8.0
      @property size
      @type number
      @default 0
      @private
    */
    size: 0,

    /**
      Retrieve the value associated with a given key.
       @method get
      @param {*} key
      @return {*} the value associated with the key, or `undefined`
      @private
    */
    get: function (key) {
      if (this.size === 0) {
        return;
      }

      var values = this._values;
      var guid = _emberMetalUtils.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
      @return {Ember.Map}
      @private
    */
    set: function (key, value) {
      var keys = this._keys;
      var values = this._values;
      var guid = _emberMetalUtils.guidFor(key);

      // ensure we don't store -0
      var k = key === -0 ? 0 : key;

      keys.add(k, guid);

      values[guid] = value;

      this.size = keys.size;

      return this;
    },

    /**
      Removes a value from the map for an associated key.
       @since 1.8.0
      @method delete
      @param {*} key
      @return {Boolean} true if an item was removed, false otherwise
      @private
    */
    delete: function (key) {
      if (this.size === 0) {
        return false;
      }
      // don't use ES6 "delete" because it will be annoying
      // to use in browsers that are not ES6 friendly;
      var keys = this._keys;
      var values = this._values;
      var guid = _emberMetalUtils.guidFor(key);

      if (keys.delete(key, guid)) {
        delete values[guid];
        this.size = keys.size;
        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
      @private
    */
    has: function (key) {
      return this._keys.has(key);
    },

    /**
      Iterate over all the keys and values. Calls the function once
      for each key, passing in value, key, and the map being iterated over,
      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.
      @private
    */
    forEach: function (callback /*, ...thisArg*/) {
      if (typeof callback !== 'function') {
        missingFunction(callback);
      }

      if (this.size === 0) {
        return;
      }

      var length = arguments.length;
      var map = this;
      var cb, thisArg;

      if (length === 2) {
        thisArg = arguments[1];
        cb = function (key) {
          callback.call(thisArg, map.get(key), key, map);
        };
      } else {
        cb = function (key) {
          callback(map.get(key), key, map);
        };
      }

      this._keys.forEach(cb);
    },

    /**
      @method clear
      @private
    */
    clear: function () {
      this._keys.clear();
      this._values = new _emberMetalEmpty_object.default();
      this.size = 0;
    },

    /**
      @method copy
      @return {Ember.Map}
      @private
    */
    copy: function () {
      return copyMap(this, new Map());
    }
  };

  /**
    @class MapWithDefault
    @namespace Ember
    @extends Ember.Map
    @private
    @constructor
    @param [options]
      @param {*} [options.defaultValue]
  */
  function MapWithDefault(options) {
    this._super$constructor();
    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`
    @private
  */
  MapWithDefault.create = function (options) {
    if (options) {
      return new MapWithDefault(options);
    } else {
      return new Map();
    }
  };

  MapWithDefault.prototype = Object.create(Map.prototype);
  MapWithDefault.prototype.constructor = MapWithDefault;
  MapWithDefault.prototype._super$constructor = Map;
  MapWithDefault.prototype._super$get = Map.prototype.get;

  /**
    Retrieve the value associated with a given key.

    @method get
    @param {*} key
    @return {*} the value associated with the key, or the default value
    @private
  */
  MapWithDefault.prototype.get = function (key) {
    var hasValue = this.has(key);

    if (hasValue) {
      return this._super$get(key);
    } else {
      var defaultValue = this.defaultValue(key);
      this.set(key, defaultValue);
      return defaultValue;
    }
  };

  /**
    @method copy
    @return {Ember.MapWithDefault}
    @private
  */
  MapWithDefault.prototype.copy = function () {
    var Constructor = this.constructor;
    return copyMap(this, new Constructor({
      defaultValue: this.defaultValue
    }));
  };

  exports.default = Map;
  exports.OrderedSet = OrderedSet;
  exports.Map = Map;
  exports.MapWithDefault = MapWithDefault;
});
enifed('ember-metal/merge', ['exports'], function (exports) {
  /**
    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'};
    var 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}
    @public
  */
  'use strict';

  exports.default = merge;

  function merge(original, updates) {
    if (!updates || typeof updates !== 'object') {
      return original;
    }

    var props = Object.keys(updates);
    var prop;
    var length = props.length;

    for (var i = 0; i < length; i++) {
      prop = props[i];
      original[prop] = updates[prop];
    }

    return original;
  }
});
enifed('ember-metal/meta', ['exports', 'ember-metal/meta_listeners', 'ember-metal/empty_object'], function (exports, _emberMetalMeta_listeners, _emberMetalEmpty_object) {
  'no use strict';
  // Remove "use strict"; from transpiled module until
  // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed

  exports.meta = meta;
  exports.peekMeta = peekMeta;
  exports.deleteMeta = deleteMeta;

  /**
  @module ember-metal
  */

  /*
   This declares several meta-programmed members on the Meta class. Such
   meta!

   In general, the `readable` variants will give you an object (if it
   already exists) that you can read but should not modify. The
   `writable` variants will give you a mutable object, and they will
   create it if it didn't already exist.

   The following methods will get generated metaprogrammatically, and
   I'm including them here for greppability:

   writableCache, readableCache, writeWatching,
   peekWatching, clearWatching, writeMixins,
   peekMixins, clearMixins, writeBindings,
   peekBindings, clearBindings, writeValues,
   peekValues, clearValues, writeDeps, forEachInDeps
   writableChainWatchers, readableChainWatchers, writableChains,
   readableChains, writableTag, readableTag

  */
  var members = {
    cache: ownMap,
    weak: ownMap,
    watching: inheritedMap,
    mixins: inheritedMap,
    bindings: inheritedMap,
    values: inheritedMap,
    deps: inheritedMapOfMaps,
    chainWatchers: ownCustomObject,
    chains: inheritedCustomObject,
    tag: ownCustomObject
  };

  var memberNames = Object.keys(members);
  var META_FIELD = '__ember_meta__';

  function Meta(obj, parentMeta) {
    this._cache = undefined;
    this._weak = undefined;
    this._watching = undefined;
    this._mixins = undefined;
    this._bindings = undefined;
    this._values = undefined;
    this._deps = undefined;
    this._chainWatchers = undefined;
    this._chains = undefined;
    this._tag = undefined;

    // used only internally
    this.source = obj;

    // when meta(obj).proto === obj, the object is intended to be only a
    // prototype and doesn't need to actually be observable itself
    this.proto = undefined;

    // The next meta in our inheritance chain. We (will) track this
    // explicitly instead of using prototypical inheritance because we
    // have detailed knowledge of how each property should really be
    // inherited, and we can optimize it much better than JS runtimes.
    this.parent = parentMeta;

    this._initializeListeners();
  }

  for (var _name in _emberMetalMeta_listeners.protoMethods) {
    Meta.prototype[_name] = _emberMetalMeta_listeners.protoMethods[_name];
  }
  memberNames.forEach(function (name) {
    return members[name](name, Meta);
  });

  // Implements a member that is a lazily created, non-inheritable
  // POJO.
  function ownMap(name, Meta) {
    var key = memberProperty(name);
    var capitalized = capitalize(name);
    Meta.prototype['writable' + capitalized] = function () {
      return this._getOrCreateOwnMap(key);
    };
    Meta.prototype['readable' + capitalized] = function () {
      return this[key];
    };
  }

  Meta.prototype._getOrCreateOwnMap = function (key) {
    var ret = this[key];
    if (!ret) {
      ret = this[key] = new _emberMetalEmpty_object.default();
    }
    return ret;
  };

  // Implements a member that is a lazily created POJO with inheritable
  // values.
  function inheritedMap(name, Meta) {
    var key = memberProperty(name);
    var capitalized = capitalize(name);

    Meta.prototype['write' + capitalized] = function (subkey, value) {
      var map = this._getOrCreateOwnMap(key);
      map[subkey] = value;
    };

    Meta.prototype['peek' + capitalized] = function (subkey) {
      return this._findInherited(key, subkey);
    };

    Meta.prototype['forEach' + capitalized] = function (fn) {
      var pointer = this;
      var seen = new _emberMetalEmpty_object.default();
      while (pointer !== undefined) {
        var map = pointer[key];
        if (map) {
          for (var _key in map) {
            if (!seen[_key]) {
              seen[_key] = true;
              fn(_key, map[_key]);
            }
          }
        }
        pointer = pointer.parent;
      }
    };

    Meta.prototype['clear' + capitalized] = function () {
      this[key] = undefined;
    };

    Meta.prototype['deleteFrom' + capitalized] = function (subkey) {
      delete this._getOrCreateOwnMap(key)[subkey];
    };

    Meta.prototype['hasIn' + capitalized] = function (subkey) {
      return this._findInherited(key, subkey) !== undefined;
    };
  }

  Meta.prototype._getInherited = function (key) {
    var pointer = this;
    while (pointer !== undefined) {
      if (pointer[key]) {
        return pointer[key];
      }
      pointer = pointer.parent;
    }
  };

  Meta.prototype._findInherited = function (key, subkey) {
    var pointer = this;
    while (pointer !== undefined) {
      var map = pointer[key];
      if (map) {
        var value = map[subkey];
        if (value !== undefined) {
          return value;
        }
      }
      pointer = pointer.parent;
    }
  };

  // Implements a member that provides a lazily created map of maps,
  // with inheritance at both levels.
  function inheritedMapOfMaps(name, Meta) {
    var key = memberProperty(name);
    var capitalized = capitalize(name);

    Meta.prototype['write' + capitalized] = function (subkey, itemkey, value) {
      var outerMap = this._getOrCreateOwnMap(key);
      var innerMap = outerMap[subkey];
      if (!innerMap) {
        innerMap = outerMap[subkey] = new _emberMetalEmpty_object.default();
      }
      innerMap[itemkey] = value;
    };

    Meta.prototype['peek' + capitalized] = function (subkey, itemkey) {
      var pointer = this;
      while (pointer !== undefined) {
        var map = pointer[key];
        if (map) {
          var value = map[subkey];
          if (value) {
            if (value[itemkey] !== undefined) {
              return value[itemkey];
            }
          }
        }
        pointer = pointer.parent;
      }
    };

    Meta.prototype['has' + capitalized] = function (subkey) {
      var pointer = this;
      while (pointer !== undefined) {
        if (pointer[key] && pointer[key][subkey]) {
          return true;
        }
        pointer = pointer.parent;
      }
      return false;
    };

    Meta.prototype['forEachIn' + capitalized] = function (subkey, fn) {
      return this._forEachIn(key, subkey, fn);
    };
  }

  Meta.prototype._forEachIn = function (key, subkey, fn) {
    var pointer = this;
    var seen = new _emberMetalEmpty_object.default();
    var calls = [];
    while (pointer !== undefined) {
      var map = pointer[key];
      if (map) {
        var innerMap = map[subkey];
        if (innerMap) {
          for (var innerKey in innerMap) {
            if (!seen[innerKey]) {
              seen[innerKey] = true;
              calls.push([innerKey, innerMap[innerKey]]);
            }
          }
        }
      }
      pointer = pointer.parent;
    }
    for (var i = 0; i < calls.length; i++) {
      var _calls$i = calls[i];
      var innerKey = _calls$i[0];
      var value = _calls$i[1];

      fn(innerKey, value);
    }
  };

  // Implements a member that provides a non-heritable, lazily-created
  // object using the method you provide.
  function ownCustomObject(name, Meta) {
    var key = memberProperty(name);
    var capitalized = capitalize(name);
    Meta.prototype['writable' + capitalized] = function (create) {
      var ret = this[key];
      if (!ret) {
        ret = this[key] = create(this.source);
      }
      return ret;
    };
    Meta.prototype['readable' + capitalized] = function () {
      return this[key];
    };
  }

  // Implements a member that provides an inheritable, lazily-created
  // object using the method you provide. We will derived children from
  // their parents by calling your object's `copy()` method.
  function inheritedCustomObject(name, Meta) {
    var key = memberProperty(name);
    var capitalized = capitalize(name);
    Meta.prototype['writable' + capitalized] = function (create) {
      var ret = this[key];
      if (!ret) {
        if (this.parent) {
          ret = this[key] = this.parent['writable' + capitalized](create).copy(this.source);
        } else {
          ret = this[key] = create(this.source);
        }
      }
      return ret;
    };
    Meta.prototype['readable' + capitalized] = function () {
      return this._getInherited(key);
    };
  }

  function memberProperty(name) {
    return '_' + name;
  }

  // there's a more general-purpose capitalize in ember-runtime, but we
  // don't want to make ember-metal depend on ember-runtime.
  function capitalize(name) {
    return name.replace(/^\w/, function (m) {
      return m.toUpperCase();
    });
  }

  var META_DESC = {
    writable: true,
    configurable: true,
    enumerable: false,
    value: null
  };

  exports.META_DESC = META_DESC;
  var EMBER_META_PROPERTY = {
    name: META_FIELD,
    descriptor: META_DESC
  };

  // choose the one appropriate for given platform
  var setMeta = function (obj, meta) {
    // if `null` already, just set it to the new value
    // otherwise define property first
    if (obj[META_FIELD] !== null) {
      if (obj.__defineNonEnumerable) {
        obj.__defineNonEnumerable(EMBER_META_PROPERTY);
      } else {
        Object.defineProperty(obj, META_FIELD, META_DESC);
      }
    }

    obj[META_FIELD] = meta;
  };

  /**
    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) {
    var maybeMeta = peekMeta(obj);
    var parent = undefined;

    // remove this code, in-favor of explicit parent
    if (maybeMeta) {
      if (maybeMeta.source === obj) {
        return maybeMeta;
      }
      parent = maybeMeta;
    }

    var newMeta = new Meta(obj, parent);
    setMeta(obj, newMeta);
    return newMeta;
  }

  function peekMeta(obj) {
    return obj[META_FIELD];
  }

  function deleteMeta(obj) {
    if (typeof obj[META_FIELD] !== 'object') {
      return;
    }
    obj[META_FIELD] = null;
  }
});
enifed('ember-metal/meta_listeners', ['exports'], function (exports) {
  /*
   When we render a rich template hierarchy, the set of events that
   *might* happen tends to be much larger than the set of events that
   actually happen. This implies that we should make listener creation &
   destruction cheap, even at the cost of making event dispatch more
   expensive.

   Thus we store a new listener with a single push and no new
   allocations, without even bothering to do deduplication -- we can
   save that for dispatch time, if an event actually happens.
   */

  /* listener flags */
  'use strict';

  var ONCE = 1;
  exports.ONCE = ONCE;
  var SUSPENDED = 2;

  exports.SUSPENDED = SUSPENDED;
  var protoMethods = {

    addToListeners: function (eventName, target, method, flags) {
      if (!this._listeners) {
        this._listeners = [];
      }
      this._listeners.push(eventName, target, method, flags);
    },

    _finalizeListeners: function () {
      if (this._listenersFinalized) {
        return;
      }
      if (!this._listeners) {
        this._listeners = [];
      }
      var pointer = this.parent;
      while (pointer) {
        var listeners = pointer._listeners;
        if (listeners) {
          this._listeners = this._listeners.concat(listeners);
        }
        if (pointer._listenersFinalized) {
          break;
        }
        pointer = pointer.parent;
      }
      this._listenersFinalized = true;
    },

    removeFromListeners: function (eventName, target, method, didRemove) {
      var pointer = this;
      while (pointer) {
        var listeners = pointer._listeners;
        if (listeners) {
          for (var index = listeners.length - 4; index >= 0; index -= 4) {
            if (listeners[index] === eventName && (!method || listeners[index + 1] === target && listeners[index + 2] === method)) {
              if (pointer === this) {
                // we are modifying our own list, so we edit directly
                if (typeof didRemove === 'function') {
                  didRemove(eventName, target, listeners[index + 2]);
                }
                listeners.splice(index, 4);
              } else {
                // we are trying to remove an inherited listener, so we do
                // just-in-time copying to detach our own listeners from
                // our inheritance chain.
                this._finalizeListeners();
                return this.removeFromListeners(eventName, target, method);
              }
            }
          }
        }
        if (pointer._listenersFinalized) {
          break;
        }
        pointer = pointer.parent;
      }
    },

    matchingListeners: function (eventName) {
      var pointer = this;
      var result = [];
      while (pointer) {
        var listeners = pointer._listeners;
        if (listeners) {
          for (var index = 0; index < listeners.length - 3; index += 4) {
            if (listeners[index] === eventName) {
              pushUniqueListener(result, listeners, index);
            }
          }
        }
        if (pointer._listenersFinalized) {
          break;
        }
        pointer = pointer.parent;
      }
      var sus = this._suspendedListeners;
      if (sus) {
        for (var susIndex = 0; susIndex < sus.length - 2; susIndex += 3) {
          if (eventName === sus[susIndex]) {
            for (var resultIndex = 0; resultIndex < result.length - 2; resultIndex += 3) {
              if (result[resultIndex] === sus[susIndex + 1] && result[resultIndex + 1] === sus[susIndex + 2]) {
                result[resultIndex + 2] |= SUSPENDED;
              }
            }
          }
        }
      }
      return result;
    },

    suspendListeners: function (eventNames, target, method, callback) {
      var sus = this._suspendedListeners;
      if (!sus) {
        sus = this._suspendedListeners = [];
      }
      for (var i = 0; i < eventNames.length; i++) {
        sus.push(eventNames[i], target, method);
      }
      try {
        return callback.call(target);
      } finally {
        if (sus.length === eventNames.length) {
          this._suspendedListeners = undefined;
        } else {
          for (var i = sus.length - 3; i >= 0; i -= 3) {
            if (sus[i + 1] === target && sus[i + 2] === method && eventNames.indexOf(sus[i]) !== -1) {
              sus.splice(i, 3);
            }
          }
        }
      }
    },

    watchedEvents: function () {
      var pointer = this;
      var names = {};
      while (pointer) {
        var listeners = pointer._listeners;
        if (listeners) {
          for (var index = 0; index < listeners.length - 3; index += 4) {
            names[listeners[index]] = true;
          }
        }
        if (pointer._listenersFinalized) {
          break;
        }
        pointer = pointer.parent;
      }
      return Object.keys(names);
    },

    _initializeListeners: function () {
      this._listeners = undefined;
      this._listenersFinalized = undefined;
      this._suspendedListeners = undefined;
    }
  };

  exports.protoMethods = protoMethods;
  function pushUniqueListener(destination, source, index) {
    var target = source[index + 1];
    var method = source[index + 2];
    for (var destinationIndex = 0; destinationIndex < destination.length - 2; destinationIndex += 3) {
      if (destination[destinationIndex] === target && destination[destinationIndex + 1] === method) {
        return;
      }
    }
    destination.push(target, method, source[index + 3]);
  }
});
enifed('ember-metal/mixin', ['exports', 'ember-metal/core', 'ember-metal/error', 'ember-metal/debug', 'ember-metal/assign', 'ember-metal/empty_object', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/utils', 'ember-metal/meta', 'ember-metal/expand_properties', 'ember-metal/properties', 'ember-metal/computed', 'ember-metal/binding', 'ember-metal/observer', 'ember-metal/events', 'ember-metal/streams/utils'], function (exports, _emberMetalCore, _emberMetalError, _emberMetalDebug, _emberMetalAssign, _emberMetalEmpty_object, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalUtils, _emberMetalMeta, _emberMetalExpand_properties, _emberMetalProperties, _emberMetalComputed, _emberMetalBinding, _emberMetalObserver, _emberMetalEvents, _emberMetalStreamsUtils) {
  'no use strict';
  // Remove "use strict"; from transpiled module until
  // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed

  /**
  @module ember
  @submodule ember-metal
  */
  exports.mixin = mixin;
  exports.default = Mixin;
  exports.required = required;
  exports.aliasMethod = aliasMethod;
  exports.observer = observer;
  exports._immediateObserver = _immediateObserver;
  exports._beforeObserver = _beforeObserver;

  function ROOT() {}
  ROOT.__hasSuper = false;

  var REQUIRED;
  var a_slice = [].slice;

  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 = _emberMetalUtils.guidFor(mixin);
      if (mixinsMeta.peekMixins(guid)) {
        return CONTINUE;
      }
      mixinsMeta.writeMixins(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, base) {
    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.
    if (!superProperty) {
      var possibleDesc = base[key];
      var superDesc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;

      superProperty = superDesc;
    }

    if (superProperty === undefined || !(superProperty instanceof _emberMetalComputed.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 = Object.create(property);
    property._getter = _emberMetalUtils.wrap(property._getter, superProperty._getter);
    if (superProperty._setter) {
      if (property._setter) {
        property._setter = _emberMetalUtils.wrap(property._setter, superProperty._setter);
      } else {
        property._setter = superProperty._setter;
      }
    }

    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 (superMethod === undefined || 'function' !== typeof superMethod) {
      return method;
    }

    return _emberMetalUtils.wrap(method, superMethod);
  }

  function applyConcatenatedProperties(obj, key, value, values) {
    var baseValue = values[key] || obj[key];

    if (baseValue) {
      if ('function' === typeof baseValue.concat) {
        if (value === null || value === undefined) {
          return baseValue;
        } else {
          return baseValue.concat(value);
        }
      } else {
        return _emberMetalUtils.makeArray(baseValue).concat(value);
      }
    } else {
      return _emberMetalUtils.makeArray(value);
    }
  }

  function applyMergedProperties(obj, key, value, values) {
    var baseValue = values[key] || obj[key];

    _emberMetalDebug.runInDebug(function () {
      if (Array.isArray(value)) {
        // use conditional to avoid stringifying every time
        _emberMetalDebug.assert('You passed in `' + JSON.stringify(value) + '` as the value for `' + key + '` but `' + key + '` cannot be an Array', false);
      }
    });

    if (!baseValue) {
      return value;
    }

    var newBase = _emberMetalAssign.default({}, baseValue);
    var 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 = ROOT;
    }

    return newBase;
  }

  function addNormalizedProperty(base, key, value, meta, descs, values, concats, mergings) {
    if (value instanceof _emberMetalProperties.Descriptor) {
      if (value === REQUIRED && descs[key]) {
        return CONTINUE;
      }

      // Wrap descriptor function to implement
      // _super() if needed
      if (value._getter) {
        value = giveDescriptorSuper(meta, key, value, values, descs, base);
      }

      descs[key] = value;
      values[key] = undefined;
    } else {
      if (concats && concats.indexOf(key) >= 0 || key === 'concatenatedProperties' || key === 'mergedProperties') {
        value = applyConcatenatedProperties(base, key, value, values);
      } else if (mergings && mergings.indexOf(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 currentMixin, props, key, concats, mergings, meta;

    function removeKeys(keyName) {
      delete descs[keyName];
      delete values[keyName];
    }

    for (var i = 0, l = mixins.length; i < l; i++) {
      currentMixin = mixins[i];
      _emberMetalDebug.assert('Expected hash or Mixin instance, got ' + Object.prototype.toString.call(currentMixin), typeof currentMixin === 'object' && currentMixin !== null && Object.prototype.toString.call(currentMixin) !== '[object Array]');

      props = mixinProperties(m, currentMixin);
      if (props === CONTINUE) {
        continue;
      }

      if (props) {
        meta = _emberMetalMeta.meta(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 (currentMixin.mixins) {
        mergeMixins(currentMixin.mixins, m, descs, values, base, keys);
        if (currentMixin._without) {
          currentMixin._without.forEach(removeKeys);
        }
      }
    }
  }

  var IS_BINDING = /^.+Binding$/;

  function detectBinding(obj, key, value, m) {
    if (IS_BINDING.test(key)) {
      m.writeBindings(key, value);
    }
  }

  function connectStreamBinding(obj, key, stream) {
    var onNotify = function (stream) {
      _emberMetalObserver._suspendObserver(obj, key, null, didChange, function () {
        _emberMetalProperty_set.trySet(obj, key, stream.value());
      });
    };

    var didChange = function () {
      stream.setValue(_emberMetalProperty_get.get(obj, key), onNotify);
    };

    // Initialize value
    _emberMetalProperty_set.set(obj, key, stream.value());

    _emberMetalObserver.addObserver(obj, key, null, didChange);

    stream.subscribe(onNotify);

    if (obj._streamBindingSubscriptions === undefined) {
      obj._streamBindingSubscriptions = new _emberMetalEmpty_object.default();
    }

    obj._streamBindingSubscriptions[key] = onNotify;
  }

  function connectBindings(obj, m) {
    // TODO Mixin.apply(instance) should disconnect binding if exists
    m.forEachBindings(function (key, binding) {
      if (binding) {
        var to = key.slice(0, -7); // strip Binding off end
        if (_emberMetalStreamsUtils.isStream(binding)) {
          connectStreamBinding(obj, to, binding);
          return;
        } else if (binding instanceof _emberMetalBinding.Binding) {
          binding = binding.copy(); // copy prototypes' instance
          binding.to(to);
        } else {
          // binding is string path
          binding = new _emberMetalBinding.Binding(to, binding);
        }
        binding.connect(obj);
        obj[key] = binding;
      }
    });
    // mark as applied
    m.clearBindings();
  }

  function finishPartial(obj, m) {
    connectBindings(obj, m || _emberMetalMeta.meta(obj));
    return obj;
  }

  function followAlias(obj, desc, m, descs, values) {
    var altKey = desc.methodName;
    var value;
    var possibleDesc;
    if (descs[altKey] || values[altKey]) {
      value = values[altKey];
      desc = descs[altKey];
    } else if ((possibleDesc = obj[altKey]) && possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor) {
      desc = possibleDesc;
      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__', _emberMetalObserver._removeBeforeObserver);
      updateObserversAndListeners(obj, key, prev, '__ember_observes__', _emberMetalObserver.removeObserver);
      updateObserversAndListeners(obj, key, prev, '__ember_listens__', _emberMetalEvents.removeListener);
    }

    if ('function' === typeof observerOrListener) {
      updateObserversAndListeners(obj, key, observerOrListener, '__ember_observesBefore__', _emberMetalObserver._addBeforeObserver);
      updateObserversAndListeners(obj, key, observerOrListener, '__ember_observes__', _emberMetalObserver.addObserver);
      updateObserversAndListeners(obj, key, observerOrListener, '__ember_listens__', _emberMetalEvents.addListener);
    }
  }

  function applyMixin(obj, mixins, partial) {
    var descs = {};
    var values = {};
    var m = _emberMetalMeta.meta(obj);
    var keys = [];
    var key, value, desc;

    obj._super = ROOT;

    // 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, m, 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);
      _emberMetalProperties.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
    @private
  */

  function mixin(obj) {
    for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }

    applyMixin(obj, args, false);
    return obj;
  }

  /**
    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(...arguments);
        this.set("filters", Ember.A());
      }
    });
    ```

    @class Mixin
    @namespace Ember
    @public
  */

  function Mixin(args, properties) {
    this.properties = properties;

    var length = args && args.length;

    if (length > 0) {
      var m = new Array(length);

      for (var i = 0; i < length; i++) {
        var x = args[i];
        if (x instanceof Mixin) {
          m[i] = x;
        } else {
          m[i] = new Mixin(undefined, x);
        }
      }

      this.mixins = m;
    } else {
      this.mixins = undefined;
    }
    this.ownerConstructor = undefined;
    this._without = undefined;
    this[_emberMetalUtils.GUID_KEY] = null;
    this[_emberMetalUtils.GUID_KEY + '_name'] = null;
    _emberMetalDebug.debugSeal(this);
  }

  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?
  _emberMetalCore.default.anyUnprocessedMixins = false;

  /**
    @method create
    @static
    @param arguments*
    @public
  */
  Mixin.create = function () {
    // ES6TODO: this relies on a global state?
    _emberMetalCore.default.anyUnprocessedMixins = true;
    var M = this;

    for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
      args[_key2] = arguments[_key2];
    }

    return new M(args, undefined);
  };

  var MixinPrototype = Mixin.prototype;

  /**
    @method reopen
    @param arguments*
    @private
  */
  MixinPrototype.reopen = function () {
    var currentMixin;

    if (this.properties) {
      currentMixin = new Mixin(undefined, this.properties);
      this.properties = undefined;
      this.mixins = [currentMixin];
    } else if (!this.mixins) {
      this.mixins = [];
    }

    var len = arguments.length;
    var mixins = this.mixins;
    var idx;

    for (idx = 0; idx < len; idx++) {
      currentMixin = arguments[idx];
      _emberMetalDebug.assert('Expected hash or Mixin instance, got ' + Object.prototype.toString.call(currentMixin), typeof currentMixin === 'object' && currentMixin !== null && Object.prototype.toString.call(currentMixin) !== '[object Array]');

      if (currentMixin instanceof Mixin) {
        mixins.push(currentMixin);
      } else {
        mixins.push(new Mixin(undefined, currentMixin));
      }
    }

    return this;
  };

  /**
    @method apply
    @param obj
    @return applied object
    @private
  */
  MixinPrototype.apply = function (obj) {
    return applyMixin(obj, [this], false);
  };

  MixinPrototype.applyPartial = function (obj) {
    return applyMixin(obj, [this], true);
  };

  MixinPrototype.toString = function Mixin_toString() {
    return '(unknown mixin)';
  };

  function _detect(curMixin, targetMixin, seen) {
    var guid = _emberMetalUtils.guidFor(curMixin);

    if (seen[guid]) {
      return false;
    }
    seen[guid] = true;

    if (curMixin === targetMixin) {
      return true;
    }
    var mixins = curMixin.mixins;
    var loc = mixins ? mixins.length : 0;
    while (--loc >= 0) {
      if (_detect(mixins[loc], targetMixin, seen)) {
        return true;
      }
    }
    return false;
  }

  /**
    @method detect
    @param obj
    @return {Boolean}
    @private
  */
  MixinPrototype.detect = function (obj) {
    if (!obj) {
      return false;
    }
    if (obj instanceof Mixin) {
      return _detect(obj, this, {});
    }
    var m = _emberMetalMeta.peekMeta(obj);
    if (!m) {
      return false;
    }
    return !!m.peekMixins(_emberMetalUtils.guidFor(this));
  };

  MixinPrototype.without = function () {
    var ret = new Mixin([this]);

    for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
      args[_key3] = arguments[_key3];
    }

    ret._without = args;
    return ret;
  };

  function _keys(ret, mixin, seen) {
    if (seen[_emberMetalUtils.guidFor(mixin)]) {
      return;
    }
    seen[_emberMetalUtils.guidFor(mixin)] = true;

    if (mixin.properties) {
      var props = Object.keys(mixin.properties);
      for (var i = 0; i < props.length; i++) {
        var key = props[i];
        ret[key] = true;
      }
    } else if (mixin.mixins) {
      mixin.mixins.forEach(function (x) {
        return _keys(ret, x, seen);
      });
    }
  }

  MixinPrototype.keys = function () {
    var keys = {};
    var seen = {};

    _keys(keys, this, seen);
    var ret = Object.keys(keys);
    return ret;
  };

  _emberMetalDebug.debugSeal(MixinPrototype);

  // returns the mixins currently applied to the specified object
  // TODO: Make Ember.mixin
  Mixin.mixins = function (obj) {
    var m = _emberMetalMeta.peekMeta(obj);
    var ret = [];
    if (!m) {
      return ret;
    }

    m.forEachMixins(function (key, currentMixin) {
      // skip primitive mixins since these are always anonymous
      if (!currentMixin.properties) {
        ret.push(currentMixin);
      }
    });

    return ret;
  };

  exports.REQUIRED = REQUIRED = new _emberMetalProperties.Descriptor();
  REQUIRED.toString = function () {
    return '(Required Property)';
  };

  /**
    Denotes a required property for a mixin

    @method required
    @for Ember
    @private
  */

  function required() {
    _emberMetalDebug.deprecate('Ember.required is deprecated as its behavior is inconsistent and unreliable.', false, { id: 'ember-metal.required', until: '3.0.0' });
    return REQUIRED;
  }

  function Alias(methodName) {
    this.isDescriptor = true;
    this.methodName = methodName;
  }

  Alias.prototype = new _emberMetalProperties.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
    @public
  */

  function aliasMethod(methodName) {
    return new Alias(methodName);
  }

  // ..........................................................
  // OBSERVER HELPER
  //

  /**
    Specify a method that observes property changes.

    ```javascript
    Ember.Object.extend({
      valueObserver: Ember.observer('value', function() {
        // Executes whenever the "value" property changes
      })
    });
    ```

    Also available as `Function.prototype.observes` if prototype extensions are
    enabled.

    @method observer
    @for Ember
    @param {String} propertyNames*
    @param {Function} func
    @return func
    @public
  */

  function observer() {
    for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
      args[_key4] = arguments[_key4];
    }

    var func = args.slice(-1)[0];
    var paths;

    var addWatchedProperty = function (path) {
      paths.push(path);
    };
    var _paths = args.slice(0, -1);

    if (typeof func !== 'function') {
      // revert to old, soft-deprecated argument ordering
      _emberMetalDebug.deprecate('Passing the dependentKeys after the callback function in Ember.observer is deprecated. Ensure the callback function is the last argument.', false, { id: 'ember-metal.observer-argument-order', until: '3.0.0' });

      func = args[0];
      _paths = args.slice(1);
    }

    paths = [];

    for (var i = 0; i < _paths.length; ++i) {
      _emberMetalExpand_properties.default(_paths[i], addWatchedProperty);
    }

    if (typeof func !== 'function') {
      throw new _emberMetalError.default('Ember.observer called without a function');
    }

    func.__ember_observes__ = paths;
    return func;
  }

  /**
    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
    @deprecated Use `Ember.observer` instead.
    @return func
    @private
  */

  function _immediateObserver() {
    _emberMetalDebug.deprecate('Usage of `Ember.immediateObserver` is deprecated, use `Ember.observer` instead.', false, { id: 'ember-metal.immediate-observer', until: '3.0.0' });

    for (var i = 0, l = arguments.length; i < l; i++) {
      var arg = arguments[i];
      _emberMetalDebug.assert('Immediate observers must observe internal properties only, not properties on other objects.', typeof arg !== 'string' || arg.indexOf('.') === -1);
    }

    return observer.apply(this, arguments);
  }

  /**
    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' }],

      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
    @deprecated
    @private
  */

  function _beforeObserver() {
    for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
      args[_key5] = arguments[_key5];
    }

    var func = args.slice(-1)[0];
    var paths;

    var addWatchedProperty = function (path) {
      paths.push(path);
    };

    var _paths = args.slice(0, -1);

    if (typeof func !== 'function') {
      // revert to old, soft-deprecated argument ordering

      func = args[0];
      _paths = args.slice(1);
    }

    paths = [];

    for (var i = 0; i < _paths.length; ++i) {
      _emberMetalExpand_properties.default(_paths[i], addWatchedProperty);
    }

    if (typeof func !== 'function') {
      throw new _emberMetalCore.default.Error('Ember.beforeObserver called without a function');
    }

    func.__ember_observesBefore__ = paths;
    return func;
  }

  exports.IS_BINDING = IS_BINDING;
  exports.Mixin = Mixin;
  exports.required = required;
  exports.REQUIRED = REQUIRED;
});
// warn, assert, wrap, et;
enifed('ember-metal/observer', ['exports', 'ember-metal/watching', 'ember-metal/events'], function (exports, _emberMetalWatching, _emberMetalEvents) {
  'use strict';

  exports.addObserver = addObserver;
  exports.observersFor = observersFor;
  exports.removeObserver = removeObserver;
  exports._addBeforeObserver = _addBeforeObserver;
  exports._suspendObserver = _suspendObserver;
  exports._suspendObservers = _suspendObservers;
  exports._removeBeforeObserver = _removeBeforeObserver;

  /**
  @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} target
    @param {Function|String} [method]
    @public
  */

  function addObserver(obj, _path, target, method) {
    _emberMetalEvents.addListener(obj, changeEvent(_path), target, method);
    _emberMetalWatching.watch(obj, _path);

    return this;
  }

  function observersFor(obj, path) {
    return _emberMetalEvents.listenersFor(obj, changeEvent(path));
  }

  /**
    @method removeObserver
    @for Ember
    @param obj
    @param {String} path
    @param {Object|Function} target
    @param {Function|String} [method]
    @public
  */

  function removeObserver(obj, path, target, method) {
    _emberMetalWatching.unwatch(obj, path);
    _emberMetalEvents.removeListener(obj, changeEvent(path), target, method);

    return this;
  }

  /**
    @method _addBeforeObserver
    @for Ember
    @param obj
    @param {String} path
    @param {Object|Function} target
    @param {Function|String} [method]
    @deprecated
    @private
  */

  function _addBeforeObserver(obj, path, target, method) {
    _emberMetalEvents.addListener(obj, beforeEvent(path), target, method);
    _emberMetalWatching.watch(obj, path);

    return this;
  }

  // Suspend observer during callback.
  //
  // This should only be used by the target of the observer
  // while it is setting the observed path.

  function _suspendObserver(obj, path, target, method, callback) {
    return _emberMetalEvents.suspendListener(obj, changeEvent(path), target, method, callback);
  }

  function _suspendObservers(obj, paths, target, method, callback) {
    var events = paths.map(changeEvent);
    return _emberMetalEvents.suspendListeners(obj, events, target, method, callback);
  }

  /**
    @method removeBeforeObserver
    @for Ember
    @param obj
    @param {String} path
    @param {Object|Function} target
    @param {Function|String} [method]
    @deprecated
    @private
  */

  function _removeBeforeObserver(obj, path, target, method) {
    _emberMetalWatching.unwatch(obj, path);
    _emberMetalEvents.removeListener(obj, beforeEvent(path), target, method);

    return this;
  }
});
enifed('ember-metal/observer_set', ['exports', 'ember-metal/utils', 'ember-metal/events'], function (exports, _emberMetalUtils, _emberMetalEvents) {
  'use strict';

  /*
    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;
    var observers = this.observers;
    var senderGuid = _emberMetalUtils.guidFor(sender);
    var keySet = observerSet[senderGuid];
    var 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;
    var 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;
      }
      _emberMetalEvents.sendEvent(sender, observer.eventName, [sender, observer.keyName], observer.listeners);
    }
  };

  ObserverSet.prototype.clear = function () {
    this.observerSet = {};
    this.observers = [];
  };
});
enifed('ember-metal/path_cache', ['exports', 'ember-metal/cache'], function (exports, _emberMetalCache) {
  'use strict';

  exports.isGlobal = isGlobal;
  exports.isGlobalPath = isGlobalPath;
  exports.hasThis = hasThis;
  exports.isPath = isPath;
  exports.getFirstKey = getFirstKey;
  exports.getTailPath = getTailPath;

  var IS_GLOBAL = /^[A-Z$]/;
  var IS_GLOBAL_PATH = /^[A-Z$].*[\.]/;
  var HAS_THIS = 'this.';

  var isGlobalCache = new _emberMetalCache.default(1000, function (key) {
    return IS_GLOBAL.test(key);
  });

  var isGlobalPathCache = new _emberMetalCache.default(1000, function (key) {
    return IS_GLOBAL_PATH.test(key);
  });

  var hasThisCache = new _emberMetalCache.default(1000, function (key) {
    return key.lastIndexOf(HAS_THIS, 0) === 0;
  });

  var firstDotIndexCache = new _emberMetalCache.default(1000, function (key) {
    return key.indexOf('.');
  });

  var firstKeyCache = new _emberMetalCache.default(1000, function (path) {
    var index = firstDotIndexCache.get(path);
    if (index === -1) {
      return path;
    } else {
      return path.slice(0, index);
    }
  });

  var tailPathCache = new _emberMetalCache.default(1000, function (path) {
    var index = firstDotIndexCache.get(path);
    if (index !== -1) {
      return path.slice(index + 1);
    }
  });

  var caches = {
    isGlobalCache: isGlobalCache,
    isGlobalPathCache: isGlobalPathCache,
    hasThisCache: hasThisCache,
    firstDotIndexCache: firstDotIndexCache,
    firstKeyCache: firstKeyCache,
    tailPathCache: tailPathCache
  };

  exports.caches = caches;

  function isGlobal(path) {
    return isGlobalCache.get(path);
  }

  function isGlobalPath(path) {
    return isGlobalPathCache.get(path);
  }

  function hasThis(path) {
    return hasThisCache.get(path);
  }

  function isPath(path) {
    return firstDotIndexCache.get(path) !== -1;
  }

  function getFirstKey(path) {
    return firstKeyCache.get(path);
  }

  function getTailPath(path) {
    return tailPathCache.get(path);
  }
});
enifed('ember-metal/properties', ['exports', 'ember-metal/debug', 'ember-metal/features', 'ember-metal/meta', 'ember-metal/property_events'], function (exports, _emberMetalDebug, _emberMetalFeatures, _emberMetalMeta, _emberMetalProperty_events) {
  /**
  @module ember-metal
  */

  'use strict';

  exports.Descriptor = Descriptor;
  exports.MANDATORY_SETTER_FUNCTION = MANDATORY_SETTER_FUNCTION;
  exports.DEFAULT_GETTER_FUNCTION = DEFAULT_GETTER_FUNCTION;
  exports.INHERITING_GETTER_FUNCTION = INHERITING_GETTER_FUNCTION;
  exports.defineProperty = defineProperty;

  // ..........................................................
  // DESCRIPTOR
  //

  /**
    Objects of this type can implement an interface to respond to requests to
    get and set. The default implementation handles simple properties.

    @class Descriptor
    @private
  */

  function Descriptor() {
    this.isDescriptor = true;
  }

  var REDEFINE_SUPPORTED = (function () {
    // https://github.com/spalger/kibana/commit/b7e35e6737df585585332857a4c397dc206e7ff9
    var a = Object.create(Object.prototype, {
      prop: {
        configurable: true,
        value: 1
      }
    });

    Object.defineProperty(a, 'prop', {
      configurable: true,
      value: 2
    });

    return a.prop === 2;
  })();
  // ..........................................................
  // DEFINING PROPERTIES API
  //

  function MANDATORY_SETTER_FUNCTION(name) {
    function SETTER_FUNCTION(value) {
      _emberMetalDebug.assert('You must use Ember.set() to set the `' + name + '` property (of ' + this + ') to `' + value + '`.', false);
    }

    SETTER_FUNCTION.isMandatorySetter = true;
    return SETTER_FUNCTION;
  }

  function DEFAULT_GETTER_FUNCTION(name) {
    return function GETTER_FUNCTION() {
      var meta = this['__ember_meta__'];
      return meta && meta.peekValues(name);
    };
  }

  function INHERITING_GETTER_FUNCTION(name) {
    function IGETTER_FUNCTION() {
      var proto = Object.getPrototypeOf(this);
      return proto && proto[name];
    }

    IGETTER_FUNCTION.isInheritingGetter = true;
    return IGETTER_FUNCTION;
  }

  /**
    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 `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('firstName', 'lastName', function() {
      return this.firstName+' '+this.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 {Descriptor} [desc] an instance of `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 possibleDesc, existingDesc, watching, value;

    if (!meta) {
      meta = _emberMetalMeta.meta(obj);
    }
    var watchEntry = meta.peekWatching(keyName);
    possibleDesc = obj[keyName];
    existingDesc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;

    watching = watchEntry !== undefined && watchEntry > 0;

    if (existingDesc) {
      existingDesc.teardown(obj, keyName);
    }

    if (desc instanceof Descriptor) {
      value = desc;

      if (watching) {
        Object.defineProperty(obj, keyName, {
          configurable: true,
          enumerable: true,
          writable: true,
          value: value
        });
      } else {
        obj[keyName] = value;
      }

      if (desc.setup) {
        desc.setup(obj, keyName);
      }
    } else {
      if (desc == null) {
        value = data;

        if (watching) {
          meta.writeValues(keyName, data);

          var defaultDescriptor = {
            configurable: true,
            enumerable: true,
            set: MANDATORY_SETTER_FUNCTION(keyName),
            get: DEFAULT_GETTER_FUNCTION(keyName)
          };

          if (REDEFINE_SUPPORTED) {
            Object.defineProperty(obj, keyName, defaultDescriptor);
          } else {
            handleBrokenPhantomDefineProperty(obj, keyName, defaultDescriptor);
          }
        } else {
          obj[keyName] = data;
        }
      } else {
        value = desc;

        // fallback to ES5
        Object.defineProperty(obj, keyName, desc);
      }
    }

    // if key is being watched, override chains that
    // were initialized with the prototype
    if (watching) {
      _emberMetalProperty_events.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;
  }

  function handleBrokenPhantomDefineProperty(obj, keyName, desc) {
    // https://github.com/ariya/phantomjs/issues/11856
    Object.defineProperty(obj, keyName, { configurable: true, writable: true, value: 'iCry' });
    Object.defineProperty(obj, keyName, desc);
  }
});
enifed('ember-metal/property_events', ['exports', 'ember-metal/utils', 'ember-metal/meta', 'ember-metal/events', 'ember-metal/observer_set', 'ember-metal/symbol'], function (exports, _emberMetalUtils, _emberMetalMeta, _emberMetalEvents, _emberMetalObserver_set, _emberMetalSymbol) {
  'use strict';

  var PROPERTY_DID_CHANGE = _emberMetalSymbol.default('PROPERTY_DID_CHANGE');

  exports.PROPERTY_DID_CHANGE = PROPERTY_DID_CHANGE;
  var beforeObserverSet = new _emberMetalObserver_set.default();
  var observerSet = new _emberMetalObserver_set.default();
  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}
    @private
  */
  function propertyWillChange(obj, keyName) {
    var m = _emberMetalMeta.peekMeta(obj);
    var watching = m && m.peekWatching(keyName) > 0 || keyName === 'length';
    var proto = m && m.proto;
    var possibleDesc = obj[keyName];
    var desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;

    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}
    @private
  */
  function propertyDidChange(obj, keyName) {
    var m = _emberMetalMeta.peekMeta(obj);
    var watching = m && m.peekWatching(keyName) > 0 || keyName === 'length';
    var proto = m && m.proto;
    var possibleDesc = obj[keyName];
    var desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;

    if (proto === obj) {
      return;
    }

    // shouldn't this mean that we're watching this key?
    if (desc && desc.didChange) {
      desc.didChange(obj, keyName);
    }

    if (obj[PROPERTY_DID_CHANGE]) {
      obj[PROPERTY_DID_CHANGE](keyName);
    }

    if (!watching && keyName !== 'length') {
      return;
    }

    if (m && m.hasDeps(keyName)) {
      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;
    }

    if (meta && meta.hasDeps(depKey)) {
      var seen = WILL_SEEN;
      var 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;
    }

    if (meta && meta.hasDeps(depKey)) {
      var seen = DID_SEEN;
      var 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 possibleDesc, desc;
    var guid = _emberMetalUtils.guidFor(obj);
    var current = seen[guid];

    if (!current) {
      current = seen[guid] = {};
    }

    if (current[depKey]) {
      return;
    }

    current[depKey] = true;

    meta.forEachInDeps(depKey, function (key, value) {
      if (!value) {
        return;
      }

      possibleDesc = obj[key];
      desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;

      if (desc && desc._suspended === obj) {
        return;
      }

      method(obj, key);
    });
  }

  function chainsWillChange(obj, keyName, m) {
    var c = m.readableChainWatchers();
    if (c) {
      c.notify(keyName, false, propertyWillChange);
    }
  }

  function chainsDidChange(obj, keyName, m) {
    var c = m.readableChainWatchers();
    if (c) {
      c.notify(keyName, true, propertyDidChange);
    }
  }

  function overrideChains(obj, keyName, m) {
    var c = m.readableChainWatchers();
    if (c) {
      c.revalidate(keyName);
    }
  }

  /**
    @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]
    @private
  */
  function changeProperties(callback, binding) {
    beginPropertyChanges();
    try {
      callback.call(binding);
    } finally {
      endPropertyChanges.call(binding);
    }
  }

  function notifyBeforeObservers(obj, keyName) {
    if (obj.isDestroying) {
      return;
    }

    var eventName = keyName + ':before';
    var listeners, added;
    if (deferred) {
      listeners = beforeObserverSet.add(obj, keyName, eventName);
      added = _emberMetalEvents.accumulateListeners(obj, eventName, listeners);
      _emberMetalEvents.sendEvent(obj, eventName, [obj, keyName], added);
    } else {
      _emberMetalEvents.sendEvent(obj, eventName, [obj, keyName]);
    }
  }

  function notifyObservers(obj, keyName) {
    if (obj.isDestroying) {
      return;
    }

    var eventName = keyName + ':change';
    var listeners;
    if (deferred) {
      listeners = observerSet.add(obj, keyName, eventName);
      _emberMetalEvents.accumulateListeners(obj, eventName, listeners);
    } else {
      _emberMetalEvents.sendEvent(obj, eventName, [obj, keyName]);
    }
  }

  exports.propertyWillChange = propertyWillChange;
  exports.propertyDidChange = propertyDidChange;
  exports.overrideChains = overrideChains;
  exports.beginPropertyChanges = beginPropertyChanges;
  exports.endPropertyChanges = endPropertyChanges;
  exports.changeProperties = changeProperties;
});
enifed('ember-metal/property_get', ['exports', 'ember-metal/debug', 'ember-metal/path_cache'], function (exports, _emberMetalDebug, _emberMetalPath_cache) {
  /**
  @module ember-metal
  */

  'use strict';

  exports.get = get;
  exports._getPath = _getPath;
  exports.getWithDefault = getWithDefault;

  var ALLOWABLE_TYPES = {
    object: true,
    function: true,
    string: true
  };

  // ..........................................................
  // 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`.
    @public
  */

  function get(obj, keyName) {
    _emberMetalDebug.assert('Get must be called with two arguments; an object and a property key', arguments.length === 2);
    _emberMetalDebug.assert('Cannot call get with \'' + keyName + '\' on an undefined object.', obj !== undefined && obj !== null);
    _emberMetalDebug.assert('The key provided to get must be a string, you passed ' + keyName, typeof keyName === 'string');
    _emberMetalDebug.assert('\'this\' in paths is not supported', !_emberMetalPath_cache.hasThis(keyName));

    // Helpers that operate with 'this' within an #each
    if (keyName === '') {
      return obj;
    }

    var value = obj[keyName];
    var desc = value !== null && typeof value === 'object' && value.isDescriptor ? value : undefined;
    var ret;

    if (desc === undefined && _emberMetalPath_cache.isPath(keyName)) {
      return _getPath(obj, keyName);
    }

    if (desc) {
      return desc.get(obj, keyName);
    } else {
      ret = value;

      if (ret === undefined && 'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) {
        return obj.unknownProperty(keyName);
      }

      return ret;
    }
  }

  function _getPath(root, path) {
    var obj = root;
    var parts = path.split('.');

    for (var i = 0; i < parts.length; i++) {
      if (!isGettable(obj)) {
        return undefined;
      }

      obj = get(obj, parts[i]);

      if (obj && obj.isDestroyed) {
        return undefined;
      }
    }

    return obj;
  }

  function isGettable(obj) {
    if (obj == null) {
      return false;
    }

    return ALLOWABLE_TYPES[typeof obj];
  }

  /**
    Retrieves the value of a property from an Object, or a default value in the
    case that the property returns `undefined`.

    ```javascript
    Ember.getWithDefault(person, 'lastName', 'Doe');
    ```

    @method getWithDefault
    @for Ember
    @param {Object} obj The object to retrieve from.
    @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.
    @public
  */

  function getWithDefault(root, key, defaultValue) {
    var value = get(root, key);

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

  exports.default = get;
});
enifed('ember-metal/property_set', ['exports', 'ember-metal/debug', 'ember-metal/features', 'ember-metal/property_get', 'ember-metal/property_events', 'ember-metal/properties', 'ember-metal/error', 'ember-metal/path_cache', 'ember-metal/meta', 'ember-metal/utils', 'ember-metal/tags'], function (exports, _emberMetalDebug, _emberMetalFeatures, _emberMetalProperty_get, _emberMetalProperty_events, _emberMetalProperties, _emberMetalError, _emberMetalPath_cache, _emberMetalMeta, _emberMetalUtils, _emberMetalTags) {
  'use strict';

  exports.set = set;
  exports.trySet = trySet;

  /**
    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.
    @public
  */

  function set(obj, keyName, value, tolerant) {
    _emberMetalDebug.assert('Set must be called with three or four arguments; an object, a property key, a value and tolerant true/false', arguments.length === 3 || arguments.length === 4);
    _emberMetalDebug.assert('Cannot call set with \'' + keyName + '\' on an undefined object.', obj !== undefined && obj !== null);
    _emberMetalDebug.assert('The key provided to set must be a string, you passed ' + keyName, typeof keyName === 'string');
    _emberMetalDebug.assert('\'this\' in paths is not supported', !_emberMetalPath_cache.hasThis(keyName));

    var meta = undefined,
        possibleDesc = undefined,
        desc = undefined;

    if (obj) {
      meta = _emberMetalMeta.peekMeta(obj);
      possibleDesc = obj[keyName];
      desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;
      _emberMetalTags.markObjectAsDirty(meta);
    }

    var isUnknown, currentValue;
    if (desc === undefined && _emberMetalPath_cache.isPath(keyName)) {
      return setPath(obj, keyName, value, tolerant);
    }

    _emberMetalDebug.assert('calling set on destroyed object: ' + _emberMetalUtils.toString(obj) + '.' + keyName + ' = ' + _emberMetalUtils.toString(value), !obj.isDestroyed);

    if (desc) {
      desc.set(obj, keyName, value);
    } else {
      if (value !== undefined && typeof obj === 'object' && 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.peekWatching(keyName) > 0) {
        if (meta.proto !== obj) {
          currentValue = obj[keyName];
        }
        // only trigger a change if the value has changed
        if (value !== currentValue) {
          _emberMetalProperty_events.propertyWillChange(obj, keyName);

          if (currentValue === undefined && !(keyName in obj) || !Object.prototype.propertyIsEnumerable.call(obj, keyName)) {
            _emberMetalProperties.defineProperty(obj, keyName, null, value); // setup mandatory setter
          } else {
              var descriptor = _emberMetalUtils.lookupDescriptor(obj, keyName);
              var isMandatorySetter = descriptor && descriptor.set && descriptor.set.isMandatorySetter;
              if (isMandatorySetter) {
                meta.writeValues(keyName, value);
              } else {
                obj[keyName] = value;
              }
            }

          _emberMetalProperty_events.propertyDidChange(obj, keyName);
        }
      } else {
        obj[keyName] = value;
        if (obj[_emberMetalProperty_events.PROPERTY_DID_CHANGE]) {
          obj[_emberMetalProperty_events.PROPERTY_DID_CHANGE](keyName);
        }
      }
    }
    return value;
  }

  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 = _emberMetalProperty_get._getPath(root, path);
    }

    if (!keyName || keyName.length === 0) {
      throw new _emberMetalError.default('Property set failed: You passed an empty path');
    }

    if (!root) {
      if (tolerant) {
        return;
      } else {
        throw new _emberMetalError.default('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} root The object to modify.
    @param {String} path The property path to set
    @param {Object} value The value to set
    @public
  */

  function trySet(root, path, value) {
    return set(root, path, value, true);
  }
});
enifed("ember-metal/replace", ["exports"], function (exports) {
  "use strict";

  exports._replace = _replace;
  exports.default = replace;
  var splice = Array.prototype.splice;

  function _replace(array, idx, amt, objects) {
    var args = [].concat(objects);
    var ret = [];
    // https://code.google.com/p/chromium/issues/detail?id=56588
    var size = 60000;
    var start = idx;
    var ends = amt;
    var count, chunk;

    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;
  }

  /**
    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
    @deprecated
    @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.
    @public
  */

  function replace(array, idx, amt, objects) {
    if (array.replace) {
      return array.replace(idx, amt, objects);
    } else {
      return _replace(array, idx, amt, objects);
    }
  }
});
enifed('ember-metal/run_loop', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-metal/utils', 'ember-metal/property_events', 'backburner'], function (exports, _emberMetalCore, _emberMetalDebug, _emberMetalUtils, _emberMetalProperty_events, _backburner) {
  'use strict';

  exports.default = run;

  function onBegin(current) {
    run.currentRunLoop = current;
  }

  function onEnd(current, next) {
    run.currentRunLoop = next;
  }

  // ES6TODO: should Backburner become es6?
  var backburner = new _backburner.default(['sync', 'actions', 'destroy'], {
    GUID_KEY: _emberMetalUtils.GUID_KEY,
    sync: {
      before: _emberMetalProperty_events.beginPropertyChanges,
      after: _emberMetalProperty_events.endPropertyChanges
    },
    defaultQueue: 'actions',
    onBegin: onBegin,
    onEnd: onEnd,
    onErrorTarget: _emberMetalCore.default,
    onErrorMethod: 'onerror'
  });

  // ..........................................................
  // 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 executed 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.
    @public
  */

  function run() {
    return backburner.run.apply(backburner, 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.
    @public
  */
  run.join = function () {
    return backburner.join.apply(backburner, arguments);
  };

  /**
    Allows you to specify which context to call the specified function in while
    adding the execution of that function to the Ember run loop. This ability
    makes this method a great way to asynchronously integrate third-party libraries
    into your Ember application.

    `run.bind` takes two main arguments, the desired context and the function to
    invoke in that context. Any additional arguments will be supplied as arguments
    to the function that is passed in.

    Let's use the creation of a TinyMCE component as an example. Currently,
    TinyMCE provides a setup configuration option we can use to do some processing
    after the TinyMCE instance is initialized but before it is actually rendered.
    We can use that setup option to do some additional setup for our component.
    The component itself could look something like the following:

    ```javascript
    App.RichTextEditorComponent = Ember.Component.extend({
      initializeTinyMCE: Ember.on('didInsertElement', function() {
        tinymce.init({
          selector: '#' + this.$().prop('id'),
          setup: Ember.run.bind(this, this.setupEditor)
        });
      }),

      setupEditor: function(editor) {
        this.set('editor', editor);

        editor.on('change', function() {
          console.log('content changed!');
        });
      }
    });
    ```

    In this example, we use Ember.run.bind to bind the setupEditor method to the
    context of the App.RichTextEditorComponent and to have the invocation of that
    method be safely handled and executed by the Ember run loop.

    @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 {Function} returns a new function that will always have a particular context
    @since 1.4.0
    @public
  */
  run.bind = function () {
    for (var _len = arguments.length, curried = Array(_len), _key = 0; _key < _len; _key++) {
      curried[_key] = arguments[_key];
    }

    return function () {
      for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }

      return run.join.apply(run, curried.concat(args));
    };
  };

  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 executed within a RunLoop
    run.end();
    ```

    @method begin
    @return {void}
    @public
  */
  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 executed within a RunLoop
    run.end();
    ```

    @method end
    @return {void}
    @public
  */
  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']
    @private
  */

  /**
    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}
    @public
  */
  run.schedule = function () /* queue, target, method */{
    checkAutoRun();
    backburner.schedule.apply(backburner, 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}
    @private
  */
  run.sync = function () {
    if (backburner.currentInstance) {
      backburner.currentInstance.queues.sync.flush();
    }
  };

  /**
    Invokes the passed target/method and optional arguments after a specified
    period of 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 {*} Timer information for use in cancelling, see `run.cancel`.
    @public
  */
  run.later = function () /*target, method*/{
    return backburner.later.apply(backburner, 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`.
    @public
  */
  run.once = function () {
    checkAutoRun();

    for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
      args[_key3] = arguments[_key3];
    }

    args.unshift('actions');
    return backburner.scheduleOnce.apply(backburner, 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
    function sayHi() {
      console.log('hi');
    }

    run(function() {
      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`.
    @public
  */
  run.scheduleOnce = function () /*queue, target, method*/{
    checkAutoRun();
    return backburner.scheduleOnce.apply(backburner, 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
    export default Ember.Component.extend({
      didInsertElement() {
        this._super(...arguments);
        run.scheduleOnce('afterRender', this, 'processChildElements');
      },

      processChildElements() {
        // ... do something with component's child component
        // elements after they've finished rendering, which
        // can't be done within this component'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`.
    @public
  */
  run.next = function () {
    for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
      args[_key4] = arguments[_key4];
    }

    args.push(1);
    return backburner.later.apply(backburner, args);
  };

  /**
    Cancels a scheduled item. Must be a value returned by `run.later()`,
    `run.once()`, `run.scheduleOnce()`, `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 runScheduleOnce = run.scheduleOnce('afterRender', myContext, function() {
      // will not be executed
    });

    run.cancel(runScheduleOnce);

    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
    @public
  */
  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
    function whoRan() {
      console.log(this.name + ' ran.');
    }

    var myContext = { name: 'debounce' };

    run.debounce(myContext, whoRan, 150);

    // less than 150ms passes
    run.debounce(myContext, whoRan, 150);

    // 150ms passes
    // whoRan 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
    function whoRan() {
      console.log(this.name + ' ran.');
    }

    var myContext = { name: 'debounce' };

    run.debounce(myContext, whoRan, 150, true);

    // console logs 'debounce ran.' one time immediately.
    // 100ms passes
    run.debounce(myContext, whoRan, 150, true);

    // 150ms passes and nothing else is logged to the console and
    // the debouncee is no longer being watched
    run.debounce(myContext, whoRan, 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`.
    @public
  */
  run.debounce = function () {
    return backburner.debounce.apply(backburner, arguments);
  };

  /**
    Ensure that the target method is never called more frequently than
    the specified spacing period. The target method is called immediately.

    ```javascript
    function whoRan() {
      console.log(this.name + ' ran.');
    }

    var myContext = { name: 'throttle' };

    run.throttle(myContext, whoRan, 150);
    // whoRan is invoked with context myContext
    // console logs 'throttle ran.'

    // 50ms passes
    run.throttle(myContext, whoRan, 150);

    // 50ms passes
    run.throttle(myContext, whoRan, 150);

    // 150ms passes
    run.throttle(myContext, whoRan, 150);
    // whoRan 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`.
    @public
  */
  run.throttle = function () {
    return backburner.throttle.apply(backburner, arguments);
  };

  // Make sure it's not an autorun during testing
  function checkAutoRun() {
    if (!run.currentRunLoop) {
      _emberMetalDebug.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 a run', !_emberMetalCore.default.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 (run.queues.indexOf(name) === -1) {
      run.queues.splice(run.queues.indexOf(after) + 1, 0, name);
    }
  };
});
enifed('ember-metal/set_properties', ['exports', 'ember-metal/property_events', 'ember-metal/property_set'], function (exports, _emberMetalProperty_events, _emberMetalProperty_set) {
  'use strict';

  exports.default = setProperties;

  /**
    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 obj
    @param {Object} properties
    @return properties
    @public
  */

  function setProperties(obj, properties) {
    if (!properties || typeof properties !== 'object') {
      return properties;
    }
    _emberMetalProperty_events.changeProperties(function () {
      var props = Object.keys(properties);
      var propertyName;

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

        _emberMetalProperty_set.set(obj, propertyName, properties[propertyName]);
      }
    });
    return properties;
  }
});
enifed('ember-metal/streams/dependency', ['exports', 'ember-metal/debug', 'ember-metal/assign', 'ember-metal/streams/utils'], function (exports, _emberMetalDebug, _emberMetalAssign, _emberMetalStreamsUtils) {
  'use strict';

  /**
    @module ember-metal
  */

  /**
    @private
    @class Dependency
    @namespace Ember.streams
    @constructor
  */
  function Dependency(depender, dependee) {
    _emberMetalDebug.assert('Dependency error: Depender must be a stream', _emberMetalStreamsUtils.isStream(depender));

    this.next = null;
    this.prev = null;
    this.depender = depender;
    this.dependee = dependee;
    this.unsubscription = null;
  }

  _emberMetalAssign.default(Dependency.prototype, {
    subscribe: function () {
      _emberMetalDebug.assert('Dependency error: Dependency tried to subscribe while already subscribed', !this.unsubscription);

      this.unsubscription = _emberMetalStreamsUtils.subscribe(this.dependee, this.depender.notify, this.depender);
    },

    unsubscribe: function () {
      if (this.unsubscription) {
        this.unsubscription();
        this.unsubscription = null;
      }
    },

    replace: function (dependee) {
      if (this.dependee !== dependee) {
        this.dependee = dependee;

        if (this.unsubscription) {
          this.unsubscribe();
          this.subscribe();
        }
        return true;
      }
      return false;
    },

    getValue: function () {
      return _emberMetalStreamsUtils.read(this.dependee);
    },

    setValue: function (value) {
      return _emberMetalStreamsUtils.setValue(this.dependee, value);
    }

    // destroy() {
    //   var next = this.next;
    //   var prev = this.prev;

    //   if (prev) {
    //     prev.next = next;
    //   } else {
    //     this.depender.dependencyHead = next;
    //   }

    //   if (next) {
    //     next.prev = prev;
    //   } else {
    //     this.depender.dependencyTail = prev;
    //   }

    //   this.unsubscribe();
    // }
  });

  exports.default = Dependency;
});
enifed('ember-metal/streams/key-stream', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/observer', 'ember-metal/streams/stream', 'ember-metal/streams/utils'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalObserver, _emberMetalStreamsStream, _emberMetalStreamsUtils) {
  'use strict';

  function labelFor(source, key) {
    return source.label ? source.label + '.' + key : key;
  }

  exports.default = _emberMetalStreamsStream.default.extend({
    init: function (source, key) {
      _emberMetalDebug.assert('KeyStream error: source must be a stream', _emberMetalStreamsUtils.isStream(source)); // TODO: This isn't necessary.
      _emberMetalDebug.assert('KeyStream error: key must be a non-empty string', typeof key === 'string' && key.length > 0);
      _emberMetalDebug.assert('KeyStream error: key must not have a \'.\'', key.indexOf('.') === -1);

      var label = labelFor(source, key);

      this.path = label;
      this.observedObject = null;
      this.key = key;
      this.sourceDep = this.addMutableDependency(source);
      this.label = label;
    },

    compute: function () {
      var object = this.sourceDep.getValue();
      var type = typeof object;

      if (!object || type === 'boolean') {
        return;
      }

      if (type === 'object') {
        return _emberMetalProperty_get.get(object, this.key);
      }

      return object[this.key];
    },

    setValue: function (value) {
      var object = this.sourceDep.getValue();
      if (object) {
        _emberMetalProperty_set.set(object, this.key, value);
      }
    },

    setSource: function (source) {
      this.sourceDep.replace(source);
      this.notify();
    },

    _super$revalidate: _emberMetalStreamsStream.default.prototype.revalidate,

    revalidate: function (value) {
      this._super$revalidate(value);

      var object = this.sourceDep.getValue();
      if (object !== this.observedObject) {
        this._clearObservedObject();

        if (object && typeof object === 'object') {
          _emberMetalObserver.addObserver(object, this.key, this, this.notify);
          this.observedObject = object;
        }
      }
    },

    _super$deactivate: _emberMetalStreamsStream.default.prototype.deactivate,

    _clearObservedObject: function () {
      if (this.observedObject) {
        _emberMetalObserver.removeObserver(this.observedObject, this.key, this, this.notify);
        this.observedObject = null;
      }
    },

    deactivate: function () {
      this._super$deactivate();
      this._clearObservedObject();
    }
  });
});
enifed('ember-metal/streams/proxy-stream', ['exports', 'ember-runtime/system/object', 'ember-metal/streams/stream'], function (exports, _emberRuntimeSystemObject, _emberMetalStreamsStream) {
  'use strict';

  var ProxyStream = _emberMetalStreamsStream.default.extend({
    init: function (source, label) {
      this.label = label;
      this.sourceDep = this.addMutableDependency(source);
    },

    compute: function () {
      return this.sourceDep.getValue();
    },

    setValue: function (value) {
      this.sourceDep.setValue(value);
    },

    setSource: function (source) {
      var didChange = this.sourceDep.replace(source);
      if (didChange || !(source instanceof _emberRuntimeSystemObject.default)) {
        // If the source changed, we must notify. If the source is not
        // an Ember.Object, we must also notify, because it could have
        // interior mutability that is otherwise not being observed.
        this.notify();
      }
    }
  });

  ProxyStream.extend = _emberMetalStreamsStream.default.extend;

  exports.default = ProxyStream;
});
enifed('ember-metal/streams/stream', ['exports', 'ember-metal/assign', 'ember-metal/debug', 'ember-metal/path_cache', 'ember-metal/observer', 'ember-metal/streams/utils', 'ember-metal/empty_object', 'ember-metal/streams/subscriber', 'ember-metal/streams/dependency', 'ember-metal/utils', 'require', 'ember-metal/symbol'], function (exports, _emberMetalAssign, _emberMetalDebug, _emberMetalPath_cache, _emberMetalObserver, _emberMetalStreamsUtils, _emberMetalEmpty_object, _emberMetalStreamsSubscriber, _emberMetalStreamsDependency, _emberMetalUtils, _require, _emberMetalSymbol) {
  'use strict';

  exports.wrap = wrap;
  var IS_STREAM = _emberMetalSymbol.default('IS_STREAM');

  exports.IS_STREAM = IS_STREAM;
  /**
    @module ember-metal
  */

  /**
    @private
    @class Stream
    @namespace Ember.stream
    @constructor
  */
  function BasicStream(label) {
    this._init(label);
  }

  var KeyStream;
  var ProxyMixin;

  BasicStream.prototype = {
    _init: function (label) {
      this[IS_STREAM] = true;
      this.label = makeLabel(label);
      this.isActive = false;
      this.isDirty = true;
      this.isDestroyed = false;
      this.cache = undefined;
      this.children = undefined;
      this.subscriberHead = null;
      this.subscriberTail = null;
      this.dependencyHead = null;
      this.dependencyTail = null;
      this.observedProxy = null;
      this.__ember_meta__ = null;
      this[_emberMetalUtils.GUID_KEY] = null;
    },

    _makeChildStream: function (key) {
      KeyStream = KeyStream || _require.default('ember-metal/streams/key-stream').default;
      return new KeyStream(this, key);
    },

    removeChild: function (key) {
      delete this.children[key];
    },

    getKey: function (key) {
      if (this.children === undefined) {
        this.children = new _emberMetalEmpty_object.default();
      }

      var keyStream = this.children[key];

      if (keyStream === undefined) {
        keyStream = this._makeChildStream(key);
        this.children[key] = keyStream;
      }

      return keyStream;
    },

    get: function (path) {
      var firstKey = _emberMetalPath_cache.getFirstKey(path);
      var tailPath = _emberMetalPath_cache.getTailPath(path);

      if (this.children === undefined) {
        this.children = new _emberMetalEmpty_object.default();
      }

      var keyStream = this.children[firstKey];

      if (keyStream === undefined) {
        keyStream = this._makeChildStream(firstKey, path);
        this.children[firstKey] = keyStream;
      }

      if (tailPath === undefined) {
        return keyStream;
      } else {
        return keyStream.get(tailPath);
      }
    },

    value: function () {
      // TODO: Ensure value is never called on a destroyed stream
      // so that we can uncomment this assertion.
      //
      // assert("Stream error: value was called after the stream was destroyed", !this.isDestroyed);

      // TODO: Remove this block. This will require ensuring we are
      // not treating streams as "volatile" anywhere.
      if (!this.isActive) {
        this.isDirty = true;
      }

      var willRevalidate = false;

      if (!this.isActive && this.subscriberHead) {
        this.activate();
        willRevalidate = true;
      }

      if (this.isDirty) {
        if (this.isActive) {
          willRevalidate = true;
        }

        this.cache = this.compute();
        this.isDirty = false;
      }

      if (willRevalidate) {
        this.revalidate(this.cache);
      }

      return this.cache;
    },

    addMutableDependency: function (object) {
      var dependency = new _emberMetalStreamsDependency.default(this, object);

      if (this.isActive) {
        dependency.subscribe();
      }

      if (this.dependencyHead === null) {
        this.dependencyHead = this.dependencyTail = dependency;
      } else {
        var tail = this.dependencyTail;
        tail.next = dependency;
        dependency.prev = tail;
        this.dependencyTail = dependency;
      }

      return dependency;
    },

    addDependency: function (object) {
      if (_emberMetalStreamsUtils.isStream(object)) {
        this.addMutableDependency(object);
      }
    },

    subscribeDependencies: function () {
      var dependency = this.dependencyHead;
      while (dependency) {
        var next = dependency.next;
        dependency.subscribe();
        dependency = next;
      }
    },

    unsubscribeDependencies: function () {
      var dependency = this.dependencyHead;
      while (dependency) {
        var next = dependency.next;
        dependency.unsubscribe();
        dependency = next;
      }
    },

    maybeDeactivate: function () {
      if (!this.subscriberHead && this.isActive) {
        this.isActive = false;
        this.unsubscribeDependencies();
        this.deactivate();
      }
    },

    activate: function () {
      this.isActive = true;
      this.subscribeDependencies();
    },

    revalidate: function (value) {
      if (value !== this.observedProxy) {
        this._clearObservedProxy();

        ProxyMixin = ProxyMixin || _require.default('ember-runtime/mixins/-proxy').default;

        if (ProxyMixin.detect(value)) {
          _emberMetalObserver.addObserver(value, 'content', this, this.notify);
          this.observedProxy = value;
        }
      }
    },

    _clearObservedProxy: function () {
      if (this.observedProxy) {
        _emberMetalObserver.removeObserver(this.observedProxy, 'content', this, this.notify);
        this.observedProxy = null;
      }
    },

    deactivate: function () {
      this._clearObservedProxy();
    },

    compute: function () {
      throw new Error('Stream error: compute not implemented');
    },

    setValue: function () {
      throw new Error('Stream error: setValue not implemented');
    },

    notify: function () {
      this.notifyExcept();
    },

    notifyExcept: function (callbackToSkip, contextToSkip) {
      if (!this.isDirty) {
        this.isDirty = true;
        this.notifySubscribers(callbackToSkip, contextToSkip);
      }
    },

    subscribe: function (callback, context) {
      _emberMetalDebug.assert('You tried to subscribe to a stream but the callback provided was not a function.', typeof callback === 'function');

      var subscriber = new _emberMetalStreamsSubscriber.default(callback, context, this);
      if (this.subscriberHead === null) {
        this.subscriberHead = this.subscriberTail = subscriber;
      } else {
        var tail = this.subscriberTail;
        tail.next = subscriber;
        subscriber.prev = tail;
        this.subscriberTail = subscriber;
      }

      var stream = this;
      return function (prune) {
        subscriber.removeFrom(stream);
        if (prune) {
          stream.prune();
        }
      };
    },

    prune: function () {
      if (this.subscriberHead === null) {
        this.destroy(true);
      }
    },

    unsubscribe: function (callback, context) {
      var subscriber = this.subscriberHead;

      while (subscriber) {
        var next = subscriber.next;
        if (subscriber.callback === callback && subscriber.context === context) {
          subscriber.removeFrom(this);
        }
        subscriber = next;
      }
    },

    notifySubscribers: function (callbackToSkip, contextToSkip) {
      var subscriber = this.subscriberHead;

      while (subscriber) {
        var next = subscriber.next;

        var callback = subscriber.callback;
        var context = subscriber.context;

        subscriber = next;

        if (callback === callbackToSkip && context === contextToSkip) {
          continue;
        }

        if (context === undefined) {
          callback(this);
        } else {
          callback.call(context, this);
        }
      }
    },

    destroy: function (prune) {
      if (!this.isDestroyed) {
        this.isDestroyed = true;

        this.subscriberHead = this.subscriberTail = null;
        this.maybeDeactivate();

        var dependencies = this.dependencies;

        if (dependencies) {
          for (var i = 0, l = dependencies.length; i < l; i++) {
            dependencies[i](prune);
          }
        }

        return true;
      }
    }
  };

  BasicStream.extend = function (object) {
    var Child = function () {
      this._init();
      this.init.apply(this, arguments);

      _emberMetalDebug.debugSeal(this);
    };

    Child.prototype = Object.create(this.prototype);

    _emberMetalAssign.default(Child.prototype, object);
    Child.extend = BasicStream.extend;
    return Child;
  };

  var Stream = BasicStream.extend({
    init: function (fn, label) {
      this._compute = fn;
      this.label = label;
    },

    compute: function () {
      return this._compute();
    }
  });

  function wrap(value, Kind, param) {
    if (_emberMetalStreamsUtils.isStream(value)) {
      return value;
    } else {
      return new Kind(value, param);
    }
  }

  function makeLabel(label) {
    if (label === undefined) {
      return '(no label)';
    } else {
      return label;
    }
  }

  exports.default = BasicStream;
  exports.Stream = Stream;
});
enifed('ember-metal/streams/subscriber', ['exports', 'ember-metal/assign'], function (exports, _emberMetalAssign) {
  'use strict';

  /**
    @module ember-metal
  */

  /**
    @private
    @class Subscriber
    @namespace Ember.streams
    @constructor
  */
  function Subscriber(callback, context) {
    this.next = null;
    this.prev = null;
    this.callback = callback;
    this.context = context;
  }

  _emberMetalAssign.default(Subscriber.prototype, {
    removeFrom: function (stream) {
      var next = this.next;
      var prev = this.prev;

      if (prev) {
        prev.next = next;
      } else {
        stream.subscriberHead = next;
      }

      if (next) {
        next.prev = prev;
      } else {
        stream.subscriberTail = prev;
      }

      stream.maybeDeactivate();
    }
  });

  exports.default = Subscriber;
});
enifed('ember-metal/streams/utils', ['exports', 'ember-metal/debug', 'ember-metal/streams/stream'], function (exports, _emberMetalDebug, _emberMetalStreamsStream) {
  'use strict';

  exports.isStream = isStream;
  exports.subscribe = subscribe;
  exports.unsubscribe = unsubscribe;
  exports.read = read;
  exports.readArray = readArray;
  exports.readHash = readHash;
  exports.scanArray = scanArray;
  exports.scanHash = scanHash;
  exports.concat = concat;
  exports.labelsFor = labelsFor;
  exports.labelsForObject = labelsForObject;
  exports.labelFor = labelFor;
  exports.or = or;
  exports.addDependency = addDependency;
  exports.zip = zip;
  exports.zipHash = zipHash;
  exports.chain = chain;
  exports.setValue = setValue;

  /*
   Check whether an object is a stream or not.

   @private
   @for Ember.stream
   @function isStream
   @param {Object|Stream} object Object to check whether it is a stream.
   @return {Boolean} `true` if the object is a stream, `false` otherwise.
  */

  function isStream(object) {
    return object && object[_emberMetalStreamsStream.IS_STREAM];
  }

  /*
   A method of subscribing to a stream which is safe for use with a non-stream
   object. If a non-stream object is passed, the function does nothing.

   @public
   @for Ember.stream
   @function subscribe
   @param {Object|Stream} object Object or stream to potentially subscribe to.
   @param {Function} callback Function to run when stream value changes.
   @param {Object} [context] the callback will be executed with this context if it
                             is provided.
   */

  function subscribe(object, callback, context) {
    if (object && object[_emberMetalStreamsStream.IS_STREAM]) {
      return object.subscribe(callback, context);
    }
  }

  /*
   A method of unsubscribing from a stream which is safe for use with a non-stream
   object. If a non-stream object is passed, the function does nothing.

   @private
   @for Ember.stream
   @function unsubscribe
   @param {Object|Stream} object Object or stream to potentially unsubscribe from.
   @param {Function} callback Function originally passed to `subscribe()`.
   @param {Object} [context] Object originally passed to `subscribe()`.
   */

  function unsubscribe(object, callback, context) {
    if (object && object[_emberMetalStreamsStream.IS_STREAM]) {
      object.unsubscribe(callback, context);
    }
  }

  /*
   Retrieve the value of a stream, or in the case where a non-stream object is passed,
   return the object itself.

   @private
   @for Ember.stream
   @function read
   @param {Object|Stream} object Object to return the value of.
   @return The stream's current value, or the non-stream object itself.
   */

  function read(object) {
    if (object && object[_emberMetalStreamsStream.IS_STREAM]) {
      return object.value();
    } else {
      return object;
    }
  }

  /*
   Map an array, replacing any streams with their values.

   @private
   @for Ember.stream
   @function readArray
   @param {Array} array The array to read values from
   @return {Array} A new array of the same length with the values of non-stream
                   objects mapped from their original positions untouched, and
                   the values of stream objects retaining their original position
                   and replaced with the stream's current value.
   */

  function readArray(array) {
    var length = array.length;
    var ret = new Array(length);
    for (var i = 0; i < length; i++) {
      ret[i] = read(array[i]);
    }
    return ret;
  }

  /*
   Map a hash, replacing any stream property values with the current value of that
   stream.

   @private
   @for Ember.stream
   @function readHash
   @param {Object} object The hash to read keys and values from.
   @return {Object} A new object with the same keys as the passed object. The
                    property values in the new object are the original values in
                    the case of non-stream objects, and the streams' current
                    values in the case of stream objects.
   */

  function readHash(object) {
    var ret = {};
    for (var key in object) {
      ret[key] = read(object[key]);
    }
    return ret;
  }

  /*
   Check whether an array contains any stream values.

   @private
   @for Ember.stream
   @function scanArray
   @param {Array} array Array given to a handlebars helper.
   @return {Boolean} `true` if the array contains a stream/bound value, `false`
                     otherwise.
  */

  function scanArray(array) {
    var length = array.length;
    var containsStream = false;

    for (var i = 0; i < length; i++) {
      if (isStream(array[i])) {
        containsStream = true;
        break;
      }
    }

    return containsStream;
  }

  /*
   Check whether a hash has any stream property values.

   @private
   @for Ember.stream
   @function scanHash
   @param {Object} hash "hash" argument given to a handlebars helper.
   @return {Boolean} `true` if the object contains a stream/bound value, `false`
                     otherwise.
   */

  function scanHash(hash) {
    var containsStream = false;

    for (var prop in hash) {
      if (isStream(hash[prop])) {
        containsStream = true;
        break;
      }
    }

    return containsStream;
  }

  var ConcatStream = _emberMetalStreamsStream.default.extend({
    init: function (array, separator) {
      this.array = array;
      this.separator = separator;

      // Used by angle bracket components to detect an attribute was provided
      // as a string literal.
      this.isConcat = true;
    },

    label: function () {
      var labels = labelsFor(this.array);
      return 'concat([' + labels.join(', ') + ']; separator=' + inspect(this.separator) + ')';
    },

    compute: function () {
      return concat(readArray(this.array), this.separator);
    }
  });

  /*
   Join an array, with any streams replaced by their current values.

   @private
   @for Ember.stream
   @function concat
   @param {Array} array An array containing zero or more stream objects and
                        zero or more non-stream objects.
   @param {String} separator String to be used to join array elements.
   @return {String} String with array elements concatenated and joined by the
                    provided separator, and any stream array members having been
                    replaced by the current value of the stream.
   */

  function concat(array, separator) {
    // TODO: Create subclass ConcatStream < Stream. Defer
    // subscribing to streams until the value() is called.
    var hasStream = scanArray(array);
    if (hasStream) {
      var stream = new ConcatStream(array, separator);

      for (var i = 0, l = array.length; i < l; i++) {
        addDependency(stream, array[i]);
      }

      return stream;
    } else {
      return array.join(separator);
    }
  }

  function labelsFor(streams) {
    var labels = [];

    for (var i = 0, l = streams.length; i < l; i++) {
      var stream = streams[i];
      labels.push(labelFor(stream));
    }

    return labels;
  }

  function labelsForObject(streams) {
    var labels = [];

    for (var prop in streams) {
      labels.push(prop + ': ' + inspect(streams[prop]));
    }

    return labels.length ? '{ ' + labels.join(', ') + ' }' : '{}';
  }

  function labelFor(maybeStream) {
    if (isStream(maybeStream)) {
      var stream = maybeStream;
      return typeof stream.label === 'function' ? stream.label() : stream.label;
    } else {
      return inspect(maybeStream);
    }
  }

  function inspect(value) {
    switch (typeof value) {
      case 'string':
        return '"' + value + '"';
      case 'object':
        return '{ ... }';
      case 'function':
        return 'function() { ... }';
      default:
        return String(value);
    }
  }

  function or(first, second) {
    var stream = new _emberMetalStreamsStream.Stream(function () {
      return first.value() || second.value();
    }, function () {
      return labelFor(first) + ' || ' + labelFor(second);
    });

    stream.addDependency(first);
    stream.addDependency(second);

    return stream;
  }

  function addDependency(stream, dependency) {
    _emberMetalDebug.assert('Cannot add a stream as a dependency to a non-stream', isStream(stream) || !isStream(dependency));
    if (isStream(stream)) {
      stream.addDependency(dependency);
    }
  }

  function zip(streams, callback, label) {
    _emberMetalDebug.assert('Must call zip with a label', !!label);

    var stream = new _emberMetalStreamsStream.Stream(function () {
      var array = readArray(streams);
      return callback ? callback(array) : array;
    }, function () {
      return label + '(' + labelsFor(streams) + ')';
    });

    for (var i = 0, l = streams.length; i < l; i++) {
      stream.addDependency(streams[i]);
    }

    return stream;
  }

  function zipHash(object, callback, label) {
    _emberMetalDebug.assert('Must call zipHash with a label', !!label);

    var stream = new _emberMetalStreamsStream.Stream(function () {
      var hash = readHash(object);
      return callback ? callback(hash) : hash;
    }, function () {
      return label + '(' + labelsForObject(object) + ')';
    });

    for (var prop in object) {
      stream.addDependency(object[prop]);
    }

    return stream;
  }

  /**
   Generate a new stream by providing a source stream and a function that can
   be used to transform the stream's value. In the case of a non-stream object,
   returns the result of the function.

   The value to transform would typically be available to the function you pass
   to `chain()` via scope. For example:

   ```javascript
       var source = ...;  // stream returning a number
                              // or a numeric (non-stream) object
       var result = chain(source, function() {
         var currentValue = read(source);
         return currentValue + 1;
       });
   ```

   In the example, result is a stream if source is a stream, or a number of
   source was numeric.

   @private
   @for Ember.stream
   @function chain
   @param {Object|Stream} value A stream or non-stream object.
   @param {Function} fn Function to be run when the stream value changes, or to
                        be run once in the case of a non-stream object.
   @return {Object|Stream} In the case of a stream `value` parameter, a new
                           stream that will be updated with the return value of
                           the provided function `fn`. In the case of a
                           non-stream object, the return value of the provided
                           function `fn`.
   */

  function chain(value, fn, label) {
    _emberMetalDebug.assert('Must call chain with a label', !!label);
    if (isStream(value)) {
      var stream = new _emberMetalStreamsStream.Stream(fn, function () {
        return label + '(' + labelFor(value) + ')';
      });
      stream.addDependency(value);
      return stream;
    } else {
      return fn();
    }
  }

  function setValue(object, value) {
    if (object && object[_emberMetalStreamsStream.IS_STREAM]) {
      object.setValue(value);
    }
  }
});
enifed('ember-metal/symbol', ['exports', 'ember-metal/utils'], function (exports, _emberMetalUtils) {
  'use strict';

  exports.default = symbol;

  function symbol(debugName) {
    // TODO: Investigate using platform symbols, but we do not
    // want to require non-enumerability for this API, which
    // would introduce a large cost.

    return _emberMetalUtils.intern(debugName + ' [id=' + _emberMetalUtils.GUID_KEY + Math.floor(Math.random() * new Date()) + ']');
  }
});
enifed('ember-metal/tags', ['exports', 'ember-metal/meta', 'require'], function (exports, _emberMetalMeta, _require2) {
  'use strict';

  exports.tagFor = tagFor;

  var hasGlimmer = _require2.has('glimmer-reference');
  var CONSTANT_TAG = undefined,
      CURRENT_TAG = undefined,
      DirtyableTag = undefined,
      makeTag = undefined;

  var markObjectAsDirty = undefined;

  exports.markObjectAsDirty = markObjectAsDirty;

  function tagFor(object, _meta) {
    if (!hasGlimmer) {
      throw new Error('Cannot call tagFor without Glimmer');
    }

    if (object && typeof object === 'object') {
      var meta = _meta || _emberMetalMeta.meta(object);
      return meta.writableTag(makeTag);
    } else {
      return CONSTANT_TAG;
    }
  }

  if (hasGlimmer) {
    var _require = _require2.default('glimmer-reference');

    DirtyableTag = _require.DirtyableTag;
    CONSTANT_TAG = _require.CONSTANT_TAG;
    CURRENT_TAG = _require.CURRENT_TAG;

    makeTag = function () {
      return new DirtyableTag();
    };

    exports.markObjectAsDirty = markObjectAsDirty = function (meta) {
      var tag = meta && meta.readableTag() || CURRENT_TAG;
      tag.dirty();
    };
  } else {
    exports.markObjectAsDirty = markObjectAsDirty = function () {};
  }
});
enifed('ember-metal/utils', ['exports'], function (exports) {
  'no use strict';
  // Remove "use strict"; from transpiled module until
  // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed

  /**
  @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
  */
  exports.uuid = uuid;
  exports.intern = intern;
  exports.generateGuid = generateGuid;
  exports.guidFor = guidFor;
  exports.wrap = wrap;
  exports.tryInvoke = tryInvoke;
  exports.makeArray = makeArray;
  exports.inspect = inspect;
  exports.applyStr = applyStr;
  exports.lookupDescriptor = lookupDescriptor;
  exports.toString = toString;
  var _uuid = 0;

  /**
    Generates a universally unique identifier. This method
    is used internally by Ember for assisting with
    the generation of GUID's and other unique identifiers.

    @public
    @return {Number} [description]
   */

  function uuid() {
    return ++_uuid;
  }

  /**
    Prefix used for guids through out Ember.
    @private
    @property GUID_PREFIX
    @for Ember
    @type String
    @final
  */
  var GUID_PREFIX = 'ember';

  // Used for guid generation...
  var numberCache = [];
  var stringCache = {};

  /**
    Strongly hint runtimes to intern the provided string.

    When do I need to use this function?

    For the most part, never. Pre-mature optimization is bad, and often the
    runtime does exactly what you need it to, and more often the trade-off isn't
    worth it.

    Why?

    Runtimes store strings in at least 2 different representations:
    Ropes and Symbols (interned strings). The Rope provides a memory efficient
    data-structure for strings created from concatenation or some other string
    manipulation like splitting.

    Unfortunately checking equality of different ropes can be quite costly as
    runtimes must resort to clever string comparison algorithms. These
    algorithms typically cost in proportion to the length of the string.
    Luckily, this is where the Symbols (interned strings) shine. As Symbols are
    unique by their string content, equality checks can be done by pointer
    comparison.

    How do I know if my string is a rope or symbol?

    Typically (warning general sweeping statement, but truthy in runtimes at
    present) static strings created as part of the JS source are interned.
    Strings often used for comparisons can be interned at runtime if some
    criteria are met.  One of these criteria can be the size of the entire rope.
    For example, in chrome 38 a rope longer then 12 characters will not
    intern, nor will segments of that rope.

    Some numbers: http://jsperf.com/eval-vs-keys/8

    Known Trick™

    @private
    @return {String} interned version of the provided string
  */

  function intern(str) {
    var obj = {};
    obj[str] = 1;
    for (var key in obj) {
      if (key === str) {
        return key;
      }
    }
    return str;
  }

  /**
    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 = intern('__ember' + +new Date());

  var GUID_DESC = {
    writable: true,
    configurable: true,
    enumerable: false,
    value: null
  };

  exports.GUID_DESC = GUID_DESC;
  var nullDescriptor = {
    configurable: true,
    writable: true,
    enumerable: false,
    value: null
  };

  var GUID_KEY_PROPERTY = {
    name: GUID_KEY,
    descriptor: nullDescriptor
  };

  exports.GUID_KEY_PROPERTY = GUID_KEY_PROPERTY;
  /**
    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;
        if (obj.__defineNonEnumerable) {
          obj.__defineNonEnumerable(GUID_KEY_PROPERTY);
        } else {
          Object.defineProperty(obj, GUID_KEY, GUID_DESC);
        }
      }
    }
    return ret;
  }

  /**
    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.

    @public
    @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) {
    if (obj && obj[GUID_KEY]) {
      return obj[GUID_KEY];
    }

    // 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 === Object) {
          return '(Object)';
        }

        if (obj === Array) {
          return '(Array)';
        }

        ret = GUID_PREFIX + uuid();

        if (obj[GUID_KEY] === null) {
          obj[GUID_KEY] = ret;
        } else {
          GUID_DESC.value = ret;

          if (obj.__defineNonEnumerable) {
            obj.__defineNonEnumerable(GUID_KEY_PROPERTY);
          } else {
            Object.defineProperty(obj, GUID_KEY, GUID_DESC);
          }
        }
        return ret;
    }
  }

  var HAS_SUPER_PATTERN = /\.(_super|call\(this|apply\(this)/;
  var fnToString = Function.prototype.toString;

  var checkHasSuper = (function () {
    var sourceAvailable = fnToString.call(function () {
      return this;
    }).indexOf('return this') > -1;

    if (sourceAvailable) {
      return function checkHasSuper(func) {
        return HAS_SUPER_PATTERN.test(fnToString.call(func));
      };
    }

    return function checkHasSuper() {
      return true;
    };
  })();

  exports.checkHasSuper = checkHasSuper;
  function ROOT() {}
  ROOT.__hasSuper = false;

  function hasSuper(func) {
    if (func.__hasSuper === undefined) {
      func.__hasSuper = checkHasSuper(func);
    }
    return func.__hasSuper;
  }

  /**
    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) {
    if (!hasSuper(func)) {
      return func;
    }
    // ensure an unwrapped super that calls _super is wrapped with a terminal _super
    if (!superFunc.wrappedFunction && hasSuper(superFunc)) {
      return _wrap(func, _wrap(superFunc, ROOT));
    }
    return _wrap(func, superFunc);
  }

  function _wrap(func, superFunc) {
    function superWrapper() {
      var orig = this._super;
      this._super = superFunc;
      var ret = func.apply(this, arguments);
      this._super = orig;
      return ret;
    }

    superWrapper.wrappedFunction = func;
    superWrapper.__ember_observes__ = func.__ember_observes__;
    superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__;
    superWrapper.__ember_listens__ = func.__ember_listens__;

    return superWrapper;
  }

  /**
    Checks to see if the `methodName` exists on the `obj`.

    ```javascript
    var foo = { bar: function() { return 'bar'; }, 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}
    @private
  */
  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
    @public
  */

  function tryInvoke(obj, methodName, args) {
    if (canInvoke(obj, methodName)) {
      return args ? applyStr(obj, methodName, args) : applyStr(obj, methodName);
    }
  }

  // ........................................
  // TYPING & ARRAY MESSAGING
  //

  var objectToString = Object.prototype.toString;

  /**
    Forces the passed object to be part of an array. If the object is already
    an array, it will return the object. Otherwise, it will add the object to
    an array. If obj is `null` or `undefined`, it will return 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}
    @private
  */

  function makeArray(obj) {
    if (obj === null || obj === undefined) {
      return [];
    }
    return Array.isArray(obj) ? obj : [obj];
  }

  /**
    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
    @private
  */

  function inspect(obj) {
    if (obj === null) {
      return 'null';
    }
    if (obj === undefined) {
      return 'undefined';
    }
    if (Array.isArray(obj)) {
      return '[' + obj + ']';
    }
    // for non objects
    var type = typeof obj;
    if (type !== 'object' && type !== 'symbol') {
      return '' + obj;
    }
    // overridden toString
    if (typeof obj.toString === 'function' && obj.toString !== objectToString) {
      return obj.toString();
    }

    // Object.prototype.toString === {}.toString
    var v;
    var 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() { ... }';
        }

        if (v && typeof v.toString !== 'function') {
          ret.push(key + ': ' + objectToString.call(v));
        } else {
          ret.push(key + ': ' + v);
        }
      }
    }
    return '{' + ret.join(', ') + '}';
  }

  /**
    @param {Object} t target
    @param {String} m method
    @param {Array} a args
    @private
  */

  function applyStr(t, m, a) {
    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);
    }
  }

  function lookupDescriptor(obj, keyName) {
    var current = obj;
    while (current) {
      var descriptor = Object.getOwnPropertyDescriptor(current, keyName);

      if (descriptor) {
        return descriptor;
      }

      current = Object.getPrototypeOf(current);
    }

    return null;
  }

  // A `toString` util function that supports objects without a `toString`
  // method, e.g. an object created with `Object.create(null)`.

  function toString(obj) {
    if (obj && obj.toString) {
      return obj.toString();
    } else {
      return objectToString.call(obj);
    }
  }

  exports.GUID_KEY = GUID_KEY;
  exports.makeArray = makeArray;
  exports.canInvoke = canInvoke;
});
enifed('ember-metal/watch_key', ['exports', 'ember-metal/features', 'ember-metal/meta', 'ember-metal/properties', 'ember-metal/utils'], function (exports, _emberMetalFeatures, _emberMetalMeta, _emberMetalProperties, _emberMetalUtils) {
  'use strict';

  exports.watchKey = watchKey;
  exports.unwatchKey = unwatchKey;

  var handleMandatorySetter = undefined;

  function watchKey(obj, keyName, meta) {
    // can't watch length on Array - it is special...
    if (keyName === 'length' && Array.isArray(obj)) {
      return;
    }

    var m = meta || _emberMetalMeta.meta(obj);

    // activate watching first time
    if (!m.peekWatching(keyName)) {
      m.writeWatching(keyName, 1);

      var possibleDesc = obj[keyName];
      var desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;
      if (desc && desc.willWatch) {
        desc.willWatch(obj, keyName);
      }

      if ('function' === typeof obj.willWatchProperty) {
        obj.willWatchProperty(keyName);
      }

      // NOTE: this is dropped for prod + minified builds
      handleMandatorySetter(m, obj, keyName);
    } else {
      m.writeWatching(keyName, (m.peekWatching(keyName) || 0) + 1);
    }
  }

  // Future traveler, although this code looks scary. It merely exists in
  // development to aid in development asertions. Production builds of
  // ember strip this entire block out
  handleMandatorySetter = function handleMandatorySetter(m, obj, keyName) {
    var descriptor = _emberMetalUtils.lookupDescriptor(obj, keyName);
    var configurable = descriptor ? descriptor.configurable : true;
    var isWritable = descriptor ? descriptor.writable : true;
    var hasValue = descriptor ? 'value' in descriptor : true;
    var possibleDesc = descriptor && descriptor.value;
    var isDescriptor = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor;

    if (isDescriptor) {
      return;
    }

    // this x in Y deopts, so keeping it in this function is better;
    if (configurable && isWritable && hasValue && keyName in obj) {
      var desc = {
        configurable: true,
        enumerable: Object.prototype.propertyIsEnumerable.call(obj, keyName),
        set: _emberMetalProperties.MANDATORY_SETTER_FUNCTION(keyName),
        get: undefined
      };

      if (Object.prototype.hasOwnProperty.call(obj, keyName)) {
        m.writeValues(keyName, obj[keyName]);
        desc.get = _emberMetalProperties.DEFAULT_GETTER_FUNCTION(keyName);
      } else {
        desc.get = _emberMetalProperties.INHERITING_GETTER_FUNCTION(keyName);
      }

      Object.defineProperty(obj, keyName, desc);
    }
  };

  function unwatchKey(obj, keyName, meta) {
    var m = meta || _emberMetalMeta.meta(obj);
    var count = m.peekWatching(keyName);
    if (count === 1) {
      m.writeWatching(keyName, 0);

      var possibleDesc = obj[keyName];
      var desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;

      if (desc && desc.didUnwatch) {
        desc.didUnwatch(obj, keyName);
      }

      if ('function' === typeof obj.didUnwatchProperty) {
        obj.didUnwatchProperty(keyName);
      }

      // It is true, the following code looks quite WAT. But have no fear, It
      // exists purely to improve development ergonomics and is removed from
      // ember.min.js and ember.prod.js builds.
      //
      // Some further context: Once a property is watched by ember, bypassing `set`
      // for mutation, will bypass observation. This code exists to assert when
      // that occurs, and attempt to provide more helpful feedback. The alternative
      // is tricky to debug partially observable properties.
      if (!desc && keyName in obj) {
        var maybeMandatoryDescriptor = _emberMetalUtils.lookupDescriptor(obj, keyName);

        if (maybeMandatoryDescriptor.set && maybeMandatoryDescriptor.set.isMandatorySetter) {
          if (maybeMandatoryDescriptor.get && maybeMandatoryDescriptor.get.isInheritingGetter) {
            delete obj[keyName];
          } else {
            Object.defineProperty(obj, keyName, {
              configurable: true,
              enumerable: Object.prototype.propertyIsEnumerable.call(obj, keyName),
              writable: true,
              value: m.peekValues(keyName)
            });
            m.deleteFromValues(keyName);
          }
        }
      }
    } else if (count > 1) {
      m.writeWatching(keyName, count - 1);
    }
  }
});
enifed('ember-metal/watch_path', ['exports', 'ember-metal/meta', 'ember-metal/chains'], function (exports, _emberMetalMeta, _emberMetalChains) {
  'use strict';

  exports.watchPath = watchPath;
  exports.unwatchPath = unwatchPath;

  // 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) {
    return (meta || _emberMetalMeta.meta(obj)).writableChains(makeChainNode);
  }

  function makeChainNode(obj) {
    return new _emberMetalChains.ChainNode(null, null, obj);
  }

  function watchPath(obj, keyPath, meta) {
    // can't watch length on Array - it is special...
    if (keyPath === 'length' && Array.isArray(obj)) {
      return;
    }

    var m = meta || _emberMetalMeta.meta(obj);
    var counter = m.peekWatching(keyPath) || 0;
    if (!counter) {
      // activate watching first time
      m.writeWatching(keyPath, 1);
      chainsFor(obj, m).add(keyPath);
    } else {
      m.writeWatching(keyPath, counter + 1);
    }
  }

  function unwatchPath(obj, keyPath, meta) {
    var m = meta || _emberMetalMeta.meta(obj);
    var counter = m.peekWatching(keyPath) || 0;

    if (counter === 1) {
      m.writeWatching(keyPath, 0);
      chainsFor(obj, m).remove(keyPath);
    } else if (counter > 1) {
      m.writeWatching(keyPath, counter - 1);
    }
  }
});
enifed('ember-metal/watching', ['exports', 'ember-metal/chains', 'ember-metal/watch_key', 'ember-metal/watch_path', 'ember-metal/path_cache', 'ember-metal/meta'], function (exports, _emberMetalChains, _emberMetalWatch_key, _emberMetalWatch_path, _emberMetalPath_cache, _emberMetalMeta) {
  /**
  @module ember-metal
  */

  'use strict';

  exports.isWatching = isWatching;
  exports.watcherCount = watcherCount;
  exports.unwatch = unwatch;
  exports.destroy = destroy;

  /**
    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} _keyPath
  */
  function watch(obj, _keyPath, m) {
    // can't watch length on Array - it is special...
    if (_keyPath === 'length' && Array.isArray(obj)) {
      return;
    }

    if (!_emberMetalPath_cache.isPath(_keyPath)) {
      _emberMetalWatch_key.watchKey(obj, _keyPath, m);
    } else {
      _emberMetalWatch_path.watchPath(obj, _keyPath, m);
    }
  }

  exports.watch = watch;

  function isWatching(obj, key) {
    var meta = _emberMetalMeta.peekMeta(obj);
    return (meta && meta.peekWatching(key)) > 0;
  }

  function watcherCount(obj, key) {
    var meta = _emberMetalMeta.peekMeta(obj);
    return meta && meta.peekWatching(key) || 0;
  }

  function unwatch(obj, _keyPath, m) {
    // can't watch length on Array - it is special...
    if (_keyPath === 'length' && Array.isArray(obj)) {
      return;
    }

    if (!_emberMetalPath_cache.isPath(_keyPath)) {
      _emberMetalWatch_key.unwatchKey(obj, _keyPath, m);
    } else {
      _emberMetalWatch_path.unwatchPath(obj, _keyPath, m);
    }
  }

  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}
    @private
  */

  function destroy(obj) {
    var meta = _emberMetalMeta.peekMeta(obj);
    var node, nodes, key, nodeObject;

    if (meta) {
      _emberMetalMeta.deleteMeta(obj);
      // remove chainWatchers to remove circular references that would prevent GC
      node = meta.readableChains();
      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[key] !== undefined) {
                NODE_STACK.push(nodes[key]);
              }
            }
          }
          // remove chainWatcher in node object
          if (node._watching) {
            nodeObject = node._object;
            if (nodeObject) {
              _emberMetalChains.removeChainWatcher(nodeObject, node._key, node);
            }
          }
        }
      }
    }
  }
});
enifed('ember-metal/weak_map', ['exports', 'ember-metal/debug', 'ember-metal/utils', 'ember-metal/meta'], function (exports, _emberMetalDebug, _emberMetalUtils, _emberMetalMeta) {
  'use strict';

  exports.default = WeakMap;

  var id = 0;
  function UNDEFINED() {}

  /*
   * @private
   * @class Ember.WeakMap
   *
   * A partial polyfill for [WeakMap](http://www.ecma-international.org/ecma-262/6.0/#sec-weakmap-objects).
   *
   * There is a small but important caveat. This implementation assumes that the
   * weak map will live longer (in the sense of garbage collection) than all of its
   * keys, otherwise it is possible to leak the values stored in the weak map. In
   * practice, most use cases satisfy this limitation which is why it is included
   * in ember-metal.
   */

  function WeakMap() {
    _emberMetalDebug.assert('Invoking the WeakMap constructor with arguments is not supported at this time', arguments.length === 0);

    this._id = _emberMetalUtils.GUID_KEY + id++;
  }

  /*
   * @method get
   * @param key {Object | Function}
   * @return {Any} stored value
   */
  WeakMap.prototype.get = function (obj) {
    var meta = _emberMetalMeta.peekMeta(obj);
    if (meta) {
      var map = meta.readableWeak();
      if (map) {
        if (map[this._id] === UNDEFINED) {
          return undefined;
        }

        return map[this._id];
      }
    }
  };

  /*
   * @method set
   * @param key {Object | Function}
   * @param value {Any}
   * @return {WeakMap} the weak map
   */
  WeakMap.prototype.set = function (obj, value) {
    _emberMetalDebug.assert('Uncaught TypeError: Invalid value used as weak map key', obj && (typeof obj === 'object' || typeof obj === 'function'));

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

    _emberMetalMeta.meta(obj).writableWeak()[this._id] = value;

    return this;
  };

  /*
   * @method has
   * @param key {Object | Function}
   * @return {boolean} if the key exists
   */
  WeakMap.prototype.has = function (obj) {
    var meta = _emberMetalMeta.peekMeta(obj);
    if (meta) {
      var map = meta.readableWeak();
      if (map) {
        return map[this._id] !== undefined;
      }
    }

    return false;
  };

  /*
   * @method delete
   * @param key {Object | Function}
   * @return {boolean} if the key was deleted
   */
  WeakMap.prototype.delete = function (obj) {
    if (this.has(obj)) {
      delete _emberMetalMeta.meta(obj).writableWeak()[this._id];
      return true;
    } else {
      return false;
    }
  };
});
enifed('ember-routing-htmlbars/helpers/query-params', ['exports', 'ember-metal/debug', 'ember-routing/system/query_params'], function (exports, _emberMetalDebug, _emberRoutingSystemQuery_params) {
  /**
  @module ember
  @submodule ember-routing-htmlbars
  */

  'use strict';

  exports.queryParamsHelper = queryParamsHelper;

  /**
    This is a helper to be used in conjunction with the link-to helper.
    It will supply url query parameters to the target route.

    Example

    ```handlebars
    {{#link-to 'posts' (query-params direction="asc")}}Sort{{/link-to}}
    ```

    @method query-params
    @for Ember.Templates.helpers
    @param {Object} hash takes a hash of query parameters
    @return {Object} A `QueryParams` object for `{{link-to}}`
    @public
  */

  function queryParamsHelper(params, hash) {
    _emberMetalDebug.assert('The `query-params` helper only accepts hash parameters, e.g. (query-params queryParamPropertyName=\'foo\') as opposed to just (query-params \'foo\')', params.length === 0);

    return _emberRoutingSystemQuery_params.default.create({
      values: hash
    });
  }
});
enifed('ember-routing-htmlbars/index', ['exports', 'ember-metal/core', 'ember-htmlbars/helpers', 'ember-htmlbars/keywords', 'ember-routing-htmlbars/helpers/query-params', 'ember-routing-htmlbars/keywords/action', 'ember-routing-htmlbars/keywords/element-action', 'ember-routing-htmlbars/keywords/render'], function (exports, _emberMetalCore, _emberHtmlbarsHelpers, _emberHtmlbarsKeywords, _emberRoutingHtmlbarsHelpersQueryParams, _emberRoutingHtmlbarsKeywordsAction, _emberRoutingHtmlbarsKeywordsElementAction, _emberRoutingHtmlbarsKeywordsRender) {
  /**
  @module ember
  @submodule ember-routing-htmlbars
  */

  'use strict';

  _emberHtmlbarsHelpers.registerHelper('query-params', _emberRoutingHtmlbarsHelpersQueryParams.queryParamsHelper);

  _emberHtmlbarsKeywords.registerKeyword('action', _emberRoutingHtmlbarsKeywordsAction.default);
  _emberHtmlbarsKeywords.registerKeyword('@element_action', _emberRoutingHtmlbarsKeywordsElementAction.default);
  _emberHtmlbarsKeywords.registerKeyword('render', _emberRoutingHtmlbarsKeywordsRender.default);

  exports.default = _emberMetalCore.default;
});
enifed('ember-routing-htmlbars/keywords/action', ['exports', 'htmlbars-runtime/hooks', 'ember-routing-htmlbars/keywords/closure-action'], function (exports, _htmlbarsRuntimeHooks, _emberRoutingHtmlbarsKeywordsClosureAction) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  /**
    The `{{action}}` helper provides a way to pass triggers for behavior (usually
    just a function) between components, and into components from controllers.

    ### Passing functions with the action helper

    There are three contexts an action helper can be used in. The first two
    contexts to discuss are attribute context, and Handlebars value context.

    ```handlebars
    {{! An example of attribute context }}
    <div onclick={{action "save"}}></div>
    {{! Examples of Handlebars value context }}
    {{input on-input=(action "save")}}
    {{yield (action "refreshData") andAnotherParam}}
    ```

    In these contexts,
    the helper is called a "closure action" helper. Its behavior is simple:
    If passed a function name, read that function off the `actions` property
    of the current context. Once that function is read (or if a function was
    passed), create a closure over that function and any arguments.

    The resulting value of an action helper used this way is simply a function.
    For example, in the attribute context:

    ```handlebars
    {{! An example of attribute context }}
    <div onclick={{action "save"}}></div>
    ```

    The resulting template render logic would be:

    ```js
    var div = document.createElement('div');
    var actionFunction = (function(context){
      return function() {
        return context.actions.save.apply(context, arguments);
      };
    })(context);
    div.onclick = actionFunction;
    ```

    Thus when the div is clicked, the action on that context is called.
    Because the `actionFunction` is just a function, closure actions can be
    passed between components and still execute in the correct context.

    Here is an example action handler on a component:

    ```js
    export default Ember.Component.extend({
      actions: {
        save() {
          this.get('model').save();
        }
      }
    });
    ```

    Actions are always looked up on the `actions` property of the current context.
    This avoids collisions in the naming of common actions, such as `destroy`.

    Two options can be passed to the `action` helper when it is used in this way.

    * `target=someProperty` will look to `someProperty` instead of the current
      context for the `actions` hash. This can be useful when targetting a
      service for actions.
    * `value="target.value"` will read the path `target.value` off the first
      argument to the action when it is called and rewrite the first argument
      to be that value. This is useful when attaching actions to event listeners.

    ### Invoking an action

    Closure actions curry both their scope and any arguments. When invoked, any
    additional arguments are added to the already curried list.

    Actions should be invoked using the [sendAction](/api/classes/Ember.Component.html#method_sendAction)
    method. The first argument to `sendAction` is the action to be called, and
    additional arguments are passed to the action function. This has interesting
    properties combined with currying of arguments. For example:

    ```js
    export default Ember.Component.extend({
      actions: {
        // Usage {{input on-input=(action (action 'setName' model) value="target.value")}}
        setName(model, name) {
          model.set('name', name);
        }
      }
    });
    ```

    The first argument (`model`) was curried over, and the run-time argument (`event`)
    becomes a second argument. Action calls can be nested this way because each simply
    returns a function. Any function can be passed to the `{{action}}` helper, including
    other actions.

    Actions invoked with `sendAction` have the same currying behavior as demonstrated
    with `on-input` above. For example:

    ```js
    export default Ember.Component.extend({
      actions: {
        setName(model, name) {
          model.set('name', name);
        }
      }
    });
    ```

    ```handlebars
    {{my-input submit=(action 'setName' model)}}
    ```

    ```js
    // app/components/my-component.js
    export default Ember.Component.extend({
      click() {
        // Note that model is not passed, it was curried in the template
        this.sendAction('submit', 'bob');
      }
    });
    ```

    ### Attaching actions to DOM elements

    The third context of the `{{action}}` helper can be called "element space".
    For example:

    ```handlebars
    {{! An example of element space }}
    <div {{action "save"}}></div>
    ```

    Used this way, the `{{action}}` helper provides a useful shortcut for
    registering an HTML element in a template for a single DOM event and
    forwarding that interaction to the template's context (controller or component).

    If the context of a template is a controller, actions used this way will
    bubble to routes when the controller does not implement the specified action.
    Once an action hits a route, it will bubble through the route hierarchy.

    ### Event Propagation

    `{{action}}` helpers called in element space can control event bubbling. Note
    that the closure style actions cannot.

    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>
    ```

    To disable bubbling with closure style actions you must create your own
    wrapper helper that makes use of `event.stopPropagation()`:

    ```handlebars
    <div onclick={{disable-bubbling (action "sayHello")}}>Hello</div>
    ```

    ```js
    // app/helpers/disable-bubbling.js
    import Ember from 'ember';

    export function disableBubbling([action]) {
      return function(event) {
        event.stopPropagation();

        return action(event);
      };
    }

    export default Ember.Helper.helper(disableBubbling);
    ```

    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
    ["Responding to Browser Events"](/api/classes/Ember.View.html#toc_responding-to-browser-events)
    in the documentation for Ember.View for more information.

    ### Specifying DOM event type

    `{{action}}` helpers called in element space can specify an 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 ["Event Names"](/api/classes/Ember.View.html#toc_event-names) for a list of
    acceptable DOM event names.

    ### Specifying whitelisted modifier keys

    `{{action}}` helpers called in element space can specify modifier keys.

    By default the `{{action}}` helper will ignore click events 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

    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
    {{! app/templates/application.hbs }}
    <div {{action "anActionName" target=someService}}>
      click me
    </div>
    ```

    ```javascript
    // app/controllers/application.js
    export default Ember.Controller.extend({
      someService: Ember.inject.service()
    });
    ```

    @method action
    @for Ember.Templates.helpers
    @public
  */

  exports.default = function (morph, env, scope, params, hash, template, inverse, visitor) {
    if (morph) {
      _htmlbarsRuntimeHooks.keyword('@element_action', morph, env, scope, params, hash, template, inverse, visitor);
      return true;
    }

    return _emberRoutingHtmlbarsKeywordsClosureAction.default(morph, env, scope, params, hash, template, inverse, visitor);
  };
});
enifed('ember-routing-htmlbars/keywords/closure-action', ['exports', 'ember-metal/streams/stream', 'ember-metal/streams/utils', 'ember-metal/symbol', 'ember-metal/property_get', 'ember-htmlbars/hooks/subexpr', 'ember-metal/error', 'ember-metal/run_loop', 'ember-metal/instrumentation', 'ember-metal/is_none'], function (exports, _emberMetalStreamsStream, _emberMetalStreamsUtils, _emberMetalSymbol, _emberMetalProperty_get, _emberHtmlbarsHooksSubexpr, _emberMetalError, _emberMetalRun_loop, _emberMetalInstrumentation, _emberMetalIs_none) {
  'use strict';

  exports.default = closureAction;
  var INVOKE = _emberMetalSymbol.default('INVOKE');
  exports.INVOKE = INVOKE;
  var ACTION = _emberMetalSymbol.default('ACTION');

  exports.ACTION = ACTION;

  function closureAction(morph, env, scope, params, hash, template, inverse, visitor) {
    var s = new _emberMetalStreamsStream.Stream(function () {
      var rawAction = params[0];
      var actionArguments = _emberMetalStreamsUtils.readArray(params.slice(1, params.length));

      var target = undefined,
          action = undefined,
          valuePath = undefined;

      if (_emberMetalIs_none.default(rawAction)) {
        var label = _emberHtmlbarsHooksSubexpr.labelForSubexpr(params, hash, 'action');
        throw new _emberMetalError.default('Action passed is null or undefined in ' + label + ' from ' + _emberMetalStreamsUtils.read(scope.getSelf()) + '.');
      } else if (rawAction[INVOKE]) {
        // on-change={{action (mut name)}}
        target = rawAction;
        action = rawAction[INVOKE];
      } else {
        // on-change={{action setName}}
        // element-space actions look to "controller" then target. Here we only
        // look to "target".
        target = _emberMetalStreamsUtils.read(scope.getSelf());
        action = _emberMetalStreamsUtils.read(rawAction);
        var actionType = typeof action;

        if (actionType === 'string') {
          var actionName = action;
          action = null;
          // on-change={{action 'setName'}}
          if (hash.target) {
            // on-change={{action 'setName' target=alternativeComponent}}
            target = _emberMetalStreamsUtils.read(hash.target);
          }
          if (target.actions) {
            action = target.actions[actionName];
          }

          if (!action) {
            throw new _emberMetalError.default('An action named \'' + actionName + '\' was not found in ' + target + '.');
          }
        } else if (action && typeof action[INVOKE] === 'function') {
          target = action;
          action = action[INVOKE];
        } else if (actionType !== 'function') {
          throw new _emberMetalError.default('An action could not be made for `' + rawAction.label + '` in ' + target + '. Please confirm that you are using either a quoted action name (i.e. `(action \'' + rawAction.label + '\')`) or a function available in ' + target + '.');
        }
      }

      if (hash.value) {
        // <button on-keypress={{action (mut name) value="which"}}
        // on-keypress is not even an Ember feature yet
        valuePath = _emberMetalStreamsUtils.read(hash.value);
      }

      return createClosureAction(this, target, action, valuePath, actionArguments);
    }, function () {
      return _emberHtmlbarsHooksSubexpr.labelForSubexpr(params, hash, 'action');
    });

    params.forEach(s.addDependency, s);
    Object.keys(hash).forEach(function (item) {
      return s.addDependency(item);
    });

    return s;
  }

  function createClosureAction(stream, target, action, valuePath, actionArguments) {
    var closureAction;

    if (actionArguments.length > 0) {
      closureAction = function () {
        var args = actionArguments;

        for (var _len = arguments.length, passedArguments = Array(_len), _key = 0; _key < _len; _key++) {
          passedArguments[_key] = arguments[_key];
        }

        if (passedArguments.length > 0) {
          args = actionArguments.concat(passedArguments);
        }
        if (valuePath && args.length > 0) {
          args[0] = _emberMetalProperty_get.get(args[0], valuePath);
        }

        var payload = { target: target, args: args, label: _emberMetalStreamsUtils.labelFor(stream) };
        return _emberMetalInstrumentation.flaggedInstrument('interaction.ember-action', payload, function () {
          return _emberMetalRun_loop.default.join.apply(_emberMetalRun_loop.default, [target, action].concat(args));
        });
      };
    } else {
      closureAction = function () {
        for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
          args[_key2] = arguments[_key2];
        }

        if (valuePath && args.length > 0) {
          args[0] = _emberMetalProperty_get.get(args[0], valuePath);
        }

        var payload = { target: target, args: args, label: _emberMetalStreamsUtils.labelFor(stream) };
        return _emberMetalInstrumentation.flaggedInstrument('interaction.ember-action', payload, function () {
          return _emberMetalRun_loop.default.join.apply(_emberMetalRun_loop.default, [target, action].concat(args));
        });
      };
    }

    closureAction[ACTION] = true;

    return closureAction;
  }
});
enifed('ember-routing-htmlbars/keywords/element-action', ['exports', 'ember-metal/debug', 'ember-metal/utils', 'ember-metal/streams/utils', 'ember-metal/run_loop', 'ember-views/streams/utils', 'ember-views/system/utils', 'ember-views/system/action_manager'], function (exports, _emberMetalDebug, _emberMetalUtils, _emberMetalStreamsUtils, _emberMetalRun_loop, _emberViewsStreamsUtils, _emberViewsSystemUtils, _emberViewsSystemAction_manager) {
  'use strict';

  exports.default = {
    setupState: function (state, env, scope, params, hash) {
      var getStream = env.hooks.get;
      var read = env.hooks.getValue;

      var actionName = read(params[0]);

      _emberMetalDebug.assert('You specified a quoteless path to the {{action}} helper ' + 'which did not resolve to an action name (a string). ' + 'Perhaps you meant to use a quoted actionName? (e.g. {{action \'save\'}}).', typeof actionName === 'string' || typeof actionName === 'function');

      var actionArgs = [];
      for (var i = 1, l = params.length; i < l; i++) {
        actionArgs.push(_emberViewsStreamsUtils.readUnwrappedModel(params[i]));
      }

      var target;
      if (hash.target) {
        if (typeof hash.target === 'string') {
          target = read(getStream(env, scope, hash.target));
        } else {
          target = read(hash.target);
        }
      } else {
        target = read(scope.getLocal('controller')) || read(scope.getSelf());
      }

      return { actionName: actionName, actionArgs: actionArgs, target: target };
    },

    isStable: function (state, env, scope, params, hash) {
      return true;
    },

    render: function (node, env, scope, params, hash, template, inverse, visitor) {
      var actionId = env.dom.getAttribute(node.element, 'data-ember-action') || _emberMetalUtils.uuid();

      ActionHelper.registerAction({
        actionId: actionId,
        node: node,
        eventName: hash.on || 'click',
        bubbles: hash.bubbles,
        preventDefault: hash.preventDefault,
        withKeyCode: hash.withKeyCode,
        allowedKeys: hash.allowedKeys
      });

      node.cleanup = function () {
        ActionHelper.unregisterAction(actionId);
      };

      env.dom.setAttribute(node.element, 'data-ember-action', actionId);
    }
  };
  var ActionHelper = {};

  exports.ActionHelper = ActionHelper;
  // registeredActions is re-exported for compatibility with older plugins
  // that were using this undocumented API.
  ActionHelper.registeredActions = _emberViewsSystemAction_manager.default.registeredActions;

  ActionHelper.registerAction = function (_ref) {
    var actionId = _ref.actionId;
    var node = _ref.node;
    var eventName = _ref.eventName;
    var preventDefault = _ref.preventDefault;
    var bubbles = _ref.bubbles;
    var allowedKeys = _ref.allowedKeys;

    var actions = _emberViewsSystemAction_manager.default.registeredActions[actionId];

    if (!actions) {
      actions = _emberViewsSystemAction_manager.default.registeredActions[actionId] = [];
    }

    actions.push({
      eventName: eventName,
      handler: function (event) {
        if (!isAllowedEvent(event, _emberMetalStreamsUtils.read(allowedKeys))) {
          return true;
        }

        if (_emberMetalStreamsUtils.read(preventDefault) !== false) {
          event.preventDefault();
        }

        if (_emberMetalStreamsUtils.read(bubbles) === false) {
          event.stopPropagation();
        }

        var _node$getState = node.getState();

        var target = _node$getState.target;
        var actionName = _node$getState.actionName;
        var actionArgs = _node$getState.actionArgs;

        _emberMetalRun_loop.default(function runRegisteredAction() {
          if (typeof actionName === 'function') {
            actionName.apply(target, actionArgs);
            return;
          }
          if (target.send) {
            target.send.apply(target, [actionName].concat(actionArgs));
          } else {
            _emberMetalDebug.assert('The action \'' + actionName + '\' did not exist on ' + target, typeof target[actionName] === 'function');

            target[actionName].apply(target, actionArgs);
          }
        });
      }
    });

    return actionId;
  };

  ActionHelper.unregisterAction = function (actionId) {
    delete _emberViewsSystemAction_manager.default.registeredActions[actionId];
  };

  var MODIFIERS = ['alt', 'shift', 'meta', 'ctrl'];
  var POINTER_EVENT_TYPE_REGEX = /^click|mouse|touch/;

  function isAllowedEvent(event, allowedKeys) {
    if (typeof allowedKeys === 'undefined') {
      if (POINTER_EVENT_TYPE_REGEX.test(event.type)) {
        return _emberViewsSystemUtils.isSimpleClick(event);
      } else {
        allowedKeys = '';
      }
    }

    if (allowedKeys.indexOf('any') >= 0) {
      return true;
    }

    for (var i = 0, l = MODIFIERS.length; i < l; i++) {
      if (event[MODIFIERS[i] + 'Key'] && allowedKeys.indexOf(MODIFIERS[i]) === -1) {
        return false;
      }
    }

    return true;
  }
});
enifed('ember-routing-htmlbars/keywords/render', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/empty_object', 'ember-metal/error', 'ember-metal/streams/utils', 'ember-runtime/system/string', 'ember-routing/system/generate_controller', 'ember-htmlbars/node-managers/view-node-manager'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalEmpty_object, _emberMetalError, _emberMetalStreamsUtils, _emberRuntimeSystemString, _emberRoutingSystemGenerate_controller, _emberHtmlbarsNodeManagersViewNodeManager) {
  /**
  @module ember
  @submodule ember-templates
  */

  'use strict';

  /**
    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}}.
    ```

    ```handlebars
    <!-- 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.Templates.helpers
    @param {String} name
    @param {Object?} context
    @param {Hash} options
    @return {String} HTML string
    @public
  */
  exports.default = {
    willRender: function (renderNode, env) {
      if (env.view.ownerView._outlets) {
        // We make sure we will get dirtied when outlet state changes.
        env.view.ownerView._outlets.push(renderNode);
      }
    },

    setupState: function (prevState, env, scope, params, hash) {
      var name = params[0];

      _emberMetalDebug.assert('The first argument of {{render}} must be quoted, e.g. {{render "sidebar"}}.', typeof name === 'string');

      return {
        parentView: env.view,
        manager: prevState.manager,
        controller: prevState.controller,
        childOutletState: childOutletState(name, env)
      };
    },

    childEnv: function (state, env) {
      return env.childWithOutletState(state.childOutletState);
    },

    isStable: function (lastState, nextState) {
      return isStable(lastState.childOutletState, nextState.childOutletState);
    },

    isEmpty: function (state) {
      return false;
    },

    render: function (node, env, scope, params, hash, template, inverse, visitor) {
      var state = node.getState();
      var name = params[0];
      var context = params[1];

      var owner = env.owner;

      // The render keyword presumes it can work without a router. This is really
      // only to satisfy the test:
      //
      //     {{view}} should not override class bindings defined on a child view"
      //
      var router = owner.lookup('router:main');

      _emberMetalDebug.assert('The second argument of {{render}} must be a path, e.g. {{render "post" post}}.', params.length < 2 || _emberMetalStreamsUtils.isStream(params[1]));

      if (params.length === 1) {
        // use the singleton controller
        _emberMetalDebug.assert('You can only use the {{render}} helper once without a model object as ' + 'its second argument, as in {{render "post" post}}.', !router || !router._lookupActiveComponentNode(name));
      } else if (params.length !== 2) {
        throw new _emberMetalError.default('You must pass a templateName to render');
      }

      var templateName = 'template:' + name;
      _emberMetalDebug.assert('You used `{{render \'' + name + '\'}}`, but \'' + name + '\' can not be ' + 'found as either a template or a view.', owner.hasRegistration('view:' + name) || owner.hasRegistration(templateName) || !!template);

      var view = owner.lookup('view:' + name);
      if (!view) {
        view = owner.lookup('view:default');
      }
      var viewHasTemplateSpecified = view && !!_emberMetalProperty_get.get(view, 'template');
      if (!template && !viewHasTemplateSpecified) {
        template = owner.lookup(templateName);
      }

      if (view) {
        view.ownerView = env.view.ownerView;
      }

      // provide controller override
      var controllerName;
      var controllerFullName;

      if (hash.controller) {
        controllerName = hash.controller;
        controllerFullName = 'controller:' + controllerName;
        delete hash.controller;

        _emberMetalDebug.assert('The controller name you supplied \'' + controllerName + '\' ' + 'did not resolve to a controller.', owner.hasRegistration(controllerFullName));
      } else {
        controllerName = name;
        controllerFullName = 'controller:' + controllerName;
      }

      var target = router;
      var controller;

      // choose name
      if (params.length > 1) {
        var factory = owner._lookupFactory(controllerFullName) || _emberRoutingSystemGenerate_controller.generateControllerFactory(owner, controllerName);

        controller = factory.create({
          model: _emberMetalStreamsUtils.read(context),
          target: target
        });

        node.addDestruction(controller);
      } else {
        controller = owner.lookup(controllerFullName) || _emberRoutingSystemGenerate_controller.default(owner, controllerName);

        controller.setProperties({
          target: target
        });
      }

      if (view) {
        view.set('controller', controller);
      }
      state.controller = controller;

      hash.viewName = _emberRuntimeSystemString.camelize(name);

      if (template && template.raw) {
        template = template.raw;
      }

      var options = {
        layout: null,
        self: controller
      };

      if (view) {
        options.component = view;
      }

      var nodeManager = _emberHtmlbarsNodeManagersViewNodeManager.default.create(node, env, hash, options, state.parentView, null, null, template);
      state.manager = nodeManager;

      if (router && params.length === 1) {
        router._connectActiveComponentNode(name, nodeManager);
      }

      nodeManager.render(env, hash, visitor);
    },

    rerender: function (node, env, scope, params, hash, template, inverse, visitor) {
      if (params.length > 1) {
        var model = _emberMetalStreamsUtils.read(params[1]);
        node.getState().controller.set('model', model);
      }
    }
  };

  function childOutletState(name, env) {
    var topLevel = env.view.ownerView;
    if (!topLevel || !topLevel.outletState) {
      return;
    }

    var outletState = topLevel.outletState;
    if (!outletState.main) {
      return;
    }

    var selectedOutletState = outletState.main.outlets['__ember_orphans__'];
    if (!selectedOutletState) {
      return;
    }
    var matched = selectedOutletState.outlets[name];
    if (matched) {
      var childState = new _emberMetalEmpty_object.default();
      childState[matched.render.outlet] = matched;
      matched.wasUsed = true;
      return childState;
    }
  }

  function isStable(a, b) {
    if (!a && !b) {
      return true;
    }
    if (!a || !b) {
      return false;
    }
    for (var outletName in a) {
      if (!isStableOutlet(a[outletName], b[outletName])) {
        return false;
      }
    }
    return true;
  }

  function isStableOutlet(a, b) {
    if (!a && !b) {
      return true;
    }
    if (!a || !b) {
      return false;
    }
    a = a.render;
    b = b.render;
    for (var key in a) {
      if (a.hasOwnProperty(key)) {
        // name is only here for logging & debugging. If two different
        // names result in otherwise identical states, they're still
        // identical.
        if (a[key] !== b[key] && key !== 'name') {
          return false;
        }
      }
    }
    return true;
  }
});
enifed('ember-routing-views/components/link-to', ['exports', 'ember-metal/features', 'ember-metal/logger', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/computed', 'ember-metal/computed_macros', 'ember-views/system/utils', 'ember-views/components/component', 'ember-runtime/inject', 'ember-runtime/system/service', 'ember-runtime/mixins/controller', 'ember-htmlbars/node-managers/component-node-manager', 'ember-htmlbars/templates/link-to', 'require'], function (exports, _emberMetalFeatures, _emberMetalLogger, _emberMetalDebug, _emberMetalProperty_get, _emberMetalComputed, _emberMetalComputed_macros, _emberViewsSystemUtils, _emberViewsComponentsComponent, _emberRuntimeInject, _emberRuntimeSystemService, _emberRuntimeMixinsController, _emberHtmlbarsNodeManagersComponentNodeManager, _emberHtmlbarsTemplatesLinkTo, _require) {
  /**
  @module ember
  @submodule ember-templates
  */

  /**
    The `{{link-to}}` component 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}}
    ```

    You can also use an inline form of `{{link-to}}` component by
    passing the link text as the first argument
    to the component:

    ```handlebars
    {{link-to 'Great Hamster Photos' 'photoGallery'}}
    ```

    Both will result in:

    ```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` component
    By default `{{link-to}}` is enabled.
    any passed value to the `disabled` component property will disable
    the `link-to` component.

    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` component you can
    override the global behaviour of `Ember.LinkComponent`.

    ```javascript
    Ember.LinkComponent.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
    router'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
    {{/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
    {{/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".

    ### Keeping a link active for other routes

    If you need a link to be 'active' even when it doesn't match
    the current route, you can use the `current-when` argument.

    ```handlebars
    {{#link-to 'photoGallery' current-when='photos'}}
      Photo Gallery
    {{/link-to}}
    ```

    This may be helpful for keeping links active for:

    * non-nested routes that are logically related
    * some secondary menu approaches
    * 'top navigation' with 'sub navigation' scenarios

    A link will be active if `current-when` is `true` or the current
    route is the route this link would transition to.

    To match multiple routes 'space-separate' the routes:

    ```handlebars
    {{#link-to 'gallery' current-when='photos drawings paintings'}}
      Art Gallery
    {{/link-to}}
    ```

    ### 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
    Router.map(function() {
      this.route("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
    Router.map(function() {
      this.route("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/comments/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
    Router.map(function() {
      this.route("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}}` component 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.LinkComponent`
    that is generated by the `{{link-to}}` component 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.LinkComponent](/api/classes/Ember.LinkComponent.html) for a
    complete list of overrideable properties. Be sure to also
    check out inherited properties of `LinkComponent`.

    ### Overriding Application-wide Defaults
    ``{{link-to}}`` creates an instance of `Ember.LinkComponent`
    for rendering. To override options for your entire
    application, reopen `Ember.LinkComponent` and supply the
    desired values:

    ``` javascript
    Ember.LinkComponent.reopen({
      activeClass: "is-active",
      tagName: 'li'
    })
    ```

    It is also possible to override the default event in
    this manner:

    ``` javascript
    Ember.LinkComponent.reopen({
      eventName: 'customEventName'
    });
    ```

    @method link-to
    @for Ember.Templates.helpers
    @param {String} routeName
    @param {Object} [context]*
    @param [options] {Object} Handlebars key/value pairs of options, you can override any property of Ember.LinkComponent
    @return {String} HTML string
    @see {Ember.LinkComponent}
    @public
  */

  /**
  @module ember
  @submodule ember-routing-views
  */

  'use strict';

  var layout = _emberHtmlbarsTemplatesLinkTo.default;

  /**
    `Ember.LinkComponent` renders an element whose `click` event triggers a
    transition of the application's instance of `Ember.Router` to
    a supplied route by name.

    `Ember.LinkComponent` components are invoked with {{#link-to}}. Properties
    of this class can be overridden with `reopen` to customize application-wide
    behavior.

    @class LinkComponent
    @namespace Ember
    @extends Ember.Component
    @see {Ember.Templates.helpers.link-to}
    @private
  **/
  var LinkComponent = _emberViewsComponentsComponent.default.extend({
    layout: layout,

    tagName: 'a',

    /**
      @deprecated Use current-when instead.
      @property currentWhen
      @private
    */
    currentWhen: _emberMetalComputed_macros.deprecatingAlias('current-when', { id: 'ember-routing-view.deprecated-current-when', until: '3.0.0' }),

    /**
      Used to determine when this `LinkComponent` is active.
       @property currentWhen
      @public
    */
    'current-when': null,

    /**
      Sets the `title` attribute of the `LinkComponent`'s HTML element.
       @property title
      @default null
      @public
    **/
    title: null,

    /**
      Sets the `rel` attribute of the `LinkComponent`'s HTML element.
       @property rel
      @default null
      @public
    **/
    rel: null,

    /**
      Sets the `tabindex` attribute of the `LinkComponent`'s HTML element.
       @property tabindex
      @default null
      @public
    **/
    tabindex: null,

    /**
      Sets the `target` attribute of the `LinkComponent`'s HTML element.
       @since 1.8.0
      @property target
      @default null
      @public
    **/
    target: null,

    /**
      The CSS class to apply to `LinkComponent`'s element when its `active`
      property is `true`.
       @property activeClass
      @type String
      @default active
      @private
    **/
    activeClass: 'active',

    /**
      The CSS class to apply to `LinkComponent`'s element when its `loading`
      property is `true`.
       @property loadingClass
      @type String
      @default loading
      @private
    **/
    loadingClass: 'loading',

    /**
      The CSS class to apply to a `LinkComponent`'s element when its `disabled`
      property is `true`.
       @property disabledClass
      @type String
      @default disabled
      @private
    **/
    disabledClass: 'disabled',
    _isDisabled: false,

    /**
      Determines whether the `LinkComponent` will trigger routing via
      the `replaceWith` routing strategy.
       @property replace
      @type Boolean
      @default false
      @public
    **/
    replace: false,

    /**
      By default the `{{link-to}}` component will bind to the `href` and
      `title` attributes. It's discouraged that you override these defaults,
      however you can push onto the array if needed.
       @property attributeBindings
      @type Array | String
      @default ['title', 'rel', 'tabindex', 'target']
      @public
    */
    attributeBindings: ['href', 'title', 'rel', 'tabindex', 'target'],

    /**
      By default the `{{link-to}}` component will bind to the `active`, `loading`,
      and `disabled` classes. It is discouraged to override these directly.
       @property classNameBindings
      @type Array
      @default ['active', 'loading', 'disabled', 'ember-transitioning-in', 'ember-transitioning-out']
      @public
    */
    classNameBindings: ['active', 'loading', 'disabled', 'transitioningIn', 'transitioningOut'],

    /**
      By default the `{{link-to}}` component 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
      @private
    */
    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 `LinkComponent`'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
      @private
    */

    /**
      An overridable method called when `LinkComponent` objects are instantiated.
       Example:
       ```javascript
      App.MyLinkComponent = Ember.LinkComponent.extend({
        init: function() {
          this._super(...arguments);
          Ember.Logger.log('Event is ' + this.get('eventName'));
        }
      });
      ```
       NOTE: If you do override `init` for a framework class like `Ember.View`,
      be sure to call `this._super(...arguments)` 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
      @private
    */
    init: function () {
      this._super.apply(this, arguments);

      // Map desired event name to invoke function
      var eventName = _emberMetalProperty_get.get(this, 'eventName');
      this.on(eventName, this, this._invoke);
    },

    _routing: _emberRuntimeInject.default.service('-routing'),

    /**
      Accessed as a classname binding to apply the `LinkComponent`'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
      @private
    */
    disabled: _emberMetalComputed.computed({
      get: function (key, value) {
        return false;
      },
      set: function (key, value) {
        if (value !== undefined) {
          this.set('_isDisabled', value);
        }

        return value ? _emberMetalProperty_get.get(this, 'disabledClass') : false;
      }
    }),

    _computeActive: function (routerState) {
      if (_emberMetalProperty_get.get(this, 'loading')) {
        return false;
      }

      var routing = _emberMetalProperty_get.get(this, '_routing');
      var models = _emberMetalProperty_get.get(this, 'models');
      var resolvedQueryParams = _emberMetalProperty_get.get(this, 'resolvedQueryParams');

      var currentWhen = _emberMetalProperty_get.get(this, 'current-when');
      var isCurrentWhenSpecified = !!currentWhen;
      currentWhen = currentWhen || _emberMetalProperty_get.get(this, 'qualifiedRouteName');
      currentWhen = currentWhen.split(' ');

      for (var i = 0, len = currentWhen.length; i < len; i++) {
        if (routing.isActiveForRoute(models, resolvedQueryParams, currentWhen[i], routerState, isCurrentWhenSpecified)) {
          return _emberMetalProperty_get.get(this, 'activeClass');
        }
      }

      return false;
    },

    /**
      Accessed as a classname binding to apply the `LinkComponent`'s `activeClass`
      CSS `class` to the element when the link is active.
       A `LinkComponent` is considered active when its `currentWhen` property is `true`
      or the application's current route is the route the `LinkComponent` would trigger
      transitions into.
       The `currentWhen` property can match against multiple routes by separating
      route names using the ` ` (space) character.
       @property active
      @private
    */
    active: _emberMetalComputed.computed('attrs.params', '_routing.currentState', function computeLinkToComponentActive() {
      var currentState = _emberMetalProperty_get.get(this, '_routing.currentState');
      if (!currentState) {
        return false;
      }

      return this._computeActive(currentState);
    }),

    willBeActive: _emberMetalComputed.computed('_routing.targetState', function computeLinkToComponentWillBeActive() {
      var routing = _emberMetalProperty_get.get(this, '_routing');
      var targetState = _emberMetalProperty_get.get(routing, 'targetState');
      if (_emberMetalProperty_get.get(routing, 'currentState') === targetState) {
        return;
      }

      return !!this._computeActive(targetState);
    }),

    transitioningIn: _emberMetalComputed.computed('active', 'willBeActive', function computeLinkToComponentTransitioningIn() {
      var willBeActive = _emberMetalProperty_get.get(this, 'willBeActive');
      if (typeof willBeActive === 'undefined') {
        return false;
      }

      return !_emberMetalProperty_get.get(this, 'active') && willBeActive && 'ember-transitioning-in';
    }),

    transitioningOut: _emberMetalComputed.computed('active', 'willBeActive', function computeLinkToComponentTransitioningOut() {
      var willBeActive = _emberMetalProperty_get.get(this, 'willBeActive');
      if (typeof willBeActive === 'undefined') {
        return false;
      }

      return _emberMetalProperty_get.get(this, 'active') && !willBeActive && 'ember-transitioning-out';
    }),

    /**
      Event handler that invokes the link, activating the associated route.
       @private
      @method _invoke
      @param {Event} event
      @private
    */
    _invoke: function (event) {
      if (!_emberViewsSystemUtils.isSimpleClick(event)) {
        return true;
      }

      var preventDefault = _emberMetalProperty_get.get(this, 'preventDefault');
      var targetAttribute = _emberMetalProperty_get.get(this, 'target');

      if (preventDefault !== false) {
        if (!targetAttribute || targetAttribute === '_self') {
          event.preventDefault();
        }
      }

      if (_emberMetalProperty_get.get(this, 'bubbles') === false) {
        event.stopPropagation();
      }

      if (_emberMetalProperty_get.get(this, '_isDisabled')) {
        return false;
      }

      if (_emberMetalProperty_get.get(this, 'loading')) {
        _emberMetalLogger.default.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;
      }

      if (targetAttribute && targetAttribute !== '_self') {
        return false;
      }

      var routing = _emberMetalProperty_get.get(this, '_routing');
      var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName');
      var models = _emberMetalProperty_get.get(this, 'models');
      var queryParamValues = _emberMetalProperty_get.get(this, 'queryParams.values');
      var shouldReplace = _emberMetalProperty_get.get(this, 'replace');

      routing.transitionTo(qualifiedRouteName, models, queryParamValues, shouldReplace);
    },

    queryParams: null,

    qualifiedRouteName: _emberMetalComputed.computed('targetRouteName', '_routing.currentState', function computeLinkToComponentQualifiedRouteName() {
      var params = _emberMetalProperty_get.get(this, 'params').slice();
      var lastParam = params[params.length - 1];
      if (lastParam && lastParam.isQueryParams) {
        params.pop();
      }
      var onlyQueryParamsSupplied = this[_emberHtmlbarsNodeManagersComponentNodeManager.HAS_BLOCK] ? params.length === 0 : params.length === 1;
      if (onlyQueryParamsSupplied) {
        return _emberMetalProperty_get.get(this, '_routing.currentRouteName');
      }
      return _emberMetalProperty_get.get(this, 'targetRouteName');
    }),

    resolvedQueryParams: _emberMetalComputed.computed('queryParams', function computeLinkToComponentResolvedQueryParams() {
      var resolvedQueryParams = {};
      var queryParams = _emberMetalProperty_get.get(this, 'queryParams');

      if (!queryParams) {
        return resolvedQueryParams;
      }

      var values = queryParams.values;
      for (var key in values) {
        if (!values.hasOwnProperty(key)) {
          continue;
        }
        resolvedQueryParams[key] = values[key];
      }

      return resolvedQueryParams;
    }),

    /**
      Sets the element's `href` attribute to the url for
      the `LinkComponent`'s targeted route.
       If the `LinkComponent`'s `tagName` is changed to a value other
      than `a`, this property will be ignored.
       @property href
      @private
    */
    href: _emberMetalComputed.computed('models', 'qualifiedRouteName', function computeLinkToComponentHref() {
      if (_emberMetalProperty_get.get(this, 'tagName') !== 'a') {
        return;
      }

      var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName');
      var models = _emberMetalProperty_get.get(this, 'models');

      if (_emberMetalProperty_get.get(this, 'loading')) {
        return _emberMetalProperty_get.get(this, 'loadingHref');
      }

      var routing = _emberMetalProperty_get.get(this, '_routing');
      var queryParams = _emberMetalProperty_get.get(this, 'queryParams.values');
      return routing.generateURL(qualifiedRouteName, models, queryParams);
    }),

    loading: _emberMetalComputed.computed('_modelsAreLoaded', 'qualifiedRouteName', function computeLinkToComponentLoading() {
      var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName');
      var modelsAreLoaded = _emberMetalProperty_get.get(this, '_modelsAreLoaded');

      if (!modelsAreLoaded || qualifiedRouteName == null) {
        return _emberMetalProperty_get.get(this, 'loadingClass');
      }
    }),

    _modelsAreLoaded: _emberMetalComputed.computed('models', function computeLinkToComponentModelsAreLoaded() {
      var models = _emberMetalProperty_get.get(this, 'models');
      for (var i = 0, l = models.length; i < l; i++) {
        if (models[i] == null) {
          return false;
        }
      }

      return true;
    }),

    _getModels: function (params) {
      var modelCount = params.length - 1;
      var models = new Array(modelCount);

      for (var i = 0; i < modelCount; i++) {
        var value = params[i + 1];

        while (_emberRuntimeMixinsController.default.detect(value)) {
          _emberMetalDebug.deprecate('Providing `{{link-to}}` with a param that is wrapped in a controller is deprecated. ' + (this.parentView ? 'Please update `' + this.parentView + '` to use `{{link-to "post" someController.model}}` instead.' : ''), false, { id: 'ember-routing-views.controller-wrapped-param', until: '3.0.0' });
          value = value.get('model');
        }

        models[i] = value;
      }

      return models;
    },

    /**
      The default href value to use while a link-to is loading.
      Only applies when tagName is 'a'
       @property loadingHref
      @type String
      @default #
      @private
    */
    loadingHref: '#',

    willRender: function () {
      var queryParams = undefined;

      // Do not mutate params in place
      var params = _emberMetalProperty_get.get(this, 'params').slice();

      _emberMetalDebug.assert('You must provide one or more parameters to the link-to component.', params.length);

      var disabledWhen = _emberMetalProperty_get.get(this, 'disabledWhen');
      if (disabledWhen !== undefined) {
        this.set('disabled', disabledWhen);
      }

      // Process the positional arguments, in order.
      // 1. Inline link title comes first, if present.
      if (!this[_emberHtmlbarsNodeManagersComponentNodeManager.HAS_BLOCK]) {
        this.set('linkTitle', params.shift());
      }

      // 2. `targetRouteName` is now always at index 0.
      this.set('targetRouteName', params[0]);

      // 3. The last argument (if still remaining) is the `queryParams` object.
      var lastParam = params[params.length - 1];

      if (lastParam && lastParam.isQueryParams) {
        queryParams = params.pop();
      } else {
        queryParams = {};
      }
      this.set('queryParams', queryParams);

      // 4. Any remaining indices (excepting `targetRouteName` at 0) are `models`.
      if (params.length > 1) {
        this.set('models', this._getModels(params));
      } else {
        this.set('models', []);
      }
    }
  });

  LinkComponent.toString = function () {
    return 'LinkComponent';
  };

  LinkComponent.reopenClass({
    positionalParams: 'params'
  });

  exports.default = LinkComponent;
});
// creates inject.service
enifed('ember-routing-views/index', ['exports', 'ember-metal/core', 'ember-routing-views/components/link-to', 'ember-routing-views/views/outlet'], function (exports, _emberMetalCore, _emberRoutingViewsComponentsLinkTo, _emberRoutingViewsViewsOutlet) {
  /**
  @module ember
  @submodule ember-routing-views
  */

  'use strict';

  _emberMetalCore.default.LinkComponent = _emberRoutingViewsComponentsLinkTo.default;
  _emberMetalCore.default.OutletView = _emberRoutingViewsViewsOutlet.OutletView;

  exports.default = _emberMetalCore.default;
});
enifed('ember-routing-views/views/outlet', ['exports', 'ember-views/views/view', 'ember-htmlbars/templates/top-level-view'], function (exports, _emberViewsViewsView, _emberHtmlbarsTemplatesTopLevelView) {
  /**
  @module ember
  @submodule ember-routing-views
  */

  'use strict';

  var CoreOutletView = _emberViewsViewsView.default.extend({
    defaultTemplate: _emberHtmlbarsTemplatesTopLevelView.default,

    init: function () {
      this._super();
      this._outlets = [];
    },

    setOutletState: function (state) {
      this.outletState = { main: state };

      if (this.env) {
        this.env.outletState = this.outletState;
      }

      if (this.lastResult) {
        this.dirtyOutlets();
        this._outlets = [];

        this.scheduleRevalidate(null, null);
      }
    },

    dirtyOutlets: function () {
      // Dirty any render nodes that correspond to outlets
      for (var i = 0; i < this._outlets.length; i++) {
        this._outlets[i].isDirty = true;
      }
    }
  });

  exports.CoreOutletView = CoreOutletView;
  var OutletView = CoreOutletView.extend({ tagName: '' });
  exports.OutletView = OutletView;
});
enifed('ember-routing/ext/controller', ['exports', 'ember-metal/property_get', 'ember-runtime/mixins/controller'], function (exports, _emberMetalProperty_get, _emberRuntimeMixinsController) {
  'use strict';

  /**
  @module ember
  @submodule ember-routing
  */

  _emberRuntimeMixinsController.default.reopen({
    concatenatedProperties: ['queryParams'],

    /**
      Defines which query parameters the controller accepts.
      If you give the names `['category','page']` it will bind
      the values of these query parameters to the variables
      `this.category` and `this.page`
       @property queryParams
      @public
    */
    queryParams: null,

    /**
      @property _qpDelegate
      @private
    */
    _qpDelegate: null, // set by route

    /**
      @method _qpChanged
      @private
    */
    _qpChanged: function (controller, _prop) {
      var prop = _prop.substr(0, _prop.length - 3);

      var delegate = controller._qpDelegate;
      var value = _emberMetalProperty_get.get(controller, prop);
      delegate(prop, value);
    },

    /**
      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
      route tree.
       ```javascript
      App.Router.map(function() {
        this.route('blogPost', { path: ':blogPostId' }, function() {
          this.route('blogComment', { path: ':blogCommentId', resetNamespace: true });
        });
      });
       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');
      aController.transitionToRoute('/blog/posts?sort=title');
      ```
       An options hash with a `queryParams` property may be provided as
      the final argument to add query parameters to the destination URL.
       ```javascript
      aController.transitionToRoute('blogPost', 1, {
        queryParams: {showComments: 'true'}
      });
       // if you just want to transition the query parameters without changing the route
      aController.transitionToRoute({queryParams: {sort: 'date'}});
      ```
       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.
      @param {Object} [options] optional hash with a queryParams property
        containing a mapping of query parameters
      @for Ember.ControllerMixin
      @method transitionToRoute
      @public
    */
    transitionToRoute: function () {
      // target may be either another controller or a router
      var target = _emberMetalProperty_get.get(this, 'target');
      var method = target.transitionToRoute || target.transitionTo;
      return method.apply(target, 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
      route tree.
       ```javascript
      App.Router.map(function() {
        this.route('blogPost', { path: ':blogPostId' }, function() {
          this.route('blogComment', { path: ':blogCommentId', resetNamespace: true });
        });
      });
       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
      @private
    */
    replaceRoute: function () {
      // target may be either another controller or a router
      var target = _emberMetalProperty_get.get(this, 'target');
      var method = target.replaceRoute || target.replaceWith;
      return method.apply(target, arguments);
    }
  });

  exports.default = _emberRuntimeMixinsController.default;
});
enifed('ember-routing/ext/run_loop', ['exports', 'ember-metal/run_loop'], function (exports, _emberMetalRun_loop) {
  'use strict';

  /**
  @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.
  _emberMetalRun_loop.default._addQueue('routerTransitions', 'actions');
});
enifed('ember-routing/index', ['exports', 'ember-metal/core', 'ember-routing/ext/run_loop', 'ember-routing/ext/controller', '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'], function (exports, _emberMetalCore, _emberRoutingExtRun_loop, _emberRoutingExtController, _emberRoutingLocationApi, _emberRoutingLocationNone_location, _emberRoutingLocationHash_location, _emberRoutingLocationHistory_location, _emberRoutingLocationAuto_location, _emberRoutingSystemGenerate_controller, _emberRoutingSystemController_for, _emberRoutingSystemDsl, _emberRoutingSystemRouter, _emberRoutingSystemRoute) {
  /**
  @module ember
  @submodule ember-routing
  */

  'use strict';

  _emberMetalCore.default.Location = _emberRoutingLocationApi.default;
  _emberMetalCore.default.AutoLocation = _emberRoutingLocationAuto_location.default;
  _emberMetalCore.default.HashLocation = _emberRoutingLocationHash_location.default;
  _emberMetalCore.default.HistoryLocation = _emberRoutingLocationHistory_location.default;
  _emberMetalCore.default.NoneLocation = _emberRoutingLocationNone_location.default;

  _emberMetalCore.default.controllerFor = _emberRoutingSystemController_for.default;
  _emberMetalCore.default.generateControllerFactory = _emberRoutingSystemGenerate_controller.generateControllerFactory;
  _emberMetalCore.default.generateController = _emberRoutingSystemGenerate_controller.default;
  _emberMetalCore.default.RouterDSL = _emberRoutingSystemDsl.default;
  _emberMetalCore.default.Router = _emberRoutingSystemRouter.default;
  _emberMetalCore.default.Route = _emberRoutingSystemRoute.default;

  exports.default = _emberMetalCore.default;
});

// ES6TODO: Cleanup modules with side-effects below
enifed('ember-routing/location/api', ['exports', 'ember-metal/debug', 'ember-metal/environment', 'ember-routing/location/util'], function (exports, _emberMetalDebug, _emberMetalEnvironment, _emberRoutingLocationUtil) {
  'use strict';

  /**
  @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.route('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.route('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.route('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.
    * detect() (optional): instructs the location to do any feature detection
        necessary. If the location needs to redirect to a different URL, it
        can cancel routing by setting the `cancelRouterSetup` property on itself
        to `false`.

    Calling setURL or replaceURL will not trigger onUpdateURL callbacks.

    ## Custom implementation

    Ember scans `app/locations/*` for extending the Location API.

    Example:

    ```javascript
    import Ember from 'ember';

    export default Ember.HistoryLocation.extend({
      implementation: 'history-url-logging',

      pushState: function (path) {
        console.log(path);
        this._super.apply(this, arguments);
      }
    });
    ```

    @class Location
    @namespace Ember
    @static
    @private
  */
  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.
      @private
    */
    create: function (options) {
      var implementation = options && options.implementation;
      _emberMetalDebug.assert('Ember.Location.create: you must specify a \'implementation\' option', !!implementation);

      var implementationClass = this.implementations[implementation];
      _emberMetalDebug.assert('Ember.Location.create: ' + implementation + ' is not a valid implementation', !!implementationClass);

      return implementationClass.create.apply(implementationClass, arguments);
    },

    implementations: {},
    _location: _emberMetalEnvironment.default.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 () {
      return _emberRoutingLocationUtil.getHash(this.location);
    }
  };
});
enifed('ember-routing/location/auto_location', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/utils', 'container/owner', 'ember-runtime/system/object', 'ember-metal/environment', 'ember-routing/location/util'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalUtils, _containerOwner, _emberRuntimeSystemObject, _emberMetalEnvironment, _emberRoutingLocationUtil) {
  'use strict';

  exports.getHistoryPath = getHistoryPath;
  exports.getHashPath = getHashPath;

  /**
  @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
    @private
  */
  exports.default = _emberRuntimeSystemObject.default.extend({
    /**
      @private
       The browser's `location` object. This is typically equivalent to
      `window.location`, but may be overridden for testing.
       @property location
      @default environment.location
    */
    location: _emberMetalEnvironment.default.location,

    /**
      @private
       The browser's `history` object. This is typically equivalent to
      `window.history`, but may be overridden for testing.
       @since 1.5.1
      @property history
      @default environment.history
    */
    history: _emberMetalEnvironment.default.history,

    /**
     @private
      The user agent's global variable. In browsers, this will be `window`.
      @since 1.11
     @property global
     @default environment.global
    */
    global: _emberMetalEnvironment.default.global,

    /**
      @private
       The browser's `userAgent`. This is typically equivalent to
      `navigator.userAgent`, but may be overridden for testing.
       @since 1.5.1
      @property userAgent
      @default environment.history
    */
    userAgent: _emberMetalEnvironment.default.userAgent,

    /**
      @private
       This property is used by the router 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: '/',

    /**
     Called by the router to instruct the location to do any feature detection
     necessary. In the case of AutoLocation, we detect whether to use history
     or hash concrete implementations.
      @private
    */
    detect: function () {
      var rootURL = this.rootURL;

      _emberMetalDebug.assert('rootURL must end with a trailing forward slash e.g. "/app/"', rootURL.charAt(rootURL.length - 1) === '/');

      var implementation = detectImplementation({
        location: this.location,
        history: this.history,
        userAgent: this.userAgent,
        rootURL: rootURL,
        documentMode: this.documentMode,
        global: this.global
      });

      if (implementation === false) {
        _emberMetalProperty_set.set(this, 'cancelRouterSetup', true);
        implementation = 'none';
      }

      var concrete = _containerOwner.getOwner(this).lookup('location:' + implementation);
      _emberMetalProperty_set.set(concrete, 'rootURL', rootURL);

      _emberMetalDebug.assert('Could not find location \'' + implementation + '\'.', !!concrete);

      _emberMetalProperty_set.set(this, 'concreteImplementation', concrete);
    },

    initState: delegateToConcreteImplementation('initState'),
    getURL: delegateToConcreteImplementation('getURL'),
    setURL: delegateToConcreteImplementation('setURL'),
    replaceURL: delegateToConcreteImplementation('replaceURL'),
    onUpdateURL: delegateToConcreteImplementation('onUpdateURL'),
    formatURL: delegateToConcreteImplementation('formatURL'),

    willDestroy: function () {
      var concreteImplementation = _emberMetalProperty_get.get(this, 'concreteImplementation');

      if (concreteImplementation) {
        concreteImplementation.destroy();
      }
    }
  });

  function delegateToConcreteImplementation(methodName) {
    return function () {
      var concreteImplementation = _emberMetalProperty_get.get(this, 'concreteImplementation');
      _emberMetalDebug.assert('AutoLocation\'s detect() method should be called before calling any other hooks.', !!concreteImplementation);

      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      return _emberMetalUtils.tryInvoke(concreteImplementation, methodName, args);
    };
  }

  /*
    Given the browser's `location`, `history` and `userAgent`, and a configured
    root URL, this function detects whether the browser supports the [History
    API](https://developer.mozilla.org/en-US/docs/Web/API/History) and returns a
    string representing the Location object to use based on its determination.

    For example, if the page loads in an evergreen browser, this function would
    return the string "history", meaning the history API and thus HistoryLocation
    should be used. If the page is loaded in IE8, it will return the string
    "hash," indicating that the History API should be simulated by manipulating the
    hash portion of the location.

  */

  function detectImplementation(options) {
    var location = options.location;
    var userAgent = options.userAgent;
    var history = options.history;
    var documentMode = options.documentMode;
    var global = options.global;
    var rootURL = options.rootURL;

    var implementation = 'none';
    var cancelRouterSetup = false;
    var currentPath = _emberRoutingLocationUtil.getFullPath(location);

    if (_emberRoutingLocationUtil.supportsHistory(userAgent, history)) {
      var historyPath = getHistoryPath(rootURL, location);

      // If the browser supports history and we have a history path, we can use
      // the history location with no redirects.
      if (currentPath === historyPath) {
        return 'history';
      } else {
        if (currentPath.substr(0, 2) === '/#') {
          history.replaceState({ path: historyPath }, null, historyPath);
          implementation = 'history';
        } else {
          cancelRouterSetup = true;
          _emberRoutingLocationUtil.replacePath(location, historyPath);
        }
      }
    } else if (_emberRoutingLocationUtil.supportsHashChange(documentMode, global)) {
      var hashPath = getHashPath(rootURL, location);

      // 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 === '/#/') {
        implementation = 'hash';
      } 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;
        _emberRoutingLocationUtil.replacePath(location, hashPath);
      }
    }

    if (cancelRouterSetup) {
      return false;
    }

    return implementation;
  }

  /**
    @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)
  */

  function getHistoryPath(rootURL, location) {
    var path = _emberRoutingLocationUtil.getPath(location);
    var hash = _emberRoutingLocationUtil.getHash(location);
    var query = _emberRoutingLocationUtil.getQuery(location);
    var rootURLIndex = path.indexOf(rootURL);
    var routeHash, hashParts;

    _emberMetalDebug.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 = path + routeHash + query;

      if (hashParts.length) {
        path += '#' + hashParts.join('#');
      }
    } else {
      path = path + query + 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
  */

  function getHashPath(rootURL, location) {
    var path = rootURL;
    var historyPath = getHistoryPath(rootURL, location);
    var routePath = historyPath.substr(rootURL.length);

    if (routePath !== '') {
      if (routePath.charAt(0) !== '/') {
        routePath = '/' + routePath;
      }

      path += '#' + routePath;
    }

    return path;
  }
});
enifed('ember-routing/location/hash_location', ['exports', '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'], function (exports, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalRun_loop, _emberMetalUtils, _emberRuntimeSystemObject, _emberRoutingLocationApi, _emberViewsSystemJquery) {
  'use strict';

  /**
  @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
    @private
  */
  exports.default = _emberRuntimeSystemObject.default.extend({
    implementation: 'hash',

    init: function () {
      _emberMetalProperty_set.set(this, 'location', _emberMetalProperty_get.get(this, '_location') || window.location);
    },

    /**
      @private
       Returns normalized location.hash
       @since 1.5.1
      @method getHash
    */
    getHash: _emberRoutingLocationApi.default._getHash,

    /**
      Returns the normalized URL, constructed from `location.hash`.
       e.g. `#/foo` => `/foo` as well as `#/foo#bar` => `/foo#bar`.
       By convention, hashed paths must begin with a forward slash, otherwise they
      are not treated as a path so we can distinguish intent.
       @private
      @method getURL
    */
    getURL: function () {
      var originalPath = this.getHash().substr(1);
      var outPath = originalPath;

      if (outPath.charAt(0) !== '/') {
        outPath = '/';

        // Only add the # if the path isn't empty.
        // We do NOT want `/#` since the ampersand
        // is only included (conventionally) when
        // the location.hash has a value
        if (originalPath) {
          outPath += '#' + originalPath;
        }
      }

      return outPath;
    },

    /**
      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) {
      _emberMetalProperty_get.get(this, 'location').hash = path;
      _emberMetalProperty_set.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) {
      _emberMetalProperty_get.get(this, 'location').replace('#' + path);
      _emberMetalProperty_set.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 _this = this;

      var guid = _emberMetalUtils.guidFor(this);

      _emberViewsSystemJquery.default(window).on('hashchange.ember-location-' + guid, function () {
        _emberMetalRun_loop.default(function () {
          var path = _this.getURL();
          if (_emberMetalProperty_get.get(_this, 'lastSetURL') === path) {
            return;
          }

          _emberMetalProperty_set.set(_this, '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 = _emberMetalUtils.guidFor(this);

      _emberViewsSystemJquery.default(window).off('hashchange.ember-location-' + guid);
    }
  });
});
enifed('ember-routing/location/history_location', ['exports', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/utils', 'ember-runtime/system/object', 'ember-routing/location/api', 'ember-views/system/jquery'], function (exports, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalUtils, _emberRuntimeSystemObject, _emberRoutingLocationApi, _emberViewsSystemJquery) {
  'use strict';

  /**
  @module ember
  @submodule ember-routing
  */

  var popstateFired = false;

  /**
    Ember.HistoryLocation implements the location API using the browser's
    history.pushState API.

    @class HistoryLocation
    @namespace Ember
    @extends Ember.Object
    @private
  */
  exports.default = _emberRuntimeSystemObject.default.extend({
    implementation: 'history',

    init: function () {
      _emberMetalProperty_set.set(this, 'location', _emberMetalProperty_get.get(this, 'location') || window.location);
      _emberMetalProperty_set.set(this, 'baseURL', _emberViewsSystemJquery.default('base').attr('href') || '');
    },

    /**
      Used to set state on first call to setURL
       @private
      @method initState
    */
    initState: function () {
      var history = _emberMetalProperty_get.get(this, 'history') || window.history;
      _emberMetalProperty_set.set(this, 'history', history);

      if (history && 'state' in history) {
        this.supportsHistory = true;
      }

      this.replaceState(this.formatURL(this.getURL()));
    },

    /**
      Will be pre-pended to path upon state change
       @property rootURL
      @default '/'
      @private
    */
    rootURL: '/',

    /**
      Returns the current `location.pathname` without `rootURL` or `baseURL`
       @private
      @method getURL
      @return url {String}
    */
    getURL: function () {
      var location = _emberMetalProperty_get.get(this, 'location');
      var path = location.pathname;

      var rootURL = _emberMetalProperty_get.get(this, 'rootURL');
      var baseURL = _emberMetalProperty_get.get(this, 'baseURL');

      // remove trailing slashes if they exists
      rootURL = rootURL.replace(/\/$/, '');
      baseURL = baseURL.replace(/\/$/, '');

      // remove baseURL and rootURL from start of path
      var url = path.replace(new RegExp('^' + baseURL + '(?=/|$)'), '').replace(new RegExp('^' + rootURL + '(?=/|$)'), '');

      var search = location.search || '';
      url += search;
      url += this.getHash();

      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 () {
      if (this.supportsHistory) {
        return _emberMetalProperty_get.get(this, 'history').state;
      }

      return this._historyState;
    },

    /**
     Pushes a new state.
      @private
     @method pushState
     @param path {String}
    */
    pushState: function (path) {
      var state = { path: path };

      _emberMetalProperty_get.get(this, 'history').pushState(state, null, path);

      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 };
      _emberMetalProperty_get.get(this, 'history').replaceState(state, null, path);

      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 _this = this;

      var guid = _emberMetalUtils.guidFor(this);

      _emberViewsSystemJquery.default(window).on('popstate.ember-location-' + guid, function (e) {
        // Ignore initial page load popstate event in Chrome
        if (!popstateFired) {
          popstateFired = true;
          if (_this.getURL() === _this._previousURL) {
            return;
          }
        }
        callback(_this.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 = _emberMetalProperty_get.get(this, 'rootURL');
      var baseURL = _emberMetalProperty_get.get(this, 'baseURL');

      if (url !== '') {
        // remove trailing slashes if they exists
        rootURL = rootURL.replace(/\/$/, '');
        baseURL = baseURL.replace(/\/$/, '');
      } else if (baseURL.match(/^\//) && rootURL.match(/^\//)) {
        // if baseURL and rootURL both start with a slash
        // ... remove trailing slash from baseURL if it exists
        baseURL = baseURL.replace(/\/$/, '');
      }

      return baseURL + rootURL + url;
    },

    /**
      Cleans up the HistoryLocation event listener.
       @private
      @method willDestroy
    */
    willDestroy: function () {
      var guid = _emberMetalUtils.guidFor(this);

      _emberViewsSystemJquery.default(window).off('popstate.ember-location-' + guid);
    },

    /**
      @private
       Returns normalized location.hash
       @method getHash
    */
    getHash: _emberRoutingLocationApi.default._getHash
  });
});
enifed('ember-routing/location/none_location', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-runtime/system/object'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberRuntimeSystemObject) {
  'use strict';

  /**
  @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
    @private
  */
  exports.default = _emberRuntimeSystemObject.default.extend({
    implementation: 'none',
    path: '',

    detect: function () {
      var rootURL = this.rootURL;

      _emberMetalDebug.assert('rootURL must end with a trailing forward slash e.g. "/app/"', rootURL.charAt(rootURL.length - 1) === '/');
    },

    /**
      Will be pre-pended to path.
       @private
      @property rootURL
      @default '/'
    */
    rootURL: '/',

    /**
      Returns the current path without `rootURL`.
       @private
      @method getURL
      @return {String} path
    */
    getURL: function () {
      var path = _emberMetalProperty_get.get(this, 'path');
      var rootURL = _emberMetalProperty_get.get(this, 'rootURL');

      // remove trailing slashes if they exists
      rootURL = rootURL.replace(/\/$/, '');

      // remove rootURL from url
      return path.replace(new RegExp('^' + rootURL + '(?=/|$)'), '');
    },

    /**
      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) {
      _emberMetalProperty_set.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) {
      _emberMetalProperty_set.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) {
      var rootURL = _emberMetalProperty_get.get(this, 'rootURL');

      if (url !== '') {
        // remove trailing slashes if they exists
        rootURL = rootURL.replace(/\/$/, '');
      }

      return rootURL + url;
    }
  });
});
enifed('ember-routing/location/util', ['exports'], function (exports) {
  /**
    @private

    Returns the current `location.pathname`, normalized for IE inconsistencies.
  */
  'use strict';

  exports.getPath = getPath;
  exports.getQuery = getQuery;
  exports.getHash = getHash;
  exports.getFullPath = getFullPath;
  exports.getOrigin = getOrigin;
  exports.supportsHashChange = supportsHashChange;
  exports.supportsHistory = supportsHistory;
  exports.replacePath = replacePath;

  function getPath(location) {
    var pathname = location.pathname;
    // Various versions of IE/Opera don't always return a leading slash
    if (pathname.charAt(0) !== '/') {
      pathname = '/' + pathname;
    }

    return pathname;
  }

  /**
    @private

    Returns the current `location.search`.
  */

  function getQuery(location) {
    return location.search;
  }

  /**
    @private

    Returns the current `location.hash` by parsing location.href since browsers
    inconsistently URL-decode `location.hash`.

    Should be passed the browser's `location` object as the first argument.

    https://bugzilla.mozilla.org/show_bug.cgi?id=483304
  */

  function getHash(location) {
    var href = location.href;
    var hashIndex = href.indexOf('#');

    if (hashIndex === -1) {
      return '';
    } else {
      return href.substr(hashIndex);
    }
  }

  function getFullPath(location) {
    return getPath(location) + getQuery(location) + getHash(location);
  }

  function getOrigin(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;
  }

  /*
    `documentMode` only exist in Internet Explorer, and it's tested because IE8 running in
    IE7 compatibility mode claims to support `onhashchange` but actually does not.

    `global` is an object that may have an `onhashchange` property.

    @private
    @function supportsHashChange
  */

  function supportsHashChange(documentMode, global) {
    return 'onhashchange' in global && (documentMode === undefined || documentMode > 7);
  }

  /*
    `userAgent` is a user agent string. We use user agent testing here, because
    the stock Android browser is known to have buggy versions of the History API,
    in some Android versions.

    @private
    @function supportsHistory
  */

  function supportsHistory(userAgent, history) {
    // Boosted from Modernizr: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/history.js
    // The stock browser on Android 2.2 & 2.3, and 4.0.x 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 :(

    // We only want Android 2 and 4.0, stock browser, and not Chrome which identifies
    // itself as 'Mobile Safari' as well, nor Windows Phone.
    if ((userAgent.indexOf('Android 2.') !== -1 || userAgent.indexOf('Android 4.0') !== -1) && userAgent.indexOf('Mobile Safari') !== -1 && userAgent.indexOf('Chrome') === -1 && userAgent.indexOf('Windows Phone') === -1) {
      return false;
    }

    return !!(history && 'pushState' in history);
  }

  /**
    Replaces the current location, making sure we explicitly include the origin
    to prevent redirecting to a different origin.

    @private
  */

  function replacePath(location, path) {
    location.replace(getOrigin(location) + path);
  }
});
enifed('ember-routing/services/routing', ['exports', 'ember-runtime/system/service', 'ember-metal/property_get', 'ember-metal/computed_macros', 'ember-routing/utils', 'ember-metal/assign'], function (exports, _emberRuntimeSystemService, _emberMetalProperty_get, _emberMetalComputed_macros, _emberRoutingUtils, _emberMetalAssign) {
  /**
  @module ember
  @submodule ember-routing
  */

  'use strict';

  /**
    The Routing service is used by LinkComponent, and provides facilities for
    the component/view layer to interact with the router.

    While still private, this service can eventually be opened up, and provides
    the set of API needed for components to control routing without interacting
    with router internals.

    @private
    @class RoutingService
  */
  exports.default = _emberRuntimeSystemService.default.extend({
    router: null,

    targetState: _emberMetalComputed_macros.readOnly('router.targetState'),
    currentState: _emberMetalComputed_macros.readOnly('router.currentState'),
    currentRouteName: _emberMetalComputed_macros.readOnly('router.currentRouteName'),
    currentPath: _emberMetalComputed_macros.readOnly('router.currentPath'),

    availableRoutes: function () {
      return Object.keys(_emberMetalProperty_get.get(this, 'router').router.recognizer.names);
    },

    hasRoute: function (routeName) {
      return _emberMetalProperty_get.get(this, 'router').hasRoute(routeName);
    },

    transitionTo: function (routeName, models, queryParams, shouldReplace) {
      var router = _emberMetalProperty_get.get(this, 'router');

      var transition = router._doTransition(routeName, models, queryParams);

      if (shouldReplace) {
        transition.method('replace');
      }
    },

    normalizeQueryParams: function (routeName, models, queryParams) {
      var router = _emberMetalProperty_get.get(this, 'router');
      router._prepareQueryParams(routeName, models, queryParams);
    },

    generateURL: function (routeName, models, queryParams) {
      var router = _emberMetalProperty_get.get(this, 'router');
      if (!router.router) {
        return;
      }

      var visibleQueryParams = {};
      _emberMetalAssign.default(visibleQueryParams, queryParams);

      this.normalizeQueryParams(routeName, models, visibleQueryParams);

      var args = _emberRoutingUtils.routeArgs(routeName, models, visibleQueryParams);
      return router.generate.apply(router, args);
    },

    isActiveForRoute: function (contexts, queryParams, routeName, routerState, isCurrentWhenSpecified) {
      var router = _emberMetalProperty_get.get(this, 'router');

      var handlers = router.router.recognizer.handlersFor(routeName);
      var leafName = handlers[handlers.length - 1].handler;
      var maximumContexts = numberOfContextsAcceptedByHandler(routeName, 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) {
        routeName = leafName;
      }

      return routerState.isActiveIntent(routeName, contexts, queryParams, !isCurrentWhenSpecified);
    }
  });

  function numberOfContextsAcceptedByHandler(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;
  }
});
enifed('ember-routing/system/cache', ['exports', 'ember-runtime/system/object'], function (exports, _emberRuntimeSystemObject) {
  'use strict';

  exports.default = _emberRuntimeSystemObject.default.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
  });
});
enifed("ember-routing/system/controller_for", ["exports"], function (exports) {
  /**
  @module ember
  @submodule ember-routing
  */

  /**
    Finds a controller instance.

    @for Ember
    @method controllerFor
    @private
  */
  "use strict";

  exports.default = controllerFor;

  function controllerFor(container, controllerName, lookupOptions) {
    return container.lookup("controller:" + controllerName, lookupOptions);
  }
});
enifed('ember-routing/system/dsl', ['exports', 'ember-metal/debug'], function (exports, _emberMetalDebug) {
  'use strict';

  /**
  @module ember
  @submodule ember-routing
  */

  function DSL(name, options) {
    this.parent = name;
    this.enableLoadingSubstates = options && options.enableLoadingSubstates;
    this.matches = [];
    this.explicitIndex = undefined;
    this.options = options;
  }

  exports.default = DSL;

  DSL.prototype = {
    route: function (name, options, callback) {
      var dummyErrorRoute = '/_unused_dummy_error_path_route_' + name + '/:error';
      if (arguments.length === 2 && typeof options === 'function') {
        callback = options;
        options = {};
      }

      if (arguments.length === 1) {
        options = {};
      }

      _emberMetalDebug.assert('\'' + name + '\' cannot be used as a route name.', (function () {
        if (options.overrideNameAssertion === true) {
          return true;
        }

        return ['array', 'basic', 'object', 'application'].indexOf(name) === -1;
      })());

      if (this.enableLoadingSubstates) {
        createRoute(this, name + '_loading', { resetNamespace: options.resetNamespace });
        createRoute(this, name + '_error', { path: dummyErrorRoute });
      }

      if (callback) {
        var fullName = getFullName(this, name, options.resetNamespace);
        var dsl = new DSL(fullName, this.options);

        createRoute(dsl, 'loading');
        createRoute(dsl, 'error', { path: dummyErrorRoute });

        callback.call(dsl);

        createRoute(this, name, options, dsl.generate());
      } else {
        createRoute(this, name, options);
      }
    },

    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;
      _emberMetalDebug.deprecate('this.resource() is deprecated. Use this.route(\'name\', { resetNamespace: true }, function () {}) instead.', false, { id: 'ember-routing.router-resource', until: '3.0.0' });
      this.route(name, options, callback);
    },

    generate: function () {
      var dslMatches = this.matches;

      if (!this.explicitIndex) {
        this.route('index', { path: '/' });
      }

      return function (match) {
        for (var i = 0, l = dslMatches.length; i < l; i++) {
          var dslMatch = dslMatches[i];
          match(dslMatch[0]).to(dslMatch[1], dslMatch[2]);
        }
      };
    }
  };

  function canNest(dsl) {
    return dsl.parent && dsl.parent !== 'application';
  }

  function getFullName(dsl, name, resetNamespace) {
    if (canNest(dsl) && resetNamespace !== true) {
      return dsl.parent + '.' + name;
    } else {
      return name;
    }
  }

  function createRoute(dsl, name, options, callback) {
    options = options || {};

    var fullName = getFullName(dsl, name, options.resetNamespace);

    if (typeof options.path !== 'string') {
      options.path = '/' + name;
    }

    dsl.push(options.path, fullName, callback);
  }

  DSL.map = function (callback) {
    var dsl = new DSL();
    callback.call(dsl);
    return dsl;
  };
});
enifed('ember-routing/system/generate_controller', ['exports', 'ember-metal/debug', 'ember-metal/property_get'], function (exports, _emberMetalDebug, _emberMetalProperty_get) {
  'use strict';

  exports.generateControllerFactory = generateControllerFactory;
  exports.default = generateController;

  /**
  @module ember
  @submodule ember-routing
  */

  /**
    Generates a controller factory

    @for Ember
    @method generateControllerFactory
    @private
  */

  function generateControllerFactory(owner, controllerName, context) {
    var Factory, fullName;

    Factory = owner._lookupFactory('controller:basic').extend({
      isGenerated: true,
      toString: function () {
        return '(generated ' + controllerName + ' controller)';
      }
    });

    fullName = 'controller:' + controllerName;

    owner.register(fullName, Factory);

    return Factory;
  }

  /**
    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
  */

  function generateController(owner, controllerName, context) {
    generateControllerFactory(owner, controllerName, context);

    var fullName = 'controller:' + controllerName;
    var instance = owner.lookup(fullName);

    if (_emberMetalProperty_get.get(instance, 'namespace.LOG_ACTIVE_GENERATION')) {
      _emberMetalDebug.info('generated -> ' + fullName, { fullName: fullName });
    }

    return instance;
  }
});
enifed('ember-routing/system/query_params', ['exports', 'ember-runtime/system/object'], function (exports, _emberRuntimeSystemObject) {
  'use strict';

  exports.default = _emberRuntimeSystemObject.default.extend({
    isQueryParams: true,
    values: null
  });
});
enifed('ember-routing/system/route', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-metal/features', 'ember-metal/error', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/get_properties', 'ember-metal/is_none', 'ember-metal/computed', 'ember-metal/assign', 'ember-runtime/utils', 'ember-metal/run_loop', 'ember-runtime/copy', 'ember-runtime/system/string', 'ember-runtime/system/object', 'ember-runtime/system/native_array', 'ember-runtime/mixins/evented', 'ember-runtime/mixins/action_handler', 'ember-routing/system/generate_controller', 'ember-routing/utils', 'container/owner', 'ember-metal/is_empty'], function (exports, _emberMetalCore, _emberMetalDebug, _emberMetalFeatures, _emberMetalError, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalGet_properties, _emberMetalIs_none, _emberMetalComputed, _emberMetalAssign, _emberRuntimeUtils, _emberMetalRun_loop, _emberRuntimeCopy, _emberRuntimeSystemString, _emberRuntimeSystemObject, _emberRuntimeSystemNative_array, _emberRuntimeMixinsEvented, _emberRuntimeMixinsAction_handler, _emberRoutingSystemGenerate_controller, _emberRoutingUtils, _containerOwner, _emberMetalIs_empty) {
  'use strict';

  var slice = Array.prototype.slice;

  function K() {
    return this;
  }

  /**
  @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
    @uses Ember.Evented
    @public
  */
  var Route = _emberRuntimeSystemObject.default.extend(_emberRuntimeMixinsAction_handler.default, _emberRuntimeMixinsEvented.default, {
    /**
      Configuration hash for this route's queryParams. The possible
      configuration options and their defaults are as follows
      (assuming a query param whose controller property is `page`):
       ```javascript
      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,
           // By default, the query param URL key is the same name as
          // the controller property name. Use `as` to specify a
          // different URL key.
          as: 'page'
        }
      }
      ```
       @property queryParams
      @for Ember.Route
      @type Object
      @public
    */
    queryParams: {},

    /**
      The name of the route, dot-delimited.
       For example, a route found at `app/routes/posts/post.js` or
      `app/posts/post/route.js` (with pods) will have a `routeName` of
      `posts.post`.
       @property routeName
      @for Ember.Route
      @type String
      @public
    */

    /**
      @private
       @property _qp
    */
    _qp: _emberMetalComputed.computed(function () {
      var _this = this;

      var controllerProto, combinedQueryParameterConfiguration;

      var controllerName = this.controllerName || this.routeName;
      var definedControllerClass = _containerOwner.getOwner(this)._lookupFactory('controller:' + controllerName);
      var queryParameterConfiguraton = _emberMetalProperty_get.get(this, 'queryParams');
      var hasRouterDefinedQueryParams = !!Object.keys(queryParameterConfiguraton).length;

      if (definedControllerClass) {
        // the developer has authored a controller class in their application for this route
        // access the prototype, find its query params and normalize their object shape
        // them merge in the query params for the route. As a mergedProperty, Route#queryParams is always
        // at least `{}`
        controllerProto = definedControllerClass.proto();

        var controllerDefinedQueryParameterConfiguration = _emberMetalProperty_get.get(controllerProto, 'queryParams');
        var normalizedControllerQueryParameterConfiguration = _emberRoutingUtils.normalizeControllerQueryParams(controllerDefinedQueryParameterConfiguration);
        combinedQueryParameterConfiguration = mergeEachQueryParams(normalizedControllerQueryParameterConfiguration, queryParameterConfiguraton);
      } else if (hasRouterDefinedQueryParams) {
        // the developer has not defined a controller but *has* supplied route query params.
        // Generate a class for them so we can later insert default values
        var generatedControllerClass = _emberRoutingSystemGenerate_controller.generateControllerFactory(_containerOwner.getOwner(this), controllerName);
        controllerProto = generatedControllerClass.proto();
        combinedQueryParameterConfiguration = queryParameterConfiguraton;
      }

      var qps = [];
      var map = {};
      var propertyNames = [];

      for (var propName in combinedQueryParameterConfiguration) {
        if (!combinedQueryParameterConfiguration.hasOwnProperty(propName)) {
          continue;
        }

        // to support the dubious feature of using unknownProperty
        // on queryParams configuration
        if (propName === 'unknownProperty' || propName === '_super') {
          // possible todo: issue deprecation warning?
          continue;
        }

        var desc = combinedQueryParameterConfiguration[propName];

        var scope = desc.scope || 'model';
        var parts;

        if (scope === 'controller') {
          parts = [];
        }

        var urlKey = desc.as || this.serializeQueryParamKey(propName);
        var defaultValue = _emberMetalProperty_get.get(controllerProto, propName);

        if (Array.isArray(defaultValue)) {
          defaultValue = _emberRuntimeSystemNative_array.A(defaultValue.slice());
        }

        var type = desc.type || _emberRuntimeUtils.typeOf(defaultValue);

        var defaultValueSerialized = this.serializeQueryParam(defaultValue, urlKey, type);
        var scopedPropertyName = controllerName + ':' + propName;
        var qp = {
          undecoratedDefaultValue: _emberMetalProperty_get.get(controllerProto, propName),
          defaultValue: defaultValue,
          serializedDefaultValue: defaultValueSerialized,
          serializedValue: defaultValueSerialized,

          type: type,
          urlKey: urlKey,
          prop: propName,
          scopedPropertyName: scopedPropertyName,
          ctrl: controllerName,
          route: this,
          parts: parts, // provided later when stashNames is called if 'model' scope
          values: null, // provided later when setup is called. no idea why.
          scope: scope,
          prefix: ''
        };

        map[propName] = map[urlKey] = map[scopedPropertyName] = qp;
        qps.push(qp);
        propertyNames.push(propName);
      }

      return {
        qps: qps,
        map: map,
        propertyNames: propertyNames,
        states: {
          /*
            Called when a query parameter changes in the URL, this route cares
            about that query parameter, but the route is not currently
            in the active route hierarchy.
          */
          inactive: function (prop, value) {
            var qp = map[prop];
            _this._qpChanged(prop, value, qp);
          },
          /*
            Called when a query parameter changes in the URL, this route cares
            about that query parameter, and the route is currently
            in the active route hierarchy.
          */
          active: function (prop, value) {
            var qp = map[prop];
            _this._qpChanged(prop, value, qp);
            return _this._activeQPChanged(map[prop], value);
          },
          /*
            Called when a value of a query parameter this route handles changes in a controller
            and the route is currently in the active route hierarchy.
          */
          allowOverrides: function (prop, value) {
            var qp = map[prop];
            _this._qpChanged(prop, value, qp);
            return _this._updatingQPChanged(map[prop]);
          }
        }
      };
    }),

    /**
      @private
       @property _names
    */
    _names: null,

    /**
      @private
       @method _stashNames
    */
    _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 = _emberMetalProperty_get.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];
        if (qp.scope === 'model') {
          qp.parts = namePaths;
        }
        qp.prefix = qp.ctrl;
      }
    },

    /**
      @private
       @property _activeQPChanged
    */
    _activeQPChanged: function (qp, value) {
      var router = this.router;
      router._activeQPChanged(qp.scopedPropertyName, value);
    },

    /**
      @private
      @method _updatingQPChanged
    */
    _updatingQPChanged: function (qp) {
      var router = this.router;
      router._updatingQPChanged(qp.urlKey);
    },

    mergedProperties: ['queryParams'],

    /**
      Retrieves parameters, for current route using the state.params
      variable and getQueryParamsFor, using the supplied routeName.
       @method paramsFor
      @param {String} name
      @public
    */
    paramsFor: function (name) {
      var route = _containerOwner.getOwner(this).lookup('route:' + name);

      if (!route) {
        return {};
      }

      var transition = this.router.router.activeTransition;
      var state = transition ? transition.state : this.router.router.state;

      var params = {};
      _emberMetalAssign.default(params, state.params[name]);
      _emberMetalAssign.default(params, getQueryParamsFor(route, state));

      return params;
    },

    /**
      Serializes the query parameter key
       @method serializeQueryParamKey
      @param {String} controllerPropertyName
      @private
    */
    serializeQueryParamKey: function (controllerPropertyName) {
      return controllerPropertyName;
    },

    /**
      Serializes value of the query parameter based on defaultValueType
       @method serializeQueryParam
      @param {Object} value
      @param {String} urlKey
      @param {String} defaultValueType
      @private
    */
    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;
    },

    /**
      Deserializes value of the query parameter based on defaultValueType
       @method deserializeQueryParam
      @param {Object} value
      @param {String} urlKey
      @param {String} defaultValueType
      @private
    */
    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 _emberRuntimeSystemNative_array.A(JSON.parse(value));
      }
      return value;
    },

    /**
      @private
       @property _optionsForQueryParam
    */
    _optionsForQueryParam: function (qp) {
      return _emberMetalProperty_get.get(this, 'queryParams.' + qp.urlKey) || _emberMetalProperty_get.get(this, 'queryParams.' + qp.prop) || {};
    },

    /**
      A hook you can use to reset controller values either when the model
      changes or the route is exiting.
       ```javascript
      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
      @since 1.7.0
      @public
    */
    resetController: K,

    /**
      @private
       @method exit
    */
    exit: function () {
      this.deactivate();
      this.trigger('deactivate');
      this.teardownViews();
    },

    /**
      @private
       @method _reset
      @since 1.7.0
    */
    _reset: function (isExiting, transition) {
      var controller = this.controller;
      controller._qpDelegate = _emberMetalProperty_get.get(this, '_qp.states.inactive');

      this.resetController(controller, isExiting, transition);
    },

    /**
      @private
       @method enter
    */
    enter: function () {
      this.connections = [];
      this.activate();
      this.trigger('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:
       ```javascript
      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
      @public
    */
    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.
       ```javascript
      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
      @public
    */
    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
      @public
    */
    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:
       ```javascript
      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()`.
       To allow the `willTransition` event to continue bubbling to the parent
      route, use `return true;`. When the `willTransition` method has a
      return value of `true` then the parent route's `willTransition` method
      will be fired, enabling "bubbling" behavior for the event.
       @event willTransition
      @param {Transition} transition
      @public
    */

    /**
      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.
       ```javascript
      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
      @public
    */

    /**
      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.
       ```javascript
      App.ApplicationRoute = Ember.Route.extend({
        actions: {
          loading: function(transition, route) {
            let controller = this.controllerFor('foo');
            controller.set('currentlyLoading', true);
             transition.finally(function() {
              controller.set('currentlyLoading', false);
            });
          }
        }
      });
      ```
       @event loading
      @param {Transition} transition
      @param {Ember.Route} route The route that triggered the loading event
      @since 1.2.0
      @public
    */

    /**
      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:
       ```javascript
      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`:
       ```javascript
      App.ApplicationRoute = Ember.Route.extend({
        actions: {
          error: function(error, transition) {
            this.controllerFor('banner').displayError(error.message);
          }
        }
      });
      ```
      @event error
      @param {Error} error
      @param {Transition} transition
      @public
    */

    /**
      This event is triggered when the router enters the route. It is
      not executed when the model for the route changes.
       ```javascript
      App.ApplicationRoute = Ember.Route.extend({
        collectAnalytics: function(){
          collectAnalytics();
        }.on('activate')
      });
      ```
       @event activate
      @since 1.9.0
      @public
    */

    /**
      This event is triggered when the router completely exits this
      route. It is not executed when the model for the route changes.
       ```javascript
      App.IndexRoute = Ember.Route.extend({
        trackPageLeaveAnalytics: function(){
          trackPageLeaveAnalytics();
        }.on('deactivate')
      });
      ```
       @event deactivate
      @since 1.9.0
      @public
    */

    /**
      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
      @public
    */

    actions: {

      queryParamsDidChange: function (changed, totalPresent, removed) {
        var qpMap = _emberMetalProperty_get.get(this, '_qp').map;

        var totalChanged = Object.keys(changed).concat(Object.keys(removed));
        for (var i = 0, len = totalChanged.length; i < len; ++i) {
          var qp = qpMap[totalChanged[i]];
          if (qp && _emberMetalProperty_get.get(this._optionsForQueryParam(qp), 'refreshModel') && this.router.currentState) {
            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;

        _emberRoutingUtils.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) {
            // Value updated in/before setupController
            value = _emberMetalProperty_get.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.serializedDefaultValue;
              value = copyDefaultValue(qp.defaultValue);
            }
          }

          controller._qpDelegate = _emberMetalProperty_get.get(route, '_qp.states.inactive');

          var thisQueryParamChanged = svalue !== qp.serializedValue;
          if (thisQueryParamChanged) {
            if (transition.queryParamsOnly && replaceUrl !== false) {
              var options = route._optionsForQueryParam(qp);
              var replaceConfigValue = _emberMetalProperty_get.get(options, 'replace');
              if (replaceConfigValue) {
                replaceUrl = true;
              } else if (replaceConfigValue === false) {
                // Explicit pushState wins over any other replaceStates.
                replaceUrl = false;
              }
            }

            _emberMetalProperty_set.set(controller, qp.prop, value);
          }

          // Stash current serialized value of controller.
          qp.serializedValue = svalue;

          var thisQueryParamHasDefaultValue = qp.serializedDefaultValue === svalue;
          if (!thisQueryParamHasDefaultValue) {
            finalParams.push({
              value: svalue,
              visible: true,
              key: presentKey || qp.urlKey
            });
          }
        }

        if (replaceUrl) {
          transition.method('replace');
        }

        qpMeta.qps.forEach(function (qp) {
          var routeQpMeta = _emberMetalProperty_get.get(qp.route, '_qp');
          var finalizedController = qp.route.controller;
          finalizedController._qpDelegate = _emberMetalProperty_get.get(routeQpMeta, 'states.active');
        });

        router._qpUpdates = null;
      }
    },

    /**
      This hook is executed when the router completely exits this route. It is
      not executed when the model for the route changes.
       @method deactivate
      @public
    */
    deactivate: K,

    /**
      This hook is executed when the router enters the route. It is not executed
      when the model for the route changes.
       @method activate
      @public
    */
    activate: 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
      route tree.
       ```javascript
      App.Router.map(function() {
        this.route('blogPost', { path:':blogPostId' }, function() {
          this.route('blogComment', { path: ':blogCommentId', resetNamespace: true });
        });
      });
       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');
      this.transitionTo('/blog/posts?sort=title');
      ```
       An options hash with a `queryParams` property may be provided as
      the final argument to add query parameters to the destination URL.
       ```javascript
      this.transitionTo('blogPost', 1, {
        queryParams: {showComments: 'true'}
      });
       // if you just want to transition the query parameters without changing the route
      this.transitionTo({queryParams: {sort: 'date'}});
      ```
       See also [replaceWith](#method_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);
            } else {
              this.transitionTo('fourOhFour');
            }
          }
        }
      });
      ```
       Transition to a nested route
       ```javascript
      App.Router.map(function() {
        this.route('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.route('breakfast', { path: ':breakfastId' }, function() {
          this.route('cereal', { path: ':cerealId', resetNamespace: true });
        });
      });
       App.IndexRoute = Ember.Route.extend({
        actions: {
          moveToChocolateCereal: function() {
            var cereal = { cerealId: 'ChocolateYumminess' };
            var breakfast = { breakfastId: 'CerealAndMilk' };
             this.transitionTo('cereal', breakfast, cereal);
          }
        }
      });
      ```
       Nested Route with Query String Example
       ```javascript
      App.Router.map(function() {
        this.route('fruits', function() {
          this.route('apples');
        });
      });
       App.IndexRoute = Ember.Route.extend({
        actions: {
          transitionToApples: function() {
            this.transitionTo('fruits.apples', {queryParams: {color: 'red'}});
          }
        }
      });
      ```
       @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.
      @param {Object} [options] optional hash with a queryParams property
        containing a mapping of query parameters
      @return {Transition} the transition object associated with this
        attempted transition
      @public
    */
    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
      @public
     */
    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
      @public
     */
    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
      @public
    */
    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
      @public
    */
    send: function () {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      if (this.router && this.router.router || !_emberMetalCore.default.testing) {
        var _router;

        (_router = this.router).send.apply(_router, args);
      } else {
        var name = args[0];
        args = slice.call(args, 1);
        var action = this.actions[name];
        if (action) {
          return this.actions[name].apply(this, args);
        }
      }
    },

    /**
      This hook is the entry point for router.js
       @private
      @method setup
    */
    setup: function (context, transition) {
      var controller;

      var controllerName = this.controllerName || this.routeName;
      var definedController = this.controllerFor(controllerName, true);

      if (!definedController) {
        controller = this.generateController(controllerName, context);
      } else {
        controller = definedController;
      }

      // Assign the route's controller so that it can more easily be
      // referenced in action handlers. Side effects. Side effects everywhere.
      if (!this.controller) {
        var propNames = _emberMetalProperty_get.get(this, '_qp.propertyNames');
        addQueryParamsObservers(controller, propNames);
        this.controller = controller;
      }

      var queryParams = _emberMetalProperty_get.get(this, '_qp');

      var states = queryParams.states;
      if (transition) {
        // Update the model dep values used to calculate cache keys.
        _emberRoutingUtils.stashParamNames(this.router, transition.state.handlerInfos);

        var params = transition.params;
        var allParams = queryParams.propertyNames;
        var cache = this._bucketCache;

        allParams.forEach(function (prop) {
          var aQp = queryParams.map[prop];

          aQp.values = params;
          var cacheKey = _emberRoutingUtils.calculateCacheKey(aQp.prefix, aQp.parts, aQp.values);

          if (cache) {
            var value = cache.lookup(cacheKey, prop, aQp.undecoratedDefaultValue);
            _emberMetalProperty_set.set(controller, prop, value);
          }
        });
      }

      controller._qpDelegate = states.allowOverrides;

      if (transition) {
        var qpValues = getQueryParamsFor(this, transition.state);
        controller.setProperties(qpValues);
      }

      this.setupController(controller, context, transition);

      if (!this._environment || this._environment.options.shouldRender) {
        this.renderTemplate(controller, context);
      }
    },

    /*
      Called when a query parameter for this route changes, regardless of whether the route
      is currently part of the active route hierarchy. This will update the query parameter's
      value in the cache so if this route becomes active, the cache value has been updated.
    */
    _qpChanged: function (prop, value, qp) {
      if (!qp) {
        return;
      }

      var cacheKey = _emberRoutingUtils.calculateCacheKey(qp.prefix || '', qp.parts, qp.values);

      // Update model-dep cache
      var cache = this._bucketCache;
      if (cache) {
        cache.stash(cacheKey, prop, value);
      }
    },
    /**
      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.
       ```javascript
      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):
       ```javascript
      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
              return Ember.RSVP.reject(e);
            });
          }
        }
      });
      ```
       @method beforeModel
      @param {Transition} transition
      @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.
      @public
    */
    beforeModel: 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.
       ```javascript
      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
      @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.
      @public
     */
    afterModel: 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
      @param {Transition} transition the transition object associated with the current transition
      @public
    */
    redirect: 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.
       ```javascript
      App.Router.map(function() {
        this.route('post', { path: '/posts/:post_id' });
      });
      ```
       The model for the `post` route is `store.findRecord('post', 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 not always
      executed. If the route is entered through a transition (e.g. when
      using the `link-to` Handlebars helper or the `transitionTo` method
      of routes), and a model context is already provided this hook
      is not called.
       A model context does not include a primitive string or number,
      which does cause the model hook to be called.
       Routes without dynamic segments will always execute the model hook.
       ```javascript
      // no dynamic segment, model hook always called
      this.transitionTo('posts');
       // model passed in, so model hook not called
      thePost = store.findRecord('post', 1);
      this.transitionTo('post', thePost);
       // integer passed in, model hook is called
      this.transitionTo('post', 1);
       // model id passed in, model hook is called
      // useful for forcing the hook to execute
      thePost = store.findRecord('post', 1);
      this.transitionTo('post', thePost.id);
      ```
        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
       ```javascript
      App.PostRoute = Ember.Route.extend({
        model: function(params) {
          return this.store.findRecord('post', params.post_id);
        }
      });
      ```
       @method model
      @param {Object} params the parameters extracted from the URL
      @param {Transition} transition
      @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.
      @public
    */
    model: function (params, transition) {
      var match, name, sawParams, value;
      var queryParams = _emberMetalProperty_get.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 _emberRuntimeCopy.default(params);
      } else if (!name) {
        if (transition.resolveIndex < 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
      @private
    */
    findModel: function () {
      var store = _emberMetalProperty_get.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
      @private
    */
    store: _emberMetalComputed.computed(function () {
      var owner = _containerOwner.getOwner(this);
      var routeName = this.routeName;
      var namespace = _emberMetalProperty_get.get(this, 'router.namespace');

      return {
        find: function (name, value) {
          var modelClass = owner._lookupFactory('model:' + name);

          _emberMetalDebug.assert('You used the dynamic segment ' + name + '_id in your route ' + routeName + ', but ' + namespace + '.' + _emberRuntimeSystemString.classify(name) + ' did not exist and you did not override your route\'s `model` hook.', !!modelClass);

          if (!modelClass) {
            return;
          }

          _emberMetalDebug.assert(_emberRuntimeSystemString.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.
       ```javascript
      App.Router.map(function() {
        this.route('post', { path: '/posts/:post_id' });
      });
       App.PostRoute = Ember.Route.extend({
        model: function(params) {
          // the server returns `{ id: 12 }`
          return Ember.$.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 routes model
      @param {Array} params an Array of parameter names for the current
        route (in the example, `['post_id']`.
      @return {Object} the serialized parameters
      @public
    */
    serialize: function (model, params) {
      if (params.length < 1) {
        return;
      }
      if (!model) {
        return;
      }

      var name = params[0];
      var object = {};

      if (params.length === 1) {
        if (name in model) {
          object[name] = _emberMetalProperty_get.get(model, name);
        } else if (/_id$/.test(name)) {
          object[name] = _emberMetalProperty_get.get(model, 'id');
        }
      } else {
        object = _emberMetalGet_properties.default(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`:
       ```javascript
      App.PhotosRoute = Ember.Route.extend({
        model: function() {
          return this.store.findAll('photo');
        },
         setupController: function(controller, model) {
          // Call _super for default behavior
          this._super(controller, model);
          // Implement your custom setup after
          this.controllerFor('application').set('showingPhotos', true);
        }
      });
      ```
       The provided controller will be one resolved based on the name
      of this route.
       If no explicit controller is defined, Ember will automatically create one.
       As an example, consider the router:
       ```javascript
      App.Router.map(function() {
        this.route('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, a basic `Ember.Controller`
      instance would be used.
       Example
       ```javascript
      App.PostRoute = Ember.Route.extend({
        setupController: function(controller, model) {
          controller.set('model', model);
        }
      });
      ```
       @method setupController
      @param {Controller} controller instance
      @param {Object} model
      @public
    */
    setupController: function (controller, context, transition) {
      if (controller && context !== undefined) {
        _emberMetalProperty_set.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`.
       ```javascript
      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}
      @public
    */
    controllerFor: function (name, _skipAssert) {
      var owner = _containerOwner.getOwner(this);
      var route = owner.lookup('route:' + name);
      var controller;

      if (route && route.controllerName) {
        name = route.controllerName;
      }

      controller = owner.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.
      _emberMetalDebug.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.
       Example
       ```javascript
      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)
      @private
    */
    generateController: function (name, model) {
      var owner = _containerOwner.getOwner(this);

      model = model || this.modelFor(name);

      return _emberRoutingSystemGenerate_controller.default(owner, name, model);
    },

    /**
      Returns the resolved 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. If the ancestor route's model was a promise,
      its resolved result is returned.
       Example
       ```javascript
      App.Router.map(function() {
          this.route('post', { path: '/post/:post_id' }, function() {
            this.route('comments', { resetNamespace: true });
          });
      });
       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
      @public
    */
    modelFor: function (name) {
      var route = _containerOwner.getOwner(this).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.
       ```javascript
      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
      @public
    */
    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:
       ```javascript
      Router.map(function() {
        this.route('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`:
       ```javascript
      // posts route
      Ember.Route.extend({
        renderTemplate: function() {
          this.render('photos', {
            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.
        ```javascript
      // 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 `templateName` properties.
       For example:
       ```javascript
      // router
      Router.map(function() {
        this.route('index');
        this.route('post', { path: '/posts/:post_id' });
      });
      ```
       ```javascript
      // 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`:
       ```javascript
      //
      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|Object} [options.controller] the controller to use for this template,
                      referenced by name or as a controller instance. Defaults to the Route's paired controller
      @param {Object} [options.model] the model object to set on `options.controller`.
                      Defaults to the return value of the Route's model hook
      @public
    */
    render: function (_name, options) {
      _emberMetalDebug.assert('The name in the given arguments is undefined', arguments.length > 0 ? !_emberMetalIs_none.default(arguments[0]) : true);

      var namePassed = typeof _name === 'string' && !!_name;
      var isDefaultRender = arguments.length === 0 || _emberMetalIs_empty.default(arguments[0]);
      var name;

      if (typeof _name === 'object' && !options) {
        name = this.routeName;
        options = _name;
      } else {
        name = _name;
      }

      var renderOptions = buildRenderOptions(this, namePassed, isDefaultRender, name, options);
      this.connections.push(renderOptions);
      _emberMetalRun_loop.default.once(this.router, '_setOutlets');
    },

    /**
      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:
       ```javascript
      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:
       ```javascript
      hideModal: function(evt) {
        this.disconnectOutlet('modal');
      }
      ```
       @method disconnectOutlet
      @param {Object|String} options the options hash or outlet name
      @public
    */
    disconnectOutlet: function (options) {
      var outletName;
      var parentView;
      if (!options || typeof options === 'string') {
        outletName = options;
      } else {
        outletName = options.outlet;
        parentView = options.parentView;

        if (options && Object.keys(options).indexOf('outlet') !== -1 && typeof options.outlet === 'undefined') {
          throw new _emberMetalError.default('You passed undefined as the outlet name.');
        }
      }
      parentView = parentView && parentView.replace(/\//g, '.');
      outletName = outletName || 'main';
      this._disconnectOutlet(outletName, parentView);
      for (var i = 0; i < this.router.router.currentHandlerInfos.length; i++) {
        // This non-local state munging is sadly necessary to maintain
        // backward compatibility with our existing semantics, which allow
        // any route to disconnectOutlet things originally rendered by any
        // other route. This should all get cut in 2.0.
        this.router.router.currentHandlerInfos[i].handler._disconnectOutlet(outletName, parentView);
      }
    },

    _disconnectOutlet: function (outletName, parentView) {
      var parent = parentRoute(this);
      if (parent && parentView === parent.routeName) {
        parentView = undefined;
      }
      for (var i = 0; i < this.connections.length; i++) {
        var connection = this.connections[i];
        if (connection.outlet === outletName && connection.into === parentView) {
          // This neuters the disconnected outlet such that it doesn't
          // render anything, but it leaves an entry in the outlet
          // hierarchy so that any existing other renders that target it
          // don't suddenly blow up. They will still stick themselves
          // into its outlets, which won't render anywhere. All of this
          // statefulness should get the machete in 2.0.
          this.connections[i] = {
            owner: connection.owner,
            into: connection.into,
            outlet: connection.outlet,
            name: connection.name,
            controller: undefined,
            template: undefined,
            ViewClass: undefined
          };
          _emberMetalRun_loop.default.once(this.router, '_setOutlets');
        }
      }
    },

    willDestroy: function () {
      this.teardownViews();
    },

    /**
      @private
       @method teardownViews
    */
    teardownViews: function () {
      if (this.connections && this.connections.length > 0) {
        this.connections = [];
        _emberMetalRun_loop.default.once(this.router, '_setOutlets');
      }
    }
  });

  _emberRuntimeMixinsAction_handler.deprecateUnderscoreActions(Route);

  Route.reopenClass({
    isRouteFactory: true
  });

  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;
    var current;
    for (var i = 0, l = handlerInfos.length; i < l; i++) {
      current = handlerInfos[i].handler;
      if (current === route) {
        return handlerInfos[i + offset];
      }
    }
  }

  function buildRenderOptions(route, namePassed, isDefaultRender, name, options) {
    var controller = options && options.controller;
    var templateName;
    var viewName;
    var ViewClass;
    var template;
    var LOG_VIEW_LOOKUPS = _emberMetalProperty_get.get(route.router, 'namespace.LOG_VIEW_LOOKUPS');
    var into = options && options.into && options.into.replace(/\//g, '.');
    var outlet = options && options.outlet || 'main';
    var owner = _containerOwner.getOwner(route);

    if (name) {
      name = name.replace(/\//g, '.');
      templateName = name;
    } else {
      name = route.routeName;
      templateName = route.templateName || name;
    }

    if (!controller) {
      if (namePassed) {
        controller = owner.lookup('controller:' + name) || route.controllerName || route.routeName;
      } else {
        controller = route.controllerName || owner.lookup('controller:' + name);
      }
    }

    if (typeof controller === 'string') {
      var controllerName = controller;
      controller = owner.lookup('controller:' + controllerName);
      if (!controller) {
        throw new _emberMetalError.default('You passed `controller: \'' + controllerName + '\'` into the `render` method, but no such controller could be found.');
      }
    }

    if (options && Object.keys(options).indexOf('outlet') !== -1 && typeof options.outlet === 'undefined') {
      throw new _emberMetalError.default('You passed undefined as the outlet name.');
    }

    if (options && options.model) {
      controller.set('model', options.model);
    }

    viewName = options && options.view || namePassed && name || route.viewName || name;
    ViewClass = owner._lookupFactory('view:' + viewName);
    template = owner.lookup('template:' + templateName);

    var parent;
    if (into && (parent = parentRoute(route)) && into === parentRoute(route).routeName) {
      into = undefined;
    }

    var renderOptions = {
      owner: owner,
      into: into,
      outlet: outlet,
      name: name,
      controller: controller,
      ViewClass: ViewClass,
      template: template || route._topLevelViewTemplate
    };

    var Component = undefined;

    if (!ViewClass && !template && !Component) {
      _emberMetalDebug.assert('Could not find "' + name + '" template, view, or component.', isDefaultRender);
      if (LOG_VIEW_LOOKUPS) {
        var fullName = 'template:' + name;
        _emberMetalDebug.info('Could not find "' + name + '" template or view. Nothing will be rendered', { fullName: fullName });
      }
    }

    return renderOptions;
  }

  function getFullQueryParams(router, state) {
    if (state.fullQueryParams) {
      return state.fullQueryParams;
    }

    state.fullQueryParams = {};
    _emberMetalAssign.default(state.fullQueryParams, state.queryParams);

    var targetRouteName = state.handlerInfos[state.handlerInfos.length - 1].name;
    router._deserializeQueryParams(targetRouteName, state.fullQueryParams);
    return state.fullQueryParams;
  }

  function getQueryParamsFor(route, state) {
    state.queryParamsFor = state.queryParamsFor || {};
    var name = route.routeName;

    if (state.queryParamsFor[name]) {
      return state.queryParamsFor[name];
    }

    var fullQueryParams = getFullQueryParams(route.router, state);

    var params = state.queryParamsFor[name] = {};

    // Copy over all the query params for this route/controller into params hash.
    var qpMeta = _emberMetalProperty_get.get(route, '_qp');
    var qps = qpMeta.qps;
    for (var i = 0, len = qps.length; i < len; ++i) {
      // Put deserialized qp on params hash.
      var qp = qps[i];

      var qpValueWasPassedIn = (qp.prop in fullQueryParams);
      params[qp.prop] = qpValueWasPassedIn ? fullQueryParams[qp.prop] : copyDefaultValue(qp.defaultValue);
    }

    return params;
  }

  function copyDefaultValue(value) {
    if (Array.isArray(value)) {
      return _emberRuntimeSystemNative_array.A(value.slice());
    }
    return value;
  }

  /*
    Merges all query parameters from a controller with those from
    a route, returning a new object and avoiding any mutations to
    the existing objects.
  */
  function mergeEachQueryParams(controllerQP, routeQP) {
    var keysAlreadyMergedOrSkippable;
    var qps = {};

    keysAlreadyMergedOrSkippable = {
      defaultValue: true,
      type: true,
      scope: true,
      as: true
    };

    // first loop over all controller qps, merging them with any matching route qps
    // into a new empty object to avoid mutating.
    for (var cqpName in controllerQP) {
      if (!controllerQP.hasOwnProperty(cqpName)) {
        continue;
      }

      var newControllerParameterConfiguration = {};
      _emberMetalAssign.default(newControllerParameterConfiguration, controllerQP[cqpName]);
      _emberMetalAssign.default(newControllerParameterConfiguration, routeQP[cqpName]);

      qps[cqpName] = newControllerParameterConfiguration;

      // allows us to skip this QP when we check route QPs.
      keysAlreadyMergedOrSkippable[cqpName] = true;
    }

    // loop over all route qps, skipping those that were merged in the first pass
    // because they also appear in controller qps
    for (var rqpName in routeQP) {
      if (!routeQP.hasOwnProperty(rqpName) || keysAlreadyMergedOrSkippable[rqpName]) {
        continue;
      }

      var newRouteParameterConfiguration = {};
      _emberMetalAssign.default(newRouteParameterConfiguration, routeQP[rqpName], controllerQP[rqpName]);
      qps[rqpName] = newRouteParameterConfiguration;
    }

    return qps;
  }

  function addQueryParamsObservers(controller, propNames) {
    propNames.forEach(function (prop) {
      controller.addObserver(prop + '.[]', controller, controller._qpChanged);
    });
  }

  function deprecateQueryParamDefaultValuesSetOnController(controllerName, routeName, propName) {
    _emberMetalDebug.deprecate('Configuring query parameter default values on controllers is deprecated. Please move the value for the property \'' + propName + '\' from the \'' + controllerName + '\' controller to the \'' + routeName + '\' route in the format: {queryParams: ' + propName + ': {defaultValue: <default value> }}', false, { id: 'ember-routing.deprecate-query-param-default-values-set-on-controller', until: '3.0.0' });
  }

  exports.default = Route;
});
// FEATURES, A, deprecate, assert, Logger

// apply default values to controllers
// detect that default value defined on router config

// detect that property was not defined on controller
enifed('ember-routing/system/router', ['exports', 'ember-metal/logger', 'ember-metal/debug', 'ember-metal/error', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/properties', 'ember-metal/empty_object', 'ember-metal/computed', 'ember-metal/assign', 'ember-metal/run_loop', 'ember-runtime/system/object', 'ember-runtime/mixins/evented', 'ember-routing/system/dsl', 'ember-routing/location/api', 'ember-routing/utils', 'ember-metal/utils', 'ember-routing/system/router_state', 'container/owner', 'ember-metal/dictionary', 'router', 'router/transition'], function (exports, _emberMetalLogger, _emberMetalDebug, _emberMetalError, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalProperties, _emberMetalEmpty_object, _emberMetalComputed, _emberMetalAssign, _emberMetalRun_loop, _emberRuntimeSystemObject, _emberRuntimeMixinsEvented, _emberRoutingSystemDsl, _emberRoutingLocationApi, _emberRoutingUtils, _emberMetalUtils, _emberRoutingSystemRouter_state, _containerOwner, _emberMetalDictionary, _router4, _routerTransition) {
  'use strict';

  exports.triggerEvent = triggerEvent;

  function K() {
    return this;
  }

  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
    @uses Ember.Evented
    @public
  */
  var EmberRouter = _emberRuntimeSystemObject.default.extend(_emberRuntimeMixinsEvented.default, {
    /**
      The `location` property determines the type of URL's that your
      application will use.
       The following location types are currently available:
       * `history` - use the browser's history API to make the URLs look just like any standard URL
      * `hash` - use `#` to separate the server part of the URL from the Ember part: `/blog/#/posts/new`
      * `none` - do not store the Ember URL in the actual browser URL (mainly used for testing)
      * `auto` - use the best option based on browser capabilites: `history` if possible, then `hash` if possible, otherwise `none`
       Note: If using ember-cli, this value is defaulted to `auto` by the `locationType` setting of `/config/environment.js`
       @property location
      @default 'hash'
      @see {Ember.Location}
      @public
    */
    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 '/'
     @public
    */
    rootURL: '/',

    _initRouterJs: function () {
      var router = this.router = new _router4.default();
      router.triggerEvent = triggerEvent;

      router._triggerWillChangeContext = K;
      router._triggerWillLeave = K;

      var dslCallbacks = this.constructor.dslCallbacks || [K];
      var dsl = this._buildDSL();

      dsl.route('application', { path: '/', resetNamespace: true, overrideNameAssertion: true }, function () {
        for (var i = 0; i < dslCallbacks.length; i++) {
          dslCallbacks[i].call(this);
        }
      });

      if (_emberMetalProperty_get.get(this, 'namespace.LOG_TRANSITIONS_INTERNAL')) {
        router.log = _emberMetalLogger.default.debug;
      }

      router.map(dsl.generate());
    },

    _buildDSL: function () {
      var moduleBasedResolver = this._hasModuleBasedResolver();

      return new _emberRoutingSystemDsl.default(null, {
        enableLoadingSubstates: !!moduleBasedResolver
      });
    },

    init: function () {
      this._super.apply(this, arguments);

      this._activeViews = {};
      this._qpCache = new _emberMetalEmpty_object.default();
      this._resetQueuedQueryParameterChanges();
      this._handledErrors = _emberMetalDictionary.default(null);
    },

    /*
      Resets all pending query paramter changes.
      Called after transitioning to a new route
      based on query parameter changes.
    */
    _resetQueuedQueryParameterChanges: function () {
      this._queuedQPChanges = {};
    },

    /**
      Represents the current URL.
       @method url
      @return {String} The current URL.
      @private
    */
    url: _emberMetalComputed.computed(function () {
      return _emberMetalProperty_get.get(this, 'location').getURL();
    }),

    _hasModuleBasedResolver: function () {
      var owner = _containerOwner.getOwner(this);

      if (!owner) {
        return false;
      }

      var resolver = owner.application && owner.application.__registry__ && owner.application.__registry__.resolver;

      if (!resolver) {
        return false;
      }

      return !!resolver.moduleBasedResolver;
    },

    /**
      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 () {
      var initialURL = _emberMetalProperty_get.get(this, 'initialURL');

      if (this.setupRouter()) {
        if (typeof initialURL === 'undefined') {
          initialURL = _emberMetalProperty_get.get(this, 'location').getURL();
        }
        var initialTransition = this.handleURL(initialURL);
        if (initialTransition && initialTransition.error) {
          throw initialTransition.error;
        }
      }
    },

    setupRouter: function () {
      var _this = this;

      this._initRouterJs();
      this._setupLocation();

      var router = this.router;
      var location = _emberMetalProperty_get.get(this, 'location');

      // Allow the Location class to cancel the router setup while it refreshes
      // the page
      if (_emberMetalProperty_get.get(location, 'cancelRouterSetup')) {
        return false;
      }

      this._setupRouter(router, location);

      location.onUpdateURL(function (url) {
        _this.handleURL(url);
      });

      return true;
    },

    /**
      Handles updating the paths and notifying any listeners of the URL
      change.
       Triggers the router level `didTransition` hook.
       For example, to notify google analytics when the route changes,
      you could use this hook.  (Note: requires also including GA scripts, etc.)
       ```javascript
      var Router = Ember.Router.extend({
        location: config.locationType,
         didTransition: function() {
          this._super(...arguments);
           return ga('send', 'pageview', {
            'page': this.get('url'),
            'title': this.get('url')
          });
        }
      });
      ```
       @method didTransition
      @public
      @since 1.2.0
    */
    didTransition: function (infos) {
      updatePaths(this);

      this._cancelSlowTransitionTimer();

      this.notifyPropertyChange('url');
      this.set('currentState', this.targetState);

      // Put this in the runloop so url will be accurate. Seems
      // less surprising than didTransition being out of sync.
      _emberMetalRun_loop.default.once(this, this.trigger, 'didTransition');

      if (_emberMetalProperty_get.get(this, 'namespace').LOG_TRANSITIONS) {
        _emberMetalLogger.default.log('Transitioned into \'' + EmberRouter._routePath(infos) + '\'');
      }
    },

    _setOutlets: function () {
      var handlerInfos = this.router.currentHandlerInfos;
      var route;
      var defaultParentState;
      var liveRoutes = null;

      if (!handlerInfos) {
        return;
      }

      for (var i = 0; i < handlerInfos.length; i++) {
        route = handlerInfos[i].handler;
        var connections = route.connections;
        var ownState;
        for (var j = 0; j < connections.length; j++) {
          var appended = appendLiveRoute(liveRoutes, defaultParentState, connections[j]);
          liveRoutes = appended.liveRoutes;
          if (appended.ownState.render.name === route.routeName || appended.ownState.render.outlet === 'main') {
            ownState = appended.ownState;
          }
        }
        if (connections.length === 0) {
          ownState = representEmptyRoute(liveRoutes, defaultParentState, route);
        }
        defaultParentState = ownState;
      }
      if (!this._toplevelView) {
        var owner = _containerOwner.getOwner(this);
        var OutletView = owner._lookupFactory('view:-outlet');
        this._toplevelView = OutletView.create();
        this._toplevelView.setOutletState(liveRoutes);
        var instance = owner.lookup('-application-instance:main');
        instance.didCreateRootView(this._toplevelView);
      } else {
        this._toplevelView.setOutletState(liveRoutes);
      }
    },

    /**
      Handles notifying any listeners of an impending URL
      change.
       Triggers the router level `willTransition` hook.
       @method willTransition
      @public
      @since 1.11.0
    */
    willTransition: function (oldInfos, newInfos, transition) {
      _emberMetalRun_loop.default.once(this, this.trigger, 'willTransition', transition);

      if (_emberMetalProperty_get.get(this, 'namespace').LOG_TRANSITIONS) {
        _emberMetalLogger.default.log('Preparing to transition from \'' + EmberRouter._routePath(oldInfos) + '\' to \'' + EmberRouter._routePath(newInfos) + '\'');
      }
    },

    handleURL: function (url) {
      // Until we have an ember-idiomatic way of accessing #hashes, we need to
      // remove it because router.js doesn't know how to handle it.
      url = url.split(/#(.+)?/)[0];
      return this._doURLTransition('handleURL', url);
    },

    _doURLTransition: function (routerJsMethod, url) {
      var transition = this.router[routerJsMethod](url || '/');
      didBeginTransition(transition, this);
      return transition;
    },

    /**
      Transition the application into another route. The route may
      be either a single route or route path:
       See [Route.transitionTo](http://emberjs.com/api/classes/Ember.Route.html#method_transitionTo) for more info.
       @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.
      @param {Object} [options] optional hash with a queryParams property
        containing a mapping of query parameters
      @return {Transition} the transition object associated with this
        attempted transition
      @public
    */
    transitionTo: function () {
      var queryParams;

      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      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 () {
      var _router;

      (_router = this.router).intermediateTransitionTo.apply(_router, arguments);

      updatePaths(this);

      var infos = this.router.currentHandlerInfos;
      if (_emberMetalProperty_get.get(this, 'namespace').LOG_TRANSITIONS) {
        _emberMetalLogger.default.log('Intermediate-transitioned into \'' + EmberRouter._routePath(infos) + '\'');
      }
    },

    replaceWith: function () {
      return this.transitionTo.apply(this, arguments).method('replace');
    },

    generate: function () {
      var _router2;

      var url = (_router2 = this.router).generate.apply(_router2, 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 isActiveIntent
      @param routeName
      @param models
      @param queryParams
      @return {Boolean}
      @private
      @since 1.7.0
    */
    isActiveIntent: function (routeName, models, queryParams) {
      return this.currentState.isActiveIntent(routeName, models, queryParams);
    },

    send: function (name, context) {
      var _router3;

      (_router3 = this.router).trigger.apply(_router3, 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 () {
      if (this.router) {
        this.router.reset();
      }
    },

    willDestroy: function () {
      if (this._toplevelView) {
        this._toplevelView.destroy();
        this._toplevelView = null;
      }
      this._super.apply(this, arguments);
      this.reset();
    },

    _lookupActiveComponentNode: function (templateName) {
      return this._activeViews[templateName];
    },

    /*
      Called when an active route's query parameter has changed.
      These changes are batched into a runloop run and trigger
      a single transition.
    */
    _activeQPChanged: function (queryParameterName, newValue) {
      this._queuedQPChanges[queryParameterName] = newValue;
      _emberMetalRun_loop.default.once(this, this._fireQueryParamTransition);
    },

    _updatingQPChanged: function (queryParameterName) {
      if (!this._qpUpdates) {
        this._qpUpdates = {};
      }
      this._qpUpdates[queryParameterName] = true;
    },

    /*
      Triggers a transition to a route based on query parameter changes.
      This is called once per runloop, to batch changes.
       e.g.
       if these methods are called in succession:
      this._activeQPChanged('foo', '10');
        // results in _queuedQPChanges = {foo: '10'}
      this._activeQPChanged('bar', false);
        // results in _queuedQPChanges = {foo: '10', bar: false}
        _queuedQPChanges will represent both of these changes
      and the transition using `transitionTo` will be triggered
      once.
    */
    _fireQueryParamTransition: function () {
      this.transitionTo({ queryParams: this._queuedQPChanges });
      this._resetQueuedQueryParameterChanges();
    },

    _connectActiveComponentNode: function (templateName, componentNode) {
      _emberMetalDebug.assert('cannot connect an activeView that already exists', !this._activeViews[templateName]);

      var _activeViews = this._activeViews;
      function disconnectActiveView() {
        delete _activeViews[templateName];
      }

      this._activeViews[templateName] = componentNode;
      componentNode.renderNode.addDestruction({ destroy: disconnectActiveView });
    },

    _setupLocation: function () {
      var location = _emberMetalProperty_get.get(this, 'location');
      var rootURL = _emberMetalProperty_get.get(this, 'rootURL');
      var owner = _containerOwner.getOwner(this);

      if ('string' === typeof location && owner) {
        var resolvedLocation = owner.lookup('location:' + location);

        if ('undefined' !== typeof resolvedLocation) {
          location = _emberMetalProperty_set.set(this, 'location', resolvedLocation);
        } else {
          // Allow for deprecated registration of custom location API's
          var options = {
            implementation: location
          };

          location = _emberMetalProperty_set.set(this, 'location', _emberRoutingLocationApi.default.create(options));
        }
      }

      if (location !== null && typeof location === 'object') {
        if (rootURL) {
          _emberMetalProperty_set.set(location, 'rootURL', rootURL);
        }

        // Allow the location to do any feature detection, such as AutoLocation
        // detecting history support. This gives it a chance to set its
        // `cancelRouterSetup` property which aborts routing.
        if (typeof location.detect === 'function') {
          location.detect();
        }

        // ensure that initState is called AFTER the rootURL is set on
        // the location instance
        if (typeof location.initState === 'function') {
          location.initState();
        }
      }
    },

    _getHandlerFunction: function () {
      var _this2 = this;

      var seen = new _emberMetalEmpty_object.default();
      var owner = _containerOwner.getOwner(this);
      var DefaultRoute = owner._lookupFactory('route:basic');

      return function (name) {
        var routeName = 'route:' + name;
        var handler = owner.lookup(routeName);

        if (seen[name]) {
          return handler;
        }

        seen[name] = true;

        if (!handler) {
          owner.register(routeName, DefaultRoute.extend());
          handler = owner.lookup(routeName);

          if (_emberMetalProperty_get.get(_this2, 'namespace.LOG_ACTIVE_GENERATION')) {
            _emberMetalDebug.info('generated -> ' + routeName, { fullName: routeName });
          }
        }

        handler.routeName = name;
        return handler;
      };
    },

    _setupRouter: function (router, location) {
      var lastURL;
      var emberRouter = this;

      router.getHandler = this._getHandlerFunction();

      var doUpdateURL = function () {
        location.setURL(lastURL);
      };

      router.updateURL = function (path) {
        lastURL = path;
        _emberMetalRun_loop.default.once(doUpdateURL);
      };

      if (location.replaceURL) {
        var doReplaceURL = function () {
          location.replaceURL(lastURL);
        };

        router.replaceURL = function (path) {
          lastURL = path;
          _emberMetalRun_loop.default.once(doReplaceURL);
        };
      }

      router.didTransition = function (infos) {
        emberRouter.didTransition(infos);
      };

      router.willTransition = function (oldInfos, newInfos, transition) {
        emberRouter.willTransition(oldInfos, newInfos, transition);
      };
    },

    _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];
        _emberMetalDebug.assert('You\'re not allowed to have more than one controller property map to the same query param key, but both `' + qps[0].qp.scopedPropertyName + '` and `' + (qps[1] ? qps[1].qp.scopedPropertyName : '') + '` map to `' + qps[0].qp.urlKey + '`. You can fix this by mapping one of the controller properties to a different query param key via the `as` config option, e.g. `' + qps[0].qp.prop + ': { as: \'other-' + qps[0].qp.prop + '\' }`', qps.length <= 1);
        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.serializedDefaultValue === queryParams[key]) {
          delete queryParams[key];
        }
      }
    },

    _doTransition: function (_targetRouteName, models, _queryParams) {
      var targetRouteName = _targetRouteName || _emberRoutingUtils.getActiveTargetName(this.router);
      _emberMetalDebug.assert('The route ' + targetRouteName + ' was not found', targetRouteName && this.router.hasRoute(targetRouteName));

      var queryParams = {};
      // merge in any queryParams from the active transition which could include
      // queryparams from the url on initial load.
      if (this.router.activeTransition) {
        _emberMetalAssign.default(queryParams, this.router.activeTransition.queryParams);
      }

      _emberMetalAssign.default(queryParams, _queryParams);
      this._prepareQueryParams(targetRouteName, models, queryParams);

      var transitionArgs = _emberRoutingUtils.routeArgs(targetRouteName, models, queryParams);
      var transition = this.router.transitionTo.apply(this.router, transitionArgs);

      didBeginTransition(transition, this);

      return transition;
    },

    _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.
       @private
     */
    _queryParamsFor: function (leafRouteName) {
      if (this._qpCache[leafRouteName]) {
        return this._qpCache[leafRouteName];
      }

      var map = {};
      var qps = [];
      this._qpCache[leafRouteName] = {
        map: map,
        qps: qps
      };

      var routerjs = this.router;
      var 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 = _emberMetalProperty_get.get(route, '_qp');

        if (!qpMeta) {
          continue;
        }

        _emberMetalAssign.default(map, qpMeta.map);
        qps.push.apply(qps, qpMeta.qps);
      }

      return {
        qps: qps,
        map: map
      };
    },

    _hydrateUnsuppliedQueryParams: function (leafRouteName, contexts, queryParams) {
      var state = calculatePostTransitionState(this, leafRouteName, contexts);
      var handlerInfos = state.handlerInfos;
      var appCache = this._bucketCache;
      _emberRoutingUtils.stashParamNames(this, handlerInfos);

      for (var i = 0, len = handlerInfos.length; i < len; ++i) {
        var route = handlerInfos[i].handler;
        var qpMeta = _emberMetalProperty_get.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.scopedPropertyName in queryParams && qp.scopedPropertyName;

          if (presentProp) {
            if (presentProp !== qp.scopedPropertyName) {
              queryParams[qp.scopedPropertyName] = queryParams[presentProp];
              delete queryParams[presentProp];
            }
          } else {
            var cacheKey = _emberRoutingUtils.calculateCacheKey(qp.ctrl, qp.parts, state.params);
            queryParams[qp.scopedPropertyName] = appCache.lookup(cacheKey, qp.prop, qp.defaultValue);
          }
        }
      }
    },

    _scheduleLoadingEvent: function (transition, originRoute) {
      this._cancelSlowTransitionTimer();
      this._slowTransitionTimer = _emberMetalRun_loop.default.scheduleOnce('routerTransitions', this, '_handleSlowTransition', transition, originRoute);
    },

    currentState: null,
    targetState: null,

    _handleSlowTransition: 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;
      }

      this.set('targetState', _emberRoutingSystemRouter_state.default.create({
        emberRouter: this,
        routerJs: this.router,
        routerJsState: this.router.activeTransition.state
      }));

      transition.trigger(true, 'loading', transition, originRoute);
    },

    _cancelSlowTransitionTimer: function () {
      if (this._slowTransitionTimer) {
        _emberMetalRun_loop.default.cancel(this._slowTransitionTimer);
      }
      this._slowTransitionTimer = null;
    },

    // These three helper functions are used to ensure errors aren't
    // re-raised if they're handled in a route's error action.
    _markErrorAsHandled: function (errorGuid) {
      this._handledErrors[errorGuid] = true;
    },

    _isErrorHandled: function (errorGuid) {
      return this._handledErrors[errorGuid];
    },

    _clearHandledError: function (errorGuid) {
      delete this._handledErrors[errorGuid];
    }
  });

  /*
    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;
        }
      }

      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 = [];
    var error;
    if (_error && typeof _error === 'object' && typeof _error.errorThrown === 'object') {
      error = _error.errorThrown;
    } else {
      error = _error;
    }

    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);
      }
    }

    _emberMetalLogger.default.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 + '.';

    // First, try a named loading state, e.g. 'foo_loading'
    childName = namespace + targetChildRouteName + '_' + name;
    if (routeHasBeenDefined(router, childName)) {
      return childName;
    }

    // Second, try general loading state, e.g. 'loading'
    childName = namespace + name;
    if (routeHasBeenDefined(router, childName)) {
      return childName;
    }
  }

  function routeHasBeenDefined(router, name) {
    var owner = _containerOwner.getOwner(router);
    return router.hasRoute(name) && (owner.hasRegistration('template:' + name) || owner.hasRegistration('route:' + name));
  }

  function triggerEvent(handlerInfos, ignoreFailure, args) {
    var name = args.shift();

    if (!handlerInfos) {
      if (ignoreFailure) {
        return;
      }
      throw new _emberMetalError.default('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 {
          // Should only hit here if a non-bubbling error action is triggered on a route.
          if (name === 'error') {
            var errorId = _emberMetalUtils.guidFor(args[0]);
            handler.router._markErrorAsHandled(errorId);
          }
          return;
        }
      }
    }

    if (defaultActionHandlers[name]) {
      defaultActionHandlers[name].apply(null, args);
      return;
    }

    if (!eventWasHandled && !ignoreFailure) {
      throw new _emberMetalError.default('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 infos = router.router.currentHandlerInfos;
    var path = EmberRouter._routePath(infos);
    var currentRouteName = infos[infos.length - 1].name;

    _emberMetalProperty_set.set(router, 'currentPath', path);
    _emberMetalProperty_set.set(router, 'currentRouteName', currentRouteName);

    var appController = _containerOwner.getOwner(router).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;
    }

    if (!('currentPath' in appController)) {
      _emberMetalProperties.defineProperty(appController, 'currentPath');
    }

    _emberMetalProperty_set.set(appController, 'currentPath', path);

    if (!('currentRouteName' in appController)) {
      _emberMetalProperties.defineProperty(appController, 'currentRouteName');
    }

    _emberMetalProperty_set.set(appController, 'currentRouteName', currentRouteName);
  }

  EmberRouter.reopenClass({
    router: null,

    /**
      The `Router.map` function allows you to define mappings from URLs to routes
      in your application. These mappings are defined within the
      supplied callback function using `this.route`.
       The first parameter is the name of the route which is used by default as the
      path name as well.
       The second parameter is the optional options hash. Available options are:
        * `path`: allows you to provide your own path as well as mark dynamic
          segments.
        * `resetNamespace`: false by default; when nesting routes, ember will
          combine the route names to form the fully-qualified route name, which is
          used with `{{link-to}}` or manually transitioning to routes. Setting
          `resetNamespace: true` will cause the route not to inherit from its
          parent route's names. This is handy for resources which can be accessed
          in multiple places as well as preventing extremely long route names.
          Keep in mind that the actual URL path behavior is still retained.
       The third parameter is a function, which can be used to nest routes.
      Nested routes, by default, will have the parent route tree's route name and
      path prepended to it's own.
       ```javascript
      App.Router.map(function(){
        this.route('post', { path: '/post/:post_id' }, function() {
          this.route('edit');
          this.route('comments', { resetNamespace: true }, function() {
            this.route('new');
          });
        });
      });
      ```
       For more detailed documentation and examples please see
      [the guides](http://emberjs.com/guides/routing/defining-your-routes/).
       @method map
      @param callback
      @public
    */
    map: function (callback) {
      if (!this.dslCallbacks) {
        this.dslCallbacks = [];
        this.reopenClass({ dslCallbacks: this.dslCallbacks });
      }

      this.dslCallbacks.push(callback);

      return this;
    },

    _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 didBeginTransition(transition, router) {
    var routerState = _emberRoutingSystemRouter_state.default.create({
      emberRouter: router,
      routerJs: router.router,
      routerJsState: transition.state
    });

    if (!router.currentState) {
      router.set('currentState', routerState);
    }
    router.set('targetState', routerState);

    transition.promise = transition.catch(function (error) {
      var errorId = _emberMetalUtils.guidFor(error);

      if (router._isErrorHandled(errorId)) {
        router._clearHandledError(errorId);
      } else {
        throw error;
      }
    });
  }

  function resemblesURL(str) {
    return typeof str === 'string' && (str === '' || str.charAt(0) === '/');
  }

  function forEachQueryParam(router, targetRouteName, queryParams, callback) {
    var qpCache = router._queryParamsFor(targetRouteName);

    for (var key in queryParams) {
      if (!queryParams.hasOwnProperty(key)) {
        continue;
      }
      var value = queryParams[key];
      var qp = qpCache.map[key];

      if (qp) {
        callback(key, value, qp);
      }
    }
  }

  function findLiveRoute(liveRoutes, name) {
    if (!liveRoutes) {
      return;
    }
    var stack = [liveRoutes];
    while (stack.length > 0) {
      var test = stack.shift();
      if (test.render.name === name) {
        return test;
      }
      var outlets = test.outlets;
      for (var outletName in outlets) {
        stack.push(outlets[outletName]);
      }
    }
  }

  function appendLiveRoute(liveRoutes, defaultParentState, renderOptions) {
    var target;
    var myState = {
      render: renderOptions,
      outlets: new _emberMetalEmpty_object.default()
    };
    if (renderOptions.into) {
      target = findLiveRoute(liveRoutes, renderOptions.into);
    } else {
      target = defaultParentState;
    }
    if (target) {
      _emberMetalProperty_set.set(target.outlets, renderOptions.outlet, myState);
    } else {
      if (renderOptions.into) {
        // Megahax time. Post-2.0-breaking-changes, we will just assert
        // right here that the user tried to target a nonexistent
        // thing. But for now we still need to support the `render`
        // helper, and people are allowed to target templates rendered
        // by the render helper. So instead we defer doing anyting with
        // these orphan renders until afterRender.
        appendOrphan(liveRoutes, renderOptions.into, myState);
      } else {
        liveRoutes = myState;
      }
    }
    return {
      liveRoutes: liveRoutes,
      ownState: myState
    };
  }

  function appendOrphan(liveRoutes, into, myState) {
    if (!liveRoutes.outlets.__ember_orphans__) {
      liveRoutes.outlets.__ember_orphans__ = {
        render: {
          name: '__ember_orphans__'
        },
        outlets: new _emberMetalEmpty_object.default()
      };
    }
    liveRoutes.outlets.__ember_orphans__.outlets[into] = myState;
    _emberMetalRun_loop.default.schedule('afterRender', function () {
      // `wasUsed` gets set by the render helper. See the function
      // `impersonateAnOutlet`.
      _emberMetalDebug.assert('You attempted to render into \'' + into + '\' but it was not found', liveRoutes.outlets.__ember_orphans__.outlets[into].wasUsed);
    });
  }

  function representEmptyRoute(liveRoutes, defaultParentState, route) {
    // the route didn't render anything
    var alreadyAppended = findLiveRoute(liveRoutes, route.routeName);
    if (alreadyAppended) {
      // But some other route has already rendered our default
      // template, so that becomes the default target for any
      // children we may have.
      return alreadyAppended;
    } else {
      // Create an entry to represent our default template name,
      // just so other routes can target it and inherit its place
      // in the outlet hierarchy.
      defaultParentState.outlets.main = {
        render: {
          name: route.routeName,
          outlet: 'main'
        },
        outlets: {}
      };
      return defaultParentState;
    }
  }

  exports.default = EmberRouter;
});

/**
@module ember
@submodule ember-routing
*/
enifed('ember-routing/system/router_state', ['exports', 'ember-metal/is_empty', 'ember-runtime/system/object', 'ember-metal/assign'], function (exports, _emberMetalIs_empty, _emberRuntimeSystemObject, _emberMetalAssign) {
  'use strict';

  var keys = Object.keys;

  var RouterState = _emberRuntimeSystemObject.default.extend({
    emberRouter: null,
    routerJs: null,
    routerJsState: null,

    isActiveIntent: function (routeName, models, queryParams, queryParamsMustMatch) {
      var state = this.routerJsState;
      if (!this.routerJs.isActiveIntent(routeName, models, null, state)) {
        return false;
      }

      var emptyQueryParams = _emberMetalIs_empty.default(keys(queryParams));

      if (queryParamsMustMatch && !emptyQueryParams) {
        var visibleQueryParams = {};
        _emberMetalAssign.default(visibleQueryParams, queryParams);

        this.emberRouter._prepareQueryParams(routeName, models, visibleQueryParams);
        return shallowEqual(visibleQueryParams, state.queryParams);
      }

      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.default = RouterState;
});
enifed('ember-routing/utils', ['exports', 'ember-metal/assign', 'ember-metal/property_get'], function (exports, _emberMetalAssign, _emberMetalProperty_get) {
  'use strict';

  exports.routeArgs = routeArgs;
  exports.getActiveTargetName = getActiveTargetName;
  exports.stashParamNames = stashParamNames;
  exports.calculateCacheKey = calculateCacheKey;
  exports.normalizeControllerQueryParams = normalizeControllerQueryParams;

  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;
  }

  function getActiveTargetName(router) {
    var handlerInfos = router.activeTransition ? router.activeTransition.state.handlerInfos : router.state.handlerInfos;
    return handlerInfos[handlerInfos.length - 1].name;
  }

  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;
  }

  function _calculateCacheValuePrefix(prefix, part) {
    // calculates the dot seperated sections from prefix that are also
    // at the start of part - which gives us the route name

    // given : prefix = site.article.comments, part = site.article.id
    //      - returns: site.article (use get(values[site.article], 'id') to get the dynamic part - used below)

    // given : prefix = site.article, part = site.article.id
    //      - returns: site.article. (use get(values[site.article], 'id') to get the dynamic part - used below)

    var prefixParts = prefix.split('.');
    var currPrefix = '';

    for (var i = 0, len = prefixParts.length; i < len; i++) {
      var currPart = prefixParts.slice(0, i + 1).join('.');
      if (part.indexOf(currPart) !== 0) {
        break;
      }
      currPrefix = currPart;
    }

    return currPrefix;
  }

  /*
    Stolen from Controller
  */

  function calculateCacheKey(prefix, _parts, values) {
    var parts = _parts || [];
    var suffixes = '';
    for (var i = 0, len = parts.length; i < len; ++i) {
      var part = parts[i];
      var cacheValuePrefix = _calculateCacheValuePrefix(prefix, part);
      var value;
      if (values) {
        if (cacheValuePrefix && cacheValuePrefix in values) {
          var partRemovedPrefix = part.indexOf(cacheValuePrefix) === 0 ? part.substr(cacheValuePrefix.length + 1) : part;
          value = _emberMetalProperty_get.get(values[cacheValuePrefix], partRemovedPrefix);
        } else {
          value = _emberMetalProperty_get.get(values, part);
        }
      }
      suffixes += '::' + part + ':' + value;
    }
    return prefix + suffixes.replace(ALL_PERIODS_REGEX, '-');
  }

  var ALL_PERIODS_REGEX = /\./g;

  /*
    Controller-defined query parameters can come in three shapes:

    Array
      queryParams: ['foo', 'bar']
    Array of simple objects where value is an alias
      queryParams: [
        {
          'foo': 'rename_foo_to_this'
        },
        {
          'bar': 'call_bar_this_instead'
        }
      ]
    Array of fully defined objects
      queryParams: [
        {
          'foo': {
            as: 'rename_foo_to_this'
          },
        }
        {
          'bar': {
            as: 'call_bar_this_instead',
            scope: 'controller'
          }
        }
      ]

    This helper normalizes all three possible styles into the
    'Array of fully defined objects' style.
  */

  function normalizeControllerQueryParams(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;
  }

  function accumulateQueryParamDescriptors(_desc, accum) {
    var desc = _desc;
    var 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' };
      _emberMetalAssign.default(tmp, singleDesc);

      accum[key] = tmp;
    }
  }
});
enifed('ember-runtime/compare', ['exports', 'ember-runtime/utils', 'ember-runtime/mixins/comparable'], function (exports, _emberRuntimeUtils, _emberRuntimeMixinsComparable) {
  'use strict';

  exports.default = compare;

  var TYPE_ORDER = {
    'undefined': 0,
    'null': 1,
    'boolean': 2,
    'number': 3,
    'string': 4,
    'array': 5,
    'object': 6,
    'instance': 7,
    'function': 8,
    'class': 9,
    'date': 10
  };

  //
  // the spaceship operator
  //
  //                      `. ___
  //                     __,' __`.                _..----....____
  //         __...--.'``;.   ,.   ;``--..__     .'    ,-._    _.-'
  //   _..-''-------'   `'   `'   `'     O ``-''._   (,;') _,'
  // ,'________________                          \`-._`-','
  //  `._              ```````````------...___   '-.._'-:
  //     ```--.._      ,.                     ````--...__\-.
  //             `.--. `-` "INFINITY IS LESS     ____    |  |`
  //               `. `.   THAN BEYOND"        ,'`````.  ;  ;`
  //                 `._`.        __________   `.      \'__/`
  //                    `-:._____/______/___/____`.     \  `
  //                                |       `._    `.    \
  //                                `._________`-.   `.   `.___
  //                                              SSt  `------'`
  function spaceship(a, b) {
    var diff = a - b;
    return (diff > 0) - (diff < 0);
  }

  /**
   Compares two javascript values and returns:

    - -1 if the first is smaller than the second,
    - 0 if both are equal,
    - 1 if the first is greater than the second.

    ```javascript
    Ember.compare('hello', 'hello');  // 0
    Ember.compare('abc', 'dfg');      // -1
    Ember.compare(2, 1);              // 1
    ```

   If the types of the two objects are different precedence occurs in the
   following order, with types earlier in the list considered `<` types
   later in the list:

    - undefined
    - null
    - boolean
    - number
    - string
    - array
    - object
    - instance
    - function
    - class
    - date

    ```javascript
    Ember.compare('hello', 50);       // 1
    Ember.compare(50, 'hello');       // -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.
   @public
  */

  function compare(v, w) {
    if (v === w) {
      return 0;
    }

    var type1 = _emberRuntimeUtils.typeOf(v);
    var type2 = _emberRuntimeUtils.typeOf(w);

    if (_emberRuntimeMixinsComparable.default) {
      if (type1 === 'instance' && _emberRuntimeMixinsComparable.default.detect(v) && v.constructor.compare) {
        return v.constructor.compare(v, w);
      }

      if (type2 === 'instance' && _emberRuntimeMixinsComparable.default.detect(w) && w.constructor.compare) {
        return w.constructor.compare(w, v) * -1;
      }
    }

    var res = spaceship(TYPE_ORDER[type1], TYPE_ORDER[type2]);

    if (res !== 0) {
      return res;
    }

    // types are equal - so we have to check values now
    switch (type1) {
      case 'boolean':
      case 'number':
        return spaceship(v, w);

      case 'string':
        return spaceship(v.localeCompare(w), 0);

      case 'array':
        var vLen = v.length;
        var wLen = w.length;
        var len = Math.min(vLen, wLen);

        for (var i = 0; i < len; i++) {
          var r = compare(v[i], w[i]);
          if (r !== 0) {
            return r;
          }
        }

        // all elements are equal now
        // shorter array should be ordered first
        return spaceship(vLen, wLen);

      case 'instance':
        if (_emberRuntimeMixinsComparable.default && _emberRuntimeMixinsComparable.default.detect(v)) {
          return v.compare(v, w);
        }
        return 0;

      case 'date':
        return spaceship(v.getTime(), w.getTime());

      default:
        return 0;
    }
  }
});
enifed('ember-runtime/computed/reduce_computed_macros', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/error', 'ember-metal/computed', 'ember-metal/observer', 'ember-runtime/compare', 'ember-runtime/utils', 'ember-runtime/system/native_array', 'ember-metal/is_none', 'ember-metal/get_properties', 'ember-metal/empty_object', 'ember-metal/utils', 'ember-metal/weak_map'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalError, _emberMetalComputed, _emberMetalObserver, _emberRuntimeCompare, _emberRuntimeUtils, _emberRuntimeSystemNative_array, _emberMetalIs_none, _emberMetalGet_properties, _emberMetalEmpty_object, _emberMetalUtils, _emberMetalWeak_map) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  exports.sum = sum;
  exports.max = max;
  exports.min = min;
  exports.map = map;
  exports.mapBy = mapBy;
  exports.filter = filter;
  exports.filterBy = filterBy;
  exports.uniq = uniq;
  exports.uniqBy = uniqBy;
  exports.intersect = intersect;
  exports.setDiff = setDiff;
  exports.collect = collect;
  exports.sort = sort;

  function reduceMacro(dependentKey, callback, initialValue) {
    return _emberMetalComputed.computed(dependentKey + '.[]', function () {
      var _this = this;

      var arr = _emberMetalProperty_get.get(this, dependentKey);

      if (arr === null || typeof arr !== 'object') {
        return initialValue;
      }

      return arr.reduce(function (previousValue, currentValue, index, array) {
        return callback.call(_this, previousValue, currentValue, index, array);
      }, initialValue);
    }).readOnly();
  }

  function arrayMacro(dependentKey, callback) {
    // This is a bit ugly
    var propertyName;
    if (/@each/.test(dependentKey)) {
      propertyName = dependentKey.replace(/\.@each.*$/, '');
    } else {
      propertyName = dependentKey;
      dependentKey += '.[]';
    }

    return _emberMetalComputed.computed(dependentKey, function () {
      var value = _emberMetalProperty_get.get(this, propertyName);
      if (_emberRuntimeUtils.isArray(value)) {
        return _emberRuntimeSystemNative_array.A(callback.call(this, value));
      } else {
        return _emberRuntimeSystemNative_array.A();
      }
    }).readOnly();
  }

  function multiArrayMacro(dependentKeys, callback) {
    var args = dependentKeys.map(function (key) {
      return key + '.[]';
    });

    args.push(function () {
      return _emberRuntimeSystemNative_array.A(callback.call(this, dependentKeys));
    });

    return _emberMetalComputed.computed.apply(this, args).readOnly();
  }

  /**
    A computed property that returns the sum of the values
    in the dependent array.

    @method sum
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computes the sum of all values in the dependentKey's array
    @since 1.4.0
    @public
  */

  function sum(dependentKey) {
    return reduceMacro(dependentKey, function (sum, item) {
      return sum + item;
    }, 0);
  }

  /**
    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 max
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computes the largest value in the dependentKey's array
    @public
  */

  function max(dependentKey) {
    return reduceMacro(dependentKey, function (max, item) {
      return Math.max(max, item);
    }, -Infinity);
  }

  /**
    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 min
    @for Ember.computed
    @param {String} dependentKey
    @return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array
    @public
  */

  function min(dependentKey) {
    return reduceMacro(dependentKey, function (min, item) {
      return Math.min(min, item);
    }, Infinity);
  }

  /**
    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.
    `index` is the integer index of the current item in the iteration.

    ```javascript
    function(item, index);
    ```

    Example

    ```javascript
    var Hamster = Ember.Object.extend({
      excitingChores: Ember.computed.map('chores', function(chore, index) {
        return chore.toUpperCase() + '!';
      })
    });

    var hamster = Hamster.create({
      chores: ['clean', 'write more unit tests']
    });

    hamster.get('excitingChores'); // ['CLEAN!', 'WRITE MORE UNIT TESTS!']
    ```

    @method map
    @for Ember.computed
    @param {String} dependentKey
    @param {Function} callback
    @return {Ember.ComputedProperty} an array mapped via the callback
    @public
  */

  function map(dependentKey, callback) {
    return arrayMacro(dependentKey, function (value) {
      return value.map(callback, this);
    });
  }

  /**
    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 mapBy
    @for Ember.computed
    @param {String} dependentKey
    @param {String} propertyKey
    @return {Ember.ComputedProperty} an array mapped to the specified key
    @public
  */

  function mapBy(dependentKey, propertyKey) {
    _emberMetalDebug.assert('Ember.computed.mapBy expects a property string for its second argument, ' + 'perhaps you meant to use "map"', typeof propertyKey === 'string');

    return map(dependentKey + '.@each.' + propertyKey, function (item) {
      return _emberMetalProperty_get.get(item, propertyKey);
    });
  }

  /**
    Filters the array by the callback.

    The callback method you provide should have the following signature.
    `item` is the current item in the iteration.
    `index` is the integer index of the current item in the iteration.
    `array` is the dependant array itself.

    ```javascript
    function(item, index, array);
    ```

    ```javascript
    var Hamster = Ember.Object.extend({
      remainingChores: Ember.computed.filter('chores', function(chore, index, array) {
        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 filter
    @for Ember.computed
    @param {String} dependentKey
    @param {Function} callback
    @return {Ember.ComputedProperty} the filtered array
    @public
  */

  function filter(dependentKey, callback) {
    return arrayMacro(dependentKey, function (value) {
      return value.filter(callback, this);
    });
  }

  /**
    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 filterBy
    @for Ember.computed
    @param {String} dependentKey
    @param {String} propertyKey
    @param {*} value
    @return {Ember.ComputedProperty} the filtered array
    @public
  */

  function filterBy(dependentKey, propertyKey, value) {
    var callback;

    if (arguments.length === 2) {
      callback = function (item) {
        return _emberMetalProperty_get.get(item, propertyKey);
      };
    } else {
      callback = function (item) {
        return _emberMetalProperty_get.get(item, propertyKey) === value;
      };
    }

    return filter(dependentKey + '.@each.' + propertyKey, callback);
  }

  /**
    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 uniq
    @for Ember.computed
    @param {String} propertyKey*
    @return {Ember.ComputedProperty} computes a new array with all the
    unique elements from the dependent array
    @public
  */

  function uniq() {
    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return multiArrayMacro(args, function (dependentKeys) {
      var _this2 = this;

      var uniq = _emberRuntimeSystemNative_array.A();

      dependentKeys.forEach(function (dependentKey) {
        var value = _emberMetalProperty_get.get(_this2, dependentKey);
        if (_emberRuntimeUtils.isArray(value)) {
          value.forEach(function (item) {
            if (uniq.indexOf(item) === -1) {
              uniq.push(item);
            }
          });
        }
      });

      return uniq;
    });
  }

  /**
    A computed property which returns a new array with all the unique
    elements from an array, with uniqueness determined by specific key.
    Example
    ```javascript
    var Hamster = Ember.Object.extend({
      uniqueFruits: Ember.computed.uniqBy('fruits', 'id')
    });
    var hamster = Hamster.create({
      fruits: [
        { id: 1, 'banana' },
        { id: 2, 'grape' },
        { id: 3, 'peach' },
        { id: 1, 'banana' }
      ]
    });
    hamster.get('uniqueFruits'); // [ { id: 1, 'banana' }, { id: 2, 'grape' }, { id: 3, 'peach' }]
    ```
    @method uniqBy
    @for Ember.computed
    @param {String} dependentKey
    @param {String} propertyKey
    @return {Ember.ComputedProperty} computes a new array with all the
    unique elements from the dependent array
    @public
  */

  function uniqBy(dependentKey, propertyKey) {
    return _emberMetalComputed.computed(dependentKey + '.[]', function () {
      var uniq = _emberRuntimeSystemNative_array.A();
      var seen = new _emberMetalEmpty_object.default();
      var list = _emberMetalProperty_get.get(this, dependentKey);
      if (_emberRuntimeUtils.isArray(list)) {
        list.forEach(function (item) {
          var guid = _emberMetalUtils.guidFor(_emberMetalProperty_get.get(item, propertyKey));
          if (!(guid in seen)) {
            seen[guid] = true;
            uniq.push(item);
          }
        });
      }
      return uniq;
    }).readOnly();
  }

  /**
    Alias for [Ember.computed.uniq](/api/#method_computed_uniq).

    @method union
    @for Ember.computed
    @param {String} propertyKey*
    @return {Ember.ComputedProperty} computes a new array with all the
    unique elements from the dependent array
    @public
  */
  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.extend({
      friendsInCommon: Ember.computed.intersect('adaFriends', 'charlesFriends')
    }).create({
      adaFriends: ['Charles Babbage', 'John Hobhouse', 'William King', 'Mary Somerville'],
      charlesFriends: ['William King', 'Mary Somerville', 'Ada Lovelace', 'George Peacock']
    });

    obj.get('friendsInCommon'); // ['William King', 'Mary Somerville']
    ```

    @method intersect
    @for Ember.computed
    @param {String} propertyKey*
    @return {Ember.ComputedProperty} computes a new array with all the
    duplicated elements from the dependent arrays
    @public
  */

  function intersect() {
    for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
      args[_key2] = arguments[_key2];
    }

    return multiArrayMacro(args, function (dependentKeys) {
      var _this3 = this;

      var arrays = dependentKeys.map(function (dependentKey) {
        var array = _emberMetalProperty_get.get(_this3, dependentKey);

        return _emberRuntimeUtils.isArray(array) ? array : [];
      });

      var results = arrays.pop().filter(function (candidate) {
        for (var i = 0; i < arrays.length; i++) {
          var found = false;
          var array = arrays[i];
          for (var j = 0; j < array.length; j++) {
            if (array[j] === candidate) {
              found = true;
              break;
            }
          }

          if (found === false) {
            return false;
          }
        }

        return true;
      });

      return _emberRuntimeSystemNative_array.A(results);
    });
  }

  /**
    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 setDiff
    @for Ember.computed
    @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
    @public
  */

  function setDiff(setAProperty, setBProperty) {
    if (arguments.length !== 2) {
      throw new _emberMetalError.default('setDiff requires exactly two dependent arrays.');
    }

    return _emberMetalComputed.computed(setAProperty + '.[]', setBProperty + '.[]', function () {
      var setA = this.get(setAProperty);
      var setB = this.get(setBProperty);

      if (!_emberRuntimeUtils.isArray(setA)) {
        return _emberRuntimeSystemNative_array.A();
      }
      if (!_emberRuntimeUtils.isArray(setB)) {
        return _emberRuntimeSystemNative_array.A(setA);
      }

      return setA.filter(function (x) {
        return setB.indexOf(x) === -1;
      });
    }).readOnly();
  }

  /**
    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 collect
    @for Ember.computed
    @param {String} dependentKey*
    @return {Ember.ComputedProperty} computed property which maps
    values of all passed in properties to an array.
    @public
  */

  function collect() {
    for (var _len3 = arguments.length, dependentKeys = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
      dependentKeys[_key3] = arguments[_key3];
    }

    return multiArrayMacro(dependentKeys, function () {
      var properties = _emberMetalGet_properties.default(this, dependentKeys);
      var res = _emberRuntimeSystemNative_array.A();
      for (var key in properties) {
        if (properties.hasOwnProperty(key)) {
          if (_emberMetalIs_none.default(properties[key])) {
            res.push(null);
          } else {
            res.push(properties[key]);
          }
        }
      }
      return res;
    });
  }

  /**
    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 sort
    @for Ember.computed
    @param {String} itemsKey
    @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
    @public
  */

  function sort(itemsKey, sortDefinition) {
    _emberMetalDebug.assert('Ember.computed.sort requires two arguments: an array key to sort and ' + 'either a sort properties key or sort function', arguments.length === 2);

    if (typeof sortDefinition === 'function') {
      return customSort(itemsKey, sortDefinition);
    } else {
      return propertySort(itemsKey, sortDefinition);
    }
  }

  function customSort(itemsKey, comparator) {
    return arrayMacro(itemsKey, function (value) {
      var _this4 = this;

      return value.slice().sort(function (x, y) {
        return comparator.call(_this4, x, y);
      });
    });
  }

  // This one needs to dynamically set up and tear down observers on the itemsKey
  // depending on the sortProperties
  function propertySort(itemsKey, sortPropertiesKey) {
    var cp = new _emberMetalComputed.ComputedProperty(function (key) {
      var _this5 = this;

      var itemsKeyIsAtThis = itemsKey === '@this';
      var sortProperties = _emberMetalProperty_get.get(this, sortPropertiesKey);

      _emberMetalDebug.assert('The sort definition for \'' + key + '\' on ' + this + ' must be a function or an array of strings', _emberRuntimeUtils.isArray(sortProperties) && sortProperties.every(function (s) {
        return typeof s === 'string';
      }));

      var normalizedSortProperties = normalizeSortProperties(sortProperties);

      // Add/remove property observers as required.
      var activeObserversMap = cp._activeObserverMap || (cp._activeObserverMap = new _emberMetalWeak_map.default());
      var activeObservers = activeObserversMap.get(this);

      if (activeObservers) {
        activeObservers.forEach(function (args) {
          _emberMetalObserver.removeObserver.apply(null, args);
        });
      }

      function sortPropertyDidChange() {
        this.notifyPropertyChange(key);
      }

      activeObservers = normalizedSortProperties.map(function (_ref) {
        var prop = _ref[0];

        var path = itemsKeyIsAtThis ? '@each.' + prop : itemsKey + '.@each.' + prop;
        var args = [_this5, path, sortPropertyDidChange];
        _emberMetalObserver.addObserver.apply(null, args);
        return args;
      });

      activeObserversMap.set(this, activeObservers);

      // Sort and return the array.
      var items = itemsKeyIsAtThis ? this : _emberMetalProperty_get.get(this, itemsKey);

      if (_emberRuntimeUtils.isArray(items)) {
        return sortByNormalizedSortProperties(items, normalizedSortProperties);
      } else {
        return _emberRuntimeSystemNative_array.A();
      }
    });

    cp._activeObserverMap = undefined;

    return cp.property(sortPropertiesKey + '.[]').readOnly();
  }

  function normalizeSortProperties(sortProperties) {
    return sortProperties.map(function (p) {
      var _p$split = p.split(':');

      var prop = _p$split[0];
      var direction = _p$split[1];

      direction = direction || 'asc';

      return [prop, direction];
    });
  }

  function sortByNormalizedSortProperties(items, normalizedSortProperties) {
    return _emberRuntimeSystemNative_array.A(items.slice().sort(function (itemA, itemB) {
      for (var i = 0; i < normalizedSortProperties.length; i++) {
        var _normalizedSortProperties$i = normalizedSortProperties[i];
        var prop = _normalizedSortProperties$i[0];
        var direction = _normalizedSortProperties$i[1];

        var result = _emberRuntimeCompare.default(_emberMetalProperty_get.get(itemA, prop), _emberMetalProperty_get.get(itemB, prop));
        if (result !== 0) {
          return direction === 'desc' ? -1 * result : result;
        }
      }

      return 0;
    }));
  }
});
enifed('ember-runtime/controllers/controller', ['exports', 'ember-metal/debug', 'ember-runtime/system/object', 'ember-runtime/mixins/controller', 'ember-runtime/inject', 'ember-runtime/mixins/action_handler'], function (exports, _emberMetalDebug, _emberRuntimeSystemObject, _emberRuntimeMixinsController, _emberRuntimeInject, _emberRuntimeMixinsAction_handler) {
  'use strict';

  /**
  @module ember
  @submodule ember-runtime
  */

  /**
    @class Controller
    @namespace Ember
    @extends Ember.Object
    @uses Ember.ControllerMixin
    @public
  */
  var Controller = _emberRuntimeSystemObject.default.extend(_emberRuntimeMixinsController.default);

  _emberRuntimeMixinsAction_handler.deprecateUnderscoreActions(Controller);

  function controllerInjectionHelper(factory) {
    _emberMetalDebug.assert('Defining an injected controller property on a ' + 'non-controller is not allowed.', _emberRuntimeMixinsController.default.detect(factory.PrototypeMixin));
  }

  /**
    Creates a property that lazily looks up another controller in the container.
    Can only be used when defining another controller.

    Example:

    ```javascript
    App.PostController = Ember.Controller.extend({
      posts: Ember.inject.controller()
    });
    ```

    This example will create a `posts` property on the `post` controller that
    looks up the `posts` controller in the container, making it easy to
    reference other controllers. This is functionally equivalent to:

    ```javascript
    App.PostController = Ember.Controller.extend({
      needs: 'posts',
      posts: Ember.computed.alias('controllers.posts')
    });
    ```

    @method controller
    @since 1.10.0
    @for Ember.inject
    @param {String} name (optional) name of the controller to inject, defaults
           to the property's name
    @return {Ember.InjectedProperty} injection descriptor instance
    @public
  */
  _emberRuntimeInject.createInjectionHelper('controller', controllerInjectionHelper);

  exports.default = Controller;
});
enifed('ember-runtime/copy', ['exports', 'ember-metal/debug', 'ember-runtime/system/object', 'ember-runtime/mixins/copyable'], function (exports, _emberMetalDebug, _emberRuntimeSystemObject, _emberRuntimeMixinsCopyable) {
  'use strict';

  exports.default = copy;

  function _copy(obj, deep, seen, copies) {
    var ret, loc, key;

    // primitive data types are immutable, just return them.
    if (typeof obj !== 'object' || obj === null) {
      return obj;
    }

    // avoid cyclical loops
    if (deep && (loc = seen.indexOf(obj)) >= 0) {
      return copies[loc];
    }

    _emberMetalDebug.assert('Cannot clone an Ember.Object that does not implement Ember.Copyable', !(obj instanceof _emberRuntimeSystemObject.default) || _emberRuntimeMixinsCopyable.default && _emberRuntimeMixinsCopyable.default.detect(obj));

    // IMPORTANT: this specific test will detect a native array only. Any other
    // object will need to implement Copyable.
    if (Array.isArray(obj)) {
      ret = obj.slice();

      if (deep) {
        loc = ret.length;

        while (--loc >= 0) {
          ret[loc] = _copy(ret[loc], deep, seen, copies);
        }
      }
    } else if (_emberRuntimeMixinsCopyable.default && _emberRuntimeMixinsCopyable.default.detect(obj)) {
      ret = obj.copy(deep, seen, copies);
    } else if (obj instanceof Date) {
      ret = new Date(obj.getTime());
    } else {
      ret = {};

      for (key in obj) {
        // support Null prototype
        if (!Object.prototype.hasOwnProperty.call(obj, 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 shallow copy of the passed object. A deep copy of the object is
    returned if the optional `deep` argument is `true`.

    If the passed object implements the `Ember.Copyable` interface, then this
    function will delegate to the object's `copy()` method and return the
    result. See `Ember.Copyable` for further details.

    For primitive values (which are immutable in JavaScript), the passed object
    is simply returned.

    @method copy
    @for Ember
    @param {Object} obj The object to clone
    @param {Boolean} [deep=false] If true, a deep copy of the object is made.
    @return {Object} The copied object
    @public
  */

  function copy(obj, deep) {
    // fast paths
    if ('object' !== typeof obj || obj === null) {
      return obj; // can't copy primitives
    }

    if (_emberRuntimeMixinsCopyable.default && _emberRuntimeMixinsCopyable.default.detect(obj)) {
      return obj.copy(deep);
    }

    return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
  }
});
enifed("ember-runtime/core", ["exports"], function (exports) {
  "use strict";
});
/**
@module ember
@submodule ember-runtime
*/
enifed('ember-runtime/ext/function', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-metal/computed', 'ember-metal/mixin'], function (exports, _emberMetalCore, _emberMetalDebug, _emberMetalComputed, _emberMetalMixin) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  var a_slice = Array.prototype.slice;
  var FunctionPrototype = Function.prototype;

  if (_emberMetalCore.default.EXTEND_PROTOTYPES === true || _emberMetalCore.default.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');
        }.property() // Call this flag to mark the function as a 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/classes/Ember.computed.html).
       @method property
      @for Function
      @public
    */
    FunctionPrototype.property = function () {
      var ret = _emberMetalComputed.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.
       See `Ember.observer`.
       @method observes
      @for Function
      @public
    */
    FunctionPrototype.observes = function () {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      args.push(this);
      return _emberMetalMixin.observer.apply(this, args);
    };

    FunctionPrototype._observesImmediately = function () {
      _emberMetalDebug.assert('Immediate observers must observe internal properties only, ' + 'not properties on other objects.', function checkIsInternalProperty() {
        for (var i = 0, l = arguments.length; i < l; i++) {
          if (arguments[i].indexOf('.') !== -1) {
            return false;
          }
        }
        return true;
      });

      // observes handles property expansion
      return this.observes.apply(this, arguments);
    };
    /**
      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
      @deprecated
      @private
    */
    FunctionPrototype.observesImmediately = _emberMetalDebug.deprecateFunc('Function#observesImmediately is deprecated. Use Function#observes instead', { id: 'ember-runtime.ext-function', until: '3.0.0' }, FunctionPrototype._observesImmediately);

    /**
      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
      @public
    */
    FunctionPrototype.on = function () {
      var events = a_slice.call(arguments);
      this.__ember_listens__ = events;

      return this;
    };
  }
});
// Ember.EXTEND_PROTOTYPES
enifed('ember-runtime/ext/rsvp', ['exports', 'ember-metal/core', 'require', 'ember-metal/debug', 'ember-metal/logger', 'ember-metal/run_loop', 'rsvp'], function (exports, _emberMetalCore, _require, _emberMetalDebug, _emberMetalLogger, _emberMetalRun_loop, _rsvp) {
  'use strict';

  exports.onerrorDefault = onerrorDefault;
  exports.after = after;

  var testModuleName = 'ember-testing/test';
  var Test;

  var asyncStart = function () {
    if (_emberMetalCore.default.Test && _emberMetalCore.default.Test.adapter) {
      _emberMetalCore.default.Test.adapter.asyncStart();
    }
  };

  var asyncEnd = function () {
    if (_emberMetalCore.default.Test && _emberMetalCore.default.Test.adapter) {
      _emberMetalCore.default.Test.adapter.asyncEnd();
    }
  };

  _rsvp.configure('async', function (callback, promise) {
    var async = !_emberMetalRun_loop.default.currentRunLoop;

    if (_emberMetalCore.default.testing && async) {
      asyncStart();
    }

    _emberMetalRun_loop.default.backburner.schedule('actions', function () {
      if (_emberMetalCore.default.testing && async) {
        asyncEnd();
      }
      callback(promise);
    });
  });

  function onerrorDefault(reason) {
    var error;

    if (reason && reason.errorThrown) {
      // jqXHR provides this
      error = reason.errorThrown;
      if (typeof error === 'string') {
        error = new Error(error);
      }
      Object.defineProperty(error, '__reason_with_error_thrown__', {
        value: reason,
        enumerable: false
      });
    } else {
      error = reason;
    }

    if (error && error.name === 'UnrecognizedURLError') {
      _emberMetalDebug.assert('The URL \'' + error.message + '\' did not match any routes in your application', false);
      return;
    }

    if (error && error.name !== 'TransitionAborted') {
      if (_emberMetalCore.default.testing) {
        // ES6TODO: remove when possible
        if (!Test && _require.has(testModuleName)) {
          Test = _require.default(testModuleName)['default'];
        }

        if (Test && Test.adapter) {
          Test.adapter.exception(error);
          _emberMetalLogger.default.error(error.stack);
        } else {
          throw error;
        }
      } else if (_emberMetalCore.default.onerror) {
        _emberMetalCore.default.onerror(error);
      } else {
        _emberMetalLogger.default.error(error.stack);
      }
    }
  }

  function after(cb) {
    _emberMetalRun_loop.default.schedule(_emberMetalRun_loop.default.queues[_emberMetalRun_loop.default.queues.length - 1], cb);
  }

  _rsvp.on('error', onerrorDefault);
  _rsvp.configure('after', after);

  exports.default = _rsvp;
});
enifed('ember-runtime/ext/string', ['exports', 'ember-metal/core', 'ember-runtime/system/string'], function (exports, _emberMetalCore, _emberRuntimeSystemString) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  var StringPrototype = String.prototype;

  if (_emberMetalCore.default.EXTEND_PROTOTYPES === true || _emberMetalCore.default.EXTEND_PROTOTYPES.String) {
    /**
      See [Ember.String.fmt](/api/classes/Ember.String.html#method_fmt).
       @method fmt
      @for String
      @private
      @deprecated
    */
    StringPrototype.fmt = function () {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      return _emberRuntimeSystemString.fmt(this, args);
    };

    /**
      See [Ember.String.w](/api/classes/Ember.String.html#method_w).
       @method w
      @for String
      @private
    */
    StringPrototype.w = function () {
      return _emberRuntimeSystemString.w(this);
    };

    /**
      See [Ember.String.loc](/api/classes/Ember.String.html#method_loc).
       @method loc
      @for String
      @private
    */
    StringPrototype.loc = function () {
      for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }

      return _emberRuntimeSystemString.loc(this, args);
    };

    /**
      See [Ember.String.camelize](/api/classes/Ember.String.html#method_camelize).
       @method camelize
      @for String
      @private
    */
    StringPrototype.camelize = function () {
      return _emberRuntimeSystemString.camelize(this);
    };

    /**
      See [Ember.String.decamelize](/api/classes/Ember.String.html#method_decamelize).
       @method decamelize
      @for String
      @private
    */
    StringPrototype.decamelize = function () {
      return _emberRuntimeSystemString.decamelize(this);
    };

    /**
      See [Ember.String.dasherize](/api/classes/Ember.String.html#method_dasherize).
       @method dasherize
      @for String
      @private
    */
    StringPrototype.dasherize = function () {
      return _emberRuntimeSystemString.dasherize(this);
    };

    /**
      See [Ember.String.underscore](/api/classes/Ember.String.html#method_underscore).
       @method underscore
      @for String
      @private
    */
    StringPrototype.underscore = function () {
      return _emberRuntimeSystemString.underscore(this);
    };

    /**
      See [Ember.String.classify](/api/classes/Ember.String.html#method_classify).
       @method classify
      @for String
      @private
    */
    StringPrototype.classify = function () {
      return _emberRuntimeSystemString.classify(this);
    };

    /**
      See [Ember.String.capitalize](/api/classes/Ember.String.html#method_capitalize).
       @method capitalize
      @for String
      @private
    */
    StringPrototype.capitalize = function () {
      return _emberRuntimeSystemString.capitalize(this);
    };
  }
});
// Ember.EXTEND_PROTOTYPES
enifed('ember-runtime/index', ['exports', 'ember-metal', 'ember-runtime/is-equal', 'ember-runtime/compare', 'ember-runtime/copy', 'ember-runtime/inject', 'ember-runtime/system/namespace', 'ember-runtime/system/object', 'ember-runtime/system/container', 'ember-runtime/system/array_proxy', 'ember-runtime/system/object_proxy', 'ember-runtime/system/core_object', 'ember-runtime/system/native_array', 'ember-runtime/system/string', '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/-proxy', 'ember-runtime/mixins/observable', 'ember-runtime/mixins/action_handler', '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-metal/features', 'ember-runtime/computed/reduce_computed_macros', 'ember-runtime/controllers/controller', 'ember-runtime/mixins/controller', 'ember-runtime/system/service', 'ember-runtime/ext/rsvp', 'ember-runtime/ext/string', 'ember-runtime/ext/function', 'ember-runtime/utils', 'ember-runtime/mixins/registry_proxy', 'ember-runtime/mixins/container_proxy', 'ember-runtime/string_registry'], function (exports, _emberMetal, _emberRuntimeIsEqual, _emberRuntimeCompare, _emberRuntimeCopy, _emberRuntimeInject, _emberRuntimeSystemNamespace, _emberRuntimeSystemObject, _emberRuntimeSystemContainer, _emberRuntimeSystemArray_proxy, _emberRuntimeSystemObject_proxy, _emberRuntimeSystemCore_object, _emberRuntimeSystemNative_array, _emberRuntimeSystemString, _emberRuntimeSystemLazy_load, _emberRuntimeMixinsArray, _emberRuntimeMixinsComparable, _emberRuntimeMixinsCopyable, _emberRuntimeMixinsEnumerable, _emberRuntimeMixinsFreezable, _emberRuntimeMixinsProxy, _emberRuntimeMixinsObservable, _emberRuntimeMixinsAction_handler, _emberRuntimeMixinsMutable_enumerable, _emberRuntimeMixinsMutable_array, _emberRuntimeMixinsTarget_action_support, _emberRuntimeMixinsEvented, _emberRuntimeMixinsPromise_proxy, _emberMetalFeatures, _emberRuntimeComputedReduce_computed_macros, _emberRuntimeControllersController, _emberRuntimeMixinsController, _emberRuntimeSystemService, _emberRuntimeExtRsvp, _emberRuntimeExtString, _emberRuntimeExtFunction, _emberRuntimeUtils, _emberRuntimeMixinsRegistry_proxy, _emberRuntimeMixinsContainer_proxy, _emberRuntimeString_registry) {
  /**
  @module ember
  @submodule ember-runtime
  */

  // BEGIN IMPORTS
  'use strict';

  // END IMPORTS

  // BEGIN EXPORTS
  _emberMetal.default.compare = _emberRuntimeCompare.default;
  _emberMetal.default.copy = _emberRuntimeCopy.default;
  _emberMetal.default.isEqual = _emberRuntimeIsEqual.default;

  _emberMetal.default.inject = _emberRuntimeInject.default;

  _emberMetal.default.Array = _emberRuntimeMixinsArray.default;

  _emberMetal.default.Comparable = _emberRuntimeMixinsComparable.default;
  _emberMetal.default.Copyable = _emberRuntimeMixinsCopyable.default;

  _emberMetal.default.Freezable = _emberRuntimeMixinsFreezable.Freezable;
  _emberMetal.default.FROZEN_ERROR = _emberRuntimeMixinsFreezable.FROZEN_ERROR;

  _emberMetal.default.MutableEnumerable = _emberRuntimeMixinsMutable_enumerable.default;
  _emberMetal.default.MutableArray = _emberRuntimeMixinsMutable_array.default;

  _emberMetal.default.TargetActionSupport = _emberRuntimeMixinsTarget_action_support.default;
  _emberMetal.default.Evented = _emberRuntimeMixinsEvented.default;

  _emberMetal.default.PromiseProxyMixin = _emberRuntimeMixinsPromise_proxy.default;

  _emberMetal.default.Observable = _emberRuntimeMixinsObservable.default;

  _emberMetal.default.typeOf = _emberRuntimeUtils.typeOf;
  _emberMetal.default.isArray = _emberRuntimeUtils.isArray;

  // ES6TODO: this seems a less than ideal way/place to add properties to Ember.computed
  var EmComputed = _emberMetal.default.computed;

  EmComputed.sum = _emberRuntimeComputedReduce_computed_macros.sum;
  EmComputed.min = _emberRuntimeComputedReduce_computed_macros.min;
  EmComputed.max = _emberRuntimeComputedReduce_computed_macros.max;
  EmComputed.map = _emberRuntimeComputedReduce_computed_macros.map;
  EmComputed.sort = _emberRuntimeComputedReduce_computed_macros.sort;
  EmComputed.setDiff = _emberRuntimeComputedReduce_computed_macros.setDiff;
  EmComputed.mapBy = _emberRuntimeComputedReduce_computed_macros.mapBy;
  EmComputed.filter = _emberRuntimeComputedReduce_computed_macros.filter;
  EmComputed.filterBy = _emberRuntimeComputedReduce_computed_macros.filterBy;
  EmComputed.uniq = _emberRuntimeComputedReduce_computed_macros.uniq;

  EmComputed.union = _emberRuntimeComputedReduce_computed_macros.union;
  EmComputed.intersect = _emberRuntimeComputedReduce_computed_macros.intersect;
  EmComputed.collect = _emberRuntimeComputedReduce_computed_macros.collect;

  _emberMetal.default.String = _emberRuntimeSystemString.default;
  _emberMetal.default.Object = _emberRuntimeSystemObject.default;
  _emberMetal.default.Container = _emberRuntimeSystemContainer.Container;
  _emberMetal.default.Registry = _emberRuntimeSystemContainer.Registry;

  _emberMetal.default.getOwner = _emberRuntimeSystemContainer.getOwner;
  _emberMetal.default.setOwner = _emberRuntimeSystemContainer.setOwner;

  _emberMetal.default._RegistryProxyMixin = _emberRuntimeMixinsRegistry_proxy.default;
  _emberMetal.default._ContainerProxyMixin = _emberRuntimeMixinsContainer_proxy.default;

  _emberMetal.default.Namespace = _emberRuntimeSystemNamespace.default;
  _emberMetal.default.Enumerable = _emberRuntimeMixinsEnumerable.default;
  _emberMetal.default.ArrayProxy = _emberRuntimeSystemArray_proxy.default;
  _emberMetal.default.ObjectProxy = _emberRuntimeSystemObject_proxy.default;
  _emberMetal.default.ActionHandler = _emberRuntimeMixinsAction_handler.default;
  _emberMetal.default.CoreObject = _emberRuntimeSystemCore_object.default;
  _emberMetal.default.NativeArray = _emberRuntimeSystemNative_array.default;
  // ES6TODO: Currently we must rely on the global from ember-metal/core to avoid circular deps
  // Ember.A = A;
  _emberMetal.default.onLoad = _emberRuntimeSystemLazy_load.onLoad;
  _emberMetal.default.runLoadHooks = _emberRuntimeSystemLazy_load.runLoadHooks;

  _emberMetal.default.Controller = _emberRuntimeControllersController.default;
  _emberMetal.default.ControllerMixin = _emberRuntimeMixinsController.default;

  _emberMetal.default.Service = _emberRuntimeSystemService.default;

  _emberMetal.default._ProxyMixin = _emberRuntimeMixinsProxy.default;

  _emberMetal.default.RSVP = _emberRuntimeExtRsvp.default;
  // END EXPORTS

  /**
    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 Object
    @private
  */
  Object.defineProperty(_emberMetal.default, 'STRINGS', {
    configurable: false,
    get: _emberRuntimeString_registry.getStrings,
    set: _emberRuntimeString_registry.setStrings
  });

  exports.default = _emberMetal.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
enifed('ember-runtime/inject', ['exports', 'ember-metal/debug', 'ember-metal/injected_property'], function (exports, _emberMetalDebug, _emberMetalInjected_property) {
  'use strict';

  exports.default = inject;
  exports.createInjectionHelper = createInjectionHelper;
  exports.validatePropertyInjections = validatePropertyInjections;

  /**
    Namespace for injection helper methods.

    @class inject
    @namespace Ember
    @static
    @public
  */

  function inject() {
    _emberMetalDebug.assert('Injected properties must be created through helpers, see \'' + Object.keys(inject).join('"', '"') + '\'');
  }

  // Dictionary of injection validations by type, added to by `createInjectionHelper`
  var typeValidators = {};

  /**
    This method allows other Ember modules to register injection helpers for a
    given container type. Helpers are exported to the `inject` namespace as the
    container type itself.

    @private
    @method createInjectionHelper
    @since 1.10.0
    @for Ember
    @param {String} type The container type the helper will inject
    @param {Function} validator A validation callback that is executed at mixin-time
  */

  function createInjectionHelper(type, validator) {
    typeValidators[type] = validator;

    inject[type] = function (name) {
      return new _emberMetalInjected_property.default(type, name);
    };
  }

  /**
    Validation function that runs per-type validation functions once for each
    injected type encountered.

    @private
    @method validatePropertyInjections
    @since 1.10.0
    @for Ember
    @param {Object} factory The factory object
  */

  function validatePropertyInjections(factory) {
    var proto = factory.proto();
    var types = [];
    var key, desc, validator, i, l;

    for (key in proto) {
      desc = proto[key];
      if (desc instanceof _emberMetalInjected_property.default && types.indexOf(desc.type) === -1) {
        types.push(desc.type);
      }
    }

    if (types.length) {
      for (i = 0, l = types.length; i < l; i++) {
        validator = typeValidators[types[i]];

        if (typeof validator === 'function') {
          validator(factory);
        }
      }
    }

    return true;
  }
});
enifed('ember-runtime/is-equal', ['exports'], function (exports) {
  /**
    Compares two objects, returning true if they are equal.

    ```javascript
    Ember.isEqual('hello', 'hello');                   // true
    Ember.isEqual(1, 2);                               // false
    ```

    `isEqual` is a more specific comparison than a triple equal comparison.
    It will call the `isEqual` instance method on the objects being
    compared, allowing finer control over when objects should be considered
    equal to each other.

    ```javascript
    let Person = Ember.Object.extend({
      isEqual(other) { return this.ssn == other.ssn; }
    });

    let personA = Person.create({name: 'Muhammad Ali', ssn: '123-45-6789'});
    let personB = Person.create({name: 'Cassius Clay', ssn: '123-45-6789'});

    Ember.isEqual(personA, personB); // true
    ```

    Due to the expense of array comparisons, collections will never be equal to
    each other even if each of their items are equal to each other.

    ```javascript
    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}
    @public
  */
  'use strict';

  exports.default = isEqual;

  function isEqual(a, b) {
    if (a && typeof a.isEqual === 'function') {
      return a.isEqual(b);
    }

    if (a instanceof Date && b instanceof Date) {
      return a.getTime() === b.getTime();
    }

    return a === b;
  }
});
enifed('ember-runtime/mixins/-proxy', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/meta', 'ember-metal/observer', 'ember-metal/property_events', 'ember-metal/computed', 'ember-metal/properties', 'ember-metal/mixin', 'ember-metal/symbol'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalMeta, _emberMetalObserver, _emberMetalProperty_events, _emberMetalComputed, _emberMetalProperties, _emberMetalMixin, _emberMetalSymbol) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  var _Mixin$create;

  exports.isProxy = isProxy;

  var IS_PROXY = _emberMetalSymbol.default('IS_PROXY');

  function isProxy(value) {
    return value && value[IS_PROXY];
  }

  function contentPropertyWillChange(content, contentKey) {
    var key = contentKey.slice(8); // remove "content."
    if (key in this) {
      return;
    } // if shadowed in proxy
    _emberMetalProperty_events.propertyWillChange(this, key);
  }

  function contentPropertyDidChange(content, contentKey) {
    var key = contentKey.slice(8); // remove "content."
    if (key in this) {
      return;
    } // if shadowed in proxy
    _emberMetalProperty_events.propertyDidChange(this, key);
  }

  /**
    `Ember.ProxyMixin` forwards all properties not defined by the proxy itself
    to a proxied `content` object.  See Ember.ObjectProxy for more details.

    @class ProxyMixin
    @namespace Ember
    @private
  */
  exports.default = _emberMetalMixin.Mixin.create((_Mixin$create = {}, _Mixin$create[IS_PROXY] = true, _Mixin$create.content = null, _Mixin$create._contentDidChange = _emberMetalMixin.observer('content', function () {
    _emberMetalDebug.assert('Can\'t set Proxy\'s content to itself', _emberMetalProperty_get.get(this, 'content') !== this);
  }), _Mixin$create.isTruthy = _emberMetalComputed.computed.bool('content'), _Mixin$create._debugContainerKey = null, _Mixin$create.willWatchProperty = function (key) {
    var contentKey = 'content.' + key;
    _emberMetalObserver._addBeforeObserver(this, contentKey, null, contentPropertyWillChange);
    _emberMetalObserver.addObserver(this, contentKey, null, contentPropertyDidChange);
  }, _Mixin$create.didUnwatchProperty = function (key) {
    var contentKey = 'content.' + key;
    _emberMetalObserver._removeBeforeObserver(this, contentKey, null, contentPropertyWillChange);
    _emberMetalObserver.removeObserver(this, contentKey, null, contentPropertyDidChange);
  }, _Mixin$create.unknownProperty = function (key) {
    var content = _emberMetalProperty_get.get(this, 'content');
    if (content) {
      _emberMetalDebug.deprecate('You attempted to access `' + key + '` from `' + this + '`, but object proxying is deprecated. Please use `model.' + key + '` instead.', !this.isController, { id: 'ember-runtime.controller-proxy', until: '3.0.0' });
      return _emberMetalProperty_get.get(content, key);
    }
  }, _Mixin$create.setUnknownProperty = function (key, value) {
    var m = _emberMetalMeta.meta(this);
    if (m.proto === this) {
      // if marked as prototype then just defineProperty
      // rather than delegate
      _emberMetalProperties.defineProperty(this, key, null, value);
      return value;
    }

    var content = _emberMetalProperty_get.get(this, 'content');
    _emberMetalDebug.assert('Cannot delegate set(\'' + key + '\', ' + value + ') to the \'content\' property of object proxy ' + this + ': its \'content\' is undefined.', content);

    _emberMetalDebug.deprecate('You attempted to set `' + key + '` from `' + this + '`, but object proxying is deprecated. Please use `model.' + key + '` instead.', !this.isController, { id: 'ember-runtime.controller-proxy', until: '3.0.0' });
    return _emberMetalProperty_set.set(content, key, value);
  }, _Mixin$create));
});

/**
  The object whose properties will be forwarded.
   @property content
  @type Ember.Object
  @default null
  @private
*/
enifed('ember-runtime/mixins/action_handler', ['exports', 'ember-metal/debug', 'ember-metal/mixin', 'ember-metal/property_get'], function (exports, _emberMetalDebug, _emberMetalMixin, _emberMetalProperty_get) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  exports.deprecateUnderscoreActions = deprecateUnderscoreActions;

  /**
    `Ember.ActionHandler` is available on some familiar classes including
    `Ember.Route`, `Ember.View`, `Ember.Component`, and `Ember.Controller`.
    (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
    @private
  */
  var ActionHandler = _emberMetalMixin.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(...arguments)` 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(...arguments);
             // 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.route("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 Object
      @default null
      @public
    */

    /**
      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
      @public
    */
    send: function (actionName) {
      for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        args[_key - 1] = arguments[_key];
      }

      var target;

      if (this.actions && this.actions[actionName]) {
        var shouldBubble = this.actions[actionName].apply(this, args) === true;
        if (!shouldBubble) {
          return;
        }
      }

      if (target = _emberMetalProperty_get.get(this, 'target')) {
        var _target;

        _emberMetalDebug.assert('The `target` for ' + this + ' (' + target + ') does not have a `send` method', typeof target.send === 'function');
        (_target = target).send.apply(_target, arguments);
      }
    },

    willMergeMixin: function (props) {
      _emberMetalDebug.assert('Specifying `_actions` and `actions` in the same mixin is not supported.', !props.actions || !props._actions);

      if (props._actions) {
        _emberMetalDebug.deprecate('Specifying actions in `_actions` is deprecated, please use `actions` instead.', false, { id: 'ember-runtime.action-handler-_actions', until: '3.0.0' });

        props.actions = props._actions;
        delete props._actions;
      }
    }
  });

  exports.default = ActionHandler;

  function deprecateUnderscoreActions(factory) {
    Object.defineProperty(factory.prototype, '_actions', {
      configurable: true,
      enumerable: false,
      set: function (value) {
        _emberMetalDebug.assert('You cannot set `_actions` on ' + this + ', please use `actions` instead.');
      },
      get: function () {
        _emberMetalDebug.deprecate('Usage of `_actions` is deprecated, use `actions` instead.', false, { id: 'ember-runtime.action-handler-_actions', until: '3.0.0' });
        return _emberMetalProperty_get.get(this, 'actions');
      }
    });
  }
});
enifed('ember-runtime/mixins/array', ['exports', 'ember-metal/core', 'ember-metal/symbol', 'ember-metal/property_get', 'ember-metal/computed', 'ember-metal/is_none', 'ember-runtime/mixins/enumerable', 'ember-metal/mixin', 'ember-metal/property_events', 'ember-metal/events', 'ember-metal/meta', 'ember-metal/tags', 'ember-runtime/system/each_proxy'], function (exports, _emberMetalCore, _emberMetalSymbol, _emberMetalProperty_get, _emberMetalComputed, _emberMetalIs_none, _emberRuntimeMixinsEnumerable, _emberMetalMixin, _emberMetalProperty_events, _emberMetalEvents, _emberMetalMeta, _emberMetalTags, _emberRuntimeSystemEach_proxy) {
  /**
  @module ember
  @submodule ember-runtime
  */

  // ..........................................................
  // HELPERS
  //
  'use strict';

  var _Mixin$create;

  exports.addArrayObserver = addArrayObserver;
  exports.removeArrayObserver = removeArrayObserver;
  exports.objectAt = objectAt;
  exports.isEmberArray = isEmberArray;

  function arrayObserversHelper(obj, target, opts, operation, notify) {
    var willChange = opts && opts.willChange || 'arrayWillChange';
    var didChange = opts && opts.didChange || 'arrayDidChange';
    var hasObservers = _emberMetalProperty_get.get(obj, 'hasArrayObservers');

    if (hasObservers === notify) {
      _emberMetalProperty_events.propertyWillChange(obj, 'hasArrayObservers');
    }

    operation(obj, '@array:before', target, willChange);
    operation(obj, '@array:change', target, didChange);

    if (hasObservers === notify) {
      _emberMetalProperty_events.propertyDidChange(obj, 'hasArrayObservers');
    }

    return obj;
  }

  function addArrayObserver(array, target, opts) {
    return arrayObserversHelper(array, target, opts, _emberMetalEvents.addListener, false);
  }

  function removeArrayObserver(array, target, opts) {
    return arrayObserversHelper(array, target, opts, _emberMetalEvents.removeListener, true);
  }

  function objectAt(content, idx) {
    if (content.objectAt) {
      return content.objectAt(idx);
    }

    return content[idx];
  }

  var EMBER_ARRAY = _emberMetalSymbol.default('EMBER_ARRAY');

  function isEmberArray(obj) {
    return obj && !!obj[EMBER_ARRAY];
  }

  // ..........................................................
  // 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 is a 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: `length()` 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
    @public
  */
  exports.default = _emberMetalMixin.Mixin.create(_emberRuntimeMixinsEnumerable.default, (_Mixin$create = {}, _Mixin$create[EMBER_ARRAY] = true, _Mixin$create.length = null, _Mixin$create.objectAt = function (idx) {
    if (idx < 0 || idx >= _emberMetalProperty_get.get(this, 'length')) {
      return undefined;
    }

    return _emberMetalProperty_get.get(this, idx);
  }, _Mixin$create.objectsAt = function (indexes) {
    var _this = this;

    return indexes.map(function (idx) {
      return objectAt(_this, idx);
    });
  }, _Mixin$create.nextObject = function (idx) {
    return objectAt(this, idx);
  }, _Mixin$create['[]'] = _emberMetalComputed.computed({
    get: function (key) {
      return this;
    },
    set: function (key, value) {
      this.replace(0, _emberMetalProperty_get.get(this, 'length'), value);
      return this;
    }
  }), _Mixin$create.firstObject = _emberMetalComputed.computed(function () {
    return objectAt(this, 0);
  }).readOnly(), _Mixin$create.lastObject = _emberMetalComputed.computed(function () {
    return objectAt(this, _emberMetalProperty_get.get(this, 'length') - 1);
  }).readOnly(), _Mixin$create.contains = function (obj) {
    return this.indexOf(obj) >= 0;
  }, _Mixin$create.slice = function (beginIndex, endIndex) {
    var ret = _emberMetalCore.default.A();
    var length = _emberMetalProperty_get.get(this, 'length');

    if (_emberMetalIs_none.default(beginIndex)) {
      beginIndex = 0;
    }

    if (_emberMetalIs_none.default(endIndex) || endIndex > length) {
      endIndex = length;
    }

    if (beginIndex < 0) {
      beginIndex = length + beginIndex;
    }

    if (endIndex < 0) {
      endIndex = length + endIndex;
    }

    while (beginIndex < endIndex) {
      ret[ret.length] = objectAt(this, beginIndex++);
    }

    return ret;
  }, _Mixin$create.indexOf = function (object, startAt) {
    var len = _emberMetalProperty_get.get(this, 'length');
    var idx;

    if (startAt === undefined) {
      startAt = 0;
    }

    if (startAt < 0) {
      startAt += len;
    }

    for (idx = startAt; idx < len; idx++) {
      if (objectAt(this, idx) === object) {
        return idx;
      }
    }

    return -1;
  }, _Mixin$create.lastIndexOf = function (object, startAt) {
    var len = _emberMetalProperty_get.get(this, 'length');
    var idx;

    if (startAt === undefined || startAt >= len) {
      startAt = len - 1;
    }

    if (startAt < 0) {
      startAt += len;
    }

    for (idx = startAt; idx >= 0; idx--) {
      if (objectAt(this, idx) === object) {
        return idx;
      }
    }

    return -1;
  }, _Mixin$create.addArrayObserver = function (target, opts) {
    return addArrayObserver(this, target, opts);
  }, _Mixin$create.removeArrayObserver = function (target, opts) {
    return removeArrayObserver(this, target, opts);
  }, _Mixin$create.hasArrayObservers = _emberMetalComputed.computed(function () {
    return _emberMetalEvents.hasListeners(this, '@array:change') || _emberMetalEvents.hasListeners(this, '@array:before');
  }), _Mixin$create.arrayContentWillChange = function (startIdx, removeAmt, addAmt) {
    var removing, lim;

    // 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;
      }
    }

    if (this.__each) {
      this.__each.arrayWillChange(this, startIdx, removeAmt, addAmt);
    }

    _emberMetalEvents.sendEvent(this, '@array:before', [this, startIdx, removeAmt, addAmt]);

    if (startIdx >= 0 && removeAmt >= 0 && _emberMetalProperty_get.get(this, 'hasEnumerableObservers')) {
      removing = [];
      lim = startIdx + removeAmt;

      for (var idx = startIdx; idx < lim; idx++) {
        removing.push(objectAt(this, idx));
      }
    } else {
      removing = removeAmt;
    }

    this.enumerableContentWillChange(removing, addAmt);

    return this;
  }, _Mixin$create.arrayContentDidChange = function (startIdx, removeAmt, addAmt) {
    var adding, lim;

    _emberMetalTags.markObjectAsDirty(_emberMetalMeta.meta(this));

    // 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;
      }
    }

    if (startIdx >= 0 && addAmt >= 0 && _emberMetalProperty_get.get(this, 'hasEnumerableObservers')) {
      adding = [];
      lim = startIdx + addAmt;

      for (var idx = startIdx; idx < lim; idx++) {
        adding.push(objectAt(this, idx));
      }
    } else {
      adding = addAmt;
    }

    this.enumerableContentDidChange(removeAmt, adding);

    if (this.__each) {
      this.__each.arrayDidChange(this, startIdx, removeAmt, addAmt);
    }

    _emberMetalEvents.sendEvent(this, '@array:change', [this, startIdx, removeAmt, addAmt]);

    var length = _emberMetalProperty_get.get(this, 'length');
    var cachedFirst = _emberMetalComputed.cacheFor(this, 'firstObject');
    var cachedLast = _emberMetalComputed.cacheFor(this, 'lastObject');

    if (objectAt(this, 0) !== cachedFirst) {
      _emberMetalProperty_events.propertyWillChange(this, 'firstObject');
      _emberMetalProperty_events.propertyDidChange(this, 'firstObject');
    }

    if (objectAt(this, length - 1) !== cachedLast) {
      _emberMetalProperty_events.propertyWillChange(this, 'lastObject');
      _emberMetalProperty_events.propertyDidChange(this, 'lastObject');
    }

    return this;
  }, _Mixin$create['@each'] = _emberMetalComputed.computed(function () {
    // TODO use Symbol or add to meta
    if (!this.__each) {
      this.__each = new _emberRuntimeSystemEach_proxy.default(this);
    }

    return this.__each;
  }).volatile(), _Mixin$create));
});
// ES6TODO: Ember.A

/**
  __Required.__ You must implement this method to apply this mixin.
   Your array must support the `length` property. Your replace methods should
  set this property whenever it changes.
   @property {Number} length
  @public
*/

/**
  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
  @public
*/

/**
  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}
  @public
 */

// overrides Ember.Enumerable version

/**
  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
  @public
*/

// optimized version from Enumerable

// 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 {Number} beginIndex (Optional) index to begin slicing from.
  @param {Number} endIndex (Optional) index to end the slice at (but not included).
  @return {Array} New array with specified slice
  @public
*/

/**
  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
  @public
*/

/**
  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
  @public
*/

// ..........................................................
// 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 as 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 {Object} opts Optional hash of configuration options including
    `willChange` and `didChange` option.
  @return {Ember.Array} receiver
  @public
*/

/**
  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 {Object} opts Optional hash of configuration options including
    `willChange` and `didChange` option.
  @return {Ember.Array} receiver
  @public
*/

/**
  Becomes true whenever the array currently has observers watching changes
  on the array.
   @property {Boolean} hasArrayObservers
  @public
*/

/**
  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
  @public
*/

/**
  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
  @public
*/

/**
  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.
   `@each` should only be used in a non-terminal context. Example:
   ```javascript
  myMethod: computed('posts.@each.author', function(){
    ...
  });
  ```
   If you merely want to watch for the array being changed, like an object being
  replaced, added or removed, use `[]` instead of `@each`.
   ```javascript
  myMethod: computed('posts.[]', function(){
    ...
  });
  ```
   @property @each
  @public
*/
enifed('ember-runtime/mixins/comparable', ['exports', 'ember-metal/mixin'], function (exports, _emberMetalMixin) {
  'use strict';

  /**
  @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
    @private
  */
  exports.default = _emberMetalMixin.Mixin.create({

    /**
      __Required.__ You must implement this method to apply this mixin.
       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 {Number} the result of the comparison
      @private
    */
    compare: null
  });
});
enifed('ember-runtime/mixins/container_proxy', ['exports', 'ember-metal/run_loop', 'ember-metal/debug', 'ember-metal/mixin'], function (exports, _emberMetalRun_loop, _emberMetalDebug, _emberMetalMixin) {
  /**
  @module ember
  @submodule ember-runtime
  */
  'use strict';

  exports.buildFakeContainerWithDeprecations = buildFakeContainerWithDeprecations;

  /**
    ContainerProxyMixin is used to provide public access to specific
    container functionality.

    @class ContainerProxyMixin
    @private
  */
  exports.default = _emberMetalMixin.Mixin.create({
    /**
     The container stores state.
      @private
     @property {Ember.Container} __container__
     */
    __container__: null,

    /**
     Returns an object that can be used to provide an owner to a
     manually created instance.
      Example:
      ```
     let owner = Ember.getOwner(this);
      User.create(
       owner.ownerInjection(),
       { username: 'rwjblue' }
     )
     ```
      @public
     @method ownerInjection
     @return {Object}
    */
    ownerInjection: function () {
      return this.__container__.ownerInjection();
    },

    /**
     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 registry = new Registry();
     var container = registry.container();
      registry.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 registry = new Registry();
     var container = registry.container();
      registry.register('api:twitter', Twitter);
      var twitter = container.lookup('api:twitter', { singleton: false });
     var twitter2 = container.lookup('api:twitter', { singleton: false });
      twitter === twitter2; //=> false
     ```
      @public
     @method lookup
     @param {String} fullName
     @param {Object} options
     @return {any}
     */
    lookup: function (fullName, options) {
      return this.__container__.lookup(fullName, options);
    },

    /**
     Given a fullName return the corresponding factory.
      @private
     @method _lookupFactory
     @param {String} fullName
     @return {any}
     */
    _lookupFactory: function (fullName, options) {
      return this.__container__.lookupFactory(fullName, options);
    },

    /**
     @private
     */
    willDestroy: function () {
      this._super.apply(this, arguments);

      if (this.__container__) {
        _emberMetalRun_loop.default(this.__container__, 'destroy');
      }
    }
  });

  function buildFakeContainerWithDeprecations(container) {
    var fakeContainer = {};
    var propertyMappings = {
      lookup: 'lookup',
      lookupFactory: '_lookupFactory'
    };

    for (var containerProperty in propertyMappings) {
      fakeContainer[containerProperty] = buildFakeContainerFunction(container, containerProperty, propertyMappings[containerProperty]);
    }

    return fakeContainer;
  }

  function buildFakeContainerFunction(container, containerProperty, ownerProperty) {
    return function () {
      _emberMetalDebug.deprecate('Using the injected `container` is deprecated. Please use the `getOwner` helper to access the owner of this object and then call `' + ownerProperty + '` instead.', false, {
        id: 'ember-application.injected-container',
        until: '3.0.0',
        url: 'http://emberjs.com/deprecations/v2.x#toc_injected-container-access'
      });
      return container[containerProperty].apply(container, arguments);
    };
  }
});
enifed('ember-runtime/mixins/controller', ['exports', 'ember-metal/mixin', 'ember-metal/alias', 'ember-runtime/mixins/action_handler', 'ember-runtime/mixins/controller_content_model_alias_deprecation'], function (exports, _emberMetalMixin, _emberMetalAlias, _emberRuntimeMixinsAction_handler, _emberRuntimeMixinsController_content_model_alias_deprecation) {
  'use strict';

  /**
    @class ControllerMixin
    @namespace Ember
    @uses Ember.ActionHandler
    @private
  */
  exports.default = _emberMetalMixin.Mixin.create(_emberRuntimeMixinsAction_handler.default, _emberRuntimeMixinsController_content_model_alias_deprecation.default, {
    /* 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 applied
      as part of the application's initialization process. In most cases the
      `target` property will automatically be set to the logical consumer of
      actions for the controller.
       @property target
      @default null
      @public
    */
    target: null,

    parentController: null,

    store: null,

    /**
      The controller's current model. When retrieving or modifying a controller's
      model, this property should be used instead of the `content` property.
       @property model
      @public
     */
    model: null,

    /**
      @private
    */
    content: _emberMetalAlias.default('model')

  });
});
enifed('ember-runtime/mixins/controller_content_model_alias_deprecation', ['exports', 'ember-metal/debug', 'ember-metal/mixin'], function (exports, _emberMetalDebug, _emberMetalMixin) {
  'use strict';

  /*
    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
    its model and ember will do the right thing.

    Used internally by Ember in `Ember.Controller`.
  */
  exports.default = _emberMetalMixin.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'];

        _emberMetalDebug.deprecate('Do not specify `content` on a Controller, use `model` instead.', false, { id: 'ember-runtime.will-merge-mixin', until: '3.0.0' });
      }
    }
  });
});
enifed('ember-runtime/mixins/copyable', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/mixin', 'ember-runtime/mixins/freezable', 'ember-metal/error'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalMixin, _emberRuntimeMixinsFreezable, _emberMetalError) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  /**
    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
    @private
  */
  exports.default = _emberMetalMixin.Mixin.create({
    /**
      __Required.__ You must implement this method to apply this mixin.
       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
      @private
    */
    copy: null,

    /**
      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
      @deprecated Use `Object.freeze` instead.
      @private
    */
    frozenCopy: function () {
      _emberMetalDebug.deprecate('`frozenCopy` is deprecated, use `Object.freeze` instead.', false, { id: 'ember-runtime.frozen-copy', until: '3.0.0' });
      if (_emberRuntimeMixinsFreezable.Freezable && _emberRuntimeMixinsFreezable.Freezable.detect(this)) {
        return _emberMetalProperty_get.get(this, 'isFrozen') ? this : this.copy().freeze();
      } else {
        throw new _emberMetalError.default(this + ' does not support freezing');
      }
    }
  });
});
enifed('ember-runtime/mixins/enumerable', ['exports', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/mixin', 'ember-metal/utils', 'ember-metal/computed', 'ember-metal/empty_object', 'ember-metal/features', 'ember-metal/property_events', 'ember-metal/events', 'ember-runtime/compare', 'require'], function (exports, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalMixin, _emberMetalUtils, _emberMetalComputed, _emberMetalEmpty_object, _emberMetalFeatures, _emberMetalProperty_events, _emberMetalEvents, _emberRuntimeCompare, _require) {
  /**
  @module ember
  @submodule ember-runtime
  */

  // ..........................................................
  // HELPERS
  //

  'use strict';

  var _emberA = undefined;

  function emberA() {
    return (_emberA || (_emberA = _require.default('ember-runtime/system/native_array').A))();
  }

  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 = _emberMetalProperty_get.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
    @private
  */
  var Enumerable = _emberMetalMixin.Mixin.create({

    /**
      __Required.__ You must implement this method to apply this mixin.
       Implement this method to make your class enumerable.
       This method will be called 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 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
      @private
    */
    nextObject: null,

    /**
      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
      @readOnly
      @public
    */
    firstObject: _emberMetalComputed.computed('[]', function () {
      if (_emberMetalProperty_get.get(this, 'length') === 0) {
        return undefined;
      }

      // handle generic enumerables
      var context = popCtx();
      var ret = this.nextObject(0, null, context);

      pushCtx(context);

      return ret;
    }).readOnly(),

    /**
      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
      @readOnly
      @public
    */
    lastObject: _emberMetalComputed.computed('[]', function () {
      var len = _emberMetalProperty_get.get(this, 'length');

      if (len === 0) {
        return undefined;
      }

      var context = popCtx();
      var idx = 0;
      var last = null;
      var cur;

      do {
        last = cur;
        cur = this.nextObject(idx++, last, context);
      } while (cur !== undefined);

      pushCtx(context);

      return last;
    }).readOnly(),

    /**
      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.
      @public
    */
    contains: function (obj) {
      var found = this.find(function (item) {
        return item === obj;
      });

      return found !== 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
      @public
    */
    forEach: function (callback, target) {
      if (typeof callback !== 'function') {
        throw new TypeError();
      }

      var context = popCtx();
      var len = _emberMetalProperty_get.get(this, 'length');
      var last = null;

      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.
      @public
    */
    getEach: _emberMetalMixin.aliasMethod('mapBy'),

    /**
      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
      @public
    */
    setEach: function (key, value) {
      return this.forEach(function (item) {
        _emberMetalProperty_set.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.
      @public
    */
    map: function (callback, target) {
      var ret = emberA();

      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.
      @public
    */
    mapBy: function (key) {
      return this.map(function (next) {
        return _emberMetalProperty_get.get(next, key);
      });
    },

    /**
      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 `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.
      @public
    */
    filter: function (callback, target) {
      var ret = emberA();

      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. 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 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.
      @public
    */
    reject: function (callback, target) {
      return this.filter(function () {
        return !callback.apply(target, 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
      @public
    */
    filterBy: function (key, value) {
      return this.filter(iter.apply(this, arguments));
    },

    /**
      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
      @public
    */
    rejectBy: function (key, value) {
      var exactValue = function (item) {
        return _emberMetalProperty_get.get(item, key) === value;
      };

      var hasValue = function (item) {
        return !!_emberMetalProperty_get.get(item, key);
      };

      var use = arguments.length === 2 ? exactValue : hasValue;

      return this.reject(use);
    },

    /**
      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`.
      @public
    */
    find: function (callback, target) {
      var len = _emberMetalProperty_get.get(this, 'length');

      if (target === undefined) {
        target = null;
      }

      var context = popCtx();
      var found = false;
      var last = null;
      var next, ret;

      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`
      @public
    */
    findBy: function (key, value) {
      return this.find(iter.apply(this, arguments));
    },

    /**
      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}
      @public
    */
    every: function (callback, target) {
      return !this.find(function (x, idx, i) {
        return !callback.call(target, x, idx, i);
      });
    },

    /**
      Returns `true` if the passed property resolves to the value of the second
      argument 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. Defaults to `true`
      @return {Boolean}
      @since 1.3.0
      @public
    */
    isEvery: function (key, value) {
      return this.every(iter.apply(this, 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
      @public
    */
    any: function (callback, target) {
      var len = _emberMetalProperty_get.get(this, 'length');
      var context = popCtx();
      var found = false;
      var last = null;
      var 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 property resolves to the value of the second
      argument 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. Defaults to `true`
      @return {Boolean}
      @since 1.3.0
      @public
    */
    isAny: function (key, value) {
      return this.any(iter.apply(this, arguments));
    },

    /**
      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.
      @public
    */
    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.
      @public
    */
    invoke: function (methodName) {
      for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        args[_key - 1] = arguments[_key];
      }

      var ret = emberA();

      this.forEach(function (x, idx) {
        var method = x && x[methodName];

        if ('function' === typeof method) {
          ret[idx] = args ? method.apply(x, 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.
      @public
    */
    toArray: function () {
      var ret = emberA();

      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.
      @public
    */
    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}
      @public
    */
    without: function (value) {
      if (!this.contains(value)) {
        return this; // nothing to do
      }

      var ret = emberA();

      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']
      ```
       This only works on primitive data types, e.g. Strings, Numbers, etc.
       @method uniq
      @return {Ember.Enumerable}
      @public
    */
    uniq: function () {
      var ret = emberA();

      this.forEach(function (k) {
        if (ret.indexOf(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 enumerable's
      content.
       For plain enumerables, this property is read only. `Array` overrides
      this method.
       @property []
      @type Array
      @return this
      @private
    */
    '[]': _emberMetalComputed.computed({
      get: function (key) {
        return this;
      }
    }),

    // ..........................................................
    // ENUMERABLE OBSERVERS
    //

    /**
      Registers an enumerable observer. Must implement `Ember.EnumerableObserver`
      mixin.
       @method addEnumerableObserver
      @param {Object} target
      @param {Object} [opts]
      @return this
      @private
    */
    addEnumerableObserver: function (target, opts) {
      var willChange = opts && opts.willChange || 'enumerableWillChange';
      var didChange = opts && opts.didChange || 'enumerableDidChange';
      var hasObservers = _emberMetalProperty_get.get(this, 'hasEnumerableObservers');

      if (!hasObservers) {
        _emberMetalProperty_events.propertyWillChange(this, 'hasEnumerableObservers');
      }

      _emberMetalEvents.addListener(this, '@enumerable:before', target, willChange);
      _emberMetalEvents.addListener(this, '@enumerable:change', target, didChange);

      if (!hasObservers) {
        _emberMetalProperty_events.propertyDidChange(this, 'hasEnumerableObservers');
      }

      return this;
    },

    /**
      Removes a registered enumerable observer.
       @method removeEnumerableObserver
      @param {Object} target
      @param {Object} [opts]
      @return this
      @private
    */
    removeEnumerableObserver: function (target, opts) {
      var willChange = opts && opts.willChange || 'enumerableWillChange';
      var didChange = opts && opts.didChange || 'enumerableDidChange';
      var hasObservers = _emberMetalProperty_get.get(this, 'hasEnumerableObservers');

      if (hasObservers) {
        _emberMetalProperty_events.propertyWillChange(this, 'hasEnumerableObservers');
      }

      _emberMetalEvents.removeListener(this, '@enumerable:before', target, willChange);
      _emberMetalEvents.removeListener(this, '@enumerable:change', target, didChange);

      if (hasObservers) {
        _emberMetalProperty_events.propertyDidChange(this, 'hasEnumerableObservers');
      }

      return this;
    },

    /**
      Becomes true whenever the array currently has observers watching changes
      on the array.
       @property hasEnumerableObservers
      @type Boolean
      @private
    */
    hasEnumerableObservers: _emberMetalComputed.computed(function () {
      return _emberMetalEvents.hasListeners(this, '@enumerable:change') || _emberMetalEvents.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
      @private
    */
    enumerableContentWillChange: function (removing, adding) {
      var removeCnt, addCnt, hasDelta;

      if ('number' === typeof removing) {
        removeCnt = removing;
      } else if (removing) {
        removeCnt = _emberMetalProperty_get.get(removing, 'length');
      } else {
        removeCnt = removing = -1;
      }

      if ('number' === typeof adding) {
        addCnt = adding;
      } else if (adding) {
        addCnt = _emberMetalProperty_get.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;
      }

      _emberMetalProperty_events.propertyWillChange(this, '[]');

      if (hasDelta) {
        _emberMetalProperty_events.propertyWillChange(this, 'length');
      }

      _emberMetalEvents.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
      @private
    */
    enumerableContentDidChange: function (removing, adding) {
      var removeCnt, addCnt, hasDelta;

      if ('number' === typeof removing) {
        removeCnt = removing;
      } else if (removing) {
        removeCnt = _emberMetalProperty_get.get(removing, 'length');
      } else {
        removeCnt = removing = -1;
      }

      if ('number' === typeof adding) {
        addCnt = adding;
      } else if (adding) {
        addCnt = _emberMetalProperty_get.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;
      }

      _emberMetalEvents.sendEvent(this, '@enumerable:change', [this, removing, adding]);

      if (hasDelta) {
        _emberMetalProperty_events.propertyDidChange(this, 'length');
      }

      _emberMetalProperty_events.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
      @public
    */
    sortBy: function () {
      var sortKeys = arguments;

      return this.toArray().sort(function (a, b) {
        for (var i = 0; i < sortKeys.length; i++) {
          var key = sortKeys[i];
          var propA = _emberMetalProperty_get.get(a, key);
          var propB = _emberMetalProperty_get.get(b, key);
          // return 1 or -1 else continue to the next sortKey
          var compareValue = _emberRuntimeCompare.default(propA, propB);

          if (compareValue) {
            return compareValue;
          }
        }
        return 0;
      });
    }
  });

  exports.default = Enumerable;
});

/**
  Returns a new enumerable that contains only items containing a unique property value.
  The default implementation returns an array regardless of the receiver type.
   ```javascript
  var arr = [{ value: 'a' }, { value: 'a' }, { value: 'b' }, { value: 'b' }];
  arr.uniqBy('value');  // [{ value: 'a' }, { value: 'b' }]
  ```
   @method uniqBy
  @return {Ember.Enumerable}
  @public
*/
enifed('ember-runtime/mixins/evented', ['exports', 'ember-metal/mixin', 'ember-metal/events'], function (exports, _emberMetalMixin, _emberMetalEvents) {
  'use strict';

  /**
  @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
    @public
   */
  exports.default = _emberMetalMixin.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
     @public
    */
    on: function (name, target, method) {
      _emberMetalEvents.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
      @public
    */
    one: function (name, target, method) {
      if (!method) {
        method = target;
        target = null;
      }

      _emberMetalEvents.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
      @public
    */
    trigger: function (name) {
      for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        args[_key - 1] = arguments[_key];
      }

      _emberMetalEvents.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
      @public
    */
    off: function (name, target, method) {
      _emberMetalEvents.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
      @public
     */
    has: function (name) {
      return _emberMetalEvents.hasListeners(this, name);
    }
  });
});
enifed('ember-runtime/mixins/freezable', ['exports', 'ember-metal/debug', 'ember-metal/mixin', 'ember-metal/property_get', 'ember-metal/property_set'], function (exports, _emberMetalDebug, _emberMetalMixin, _emberMetalProperty_get, _emberMetalProperty_set) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  /**
    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
    @deprecated Use `Object.freeze` instead.
    @private
  */
  var Freezable = _emberMetalMixin.Mixin.create({

    init: function () {
      _emberMetalDebug.deprecate('`Ember.Freezable` is deprecated, use `Object.freeze` instead.', false, { id: 'ember-runtime.freezable-init', until: '3.0.0' });
      this._super.apply(this, arguments);
    },

    /**
      Set to `true` when the object is frozen. Use this property to detect
      whether your object is frozen or not.
       @property isFrozen
      @type Boolean
      @private
    */
    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
      @private
    */
    freeze: function () {
      if (_emberMetalProperty_get.get(this, 'isFrozen')) {
        return this;
      }

      _emberMetalProperty_set.set(this, 'isFrozen', true);
      return this;
    }

  });

  exports.Freezable = Freezable;
  var FROZEN_ERROR = 'Frozen object cannot be modified.';
  exports.FROZEN_ERROR = FROZEN_ERROR;
});
enifed('ember-runtime/mixins/mutable_array', ['exports', 'ember-metal/property_get', 'ember-metal/error', 'ember-metal/mixin', 'ember-runtime/mixins/array', 'ember-runtime/mixins/mutable_enumerable', 'ember-runtime/mixins/enumerable'], function (exports, _emberMetalProperty_get, _emberMetalError, _emberMetalMixin, _emberRuntimeMixinsArray, _emberRuntimeMixinsMutable_enumerable, _emberRuntimeMixinsEnumerable) {
  /**
  @module ember
  @submodule ember-runtime
  */

  // require('ember-runtime/mixins/array');
  // require('ember-runtime/mixins/mutable_enumerable');

  // ..........................................................
  // CONSTANTS
  //

  'use strict';

  var OUT_OF_RANGE_EXCEPTION = 'Index out of range';
  var EMPTY = [];

  // ..........................................................
  // HELPERS
  //

  /**
    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.
    One concrete implementations of this class include ArrayProxy.

    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
    @public
  */
  exports.default = _emberMetalMixin.Mixin.create(_emberRuntimeMixinsArray.default, _emberRuntimeMixinsMutable_enumerable.default, {

    /**
      __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*
      @public
    */
    replace: null,

    /**
      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.
      @public
    */
    clear: function () {
      var len = _emberMetalProperty_get.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
      @public
    */
    insertAt: function (idx, object) {
      if (idx > _emberMetalProperty_get.get(this, 'length')) {
        throw new _emberMetalError.default(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
      @public
    */
    removeAt: function (start, len) {
      if ('number' === typeof start) {
        if (start < 0 || start >= _emberMetalProperty_get.get(this, 'length')) {
          throw new _emberMetalError.default(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
      @public
    */
    pushObject: function (obj) {
      this.insertAt(_emberMetalProperty_get.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
      @public
    */
    pushObjects: function (objects) {
      if (!(_emberRuntimeMixinsEnumerable.default.detect(objects) || Array.isArray(objects))) {
        throw new TypeError('Must pass Ember.Enumerable to Ember.MutableArray#pushObjects');
      }
      this.replace(_emberMetalProperty_get.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
      @public
    */
    popObject: function () {
      var len = _emberMetalProperty_get.get(this, 'length');
      if (len === 0) {
        return null;
      }

      var ret = _emberRuntimeMixinsArray.objectAt(this, 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
      @public
    */
    shiftObject: function () {
      if (_emberMetalProperty_get.get(this, 'length') === 0) {
        return null;
      }

      var ret = _emberRuntimeMixinsArray.objectAt(this, 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
      @public
    */
    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
      @public
    */
    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
       @public
    */
    reverseObjects: function () {
      var len = _emberMetalProperty_get.get(this, 'length');
      if (len === 0) {
        return this;
      }

      var objects = this.toArray().reverse();
      this.replace(0, len, objects);
      return this;
    },

    /**
      Replace all 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
      @public
    */
    setObjects: function (objects) {
      if (objects.length === 0) {
        return this.clear();
      }

      var len = _emberMetalProperty_get.get(this, 'length');
      this.replace(0, len, objects);
      return this;
    },

    // ..........................................................
    // IMPLEMENT Ember.MutableEnumerable
    //

    /**
      Remove all occurrences 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
      @public
    */
    removeObject: function (obj) {
      var loc = _emberMetalProperty_get.get(this, 'length') || 0;
      while (--loc >= 0) {
        var curObject = _emberRuntimeMixinsArray.objectAt(this, 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
      @public
    */
    addObject: function (obj) {
      if (!this.contains(obj)) {
        this.pushObject(obj);
      }

      return this;
    }
  });
});
enifed('ember-runtime/mixins/mutable_enumerable', ['exports', 'ember-runtime/mixins/enumerable', 'ember-metal/mixin', 'ember-metal/property_events'], function (exports, _emberRuntimeMixinsEnumerable, _emberMetalMixin, _emberMetalProperty_events) {
  'use strict';

  /**
  @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
    @public
  */
  exports.default = _emberMetalMixin.Mixin.create(_emberRuntimeMixinsEnumerable.default, {

    /**
      __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
      @public
    */
    addObject: null,

    /**
      Adds each object in the passed enumerable to the receiver.
       @method addObjects
      @param {Ember.Enumerable} objects the objects to add.
      @return {Object} receiver
      @public
    */
    addObjects: function (objects) {
      var _this = this;

      _emberMetalProperty_events.beginPropertyChanges(this);
      objects.forEach(function (obj) {
        return _this.addObject(obj);
      });
      _emberMetalProperty_events.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
      @public
    */
    removeObject: null,

    /**
      Removes each object in the passed enumerable from the receiver.
       @method removeObjects
      @param {Ember.Enumerable} objects the objects to remove
      @return {Object} receiver
      @public
    */
    removeObjects: function (objects) {
      _emberMetalProperty_events.beginPropertyChanges(this);
      for (var i = objects.length - 1; i >= 0; i--) {
        this.removeObject(objects[i]);
      }
      _emberMetalProperty_events.endPropertyChanges(this);
      return this;
    }
  });
});
enifed('ember-runtime/mixins/observable', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', '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'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalGet_properties, _emberMetalSet_properties, _emberMetalMixin, _emberMetalEvents, _emberMetalProperty_events, _emberMetalObserver, _emberMetalComputed, _emberMetalIs_none) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  /**
    ## 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 using the `Ember.observer`
    function in classes that you write.

    For example:

    ```javascript
    Ember.Object.extend({
      valueObserver: Ember.observer('value', function(sender, key, value, rev) {
        // Executes whenever the "value" property changes
        // See the addObserver method for more information about the callback arguments
      })
    });
    ```

    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
    @public
  */
  exports.default = _emberMetalMixin.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.
      @public
    */
    get: function (keyName) {
      return _emberMetalProperty_get.get(this, keyName);
    },

    /**
      To get the values of 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 {Object}
      @public
    */
    getProperties: function () {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      return _emberMetalGet_properties.default.apply(null, [this].concat(args));
    },

    /**
      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.
       @method set
      @param {String} keyName The property to set
      @param {Object} value The value to set or `null`.
      @return {Object} The passed value
      @public
    */
    set: function (keyName, value) {
      return _emberMetalProperty_set.set(this, keyName, value);
    },

    /**
      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 {Object} hash the hash of keys and values to set
      @return {Object} The passed in hash
      @public
    */
    setProperties: function (hash) {
      return _emberMetalSet_properties.default(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}
      @private
    */
    beginPropertyChanges: function () {
      _emberMetalProperty_events.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}
      @private
    */
    endPropertyChanges: function () {
      _emberMetalProperty_events.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}
      @private
    */
    propertyWillChange: function (keyName) {
      _emberMetalProperty_events.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}
      @private
    */
    propertyDidChange: function (keyName) {
      _emberMetalProperty_events.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}
      @public
    */
    notifyPropertyChange: function (keyName) {
      this.propertyWillChange(keyName);
      this.propertyDidChange(keyName);
      return this;
    },

    /**
      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.
      @public
    */
    addObserver: function (key, target, method) {
      _emberMetalObserver.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.
      @public
    */
    removeObserver: function (key, target, method) {
      _emberMetalObserver.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}
      @private
    */
    hasObserverFor: function (key) {
      return _emberMetalEvents.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.
      @public
    */
    getWithDefault: function (keyName, defaultValue) {
      return _emberMetalProperty_get.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
      @public
    */
    incrementProperty: function (keyName, increment) {
      if (_emberMetalIs_none.default(increment)) {
        increment = 1;
      }
      _emberMetalDebug.assert('Must pass a numeric value to incrementProperty', !isNaN(parseFloat(increment)) && isFinite(increment));
      return _emberMetalProperty_set.set(this, keyName, (parseFloat(_emberMetalProperty_get.get(this, keyName)) || 0) + increment);
    },

    /**
      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
      @public
    */
    decrementProperty: function (keyName, decrement) {
      if (_emberMetalIs_none.default(decrement)) {
        decrement = 1;
      }
      _emberMetalDebug.assert('Must pass a numeric value to decrementProperty', !isNaN(parseFloat(decrement)) && isFinite(decrement));
      return _emberMetalProperty_set.set(this, keyName, (_emberMetalProperty_get.get(this, keyName) || 0) - decrement);
    },

    /**
      Set the value of a boolean property to the opposite of its
      current value.
       ```javascript
      starship.toggleProperty('warpDriveEngaged');
      ```
       @method toggleProperty
      @param {String} keyName The name of the property to toggle
      @return {Boolean} The new property value
      @public
    */
    toggleProperty: function (keyName) {
      return _emberMetalProperty_set.set(this, keyName, !_emberMetalProperty_get.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
      @public
    */
    cacheFor: function (keyName) {
      return _emberMetalComputed.cacheFor(this, keyName);
    },

    // intended for debugging purposes
    observersForKey: function (keyName) {
      return _emberMetalObserver.observersFor(this, keyName);
    }
  });
});
enifed('ember-runtime/mixins/promise_proxy', ['exports', 'ember-metal/property_get', 'ember-metal/set_properties', 'ember-metal/computed', 'ember-metal/mixin', 'ember-metal/error'], function (exports, _emberMetalProperty_get, _emberMetalSet_properties, _emberMetalComputed, _emberMetalMixin, _emberMetalError) {
  'use strict';

  var not = _emberMetalComputed.computed.not;
  var or = _emberMetalComputed.computed.or;

  /**
    @module ember
    @submodule ember-runtime
  */

  function tap(proxy, promise) {
    _emberMetalSet_properties.default(proxy, {
      isFulfilled: false,
      isRejected: false
    });

    return promise.then(function (value) {
      _emberMetalSet_properties.default(proxy, {
        content: value,
        isFulfilled: true
      });
      return value;
    }, function (reason) {
      _emberMetalSet_properties.default(proxy, {
        reason: reason,
        isRejected: true
      });
      throw reason;
    }, 'Ember: PromiseProxy');
  }

  /**
    A low level mixin making ObjectProxy promise-aware.

    ```javascript
    var ObjectPromiseProxy = Ember.ObjectProxy.extend(Ember.PromiseProxyMixin);

    var proxy = ObjectPromiseProxy.create({
      promise: $.getJSON('/some/remote/data.json')
    });

    proxy.then(function(json){
       // the json
    }, function(reason) {
       // the reason why you have no json
    });
    ```

    the proxy has bindable attributes which
    track the promises life cycle

    ```javascript
    proxy.get('isPending')   //=> true
    proxy.get('isSettled')  //=> false
    proxy.get('isRejected')  //=> false
    proxy.get('isFulfilled') //=> false
    ```

    When the $.getJSON completes, and the promise is fulfilled
    with json, the life cycle attributes will update accordingly.

    ```javascript
    proxy.get('isPending')   //=> false
    proxy.get('isSettled')   //=> true
    proxy.get('isRejected')  //=> false
    proxy.get('isFulfilled') //=> true
    ```

    As the proxy is an ObjectProxy, and the json now its content,
    all the json properties will be available directly from the proxy.

    ```javascript
    // Assuming the following json:
    {
      firstName: 'Stefan',
      lastName: 'Penner'
    }

    // both properties will accessible on the proxy
    proxy.get('firstName') //=> 'Stefan'
    proxy.get('lastName')  //=> 'Penner'
    ```

    @class Ember.PromiseProxyMixin
    @public
  */
  exports.default = _emberMetalMixin.Mixin.create({
    /**
      If the proxied promise is rejected this will contain the reason
      provided.
       @property reason
      @default null
      @public
    */
    reason: null,

    /**
      Once the proxied promise has settled this will become `false`.
       @property isPending
      @default true
      @public
    */
    isPending: not('isSettled').readOnly(),

    /**
      Once the proxied promise has settled this will become `true`.
       @property isSettled
      @default false
      @public
    */
    isSettled: or('isRejected', 'isFulfilled').readOnly(),

    /**
      Will become `true` if the proxied promise is rejected.
       @property isRejected
      @default false
      @public
    */
    isRejected: false,

    /**
      Will become `true` if the proxied promise is fulfilled.
       @property isFulfilled
      @default false
      @public
    */
    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.ObjectProxy.extend(Ember.PromiseProxyMixin).create({
        promise: <thenable>
      });
      ```
       @property promise
      @public
    */
    promise: _emberMetalComputed.computed({
      get: function () {
        throw new _emberMetalError.default('PromiseProxy\'s promise must be set');
      },
      set: function (key, promise) {
        return tap(this, promise);
      }
    }),

    /**
      An alias to the proxied promise's `then`.
       See RSVP.Promise.then.
       @method then
      @param {Function} callback
      @return {RSVP.Promise}
      @public
    */
    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
      @public
    */
    '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
      @public
    */
    'finally': promiseAlias('finally')

  });

  function promiseAlias(name) {
    return function () {
      var promise = _emberMetalProperty_get.get(this, 'promise');
      return promise[name].apply(promise, arguments);
    };
  }
});
enifed('ember-runtime/mixins/registry_proxy', ['exports', 'ember-metal/debug', 'ember-metal/mixin'], function (exports, _emberMetalDebug, _emberMetalMixin) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  exports.buildFakeRegistryWithDeprecations = buildFakeRegistryWithDeprecations;

  /**
    RegistryProxyMixin is used to provide public access to specific
    registry functionality.

    @class RegistryProxyMixin
    @private
  */
  exports.default = _emberMetalMixin.Mixin.create({
    __registry__: null,

    /**
     Given a fullName return the corresponding factory.
      @public
     @method resolveRegistration
     @param {String} fullName
     @return {Function} fullName's factory
     */
    resolveRegistration: registryAlias('resolve'),

    /**
      Registers a factory that can be used for dependency injection (with
      `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();
      var 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
      @public
     */
    register: registryAlias('register'),

    /**
     Unregister a factory.
      ```javascript
     var App = Ember.Application.create();
     var User = Ember.Object.extend();
     App.register('model:user', User);
      App.resolveRegistration('model:user').create() instanceof User //=> true
      App.unregister('model:user')
     App.resolveRegistration('model:user') === undefined //=> true
     ```
      @public
     @method unregister
     @param {String} fullName
     */
    unregister: registryAlias('unregister'),

    /**
     Check if a factory is registered.
      @public
     @method hasRegistration
     @param {String} fullName
     @return {Boolean}
     */
    hasRegistration: registryAlias('has'),

    /**
     Register an option for a particular factory.
      @public
     @method registerOption
     @param {String} fullName
     @param {String} optionName
     @param {Object} options
     */
    registerOption: registryAlias('option'),

    /**
     Return a specific registered option for a particular factory.
      @public
     @method registeredOption
     @param  {String} fullName
     @param  {String} optionName
     @return {Object} options
     */
    registeredOption: registryAlias('getOption'),

    /**
     Register options for a particular factory.
      @public
     @method registerOptions
     @param {String} fullName
     @param {Object} options
     */
    registerOptions: registryAlias('options'),

    /**
     Return registered options for a particular factory.
      @public
     @method registeredOptions
     @param  {String} fullName
     @return {Object} options
     */
    registeredOptions: registryAlias('getOptions'),

    /**
     Allow registering options for all factories of a type.
      ```javascript
     var App = Ember.Application.create();
     var appInstance = App.buildInstance();
      // if all of type `connection` must not be singletons
     appInstance.optionsForType('connection', { singleton: false });
      appInstance.register('connection:twitter', TwitterConnection);
     appInstance.register('connection:facebook', FacebookConnection);
      var twitter = appInstance.lookup('connection:twitter');
     var twitter2 = appInstance.lookup('connection:twitter');
      twitter === twitter2; // => false
      var facebook = appInstance.lookup('connection:facebook');
     var facebook2 = appInstance.lookup('connection:facebook');
      facebook === facebook2; // => false
     ```
      @public
     @method registerOptionsForType
     @param {String} type
     @param {Object} options
     */
    registerOptionsForType: registryAlias('optionsForType'),

    /**
     Return the registered options for all factories of a type.
      @public
     @method registeredOptionsForType
     @param {String} type
     @return {Object} options
     */
    registeredOptionsForType: registryAlias('getOptionsForType'),

    /**
      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();
      var 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.
       **Note:** 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`.
       @public
      @method inject
      @param  factoryNameOrType {String}
      @param  property {String}
      @param  injectionName {String}
    **/
    inject: registryAlias('injection')
  });

  function registryAlias(name) {
    return function () {
      var _registry__;

      return (_registry__ = this.__registry__)[name].apply(_registry__, arguments);
    };
  }

  function buildFakeRegistryWithDeprecations(instance, typeForMessage) {
    var fakeRegistry = {};
    var registryProps = {
      resolve: 'resolveRegistration',
      register: 'register',
      unregister: 'unregister',
      has: 'hasRegistration',
      option: 'registerOption',
      options: 'registerOptions',
      getOptions: 'registeredOptions',
      optionsForType: 'registerOptionsForType',
      getOptionsForType: 'registeredOptionsForType',
      injection: 'inject'
    };

    for (var deprecatedProperty in registryProps) {
      fakeRegistry[deprecatedProperty] = buildFakeRegistryFunction(instance, typeForMessage, deprecatedProperty, registryProps[deprecatedProperty]);
    }

    return fakeRegistry;
  }

  function buildFakeRegistryFunction(instance, typeForMessage, deprecatedProperty, nonDeprecatedProperty) {
    return function () {
      _emberMetalDebug.deprecate('Using `' + typeForMessage + '.registry.' + deprecatedProperty + '` is deprecated. Please use `' + typeForMessage + '.' + nonDeprecatedProperty + '` instead.', false, {
        id: 'ember-application.app-instance-registry',
        until: '3.0.0',
        url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-application-registry-ember-applicationinstance-registry'
      });
      return instance[nonDeprecatedProperty].apply(instance, arguments);
    };
  }
});
enifed('ember-runtime/mixins/target_action_support', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/mixin', 'ember-metal/computed'], function (exports, _emberMetalCore, _emberMetalDebug, _emberMetalProperty_get, _emberMetalMixin, _emberMetalComputed) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  /**
  `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
  @private
  */
  var TargetActionSupport = _emberMetalMixin.Mixin.create({
    target: null,
    action: null,
    actionContext: null,

    targetObject: _emberMetalComputed.computed('target', function () {
      if (this._targetObject) {
        return this._targetObject;
      }

      var target = _emberMetalProperty_get.get(this, 'target');

      if (typeof target === 'string') {
        var value = _emberMetalProperty_get.get(this, target);
        if (value === undefined) {
          value = _emberMetalProperty_get.get(_emberMetalCore.default.lookup, target);
        }

        return value;
      } else {
        return target;
      }
    }),

    actionContextObject: _emberMetalComputed.computed(function () {
      var actionContext = _emberMetalProperty_get.get(this, 'actionContext');

      if (typeof actionContext === 'string') {
        var value = _emberMetalProperty_get.get(this, actionContext);
        if (value === undefined) {
          value = _emberMetalProperty_get.get(_emberMetalCore.default.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 {Object} (optional, with the optional keys action, target and/or actionContext)
    @return {Boolean} true if the action was sent successfully and did not return false
    @private
    */
    triggerAction: function () {
      var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

      var action = opts.action || _emberMetalProperty_get.get(this, 'action');
      var target = opts.target || _emberMetalProperty_get.get(this, 'targetObject');
      var actionContext = opts.actionContext;

      function args(options, actionName) {
        var ret = [];
        if (actionName) {
          ret.push(actionName);
        }

        return ret.concat(options);
      }

      if (typeof actionContext === 'undefined') {
        actionContext = _emberMetalProperty_get.get(this, 'actionContextObject') || this;
      }

      if (target && action) {
        var ret;

        if (target.send) {
          ret = target.send.apply(target, args(actionContext, action));
        } else {
          _emberMetalDebug.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;
});
// Ember.lookup
enifed("ember-runtime/string_registry", ["exports"], function (exports) {
  // STATE within a module is frowned apon, this exists
  // to support Ember.STRINGS but shield ember internals from this legacy global
  // API.
  "use strict";

  exports.setStrings = setStrings;
  exports.getStrings = getStrings;
  exports.get = get;
  var STRINGS = {};

  function setStrings(strings) {
    STRINGS = strings;
  }

  function getStrings() {
    return STRINGS;
  }

  function get(name) {
    return STRINGS[name];
  }
});
enifed('ember-runtime/system/application', ['exports', 'ember-runtime/system/namespace'], function (exports, _emberRuntimeSystemNamespace) {
  'use strict';

  exports.default = _emberRuntimeSystemNamespace.default.extend();
});
enifed('ember-runtime/system/array_proxy', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-runtime/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-metal/alias', 'ember-runtime/mixins/array'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberRuntimeUtils, _emberMetalComputed, _emberMetalMixin, _emberMetalProperty_events, _emberMetalError, _emberRuntimeSystemObject, _emberRuntimeMixinsMutable_array, _emberRuntimeMixinsEnumerable, _emberMetalAlias, _emberRuntimeMixinsArray) {
  'use strict';

  /**
  @module ember
  @submodule ember-runtime
  */

  var OUT_OF_RANGE_EXCEPTION = 'Index out of range';
  var EMPTY = [];

  function K() {
    return this;
  }

  /**
    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
    @public
  */
  var ArrayProxy = _emberRuntimeSystemObject.default.extend(_emberRuntimeMixinsMutable_array.default, {

    /**
      The content array. Must be an object that implements `Ember.Array` and/or
      `Ember.MutableArray.`
       @property content
      @type Ember.Array
      @private
    */
    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
     @private
    */
    arrangedContent: _emberMetalAlias.default('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
      @private
    */
    objectAtContent: function (idx) {
      return _emberRuntimeMixinsArray.objectAt(_emberMetalProperty_get.get(this, 'arrangedContent'), 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}
      @private
    */
    replaceContent: function (idx, amt, objects) {
      _emberMetalProperty_get.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: _emberMetalMixin._beforeObserver('content', function () {
      this._teardownContent();
    }),

    _teardownContent: function () {
      var content = _emberMetalProperty_get.get(this, 'content');

      if (content) {
        _emberRuntimeMixinsArray.removeArrayObserver(content, this, {
          willChange: 'contentArrayWillChange',
          didChange: 'contentArrayDidChange'
        });
      }
    },

    /**
      Override to implement content array `willChange` observer.
       @method contentArrayWillChange
       @param {Ember.Array} contentArray the content array
      @param {Number} start starting index of the change
      @param {Number} removeCount count of items removed
      @param {Number} addCount count of items added
      @private
    */
    contentArrayWillChange: K,
    /**
      Override to implement content array `didChange` observer.
       @method contentArrayDidChange
       @param {Ember.Array} contentArray the content array
      @param {Number} start starting index of the change
      @param {Number} removeCount count of items removed
      @param {Number} addCount count of items added
      @private
    */
    contentArrayDidChange: K,

    /**
      Invoked when the content property changes. Notifies observers that the
      entire array content has changed.
       @private
      @method _contentDidChange
    */
    _contentDidChange: _emberMetalMixin.observer('content', function () {
      var content = _emberMetalProperty_get.get(this, 'content');

      _emberMetalDebug.assert('Can\'t set ArrayProxy\'s content to itself', content !== this);

      this._setupContent();
    }),

    _setupContent: function () {
      var content = _emberMetalProperty_get.get(this, 'content');

      if (content) {
        _emberMetalDebug.assert('ArrayProxy expects an Array or Ember.ArrayProxy, but you passed ' + typeof content, _emberRuntimeUtils.isArray(content) || content.isDestroyed);

        _emberRuntimeMixinsArray.addArrayObserver(content, this, {
          willChange: 'contentArrayWillChange',
          didChange: 'contentArrayDidChange'
        });
      }
    },

    _arrangedContentWillChange: _emberMetalMixin._beforeObserver('arrangedContent', function () {
      var arrangedContent = _emberMetalProperty_get.get(this, 'arrangedContent');
      var len = arrangedContent ? _emberMetalProperty_get.get(arrangedContent, 'length') : 0;

      this.arrangedContentArrayWillChange(this, 0, len, undefined);
      this.arrangedContentWillChange(this);

      this._teardownArrangedContent(arrangedContent);
    }),

    _arrangedContentDidChange: _emberMetalMixin.observer('arrangedContent', function () {
      var arrangedContent = _emberMetalProperty_get.get(this, 'arrangedContent');
      var len = arrangedContent ? _emberMetalProperty_get.get(arrangedContent, 'length') : 0;

      _emberMetalDebug.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 = _emberMetalProperty_get.get(this, 'arrangedContent');

      if (arrangedContent) {
        _emberMetalDebug.assert('ArrayProxy expects an Array or Ember.ArrayProxy, but you passed ' + typeof arrangedContent, _emberRuntimeUtils.isArray(arrangedContent) || arrangedContent.isDestroyed);

        _emberRuntimeMixinsArray.addArrayObserver(arrangedContent, this, {
          willChange: 'arrangedContentArrayWillChange',
          didChange: 'arrangedContentArrayDidChange'
        });
      }
    },

    _teardownArrangedContent: function () {
      var arrangedContent = _emberMetalProperty_get.get(this, 'arrangedContent');

      if (arrangedContent) {
        _emberRuntimeMixinsArray.removeArrayObserver(arrangedContent, this, {
          willChange: 'arrangedContentArrayWillChange',
          didChange: 'arrangedContentArrayDidChange'
        });
      }
    },

    arrangedContentWillChange: K,
    arrangedContentDidChange: K,

    objectAt: function (idx) {
      return _emberMetalProperty_get.get(this, 'content') && this.objectAtContent(idx);
    },

    length: _emberMetalComputed.computed(function () {
      var arrangedContent = _emberMetalProperty_get.get(this, 'arrangedContent');
      return arrangedContent ? _emberMetalProperty_get.get(arrangedContent, 'length') : 0;
      // No dependencies since Enumerable notifies length of change
    }),

    _replace: function (idx, amt, objects) {
      var content = _emberMetalProperty_get.get(this, 'content');
      _emberMetalDebug.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 (_emberMetalProperty_get.get(this, 'arrangedContent') === _emberMetalProperty_get.get(this, 'content')) {
        this._replace.apply(this, arguments);
      } else {
        throw new _emberMetalError.default('Using replace on an arranged ArrayProxy is not allowed.');
      }
    },

    _insertAt: function (idx, object) {
      if (idx > _emberMetalProperty_get.get(this, 'content.length')) {
        throw new _emberMetalError.default(OUT_OF_RANGE_EXCEPTION);
      }

      this._replace(idx, 0, [object]);
      return this;
    },

    insertAt: function (idx, object) {
      if (_emberMetalProperty_get.get(this, 'arrangedContent') === _emberMetalProperty_get.get(this, 'content')) {
        return this._insertAt(idx, object);
      } else {
        throw new _emberMetalError.default('Using insertAt on an arranged ArrayProxy is not allowed.');
      }
    },

    removeAt: function (start, len) {
      if ('number' === typeof start) {
        var content = _emberMetalProperty_get.get(this, 'content');
        var arrangedContent = _emberMetalProperty_get.get(this, 'arrangedContent');
        var indices = [];
        var i;

        if (start < 0 || start >= _emberMetalProperty_get.get(this, 'length')) {
          throw new _emberMetalError.default(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(_emberRuntimeMixinsArray.objectAt(arrangedContent, i)));
        }

        // Replace in reverse order since indices will change
        indices.sort(function (a, b) {
          return b - a;
        });

        _emberMetalProperty_events.beginPropertyChanges();
        for (i = 0; i < indices.length; i++) {
          this._replace(indices[i], 1, EMPTY);
        }
        _emberMetalProperty_events.endPropertyChanges();
      }

      return this;
    },

    pushObject: function (obj) {
      this._insertAt(_emberMetalProperty_get.get(this, 'content.length'), obj);
      return obj;
    },

    pushObjects: function (objects) {
      if (!(_emberRuntimeMixinsEnumerable.default.detect(objects) || _emberRuntimeUtils.isArray(objects))) {
        throw new TypeError('Must pass Ember.Enumerable to Ember.MutableArray#pushObjects');
      }
      this._replace(_emberMetalProperty_get.get(this, 'length'), 0, objects);
      return this;
    },

    setObjects: function (objects) {
      if (objects.length === 0) {
        return this.clear();
      }

      var len = _emberMetalProperty_get.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.apply(this, arguments);
      this._setupContent();
      this._setupArrangedContent();
    },

    willDestroy: function () {
      this._teardownArrangedContent();
      this._teardownContent();
    }
  });

  exports.default = ArrayProxy;
});
enifed('ember-runtime/system/container', ['exports', 'ember-metal/property_set', 'container/registry', 'container/container', 'container/owner'], function (exports, _emberMetalProperty_set, _containerRegistry, _containerContainer, _containerOwner) {
  'use strict';

  _containerRegistry.default.set = _emberMetalProperty_set.set;
  _containerContainer.default.set = _emberMetalProperty_set.set;

  exports.Registry = _containerRegistry.default;
  exports.Container = _containerContainer.default;
  exports.getOwner = _containerOwner.getOwner;
  exports.setOwner = _containerOwner.setOwner;
});
enifed('ember-runtime/system/core_object', ['exports', 'ember-metal/debug', 'ember-metal/features', 'ember-metal/assign', 'ember-metal/property_get', 'ember-metal/utils', 'ember-metal/meta', 'ember-metal/chains', 'ember-metal/events', 'ember-metal/mixin', 'ember-metal/error', 'ember-runtime/mixins/action_handler', 'ember-metal/properties', 'ember-metal/binding', 'ember-metal/computed', 'ember-metal/injected_property', 'ember-metal/run_loop', 'ember-metal/watching', 'ember-metal/core', 'ember-runtime/inject', 'ember-metal/symbol'], function (exports, _emberMetalDebug, _emberMetalFeatures, _emberMetalAssign, _emberMetalProperty_get, _emberMetalUtils, _emberMetalMeta, _emberMetalChains, _emberMetalEvents, _emberMetalMixin, _emberMetalError, _emberRuntimeMixinsAction_handler, _emberMetalProperties, _emberMetalBinding, _emberMetalComputed, _emberMetalInjected_property, _emberMetalRun_loop, _emberMetalWatching, _emberMetalCore, _emberRuntimeInject, _emberMetalSymbol) {
  'no use strict';
  // Remove "use strict"; from transpiled module until
  // https://bugs.webkit.org/show_bug.cgi?id=138038 is fixed

  /**
    @module ember
    @submodule ember-runtime
  */

  // using ember-metal/lib/main here to ensure that ember-debug is setup
  // if present

  var _Mixin$create;

  var POST_INIT = _emberMetalSymbol.default('POST_INIT');
  exports.POST_INIT = POST_INIT;
  var schedule = _emberMetalRun_loop.default.schedule;
  var applyMixin = _emberMetalMixin.Mixin._apply;
  var finishPartial = _emberMetalMixin.Mixin.finishPartial;
  var reopen = _emberMetalMixin.Mixin.prototype.reopen;
  var hasCachedComputedProperties = false;

  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;
    var initProperties;

    var Class = function () {
      if (!wasApplied) {
        Class.proto(); // prepare prototype...
      }

      if (arguments.length > 0) {
        initProperties = [arguments[0]];
      }

      this.__defineNonEnumerable(_emberMetalUtils.GUID_KEY_PROPERTY);
      var m = _emberMetalMeta.meta(this);
      var proto = m.proto;
      m.proto = this;
      if (initProperties) {
        // capture locally so we can clear the closed over variable
        var props = initProperties;
        initProperties = null;

        var concatenatedProperties = this.concatenatedProperties;
        var mergedProperties = this.mergedProperties;

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

          _emberMetalDebug.assert('Ember.Object.create no longer supports mixing in other ' + 'definitions, use .extend & .create separately instead.', !(properties instanceof _emberMetalMixin.Mixin));

          if (typeof properties !== 'object' && properties !== undefined) {
            throw new _emberMetalError.default('Ember.Object.create only accepts objects.');
          }

          if (!properties) {
            continue;
          }

          var keyNames = Object.keys(properties);

          for (var j = 0, ll = keyNames.length; j < ll; j++) {
            var keyName = keyNames[j];
            var value = properties[keyName];

            if (_emberMetalMixin.IS_BINDING.test(keyName)) {
              m.writeBindings(keyName, value);
            }

            var possibleDesc = this[keyName];
            var desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;

            _emberMetalDebug.assert('Ember.Object.create no longer supports defining computed ' + 'properties. Define computed properties using extend() or reopen() ' + 'before calling create().', !(value instanceof _emberMetalComputed.ComputedProperty));
            _emberMetalDebug.assert('Ember.Object.create no longer supports defining methods that call _super.', !(typeof value === 'function' && value.toString().indexOf('._super') !== -1));
            _emberMetalDebug.assert('`actions` must be provided at extend time, not at create time, ' + 'when Ember.ActionHandler is used (i.e. views, controllers & routes).', !(keyName === 'actions' && _emberRuntimeMixinsAction_handler.default.detect(this)));

            if (concatenatedProperties && concatenatedProperties.length > 0 && concatenatedProperties.indexOf(keyName) >= 0) {
              var baseValue = this[keyName];

              if (baseValue) {
                if ('function' === typeof baseValue.concat) {
                  value = baseValue.concat(value);
                } else {
                  value = _emberMetalUtils.makeArray(baseValue).concat(value);
                }
              } else {
                value = _emberMetalUtils.makeArray(value);
              }
            }

            if (mergedProperties && mergedProperties.length && mergedProperties.indexOf(keyName) >= 0) {
              var originalValue = this[keyName];

              value = _emberMetalAssign.default({}, originalValue, value);
            }

            if (desc) {
              desc.set(this, keyName, value);
            } else {
              if (typeof this.setUnknownProperty === 'function' && !(keyName in this)) {
                this.setUnknownProperty(keyName, value);
              } else {
                _emberMetalProperties.defineProperty(this, keyName, null, value); // setup mandatory setter
              }
            }
          }
        }
      }

      finishPartial(this, m);

      var length = arguments.length;

      if (length === 0) {
        this.init();
      } else if (length === 1) {
        this.init(arguments[0]);
      } else {
        // v8 bug potentially incorrectly deopts this function: https://code.google.com/p/v8/issues/detail?id=3709
        // we may want to keep this around till this ages out on mobile
        var args = new Array(length);
        for (var x = 0; x < length; x++) {
          args[x] = arguments[x];
        }
        this.init.apply(this, args);
      }

      this[POST_INIT]();

      m.proto = proto;
      _emberMetalChains.finishChains(this);
      _emberMetalEvents.sendEvent(this, 'init');
    };

    Class.toString = _emberMetalMixin.Mixin.prototype.toString;
    Class.willReopen = function () {
      if (wasApplied) {
        Class.PrototypeMixin = _emberMetalMixin.Mixin.create(Class.PrototypeMixin);
      }

      wasApplied = false;
    };

    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);
      }

      return this.prototype;
    };

    return Class;
  }

  /**
    @class CoreObject
    @namespace Ember
    @public
  */
  var CoreObject = makeCtor();
  CoreObject.toString = function () {
    return 'Ember.CoreObject';
  };
  CoreObject.PrototypeMixin = _emberMetalMixin.Mixin.create((_Mixin$create = {
    reopen: function () {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      applyMixin(this, args, 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`,
      be sure to call `this._super(...arguments)` 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
      @public
    */
    init: function () {}

  }, _Mixin$create[POST_INIT] = function () {}, _Mixin$create.__defineNonEnumerable = function (property) {
    Object.defineProperty(this, property.name, property.descriptor);
    //this[property.name] = property.descriptor.value;
  }, _Mixin$create.concatenatedProperties = null, _Mixin$create.mergedProperties = null, _Mixin$create.isDestroyed = false, _Mixin$create.isDestroying = false, _Mixin$create.destroy = function () {
    if (this.isDestroying) {
      return;
    }
    this.isDestroying = true;

    schedule('actions', this, this.willDestroy);
    schedule('destroy', this, this._scheduledDestroy);
    return this;
  }, _Mixin$create.willDestroy = _emberMetalCore.K, _Mixin$create._scheduledDestroy = function () {
    if (this.isDestroyed) {
      return;
    }
    _emberMetalWatching.destroy(this);
    this.isDestroyed = true;
  }, _Mixin$create.bind = function (to, from) {
    if (!(from instanceof _emberMetalBinding.Binding)) {
      from = _emberMetalBinding.Binding.from(from);
    }
    from.to(to).connect(this);
    return from;
  }, _Mixin$create.toString = function () {
    var hasToStringExtension = typeof this.toStringExtension === 'function';
    var extension = hasToStringExtension ? ':' + this.toStringExtension() : '';
    var ret = '<' + this.constructor.toString() + ':' + _emberMetalUtils.guidFor(this) + extension + '>';

    return ret;
  }, _Mixin$create));

  CoreObject.PrototypeMixin.ownerConstructor = CoreObject;

  CoreObject.__super__ = null;

  var ClassMixinProps = {

    ClassMixin: _emberMetalMixin.REQUIRED,

    PrototypeMixin: _emberMetalMixin.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
      @public
    */
    extend: function () {
      var Class = makeCtor();
      var proto;
      Class.ClassMixin = _emberMetalMixin.Mixin.create(this.ClassMixin);
      Class.PrototypeMixin = _emberMetalMixin.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 = Object.create(this.prototype);
      proto.constructor = Class;
      _emberMetalUtils.generateGuid(proto);
      _emberMetalMeta.meta(proto).proto = proto; // this will disable observers on prototype

      Class.ClassMixin.apply(Class);
      return Class;
    },

    /**
      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`.
       @method create
      @static
      @param [arguments]*
      @public
    */
    create: function () {
      var C = this;

      for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }

      if (args.length > 0) {
        this._initProperties(args);
      }
      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
      @public
    */
    reopen: function () {
      this.willReopen();
      reopen.apply(this.PrototypeMixin, 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
      @public
    */
    reopenClass: function () {
      reopen.apply(this.ClassMixin, 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()`.
       @static
      @method metaForProperty
      @param key {String} property name
      @private
    */
    metaForProperty: function (key) {
      var proto = this.proto();
      var possibleDesc = proto[key];
      var desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined;

      _emberMetalDebug.assert('metaForProperty() could not find a computed property ' + 'with key \'' + key + '\'.', !!desc && desc instanceof _emberMetalComputed.ComputedProperty);
      return desc._meta || {};
    },

    _computedProperties: _emberMetalComputed.computed(function () {
      hasCachedComputedProperties = true;
      var proto = this.proto();
      var property;
      var properties = [];

      for (var name in proto) {
        property = proto[name];

        if (property && property.isDescriptor) {
          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.
       @static
      @method eachComputedProperty
      @param {Function} callback
      @param {Object} binding
      @private
    */
    eachComputedProperty: function (callback, binding) {
      var property;
      var empty = {};

      var properties = _emberMetalProperty_get.get(this, '_computedProperties');

      for (var i = 0, length = properties.length; i < length; i++) {
        property = properties[i];
        callback.call(binding || this, property.name, property.meta || empty);
      }
    }
  };

  function injectedPropertyAssertion() {
    _emberMetalDebug.assert('Injected properties are invalid', _emberRuntimeInject.validatePropertyInjections(this));
  }

  _emberMetalDebug.runInDebug(function () {
    /**
      Provides lookup-time type validation for injected properties.
       @private
      @method _onLookup
    */
    ClassMixinProps._onLookup = injectedPropertyAssertion;
  });

  /**
    Returns a hash of property names and container names that injected
    properties will lookup on the container lazily.

    @method _lazyInjections
    @return {Object} Hash of all lazy injected property keys to container names
    @private
  */
  ClassMixinProps._lazyInjections = function () {
    var injections = {};
    var proto = this.proto();
    var key, desc;

    for (key in proto) {
      desc = proto[key];
      if (desc instanceof _emberMetalInjected_property.default) {
        injections[key] = desc.type + ':' + (desc.name || key);
      }
    }

    return injections;
  };

  var ClassMixin = _emberMetalMixin.Mixin.create(ClassMixinProps);

  ClassMixin.ownerConstructor = CoreObject;

  CoreObject.ClassMixin = ClassMixin;

  ClassMixin.apply(CoreObject);

  CoreObject.reopen({
    didDefineProperty: function (proto, key, value) {
      if (hasCachedComputedProperties === false) {
        return;
      }
      if (value instanceof _emberMetalComputed.ComputedProperty) {
        var cache = _emberMetalMeta.meta(this.constructor).readableCache();

        if (cache && cache._computedProperties !== undefined) {
          cache._computedProperties = undefined;
        }
      }
    }
  });

  exports.default = CoreObject;
});

// 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.

/**
  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 Ember to 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
  @public
*/

/**
  Defines the properties that will be merged 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 merging the superclass property value
  with the subclass property's value. An example of this in use within Ember
  is the `queryParams` property of routes.
   Here is some sample code showing the difference between a merged
  property and a normal one:
   ```javascript
  App.BarRoute = Ember.Route.extend({
    someNonMergedProperty: {
      nonMerged: 'superclass value of nonMerged'
    },
    queryParams: {
      page: {replace: false},
      limit: {replace: true}
    }
  });
   App.FooBarRoute = App.BarRoute.extend({
    someNonMergedProperty: {
      completelyNonMerged: 'subclass value of nonMerged'
    },
    queryParams: {
      limit: {replace: false}
    }
  });
   var fooBarRoute = App.FooBarRoute.create();
   fooBarRoute.get('someNonMergedProperty');
  // => { completelyNonMerged: 'subclass value of nonMerged' }
  //
  // Note the entire object, including the nonMerged property of
  // the superclass object, has been replaced
   fooBarRoute.get('queryParams');
  // => {
  //   page: {replace: false},
  //   limit: {replace: false}
  // }
  //
  // Note the page remains from the superclass, and the
  // `limit` property's value of `false` has been merged from
  // the subclass.
  ```
   This behavior is not available during object `create` calls. It is only
  available at `extend` time.
   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 merged property (to not
  mislead your users to think they can override the property in a subclass).
   @property mergedProperties
  @type Array
  @default null
  @public
*/

/**
  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
  @public
*/

/**
  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
  @public
*/

/**
  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
  @public
*/

/**
  Override to implement teardown.
   @method willDestroy
  @public
*/

/**
  Invoked by the run loop to actually destroy the object. This is
  scheduled for execution by the `destroy` method.
   @private
  @method _scheduledDestroy
*/

/**
  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
  @public
*/
enifed('ember-runtime/system/each_proxy', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/observer', 'ember-metal/property_events', 'ember-metal/empty_object', 'ember-runtime/mixins/array'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalObserver, _emberMetalProperty_events, _emberMetalEmpty_object, _emberRuntimeMixinsArray) {
  'use strict';

  /**
    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.
    @class EachProxy
    @private
  */
  function EachProxy(content) {
    this._content = content;
    this._keys = undefined;
    this.__ember_meta__ = null;
  }

  EachProxy.prototype = {
    __defineNonEnumerable: function (property) {
      this[property.name] = property.descriptor.value;
    },

    // ..........................................................
    // ARRAY CHANGES
    // Invokes whenever the content array itself changes.

    arrayWillChange: function (content, idx, removedCnt, addedCnt) {
      var keys = this._keys;
      var lim = removedCnt > 0 ? idx + removedCnt : -1;
      for (var key in keys) {
        if (lim > 0) {
          removeObserverForContentKey(content, key, this, idx, lim);
        }
        _emberMetalProperty_events.propertyWillChange(this, key);
      }
    },

    arrayDidChange: function (content, idx, removedCnt, addedCnt) {
      var keys = this._keys;
      var lim = addedCnt > 0 ? idx + addedCnt : -1;
      for (var key in keys) {
        if (lim > 0) {
          addObserverForContentKey(content, key, this, idx, lim);
        }
        _emberMetalProperty_events.propertyDidChange(this, key);
      }
    },

    // ..........................................................
    // LISTEN FOR NEW OBSERVERS AND OTHER EVENT LISTENERS
    // Start monitoring keys based on who is listening...

    willWatchProperty: function (property) {
      this.beginObservingContentKey(property);
    },

    didUnwatchProperty: function (property) {
      this.stopObservingContentKey(property);
    },

    // ..........................................................
    // CONTENT KEY OBSERVING
    // Actual watch keys on the source content.

    beginObservingContentKey: function (keyName) {
      var keys = this._keys;
      if (!keys) {
        keys = this._keys = new _emberMetalEmpty_object.default();
      }

      if (!keys[keyName]) {
        keys[keyName] = 1;
        var content = this._content;
        var len = _emberMetalProperty_get.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;
        var len = _emberMetalProperty_get.get(content, 'length');

        removeObserverForContentKey(content, keyName, this, 0, len);
      }
    },

    contentKeyWillChange: function (obj, keyName) {
      _emberMetalProperty_events.propertyWillChange(this, keyName);
    },

    contentKeyDidChange: function (obj, keyName) {
      _emberMetalProperty_events.propertyDidChange(this, keyName);
    }
  };

  function addObserverForContentKey(content, keyName, proxy, idx, loc) {
    while (--loc >= idx) {
      var item = _emberRuntimeMixinsArray.objectAt(content, loc);
      if (item) {
        _emberMetalDebug.assert('When using @each to observe the array ' + content + ', the array must return an object', typeof item === 'object');
        _emberMetalObserver._addBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
        _emberMetalObserver.addObserver(item, keyName, proxy, 'contentKeyDidChange');
      }
    }
  }

  function removeObserverForContentKey(content, keyName, proxy, idx, loc) {
    while (--loc >= idx) {
      var item = _emberRuntimeMixinsArray.objectAt(content, loc);
      if (item) {
        _emberMetalObserver._removeBeforeObserver(item, keyName, proxy, 'contentKeyWillChange');
        _emberMetalObserver.removeObserver(item, keyName, proxy, 'contentKeyDidChange');
      }
    }
  }

  exports.default = EachProxy;
});
enifed('ember-runtime/system/lazy_load', ['exports', 'ember-metal/core', 'ember-runtime/system/native_array'], function (exports, _emberMetalCore, _emberRuntimeSystemNative_array) {
  /*globals CustomEvent */

  'use strict';

  exports.onLoad = onLoad;
  exports.runLoadHooks = runLoadHooks;

  /**
    @module ember
    @submodule ember-runtime
  */

  var loadHooks = _emberMetalCore.default.ENV.EMBER_LOAD_HOOKS || {};
  var loaded = {};
  var _loaded = loaded;

  exports._loaded = _loaded;
  /**
    Detects when a specific package of Ember (e.g. 'Ember.Application')
    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.Application' function(hbars) {
      hbars.registerHelper(...);
    });
    ```

    @method onLoad
    @for Ember
    @param name {String} name of hook
    @param callback {Function} callback to be called
    @private
  */

  function onLoad(name, callback) {
    var object = loaded[name];

    loadHooks[name] = loadHooks[name] || _emberRuntimeSystemNative_array.A();
    loadHooks[name].pushObject(callback);

    if (object) {
      callback(object);
    }
  }

  /**
    Called when an Ember.js package (e.g Ember.Application) 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
    @private
  */

  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]) {
      loadHooks[name].forEach(function (callback) {
        return callback(object);
      });
    }
  }
});
// Ember.ENV.EMBER_LOAD_HOOKS
enifed('ember-runtime/system/namespace', ['exports', 'ember-metal/core', 'ember-metal/property_get', 'ember-metal/utils', 'ember-metal/mixin', 'ember-runtime/system/object'], function (exports, _emberMetalCore, _emberMetalProperty_get, _emberMetalUtils, _emberMetalMixin, _emberRuntimeSystemObject) {
  /**
  @module ember
  @submodule ember-runtime
  */

  // Ember.lookup, Ember.BOOTED, Ember.NAME_KEY, Ember.anyUnprocessedMixins
  'use strict';

  /**
    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
    @public
  */
  var Namespace = _emberRuntimeSystemObject.default.extend({
    isNamespace: true,

    init: function () {
      Namespace.NAMESPACES.push(this);
      Namespace.PROCESSED = false;
    },

    toString: function () {
      var name = _emberMetalProperty_get.get(this, 'name') || _emberMetalProperty_get.get(this, 'modulePrefix');
      if (name) {
        return name;
      }

      findNamespaces();
      return this[NAME_KEY];
    },

    nameClasses: function () {
      processNamespace([this.toString()], this, {});
    },

    destroy: function () {
      var namespaces = Namespace.NAMESPACES;
      var toString = this.toString();

      if (toString) {
        _emberMetalCore.default.lookup[toString] = undefined;
        delete Namespace.NAMESPACES_BY_ID[toString];
      }
      namespaces.splice(namespaces.indexOf(this), 1);
      this._super.apply(this, arguments);
    }
  });

  Namespace.reopenClass({
    NAMESPACES: [_emberMetalCore.default],
    NAMESPACES_BY_ID: {},
    PROCESSED: false,
    processAll: processAllNamespaces,
    byName: function (name) {
      if (!_emberMetalCore.default.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 && !obj[NAME_KEY]) {
        // Replace the class' `toString` with the dot-separated path
        // and set its `NAME_KEY`
        obj[NAME_KEY] = paths.join('.');

        // Support nested namespaces
      } else if (obj && obj.isNamespace) {
          // Skip aliased namespaces
          if (seen[_emberMetalUtils.guidFor(obj)]) {
            continue;
          }
          seen[_emberMetalUtils.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 = _emberMetalCore.default.lookup;
    var obj;

    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 = _emberMetalCore.default.NAME_KEY = _emberMetalUtils.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 (!_emberMetalCore.default.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;
    var unprocessedMixins = _emberMetalCore.default.anyUnprocessedMixins;

    if (unprocessedNamespaces) {
      findNamespaces();
      Namespace.PROCESSED = true;
    }

    if (unprocessedNamespaces || unprocessedMixins) {
      var namespaces = Namespace.NAMESPACES;
      var namespace;

      for (var i = 0, l = namespaces.length; i < l; i++) {
        namespace = namespaces[i];
        processNamespace([namespace.toString()], namespace, {});
      }

      _emberMetalCore.default.anyUnprocessedMixins = false;
    }
  }

  function makeToString(ret) {
    return function () {
      return ret;
    };
  }

  _emberMetalMixin.Mixin.prototype.toString = classToString; // ES6TODO: altering imported objects. SBB.

  exports.default = Namespace;
});
enifed('ember-runtime/system/native_array', ['exports', 'ember-metal/core', 'ember-metal/replace', 'ember-metal/property_get', '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'], function (exports, _emberMetalCore, _emberMetalReplace, _emberMetalProperty_get, _emberMetalMixin, _emberRuntimeMixinsArray, _emberRuntimeMixinsMutable_array, _emberRuntimeMixinsObservable, _emberRuntimeMixinsCopyable, _emberRuntimeMixinsFreezable, _emberRuntimeCopy) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  // 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 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.apply(Array.prototype)`.

    @class NativeArray
    @namespace Ember
    @uses Ember.MutableArray
    @uses Ember.Observable
    @uses Ember.Copyable
    @public
  */
  var NativeArray = _emberMetalMixin.Mixin.create(_emberRuntimeMixinsMutable_array.default, _emberRuntimeMixinsObservable.default, _emberRuntimeMixinsCopyable.default, {

    // 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 _emberRuntimeMixinsFreezable.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 ? _emberMetalProperty_get.get(objects, 'length') : 0;
      this.arrayContentWillChange(idx, amt, len);

      if (len === 0) {
        this.splice(idx, amt);
      } else {
        _emberMetalReplace._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;
    },

    indexOf: Array.prototype.indexOf,
    lastIndexOf: Array.prototype.lastIndexOf,

    copy: function (deep) {
      if (deep) {
        return this.map(function (item) {
          return _emberRuntimeCopy.default(item, true);
        });
      }

      return this.slice();
    }
  });

  // Remove any methods implemented natively so we don't override them
  var ignore = ['length'];
  NativeArray.keys().forEach(function (methodName) {
    if (Array.prototype[methodName]) {
      ignore.push(methodName);
    }
  });

  exports.NativeArray // TODO: only use default export
   = 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
    export default Ember.Component.extend({
      tagName: 'ul',
      classNames: ['pagination'],

      init() {
        this._super(...arguments);

        if (!this.get('content')) {
          this.set('content', Ember.A());
        }
      }
    });
    ```

    @method A
    @for Ember
    @return {Ember.NativeArray}
    @public
  */
  var A;

  if (_emberMetalCore.default.EXTEND_PROTOTYPES === true || _emberMetalCore.default.EXTEND_PROTOTYPES.Array) {
    NativeArray.apply(Array.prototype);
    exports. // ES6TODO: Setting A onto the object returned by ember-metal/core to avoid circles
    A = A = function (arr) {
      return arr || [];
    };
  } else {
    exports.A = A = function (arr) {
      if (!arr) {
        arr = [];
      }
      return _emberRuntimeMixinsArray.default.detect(arr) ? arr : NativeArray.apply(arr);
    };
  }

  _emberMetalCore.default.A = A;exports.A = A;
  exports.NativeArray = NativeArray;
  exports.default = NativeArray;
});
// Ember.EXTEND_PROTOTYPES
enifed('ember-runtime/system/object', ['exports', 'ember-runtime/system/core_object', 'ember-runtime/mixins/observable'], function (exports, _emberRuntimeSystemCore_object, _emberRuntimeMixinsObservable) {
  /**
  @module ember
  @submodule ember-runtime
  */

  'use strict';

  /**
    `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
    @public
  */
  var EmberObject = _emberRuntimeSystemCore_object.default.extend(_emberRuntimeMixinsObservable.default);
  EmberObject.toString = function () {
    return 'Ember.Object';
  };

  exports.default = EmberObject;
});
enifed('ember-runtime/system/object_proxy', ['exports', 'ember-runtime/system/object', 'ember-runtime/mixins/-proxy'], function (exports, _emberRuntimeSystemObject, _emberRuntimeMixinsProxy) {
  'use strict';

  /**
    `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
    @extends Ember._ProxyMixin
    @public
  */

  exports.default = _emberRuntimeSystemObject.default.extend(_emberRuntimeMixinsProxy.default);
});
enifed('ember-runtime/system/service', ['exports', 'ember-runtime/system/object', 'ember-runtime/inject'], function (exports, _emberRuntimeSystemObject, _emberRuntimeInject) {
  'use strict';

  /**
    Creates a property that lazily looks up a service in the container. There
    are no restrictions as to what objects a service can be injected into.

    Example:

    ```javascript
    App.ApplicationRoute = Ember.Route.extend({
      authManager: Ember.inject.service('auth'),

      model: function() {
        return this.get('authManager').findCurrentUser();
      }
    });
    ```

    This example will create an `authManager` property on the application route
    that looks up the `auth` service in the container, making it easily
    accessible in the `model` hook.

    @method service
    @since 1.10.0
    @for Ember.inject
    @param {String} name (optional) name of the service to inject, defaults to
           the property's name
    @return {Ember.InjectedProperty} injection descriptor instance
    @public
  */
  _emberRuntimeInject.createInjectionHelper('service');

  /**
    @class Service
    @namespace Ember
    @extends Ember.Object
    @since 1.10.0
    @public
  */
  var Service = _emberRuntimeSystemObject.default.extend();

  Service.reopenClass({
    isServiceFactory: true
  });

  exports.default = Service;
});
enifed('ember-runtime/system/string', ['exports', 'ember-metal/debug', 'ember-metal/utils', 'ember-runtime/utils', 'ember-runtime/string_registry', 'ember-metal/cache'], function (exports, _emberMetalDebug, _emberMetalUtils, _emberRuntimeUtils, _emberRuntimeString_registry, _emberMetalCache) {
  /**
  @module ember
  @submodule ember-runtime
  */
  'use strict';

  var STRING_DASHERIZE_REGEXP = /[ _]/g;

  var STRING_DASHERIZE_CACHE = new _emberMetalCache.default(1000, function (key) {
    return decamelize(key).replace(STRING_DASHERIZE_REGEXP, '-');
  });

  var STRING_CAMELIZE_REGEXP_1 = /(\-|\_|\.|\s)+(.)?/g;
  var STRING_CAMELIZE_REGEXP_2 = /(^|\/)([A-Z])/g;

  var CAMELIZE_CACHE = new _emberMetalCache.default(1000, function (key) {
    return key.replace(STRING_CAMELIZE_REGEXP_1, function (match, separator, chr) {
      return chr ? chr.toUpperCase() : '';
    }).replace(STRING_CAMELIZE_REGEXP_2, function (match, separator, chr) {
      return match.toLowerCase();
    });
  });

  var STRING_CLASSIFY_REGEXP_1 = /^(\-|_)+(.)?/;
  var STRING_CLASSIFY_REGEXP_2 = /(.)(\-|\_|\.|\s)+(.)?/g;
  var STRING_CLASSIFY_REGEXP_3 = /(^|\/|\.)([a-z])/g;

  var CLASSIFY_CACHE = new _emberMetalCache.default(1000, function (str) {
    var replace1 = function (match, separator, chr) {
      return chr ? '_' + chr.toUpperCase() : '';
    };
    var replace2 = function (match, initialChar, separator, chr) {
      return initialChar + (chr ? chr.toUpperCase() : '');
    };
    var parts = str.split('/');
    for (var i = 0, len = parts.length; i < len; i++) {
      parts[i] = parts[i].replace(STRING_CLASSIFY_REGEXP_1, replace1).replace(STRING_CLASSIFY_REGEXP_2, replace2);
    }
    return parts.join('/').replace(STRING_CLASSIFY_REGEXP_3, function (match, separator, chr) {
      return match.toUpperCase();
    });
  });

  var STRING_UNDERSCORE_REGEXP_1 = /([a-z\d])([A-Z]+)/g;
  var STRING_UNDERSCORE_REGEXP_2 = /\-|\s+/g;

  var UNDERSCORE_CACHE = new _emberMetalCache.default(1000, function (str) {
    return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
  });

  var STRING_CAPITALIZE_REGEXP = /(^|\/)([a-z])/g;

  var CAPITALIZE_CACHE = new _emberMetalCache.default(1000, function (str) {
    return str.replace(STRING_CAPITALIZE_REGEXP, function (match, separator, chr) {
      return match.toUpperCase();
    });
  });

  var STRING_DECAMELIZE_REGEXP = /([a-z\d])([A-Z])/g;

  var DECAMELIZE_CACHE = new _emberMetalCache.default(1000, function (str) {
    return str.replace(STRING_DECAMELIZE_REGEXP, '$1_$2').toLowerCase();
  });

  function _fmt(str, formats) {
    var cachedFormats = formats;

    if (!_emberRuntimeUtils.isArray(cachedFormats) || arguments.length > 2) {
      cachedFormats = new Array(arguments.length - 1);

      for (var i = 1, l = arguments.length; i < l; i++) {
        cachedFormats[i - 1] = arguments[i];
      }
    }

    // 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 = cachedFormats[argIndex];
      return s === null ? '(null)' : s === undefined ? '' : _emberMetalUtils.inspect(s);
    });
  }

  function fmt(str, formats) {
    _emberMetalDebug.deprecate('Ember.String.fmt is deprecated, use ES6 template strings instead.', false, { id: 'ember-string-utils.fmt', until: '3.0.0', url: 'http://babeljs.io/docs/learn-es2015/#template-strings' });
    return _fmt.apply(undefined, arguments);
  }

  function loc(str, formats) {
    if (!_emberRuntimeUtils.isArray(formats) || arguments.length > 2) {
      formats = Array.prototype.slice.call(arguments, 1);
    }

    str = _emberRuntimeString_registry.get(str) || str;
    return _fmt(str, formats);
  }

  function w(str) {
    return str.split(/\s+/);
  }

  function decamelize(str) {
    return DECAMELIZE_CACHE.get(str);
  }

  function dasherize(str) {
    return STRING_DASHERIZE_CACHE.get(str);
  }

  function camelize(str) {
    return CAMELIZE_CACHE.get(str);
  }

  function classify(str) {
    return CLASSIFY_CACHE.get(str);
  }

  function underscore(str) {
    return UNDERSCORE_CACHE.get(str);
  }

  function capitalize(str) {
    return CAPITALIZE_CACHE.get(str);
  }

  /**
    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
    @public
  */
  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
      @public
      @deprecated Use ES6 template strings instead: http://babeljs.io/docs/learn-es2015/#template-strings
    */
    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
      @public
    */
    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
      @public
    */
    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.
      @public
    */
    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'
      'privateDocs/ownerInvoice'.dasherize(); // 'private-docs/owner-invoice'
      ```
       @method dasherize
      @param {String} str The string to dasherize.
      @return {String} the dasherized string.
      @public
    */
    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'
      'private-docs/owner-invoice'.camelize(); // 'privateDocs/ownerInvoice'
      ```
       @method camelize
      @param {String} str The string to camelize.
      @return {String} the camelized string.
      @public
    */
    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'
      'private-docs/owner-invoice'.classify(); // 'PrivateDocs/OwnerInvoice'
      ```
       @method classify
      @param {String} str the string to classify
      @return {String} the classified string
      @public
    */
    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'
      'privateDocs/ownerInvoice'.underscore(); // 'private_docs/owner_invoice'
      ```
       @method underscore
      @param {String} str The string to underscore.
      @return {String} the underscored string.
      @public
    */
    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'
      'privateDocs/ownerInvoice'.capitalize(); // 'PrivateDocs/ownerInvoice'
      ```
       @method capitalize
      @param {String} str The string to capitalize.
      @return {String} The capitalized string.
      @public
    */
    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;
});
enifed('ember-runtime/utils', ['exports', 'ember-runtime/mixins/array', 'ember-runtime/system/object'], function (exports, _emberRuntimeMixinsArray, _emberRuntimeSystemObject) {
  'use strict';

  exports.isArray = isArray;
  exports.typeOf = typeOf;

  // ........................................
  // TYPING & ARRAY MESSAGING
  //
  var TYPE_MAP = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regexp',
    '[object Object]': 'object'
  };

  var toString = Object.prototype.toString;

  /**
    Returns true if the passed object is an array or Array-like.

    Objects are considered Array-like if any of the following are true:

      - the object is a native Array
      - the object has an objectAt property
      - 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 an 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
    @public
  */

  function isArray(obj) {
    if (!obj || obj.setInterval) {
      return false;
    }
    if (Array.isArray(obj)) {
      return true;
    }
    if (_emberRuntimeMixinsArray.default.detect(obj)) {
      return true;
    }

    var type = typeOf(obj);
    if ('array' === type) {
      return true;
    }
    if (obj.length !== undefined && 'object' === type) {
      return true;
    }
    return false;
  }

  /**
    Returns a consistent type for the passed object.

    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
    @public
  */

  function typeOf(item) {
    if (item === null) {
      return 'null';
    }
    if (item === undefined) {
      return 'undefined';
    }
    var ret = TYPE_MAP[toString.call(item)] || 'object';

    if (ret === 'function') {
      if (_emberRuntimeSystemObject.default.detect(item)) {
        ret = 'class';
      }
    } else if (ret === 'object') {
      if (item instanceof Error) {
        ret = 'error';
      } else if (item instanceof _emberRuntimeSystemObject.default) {
        ret = 'instance';
      } else if (item instanceof Date) {
        ret = 'date';
      }
    }

    return ret;
  }
});
enifed('ember-template-compiler/compat', ['exports', 'ember-metal/core', 'ember-template-compiler/compat/precompile', 'ember-template-compiler/system/compile', 'ember-template-compiler/system/template'], function (exports, _emberMetalCore, _emberTemplateCompilerCompatPrecompile, _emberTemplateCompilerSystemCompile, _emberTemplateCompilerSystemTemplate) {
  'use strict';

  var EmberHandlebars = _emberMetalCore.default.Handlebars = _emberMetalCore.default.Handlebars || {};

  EmberHandlebars.precompile = _emberTemplateCompilerCompatPrecompile.default;
  EmberHandlebars.compile = _emberTemplateCompilerSystemCompile.default;
  EmberHandlebars.template = _emberTemplateCompilerSystemTemplate.default;
});
enifed('ember-template-compiler/compat/precompile', ['exports', 'require', 'ember-template-compiler/system/compile_options'], function (exports, _require, _emberTemplateCompilerSystemCompile_options) {
  /**
  @module ember
  @submodule ember-template-compiler
  */
  'use strict';

  var compile, compileSpec;

  exports.default = function (string) {
    if ((!compile || !compileSpec) && _require.has('htmlbars-compiler/compiler')) {
      var Compiler = _require.default('htmlbars-compiler/compiler');

      compile = Compiler.compile;
      compileSpec = Compiler.compileSpec;
    }

    if (!compile || !compileSpec) {
      throw new Error('Cannot call `precompile` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `precompile`.');
    }

    var asObject = arguments[1] === undefined ? true : arguments[1];
    var compileFunc = asObject ? compile : compileSpec;

    return compileFunc(string, _emberTemplateCompilerSystemCompile_options.default());
  };
});
enifed('ember-template-compiler/index', ['exports', 'ember-metal', 'ember-template-compiler/system/precompile', 'ember-template-compiler/system/compile', 'ember-template-compiler/system/template', 'ember-template-compiler/plugins', 'ember-template-compiler/plugins/transform-old-binding-syntax', 'ember-template-compiler/plugins/transform-old-class-binding-syntax', 'ember-template-compiler/plugins/transform-item-class', 'ember-template-compiler/plugins/transform-closure-component-attrs-into-mut', 'ember-template-compiler/plugins/transform-component-attrs-into-mut', 'ember-template-compiler/plugins/transform-component-curly-to-readonly', 'ember-template-compiler/plugins/transform-angle-bracket-components', 'ember-template-compiler/plugins/transform-input-on-to-onEvent', 'ember-template-compiler/plugins/transform-top-level-components', 'ember-template-compiler/plugins/deprecate-render-model', 'ember-template-compiler/plugins/prevent-render-block', 'ember-template-compiler/plugins/transform-inline-link-to', 'ember-template-compiler/plugins/assert-no-view-and-controller-paths', 'ember-template-compiler/plugins/assert-no-view-helper', 'ember-template-compiler/plugins/assert-no-each-in', 'ember-template-compiler/compat'], function (exports, _emberMetal, _emberTemplateCompilerSystemPrecompile, _emberTemplateCompilerSystemCompile, _emberTemplateCompilerSystemTemplate, _emberTemplateCompilerPlugins, _emberTemplateCompilerPluginsTransformOldBindingSyntax, _emberTemplateCompilerPluginsTransformOldClassBindingSyntax, _emberTemplateCompilerPluginsTransformItemClass, _emberTemplateCompilerPluginsTransformClosureComponentAttrsIntoMut, _emberTemplateCompilerPluginsTransformComponentAttrsIntoMut, _emberTemplateCompilerPluginsTransformComponentCurlyToReadonly, _emberTemplateCompilerPluginsTransformAngleBracketComponents, _emberTemplateCompilerPluginsTransformInputOnToOnEvent, _emberTemplateCompilerPluginsTransformTopLevelComponents, _emberTemplateCompilerPluginsDeprecateRenderModel, _emberTemplateCompilerPluginsPreventRenderBlock, _emberTemplateCompilerPluginsTransformInlineLinkTo, _emberTemplateCompilerPluginsAssertNoViewAndControllerPaths, _emberTemplateCompilerPluginsAssertNoViewHelper, _emberTemplateCompilerPluginsAssertNoEachIn, _emberTemplateCompilerCompat) {
  'use strict';

  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformOldBindingSyntax.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformOldClassBindingSyntax.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformItemClass.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformClosureComponentAttrsIntoMut.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformComponentAttrsIntoMut.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformComponentCurlyToReadonly.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformAngleBracketComponents.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformInputOnToOnEvent.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformTopLevelComponents.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsDeprecateRenderModel.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsPreventRenderBlock.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsAssertNoEachIn.default);
  _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformInlineLinkTo.default);

  if (!_emberMetal.default.ENV._ENABLE_LEGACY_VIEW_SUPPORT) {
    _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsAssertNoViewAndControllerPaths.default);
    _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsAssertNoViewHelper.default);
  }

  exports._Ember = _emberMetal.default;
  exports.precompile = _emberTemplateCompilerSystemPrecompile.default;
  exports.compile = _emberTemplateCompilerSystemCompile.default;
  exports.template = _emberTemplateCompilerSystemTemplate.default;
  exports.registerPlugin = _emberTemplateCompilerPlugins.registerPlugin;
});

// used for adding Ember.Handlebars.compile for backwards compat
enifed('ember-template-compiler/plugins', ['exports'], function (exports) {
  /**
  @module ember
  @submodule ember-template-compiler
  */

  /**
   @private
   @property helpers
  */
  'use strict';

  exports.registerPlugin = registerPlugin;
  var plugins = {
    ast: []
  };

  /**
    Adds an AST plugin to be used by Ember.HTMLBars.compile.

    @private
    @method registerASTPlugin
  */

  function registerPlugin(type, Plugin) {
    if (!plugins[type]) {
      throw new Error('Attempting to register "' + Plugin + '" as "' + type + '" which is not a valid HTMLBars plugin type.');
    }

    plugins[type].push(Plugin);
  }

  exports.default = plugins;
});
enifed('ember-template-compiler/plugins/assert-no-each-in', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalCore, _emberMetalDebug, _emberTemplateCompilerSystemCalculateLocationDisplay) {
  'use strict';

  function AssertNoEachIn() {
    var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

    this.syntax = null;
    this.options = options;
  }

  AssertNoEachIn.prototype.transform = function AssertNoEachIn_transform(ast) {
    if (!!_emberMetalCore.default.ENV._ENABLE_LEGACY_VIEW_SUPPORT) {
      return ast;
    }
    var walker = new this.syntax.Walker();
    var moduleName = this.options && this.options.moduleName;

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }
      assertHelper(moduleName, node);
    });

    return ast;
  };

  function assertHelper(moduleName, node) {
    var moduleInfo = _emberTemplateCompilerSystemCalculateLocationDisplay.default(moduleName, node.loc);
    var singular = node.params[0].original;
    var plural = node.params[2].original;

    _emberMetalDebug.assert('Using {{#each ' + singular + ' in ' + plural + '}} ' + moduleInfo + 'is no longer supported in Ember 2.0+, please use {{#each ' + plural + ' as |' + singular + '|}}');
  }

  function validate(node) {
    return (node.type === 'BlockStatement' || node.type === 'MustacheStatement') && node.path.original === 'each' && node.params.length === 3 && node.params[1].type === 'PathExpression' && node.params[1].original === 'in';
  }

  exports.default = AssertNoEachIn;
});
enifed('ember-template-compiler/plugins/assert-no-view-and-controller-paths', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalCore, _emberMetalDebug, _emberTemplateCompilerSystemCalculateLocationDisplay) {
  'use strict';

  function AssertNoViewAndControllerPaths() {
    var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

    // set later within HTMLBars to the syntax package
    this.syntax = null;
    this.options = options;
  }

  /**
    @private
    @method transform
    @param {AST} ast The AST to be transformed.
  */
  AssertNoViewAndControllerPaths.prototype.transform = function AssertNoViewAndControllerPaths_transform(ast) {
    var walker = new this.syntax.Walker();
    var moduleName = this.options && this.options.moduleName;

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      assertPath(moduleName, node, node.path);
      assertPaths(moduleName, node, node.params);
      assertHash(moduleName, node, node.hash);
    });

    return ast;
  };

  function assertHash(moduleName, node, hash) {
    if (!hash || !hash.pairs) {
      return;
    }
    var i, l, pair, paths;
    for (i = 0, l = hash.pairs.length; i < l; i++) {
      pair = hash.pairs[i];
      paths = pair.value.params;
      assertPaths(moduleName, pair, paths);
    }
  }

  function assertPaths(moduleName, node, paths) {
    if (!paths) {
      return;
    }
    var i, l, path;
    for (i = 0, l = paths.length; i < l; i++) {
      path = paths[i];
      assertPath(moduleName, node, path);
    }
  }

  function assertPath(moduleName, node, path) {
    _emberMetalDebug.assert('Using `{{' + (path && path.type === 'PathExpression' && path.parts[0]) + '}}` or any path based on it ' + _emberTemplateCompilerSystemCalculateLocationDisplay.default(moduleName, node.loc) + 'has been removed in Ember 2.0', (function () {
      var noAssertion = true;

      // allow opt-out of the assertion when legacy addons are present
      var viewKeyword = path && path.type === 'PathExpression' && path.parts && path.parts[0];
      if (viewKeyword === 'view') {
        noAssertion = _emberMetalCore.default.ENV._ENABLE_LEGACY_VIEW_SUPPORT;
      }

      return noAssertion;
    })(), {
      id: path.parts && path.parts[0] === 'view' ? 'view.keyword.view' : 'view.keyword.controller',
      until: '2.0.0'
    });
  }

  function validate(node) {
    return node.type === 'MustacheStatement' || node.type === 'BlockStatement';
  }

  exports.default = AssertNoViewAndControllerPaths;
});
enifed('ember-template-compiler/plugins/assert-no-view-helper', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalCore, _emberMetalDebug, _emberTemplateCompilerSystemCalculateLocationDisplay) {
  'use strict';

  function AssertNoViewHelper() {
    var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

    // set later within HTMLBars to the syntax package
    this.syntax = null;
    this.options = options;
  }

  /**
    @private
    @method transform
    @param {AST} ast The AST to be transformed.
  */
  AssertNoViewHelper.prototype.transform = function AssertNoViewHelper_transform(ast) {
    if (!!_emberMetalCore.default.ENV._ENABLE_LEGACY_VIEW_SUPPORT) {
      return ast;
    }
    var walker = new this.syntax.Walker();
    var moduleName = this.options && this.options.moduleName;

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      assertHelper(moduleName, node);
    });

    return ast;
  };

  function assertHelper(moduleName, node) {
    var paramValue = node.params.length && node.params[0].value;

    if (!paramValue) {
      return;
    } else {
      _emberMetalDebug.assert('Using the `{{view "string"}}` helper is removed in 2.0. ' + _emberTemplateCompilerSystemCalculateLocationDisplay.default(moduleName, node.loc), _emberMetalCore.default.ENV._ENABLE_LEGACY_VIEW_SUPPORT, { id: 'view.helper', until: '2.0.0' });
    }
  }

  function validate(node) {
    return (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && node.path.parts[0] === 'view';
  }

  exports.default = AssertNoViewHelper;
});
enifed('ember-template-compiler/plugins/deprecate-render-model', ['exports', 'ember-metal/debug', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalDebug, _emberTemplateCompilerSystemCalculateLocationDisplay) {
  'use strict';

  exports.default = DeprecateRenderModel;

  function DeprecateRenderModel(options) {
    this.syntax = null;
    this.options = options;
  }

  DeprecateRenderModel.prototype.transform = function DeprecateRenderModel_transform(ast) {
    var moduleName = this.options.moduleName;
    var walker = new this.syntax.Walker();

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      each(node.params, function (param) {
        if (param.type !== 'PathExpression') {
          return;
        }

        _emberMetalDebug.deprecate(deprecationMessage(moduleName, node, param), false, {
          id: 'ember-template-compiler.deprecate-render-model',
          until: '3.0.0',
          url: 'http://emberjs.com/deprecations/v2.x#toc_model-param-in-code-render-code-helper'
        });
      });
    });

    return ast;
  };

  function validate(node) {
    return node.type === 'MustacheStatement' && node.path.original === 'render' && node.params.length > 1;
  }

  function each(list, callback) {
    for (var i = 0, l = list.length; i < l; i++) {
      callback(list[i]);
    }
  }

  function deprecationMessage(moduleName, node, param) {
    var sourceInformation = _emberTemplateCompilerSystemCalculateLocationDisplay.default(moduleName, node.loc);
    var componentName = node.params[0].original;
    var modelName = param.original;
    var original = '{{render "' + componentName + '" ' + modelName + '}}';
    var preferred = '{{' + componentName + ' model=' + modelName + '}}';

    return 'Please refactor `' + original + '` to a component and invoke via' + (' `' + preferred + '`. ' + sourceInformation);
  }
});
enifed('ember-template-compiler/plugins/prevent-render-block', ['exports', 'ember-metal/error', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalError, _emberTemplateCompilerSystemCalculateLocationDisplay) {
  'use strict';

  exports.default = PreventRenderBlock;

  function PreventRenderBlock(options) {
    this.syntax = null;
    this.options = options;
  }

  PreventRenderBlock.prototype.transform = function PreventRenderBlock_transform(ast) {
    var moduleName = this.options.moduleName;
    var walker = new this.syntax.Walker();

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      throw new _emberMetalError.default(assertionMessage(moduleName, node));
    });

    return ast;
  };

  function validate(node) {
    return node.type === 'BlockStatement' && node.path.original === 'render';
  }

  function assertionMessage(moduleName, node) {
    var sourceInformation = _emberTemplateCompilerSystemCalculateLocationDisplay.default(moduleName, node.loc);

    return 'Usage of `render` in block form is unsupported ' + sourceInformation + '.';
  }
});
enifed('ember-template-compiler/plugins/transform-angle-bracket-components', ['exports'], function (exports) {
  'use strict';

  function TransformAngleBracketComponents() {
    // set later within HTMLBars to the syntax package
    this.syntax = null;
  }

  /**
    @private
    @method transform
    @param {AST} ast The AST to be transformed.
  */
  TransformAngleBracketComponents.prototype.transform = function TransformAngleBracketComponents_transform(ast) {
    var walker = new this.syntax.Walker();

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      node.tag = '<' + node.tag + '>';
    });

    return ast;
  };

  function validate(node) {
    return node.type === 'ComponentNode';
  }

  exports.default = TransformAngleBracketComponents;
});
enifed('ember-template-compiler/plugins/transform-closure-component-attrs-into-mut', ['exports'], function (exports) {
  'use strict';

  function TransformClosureComponentAttrsIntoMut() {
    // set later within HTMLBars to the syntax package
    this.syntax = null;
  }

  /**
    @private
    @method transform
    @param {AST} ast The AST to be transformed.
  */
  TransformClosureComponentAttrsIntoMut.prototype.transform = function TransformClosureComponentAttrsIntoMut_transform(ast) {
    var b = this.syntax.builders;

    this.syntax.traverse(ast, {
      SubExpression: function (node) {
        if (isComponentClosure(node)) {
          mutParameters(b, node);
        }
      }
    });

    return ast;
  };

  function isComponentClosure(node) {
    return node.type === 'SubExpression' && node.path.original === 'component';
  }

  function mutParameters(builder, node) {
    for (var i = 1; i < node.params.length; i++) {
      if (node.params[i].type === 'PathExpression') {
        node.params[i] = builder.sexpr(builder.path('@mut'), [node.params[i]]);
      }
    }

    each(node.hash.pairs, function (pair) {
      var value = pair.value;

      if (value.type === 'PathExpression') {
        pair.value = builder.sexpr(builder.path('@mut'), [pair.value]);
      }
    });
  }

  function each(list, callback) {
    for (var i = 0, l = list.length; i < l; i++) {
      callback(list[i]);
    }
  }

  exports.default = TransformClosureComponentAttrsIntoMut;
});
enifed('ember-template-compiler/plugins/transform-component-attrs-into-mut', ['exports'], function (exports) {
  'use strict';

  function TransformComponentAttrsIntoMut() {
    // set later within HTMLBars to the syntax package
    this.syntax = null;
  }

  /**
    @private
    @method transform
    @param {AST} ast The AST to be transformed.
  */
  TransformComponentAttrsIntoMut.prototype.transform = function TransformComponentAttrsIntoMut_transform(ast) {
    var b = this.syntax.builders;
    var walker = new this.syntax.Walker();

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      each(node.hash.pairs, function (pair) {
        var value = pair.value;

        if (value.type === 'PathExpression') {
          pair.value = b.sexpr(b.path('@mut'), [pair.value]);
        }
      });
    });

    return ast;
  };

  function validate(node) {
    return node.type === 'BlockStatement' || node.type === 'MustacheStatement';
  }

  function each(list, callback) {
    for (var i = 0, l = list.length; i < l; i++) {
      callback(list[i]);
    }
  }

  exports.default = TransformComponentAttrsIntoMut;
});
enifed('ember-template-compiler/plugins/transform-component-curly-to-readonly', ['exports'], function (exports) {
  'use strict';

  function TransformComponentCurlyToReadonly() {
    // set later within HTMLBars to the syntax package
    this.syntax = null;
  }

  /**
    @private
    @method transform
    @param {AST} ast The AST to be transformed.
  */
  TransformComponentCurlyToReadonly.prototype.transform = function TransformComponetnCurlyToReadonly_transform(ast) {
    var b = this.syntax.builders;
    var walker = new this.syntax.Walker();

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      each(node.attributes, function (attr) {
        if (attr.value.type !== 'MustacheStatement') {
          return;
        }
        if (attr.value.params.length || attr.value.hash.pairs.length) {
          return;
        }

        attr.value = b.mustache(b.path('readonly'), [attr.value.path], null, !attr.value.escape);
      });
    });

    return ast;
  };

  function validate(node) {
    return node.type === 'ComponentNode';
  }

  function each(list, callback) {
    for (var i = 0, l = list.length; i < l; i++) {
      callback(list[i]);
    }
  }

  exports.default = TransformComponentCurlyToReadonly;
});
enifed('ember-template-compiler/plugins/transform-inline-link-to', ['exports'], function (exports) {
  'use strict';

  exports.default = TransformInlineLinkTo;

  function TransformInlineLinkTo(options) {
    this.options = options;
    this.syntax = null;
  }

  TransformInlineLinkTo.prototype.transform = function TransformInlineLinkTo_transform(ast) {
    var _syntax = this.syntax;
    var traverse = _syntax.traverse;
    var b = _syntax.builders;

    function buildProgram(content, loc) {
      return b.program([buildStatement(content, loc)], null, loc);
    }

    function buildStatement(content, loc) {
      switch (content.type) {
        case 'PathExpression':
          return b.mustache(content, null, null, null, loc);

        case 'SubExpression':
          return b.mustache(content.path, content.params, content.hash, null, loc);

        // The default case handles literals.
        default:
          return b.text('' + content.value, loc);
      }
    }

    function unsafeHtml(expr) {
      return b.sexpr('-html-safe', [expr]);
    }

    traverse(ast, {
      MustacheStatement: function (node) {
        if (node.path.original === 'link-to') {
          var content = node.escaped ? node.params[0] : unsafeHtml(node.params[0]);
          return b.block('link-to', node.params.slice(1), node.hash, buildProgram(content, node.loc), null, node.loc);
        }
      }
    });

    return ast;
  };
});
enifed('ember-template-compiler/plugins/transform-input-on-to-onEvent', ['exports', 'ember-metal/debug', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalDebug, _emberTemplateCompilerSystemCalculateLocationDisplay) {
  'use strict';

  /**
   @module ember
   @submodule ember-htmlbars
  */

  /**
    An HTMLBars AST transformation that replaces all instances of

    ```handlebars
   {{input on="enter" action="doStuff"}}
   {{input on="key-press" action="doStuff"}}
    ```

    with

    ```handlebars
   {{input enter="doStuff"}}
   {{input key-press="doStuff"}}
    ```

    @private
    @class TransformInputOnToOnEvent
  */
  function TransformInputOnToOnEvent() {
    var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];

    // set later within HTMLBars to the syntax package
    this.syntax = null;
    this.options = options;
  }

  /**
    @private
    @method transform
    @param {AST} ast The AST to be transformed.
  */
  TransformInputOnToOnEvent.prototype.transform = function TransformInputOnToOnEvent_transform(ast) {
    var pluginContext = this;
    var b = pluginContext.syntax.builders;
    var walker = new pluginContext.syntax.Walker();
    var moduleName = pluginContext.options.moduleName;

    walker.visit(ast, function (node) {
      if (pluginContext.validate(node)) {
        var action = hashPairForKey(node.hash, 'action');
        var on = hashPairForKey(node.hash, 'on');
        var onEvent = hashPairForKey(node.hash, 'onEvent');
        var normalizedOn = on || onEvent;
        var moduleInfo = _emberTemplateCompilerSystemCalculateLocationDisplay.default(moduleName, node.loc);

        if (normalizedOn && normalizedOn.value.type !== 'StringLiteral') {
          _emberMetalDebug.deprecate('Using a dynamic value for \'#{normalizedOn.key}=\' with the \'{{input}}\' helper ' + moduleInfo + 'is deprecated.', false, { id: 'ember-template-compiler.transform-input-on-to-onEvent.dynamic-value', until: '3.0.0' });

          normalizedOn.key = 'onEvent';
          return; // exit early, as we cannot transform further
        }

        removeFromHash(node.hash, normalizedOn);
        removeFromHash(node.hash, action);

        if (!action) {
          _emberMetalDebug.deprecate('Using \'{{input ' + normalizedOn.key + '="' + normalizedOn.value.value + '" ...}}\' without specifying an action ' + moduleInfo + 'will do nothing.', false, { id: 'ember-template-compiler.transform-input-on-to-onEvent.no-action', until: '3.0.0' });

          return; // exit early, if no action was available there is nothing to do
        }

        var specifiedOn = normalizedOn ? normalizedOn.key + '="' + normalizedOn.value.value + '" ' : '';
        if (normalizedOn && normalizedOn.value.value === 'keyPress') {
          // using `keyPress` in the root of the component will
          // clobber the keyPress event handler
          normalizedOn.value.value = 'key-press';
        }

        var expected = (normalizedOn ? normalizedOn.value.value : 'enter') + '="' + action.value.original + '"';

        _emberMetalDebug.deprecate('Using \'{{input ' + specifiedOn + 'action="' + action.value.original + '"}}\' ' + moduleInfo + 'is deprecated. Please use \'{{input ' + expected + '}}\' instead.', false, { id: 'ember-template-compiler.transform-input-on-to-onEvent.normalized-on', until: '3.0.0' });
        if (!normalizedOn) {
          normalizedOn = b.pair('onEvent', b.string('enter'));
        }

        node.hash.pairs.push(b.pair(normalizedOn.value.value, action.value));
      }
    });

    return ast;
  };

  TransformInputOnToOnEvent.prototype.validate = function TransformWithAsToHash_validate(node) {
    return node.type === 'MustacheStatement' && node.path.original === 'input' && (hashPairForKey(node.hash, 'action') || hashPairForKey(node.hash, 'on') || hashPairForKey(node.hash, 'onEvent'));
  };

  function hashPairForKey(hash, key) {
    for (var i = 0, l = hash.pairs.length; i < l; i++) {
      var pair = hash.pairs[i];
      if (pair.key === key) {
        return pair;
      }
    }

    return false;
  }

  function removeFromHash(hash, pairToRemove) {
    var newPairs = [];
    for (var i = 0, l = hash.pairs.length; i < l; i++) {
      var pair = hash.pairs[i];

      if (pair !== pairToRemove) {
        newPairs.push(pair);
      }
    }

    hash.pairs = newPairs;
  }

  exports.default = TransformInputOnToOnEvent;
});
enifed('ember-template-compiler/plugins/transform-item-class', ['exports'], function (exports) {
  'use strict';

  exports.default = TransformItemClass;

  function TransformItemClass() {
    this.syntax = null;
  }

  TransformItemClass.prototype.transform = function TransformItemClass_transform(ast) {
    var b = this.syntax.builders;
    var walker = new this.syntax.Walker();

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      each(node.hash.pairs, function (pair) {
        var key = pair.key;
        var value = pair.value;

        if (key !== 'itemClass') {
          return;
        }
        if (value.type === 'StringLiteral') {
          return;
        }

        var propName = value.original;
        var params = [value];
        var sexprParams = [b.string(propName), b.path(propName)];

        params.push(b.sexpr(b.string('-normalize-class'), sexprParams));
        var sexpr = b.sexpr(b.string('if'), params);

        pair.value = sexpr;
      });
    });

    return ast;
  };

  function validate(node) {
    return (node.type === 'BlockStatement' || node.type === 'MustacheStatement') && node.path.original === 'collection';
  }

  function each(list, callback) {
    for (var i = 0, l = list.length; i < l; i++) {
      callback(list[i]);
    }
  }
});
enifed('ember-template-compiler/plugins/transform-old-binding-syntax', ['exports', 'ember-metal/debug', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalDebug, _emberTemplateCompilerSystemCalculateLocationDisplay) {
  'use strict';

  exports.default = TransformOldBindingSyntax;

  function TransformOldBindingSyntax(options) {
    this.syntax = null;
    this.options = options;
  }

  TransformOldBindingSyntax.prototype.transform = function TransformOldBindingSyntax_transform(ast) {
    var moduleName = this.options.moduleName;
    var b = this.syntax.builders;
    var walker = new this.syntax.Walker();

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      each(node.hash.pairs, function (pair) {
        var key = pair.key;
        var value = pair.value;

        var sourceInformation = _emberTemplateCompilerSystemCalculateLocationDisplay.default(moduleName, pair.loc);

        if (key === 'classBinding') {
          return;
        }

        _emberMetalDebug.assert('Setting \'attributeBindings\' via template helpers is not allowed ' + sourceInformation, key !== 'attributeBindings');

        if (key.substr(-7) === 'Binding') {
          var newKey = key.slice(0, -7);

          _emberMetalDebug.deprecate('You\'re using legacy binding syntax: ' + key + '=' + exprToString(value) + ' ' + sourceInformation + '. Please replace with ' + newKey + '=' + value.original, false, { id: 'ember-template-compiler.transform-old-binding-syntax', until: '3.0.0' });

          pair.key = newKey;
          if (value.type === 'StringLiteral') {
            pair.value = b.path(value.original);
          }
        }
      });
    });

    return ast;
  };

  function validate(node) {
    return node.type === 'BlockStatement' || node.type === 'MustacheStatement';
  }

  function each(list, callback) {
    for (var i = 0, l = list.length; i < l; i++) {
      callback(list[i]);
    }
  }

  function exprToString(expr) {
    switch (expr.type) {
      case 'StringLiteral':
        return '"' + expr.original + '"';
      case 'PathExpression':
        return expr.original;
    }
  }
});
enifed('ember-template-compiler/plugins/transform-old-class-binding-syntax', ['exports'], function (exports) {
  'use strict';

  exports.default = TransformOldClassBindingSyntax;

  function TransformOldClassBindingSyntax(options) {
    this.syntax = null;
    this.options = options;
  }

  TransformOldClassBindingSyntax.prototype.transform = function TransformOldClassBindingSyntax_transform(ast) {
    var b = this.syntax.builders;
    var walker = new this.syntax.Walker();

    walker.visit(ast, function (node) {
      if (!validate(node)) {
        return;
      }

      var allOfTheMicrosyntaxes = [];
      var allOfTheMicrosyntaxIndexes = [];
      var classPair = undefined;

      each(node.hash.pairs, function (pair, index) {
        var key = pair.key;

        if (key === 'classBinding' || key === 'classNameBindings') {
          allOfTheMicrosyntaxIndexes.push(index);
          allOfTheMicrosyntaxes.push(pair);
        } else if (key === 'class') {
          classPair = pair;
        }
      });

      if (allOfTheMicrosyntaxes.length === 0) {
        return;
      }

      var classValue = [];

      if (classPair) {
        classValue.push(classPair.value);
        classValue.push(b.string(' '));
      } else {
        classPair = b.pair('class', null);
        node.hash.pairs.push(classPair);
      }

      each(allOfTheMicrosyntaxIndexes, function (index) {
        node.hash.pairs.splice(index, 1);
      });

      each(allOfTheMicrosyntaxes, function (_ref) {
        var value = _ref.value;
        var loc = _ref.loc;

        var sexprs = [];
        // TODO: add helpful deprecation when both `classNames` and `classNameBindings` can
        // be removed.

        if (value.type === 'StringLiteral') {
          var microsyntax = parseMicrosyntax(value.original);

          buildSexprs(microsyntax, sexprs, b);

          classValue.push.apply(classValue, sexprs);
        }
      });

      var hash = b.hash();
      classPair.value = b.sexpr(b.string('concat'), classValue, hash);
    });

    return ast;
  };

  function buildSexprs(microsyntax, sexprs, b) {
    for (var i = 0, l = microsyntax.length; i < l; i++) {
      var _microsyntax$i = microsyntax[i];
      var propName = _microsyntax$i[0];
      var activeClass = _microsyntax$i[1];
      var inactiveClass = _microsyntax$i[2];

      var sexpr = undefined;

      // :my-class-name microsyntax for static values
      if (propName === '') {
        sexpr = b.string(activeClass);
      } else {
        var params = [b.path(propName)];

        if (activeClass) {
          params.push(b.string(activeClass));
        } else {
          var sexprParams = [b.string(propName), b.path(propName)];

          var hash = b.hash();
          if (activeClass !== undefined) {
            hash.pairs.push(b.pair('activeClass', b.string(activeClass)));
          }

          if (inactiveClass !== undefined) {
            hash.pairs.push(b.pair('inactiveClass', b.string(inactiveClass)));
          }

          params.push(b.sexpr(b.string('-normalize-class'), sexprParams, hash));
        }

        if (inactiveClass) {
          params.push(b.string(inactiveClass));
        }

        sexpr = b.sexpr(b.string('if'), params);
      }

      sexprs.push(sexpr);
      sexprs.push(b.string(' '));
    }
  }

  function validate(node) {
    return node.type === 'BlockStatement' || node.type === 'MustacheStatement';
  }

  function each(list, callback) {
    for (var i = 0, l = list.length; i < l; i++) {
      callback(list[i], i);
    }
  }

  function parseMicrosyntax(string) {
    var segments = string.split(' ');

    for (var i = 0, l = segments.length; i < l; i++) {
      segments[i] = segments[i].split(':');
    }

    return segments;
  }
});
enifed('ember-template-compiler/plugins/transform-top-level-components', ['exports'], function (exports) {
  'use strict';

  function TransformTopLevelComponents() {
    // set later within HTMLBars to the syntax package
    this.syntax = null;
  }

  /**
    @private
    @method transform
    @param {AST} The AST to be transformed.
  */
  TransformTopLevelComponents.prototype.transform = function TransformTopLevelComponents_transform(ast) {
    var b = this.syntax.builders;

    hasSingleComponentNode(ast, function (component) {
      if (component.type === 'ComponentNode') {
        component.tag = '@' + component.tag;
        component.isStatic = true;
      }
    }, function (element) {
      var hasTripleCurlies = element.attributes.some(function (attr) {
        return attr.value.escaped === false;
      });

      if (element.modifiers.length || hasTripleCurlies) {
        return element;
      } else {
        // TODO: Properly copy loc from children
        var program = b.program(element.children);
        var component = b.component('@<' + element.tag + '>', element.attributes, program, element.loc);
        component.isStatic = true;
        return component;
      }
    });

    return ast;
  };

  function hasSingleComponentNode(program, componentCallback, elementCallback) {
    var loc = program.loc;
    var body = program.body;

    if (!loc || loc.start.line !== 1 || loc.start.column !== 0) {
      return;
    }

    var lastComponentNode = undefined;
    var lastIndex = undefined;
    var nodeCount = 0;

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

      // text node with whitespace only
      if (curr.type === 'TextNode' && /^[\s]*$/.test(curr.chars)) {
        continue;
      }

      // has multiple root elements if we've been here before
      if (nodeCount++ > 0) {
        return false;
      }

      if (curr.type === 'ComponentNode' || curr.type === 'ElementNode') {
        lastComponentNode = curr;
        lastIndex = i;
      }
    }

    if (!lastComponentNode) {
      return;
    }

    if (lastComponentNode.type === 'ComponentNode') {
      componentCallback(lastComponentNode);
    }
  }

  exports.default = TransformTopLevelComponents;
});
enifed('ember-template-compiler/system/calculate-location-display', ['exports'], function (exports) {
  'use strict';

  exports.default = calculateLocationDisplay;

  function calculateLocationDisplay(moduleName, _loc) {
    var loc = _loc || {};

    var _ref = loc.start || {};

    var column = _ref.column;
    var line = _ref.line;

    var moduleInfo = '';
    if (moduleName) {
      moduleInfo += '\'' + moduleName + '\' ';
    }

    if (line !== undefined && column !== undefined) {
      if (moduleName) {
        // only prepend @ if the moduleName was present
        moduleInfo += '@ ';
      }
      moduleInfo += 'L' + line + ':C' + column;
    }

    if (moduleInfo) {
      moduleInfo = '(' + moduleInfo + ') ';
    }

    return moduleInfo;
  }
});
enifed('ember-template-compiler/system/compile', ['exports', 'ember-metal/features', 'require', 'ember-template-compiler/system/compile_options', 'ember-template-compiler/system/template'], function (exports, _emberMetalFeatures, _require, _emberTemplateCompilerSystemCompile_options, _emberTemplateCompilerSystemTemplate) {
  /**
  @module ember
  @submodule ember-template-compiler
  */

  'use strict';

  var compile;

  /**
    Uses HTMLBars `compile` function to process a string into a compiled template.

    This is not present in production builds.

    @private
    @method compile
    @param {String} templateString This is the string to be compiled by HTMLBars.
    @param {Object} options This is an options hash to augment the compiler options.
  */

  exports.default = function (templateString, options) {
    if (!compile && _require.has('htmlbars-compiler/compiler')) {
      compile = _require.default('htmlbars-compiler/compiler').compile;
    }

    if (!compile) {
      throw new Error('Cannot call `compile` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `compile`.');
    }

    var templateSpec = compile(templateString, _emberTemplateCompilerSystemCompile_options.default(options));

    return _emberTemplateCompilerSystemTemplate.default(templateSpec);
  };
});
enifed('ember-template-compiler/system/compile_options', ['exports', 'ember-metal/assign', 'ember-template-compiler/plugins'], function (exports, _emberMetalAssign, _emberTemplateCompilerPlugins) {
  /**
  @module ember
  @submodule ember-template-compiler
  */

  'use strict';

  var compileOptions = undefined;
  var fragmentReason = undefined;

  /**
    @private
    @property compileOptions
  */
  compileOptions = function (_options) {
    var disableComponentGeneration = true;

    var options = undefined;
    // When calling `Ember.Handlebars.compile()` a second argument of `true`
    // had a special meaning (long since lost), this just gaurds against
    // `options` being true, and causing an error during compilation.
    if (_options === true) {
      options = {};
    } else {
      options = _emberMetalAssign.default({}, _options);
    }

    options.disableComponentGeneration = disableComponentGeneration;

    var plugins = {
      ast: _emberTemplateCompilerPlugins.default.ast.slice()
    };

    if (options.plugins && options.plugins.ast) {
      plugins.ast = plugins.ast.concat(options.plugins.ast);
    }
    options.plugins = plugins;

    options.buildMeta = function buildMeta(program) {
      return {
        fragmentReason: fragmentReason(program),
        revision: 'Ember@2.6.2',
        loc: program.loc,
        moduleName: options.moduleName
      };
    };

    return options;
  };

  fragmentReason = function (program) {
    var loc = program.loc;
    var body = program.body;

    if (!loc || loc.start.line !== 1 || loc.start.column !== 0) {
      return false;
    }

    var candidate = undefined;
    var nodeCount = 0;

    var problems = {};

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

      // text node with whitespace only
      if (curr.type === 'TextNode' && /^[\s]*$/.test(curr.chars)) {
        continue;
      }

      // has multiple root elements if we've been here before
      if (nodeCount++ > 0) {
        problems['multiple-nodes'] = true;
      }

      if (curr.type === 'ComponentNode' || curr.type === 'ElementNode') {
        candidate = curr;
      } else {
        problems['wrong-type'] = true;
      }
    }

    if (nodeCount === 0) {
      return { name: 'missing-wrapper', problems: ['empty-body'] };
    }

    var problemList = Object.keys(problems);
    if (problemList.length) {
      return { name: 'missing-wrapper', problems: problemList };
    }

    if (candidate.type === 'ComponentNode') {
      return false;
    } else if (candidate.modifiers.length) {
      return { name: 'modifiers', modifiers: candidate.modifiers.map(function (m) {
          return m.path.original;
        }) };
    } else if (candidate.attributes.some(function (attr) {
      return !attr.value.escaped;
    })) {
      return { name: 'triple-curlies' };
    } else {
      return false;
    }
  };

  exports.default = compileOptions;
});
enifed('ember-template-compiler/system/precompile', ['exports', 'ember-metal/features', 'require', 'ember-template-compiler/system/compile_options'], function (exports, _emberMetalFeatures, _require, _emberTemplateCompilerSystemCompile_options) {
  /**
  @module ember
  @submodule ember-template-compiler
  */

  'use strict';

  var compileSpec;

  /**
    Uses HTMLBars `compile` function to process a string into a compiled template string.
    The returned string must be passed through `Ember.HTMLBars.template`.

    This is not present in production builds.

    @private
    @method precompile
    @param {String} templateString This is the string to be compiled by HTMLBars.
  */

  exports.default = function (templateString, options) {
    if (!compileSpec && _require.has('htmlbars-compiler/compiler')) {
      compileSpec = _require.default('htmlbars-compiler/compiler').compileSpec;
    }

    if (!compileSpec) {
      throw new Error('Cannot call `compileSpec` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `compileSpec`.');
    }

    return compileSpec(templateString, _emberTemplateCompilerSystemCompile_options.default(options));
  };
});
enifed('ember-template-compiler/system/template', ['exports', 'ember-metal/features', 'require'], function (exports, _emberMetalFeatures, _require2) {
  'use strict';

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

  /**
    Augments the default precompiled output of an HTMLBars template with
    additional information needed by Ember.

    @private
    @method template
    @param {Function} templateSpec This is the compiled HTMLBars template spec.
  */

  var template = undefined;

  var _require = _require2.default('htmlbars-runtime/hooks');

  var wrap = _require.wrap;

  template = function (templateSpec) {
    if (!templateSpec.render) {
      templateSpec = wrap(templateSpec);
    }

    templateSpec.isTop = true;
    templateSpec.isMethod = false;

    return templateSpec;
  };
  exports.default = template;
});
enifed('ember-testing/adapters/adapter', ['exports', 'ember-runtime/system/object'], function (exports, _emberRuntimeSystemObject) {
  'use strict';

  function K() {
    return this;
  }

  /**
   @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
    @public
  */
  var Adapter = _emberRuntimeSystemObject.default.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: K,

    /**
      This callback will be called whenever an async operation has completed.
       @public
      @method asyncEnd
    */
    asyncEnd: 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;
});
enifed('ember-testing/adapters/qunit', ['exports', 'ember-testing/adapters/adapter', 'ember-metal/utils'], function (exports, _emberTestingAdaptersAdapter, _emberMetalUtils) {
  'use strict';

  /**
    This class implements the methods defined by Ember.Test.Adapter for the
    QUnit testing framework.

    @class QUnitAdapter
    @namespace Ember.Test
    @extends Ember.Test.Adapter
    @public
  */
  exports.default = _emberTestingAdaptersAdapter.default.extend({
    asyncStart: function () {
      QUnit.stop();
    },
    asyncEnd: function () {
      QUnit.start();
    },
    exception: function (error) {
      ok(false, _emberMetalUtils.inspect(error));
    }
  });
});
enifed('ember-testing/helpers', ['exports', 'ember-metal/property_get', 'ember-metal/error', 'ember-metal/run_loop', 'ember-views/system/jquery', 'ember-testing/test', 'ember-runtime/ext/rsvp', 'ember-metal/features'], function (exports, _emberMetalProperty_get, _emberMetalError, _emberMetalRun_loop, _emberViewsSystemJquery, _emberTestingTest, _emberRuntimeExtRsvp, _emberMetalFeatures) {
  'use strict';

  /**
  @module ember
  @submodule ember-testing
  */

  var helper = _emberTestingTest.default.registerHelper;
  var asyncHelper = _emberTestingTest.default.registerAsyncHelper;

  var keyboardEventTypes, mouseEventTypes, buildKeyboardEvent, buildMouseEvent, buildBasicEvent, fireEvent, focus;

  var defaultEventOptions = { canBubble: true, cancelable: true };
  keyboardEventTypes = ['keydown', 'keypress', 'keyup'];
  mouseEventTypes = ['click', 'mousedown', 'mouseup', 'dblclick', 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', 'mouseover'];

  buildKeyboardEvent = function buildKeyboardEvent(type) {
    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

    var event = undefined;
    try {
      event = document.createEvent('KeyEvents');
      var eventOpts = _emberViewsSystemJquery.default.extend({}, defaultEventOptions, options);
      event.initKeyEvent(type, eventOpts.canBubble, eventOpts.cancelable, window, eventOpts.ctrlKey, eventOpts.altKey, eventOpts.shiftKey, eventOpts.metaKey, eventOpts.keyCode, eventOpts.charCode);
    } catch (e) {
      event = buildBasicEvent(type, options);
    }
    return event;
  };

  buildMouseEvent = function buildMouseEvent(type) {
    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

    var event = undefined;
    try {
      event = document.createEvent('MouseEvents');
      var eventOpts = _emberViewsSystemJquery.default.extend({}, defaultEventOptions, options);
      event.initMouseEvent(type, eventOpts.canBubble, eventOpts.cancelable, window, eventOpts.detail, eventOpts.screenX, eventOpts.screenY, eventOpts.clientX, eventOpts.clientY, eventOpts.ctrlKey, eventOpts.altKey, eventOpts.shiftKey, eventOpts.metaKey, eventOpts.button, eventOpts.relatedTarget);
    } catch (e) {
      event = buildBasicEvent(type, options);
    }
    return event;
  };

  buildBasicEvent = function buildBasicEvent(type) {
    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

    var event = document.createEvent('Events');
    event.initEvent(type, true, true);
    _emberViewsSystemJquery.default.extend(event, options);
    return event;
  };

  fireEvent = function fireEvent(element, type) {
    var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

    if (!element) {
      return;
    }
    var event = undefined;
    if (keyboardEventTypes.indexOf(type) > -1) {
      event = buildKeyboardEvent(type, options);
    } else if (mouseEventTypes.indexOf(type) > -1) {
      var rect = element.getBoundingClientRect();
      var x = rect.left + 1;
      var y = rect.top + 1;
      var simulatedCoordinates = {
        screenX: x + 5,
        screenY: y + 95,
        clientX: x,
        clientY: y
      };
      event = buildMouseEvent(type, _emberViewsSystemJquery.default.extend(simulatedCoordinates, options));
    } else {
      event = buildBasicEvent(type, options);
    }
    element.dispatchEvent(event);
  };

  focus = function focus(el) {
    if (!el) {
      return;
    }
    var $el = _emberViewsSystemJquery.default(el);
    if ($el.is(':input, [contenteditable=true]')) {
      var type = $el.prop('type');
      if (type !== 'checkbox' && type !== 'radio' && type !== 'hidden') {
        _emberMetalRun_loop.default(null, 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()) {
            el.focus();
          } else {
            $el.trigger('focusin');
          }
        });
      }
    }
  };

  function currentRouteName(app) {
    var routingService = app.__container__.lookup('service:-routing');

    return _emberMetalProperty_get.get(routingService, 'currentRouteName');
  }

  function currentPath(app) {
    var routingService = app.__container__.lookup('service:-routing');

    return _emberMetalProperty_get.get(routingService, 'currentPath');
  }

  function currentURL(app) {
    var router = app.__container__.lookup('router:main');

    return _emberMetalProperty_get.get(router, 'location').getURL();
  }

  function pauseTest() {
    _emberTestingTest.default.adapter.asyncStart();
    return new _emberRuntimeExtRsvp.default.Promise(function () {}, 'TestAdapter paused promise');
  }

  function visit(app, url) {
    var router = app.__container__.lookup('router:main');
    var shouldHandleURL = false;

    app.boot().then(function () {
      router.location.setURL(url);

      if (shouldHandleURL) {
        _emberMetalRun_loop.default(app.__deprecatedInstance__, 'handleURL', url);
      }
    });

    if (app._readinessDeferrals > 0) {
      router['initialURL'] = url;
      _emberMetalRun_loop.default(app, 'advanceReadiness');
      delete router['initialURL'];
    } else {
      shouldHandleURL = true;
    }

    return app.testHelpers.wait();
  }

  function click(app, selector, context) {
    var $el = app.testHelpers.findWithAssert(selector, context);
    var el = $el[0];

    _emberMetalRun_loop.default(null, fireEvent, el, 'mousedown');

    focus(el);

    _emberMetalRun_loop.default(null, fireEvent, el, 'mouseup');
    _emberMetalRun_loop.default(null, fireEvent, el, 'click');

    return app.testHelpers.wait();
  }

  function triggerEvent(app, selector, contextOrType, typeOrOptions, possibleOptions) {
    var arity = arguments.length;
    var context, type, options;

    if (arity === 3) {
      // context and options are optional, so this is
      // app, selector, type
      context = null;
      type = contextOrType;
      options = {};
    } else if (arity === 4) {
      // context and options are optional, so this is
      if (typeof typeOrOptions === 'object') {
        // either
        // app, selector, type, options
        context = null;
        type = contextOrType;
        options = typeOrOptions;
      } else {
        // or
        // app, selector, context, type
        context = contextOrType;
        type = typeOrOptions;
        options = {};
      }
    } else {
      context = contextOrType;
      type = typeOrOptions;
      options = possibleOptions;
    }

    var $el = app.testHelpers.findWithAssert(selector, context);
    var el = $el[0];

    _emberMetalRun_loop.default(null, fireEvent, el, type, options);

    return app.testHelpers.wait();
  }

  function keyEvent(app, selector, contextOrType, typeOrKeyCode, keyCode) {
    var context, type;

    if (typeof keyCode === 'undefined') {
      context = null;
      keyCode = typeOrKeyCode;
      type = contextOrType;
    } else {
      context = contextOrType;
      type = typeOrKeyCode;
    }

    return app.testHelpers.triggerEvent(selector, context, type, { keyCode: keyCode, which: keyCode });
  }

  function fillIn(app, selector, contextOrText, text) {
    var $el, el, context;
    if (typeof text === 'undefined') {
      text = contextOrText;
    } else {
      context = contextOrText;
    }
    $el = app.testHelpers.findWithAssert(selector, context);
    el = $el[0];
    focus(el);
    _emberMetalRun_loop.default(function () {
      $el.val(text);
      fireEvent(el, 'input');
      fireEvent(el, 'change');
    });
    return app.testHelpers.wait();
  }

  function findWithAssert(app, selector, context) {
    var $el = app.testHelpers.find(selector, context);
    if ($el.length === 0) {
      throw new _emberMetalError.default('Element ' + selector + ' not found.');
    }
    return $el;
  }

  function find(app, selector, context) {
    var $el;
    context = context || _emberMetalProperty_get.get(app, 'rootElement');
    $el = app.$(selector, context);

    return $el;
  }

  function andThen(app, callback) {
    return app.testHelpers.wait(callback(app));
  }

  function wait(app, value) {
    return new _emberRuntimeExtRsvp.default.Promise(function (resolve) {
      var router = app.__container__.lookup('router:main');

      // Every 10ms, poll for the async thing to have finished
      var watcher = setInterval(function () {
        // 1. If the router is loading, keep polling
        var routerIsLoading = router.router && !!router.router.activeTransition;
        if (routerIsLoading) {
          return;
        }

        // 2. If there are pending Ajax requests, keep polling
        if (_emberTestingTest.default.pendingAjaxRequests) {
          return;
        }

        // 3. If there are scheduled timers or we are inside of a run loop, keep polling
        if (_emberMetalRun_loop.default.hasScheduledTimers() || _emberMetalRun_loop.default.currentRunLoop) {
          return;
        }
        if (_emberTestingTest.default.waiters && _emberTestingTest.default.waiters.any(function (waiter) {
          var context = waiter[0];
          var callback = waiter[1];
          return !callback.call(context);
        })) {
          return;
        }
        // Stop polling
        clearInterval(watcher);

        // Synchronously resolve the promise
        _emberMetalRun_loop.default(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}
    @public
  */
  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}
    @public
  */
  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
    @public
  */
  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}
    @public
  */
  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
    @public
  */
  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
    @public
  */
  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', password)
      .click('.submit')

      return app.testHelpers.wait();
    });

    @method wait
    @param {Object} value The value to be returned.
    @return {RSVP.Promise}
    @public
  */
  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
  @public
  */
  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
  @public
  */
  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
  @public
  */
  helper('currentURL', currentURL);

  /**
   Pauses the current test - this is useful for debugging while testing or for test-driving.
   It allows you to inspect the state of your application at any point.

   Example (The test will pause before clicking the button):

   ```javascript
   visit('/')
   return pauseTest();

   click('.btn');
   ```

   @since 1.9.0
   @method pauseTest
   @return {Object} A promise that will never resolve
   @public
  */
  helper('pauseTest', pauseTest);

  /**
    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
   @public
  */
  asyncHelper('triggerEvent', triggerEvent);
});

// 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.
enifed('ember-testing/index', ['exports', '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 (exports, _emberMetalCore, _emberTestingInitializers, _emberTestingSupport, _emberTestingSetup_for_testing, _emberTestingTest, _emberTestingAdaptersAdapter, _emberTestingAdaptersQunit, _emberTestingHelpers) {
  'use strict';

  // adds helpers to helpers object in Test

  /**
    @module ember
    @submodule ember-testing
  */

  _emberMetalCore.default.Test = _emberTestingTest.default;
  _emberMetalCore.default.Test.Adapter = _emberTestingAdaptersAdapter.default;
  _emberMetalCore.default.Test.QUnitAdapter = _emberTestingAdaptersQunit.default;
  _emberMetalCore.default.setupForTesting = _emberTestingSetup_for_testing.default;
});
// to setup initializer
// to handle various edge cases
enifed('ember-testing/initializers', ['exports', 'ember-runtime/system/lazy_load'], function (exports, _emberRuntimeSystemLazy_load) {
  'use strict';

  var name = 'deferReadiness in `testing` mode';

  _emberRuntimeSystemLazy_load.onLoad('Ember.Application', function (Application) {
    if (!Application.initializers[name]) {
      Application.initializer({
        name: name,

        initialize: function (application) {
          if (application.testing) {
            application.deferReadiness();
          }
        }
      });
    }
  });
});
enifed('ember-testing/setup_for_testing', ['exports', 'ember-metal/core', 'ember-testing/adapters/qunit', 'ember-views/system/jquery'], function (exports, _emberMetalCore, _emberTestingAdaptersQunit, _emberViewsSystemJquery) {
  'use strict';

  exports.default = setupForTesting;

  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
    @private
  */

  function setupForTesting() {
    if (!Test) {
      Test = requireModule('ember-testing/test')['default'];
    }

    _emberMetalCore.default.testing = true;

    // if adapter is not manually set default to QUnit
    if (!Test.adapter) {
      Test.adapter = _emberTestingAdaptersQunit.default.create();
    }

    requests = [];
    Test.pendingAjaxRequests = requests.length;

    _emberViewsSystemJquery.default(document).off('ajaxSend', incrementAjaxPendingRequests);
    _emberViewsSystemJquery.default(document).off('ajaxComplete', decrementAjaxPendingRequests);
    _emberViewsSystemJquery.default(document).on('ajaxSend', incrementAjaxPendingRequests);
    _emberViewsSystemJquery.default(document).on('ajaxComplete', decrementAjaxPendingRequests);
  }
});

// import Test from "ember-testing/test";  // ES6TODO: fix when cycles are supported
enifed('ember-testing/support', ['exports', 'ember-metal/debug', 'ember-views/system/jquery', 'ember-metal/environment'], function (exports, _emberMetalDebug, _emberViewsSystemJquery, _emberMetalEnvironment) {
  'use strict';

  /**
    @module ember
    @submodule ember-testing
  */

  var $ = _emberViewsSystemJquery.default;

  /**
    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();
  }

  if (_emberMetalEnvironment.default.hasDOM) {
    $(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 () {
        _emberMetalDebug.warn('clicked checkboxes should be checked! the jQuery patch didn\'t work', this.checked, { id: 'ember-testing.test-checkbox-click' });
      });
    });
  }
});
enifed('ember-testing/test', ['exports', 'ember-metal/run_loop', 'ember-runtime/ext/rsvp', 'ember-testing/setup_for_testing', 'ember-application/system/application', 'ember-runtime/system/native_array'], function (exports, _emberMetalRun_loop, _emberRuntimeExtRsvp, _emberTestingSetup_for_testing, _emberApplicationSystemApplication, _emberRuntimeSystemNative_array) {
  'use strict';

  /**
    @module ember
    @submodule ember-testing
  */
  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
    @public
  */
  var Test = {
    /**
      Hash containing all known test helpers.
       @property _helpers
      @private
      @since 1.7.0
    */
    _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.
      @param {String} label An optional string for identifying the promise.
    */
    promise: function (resolver, label) {
      var fullLabel = 'Ember.Test.promise: ' + (label || '<Unknown Promise>');
      return new Test.Promise(resolver, fullLabel);
    },

    /**
     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 = _emberRuntimeSystemNative_array.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) {
      if (!this.waiters) {
        return;
      }
      if (arguments.length === 1) {
        callback = context;
        context = null;
      }
      this.waiters = _emberRuntimeSystemNative_array.A(this.waiters.filter(function (elt) {
        return !(elt[0] === context && elt[1] === callback);
      }));
    }
  };

  function helper(app, name) {
    var fn = helpers[name].method;
    var meta = helpers[name].meta;

    return function () {
      for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
        args[_key] = arguments[_key];
      }

      var 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);
      }

      lastPromise = run(function () {
        return Test.resolve(Test.lastPromise);
      });

      // wait for last helper's promise to resolve and then
      // execute. To be safe, we need to tell the adapter we're going
      // asynchronous here, because fn may not be invoked before we
      // return.
      Test.adapter.asyncStart();
      return lastPromise.then(function () {
        return fn.apply(app, args);
      }).finally(function () {
        Test.adapter.asyncEnd();
      });
    };
  }

  function run(fn) {
    if (!_emberMetalRun_loop.default.currentRunLoop) {
      return _emberMetalRun_loop.default(fn);
    } else {
      return fn();
    }
  }

  _emberApplicationSystemApplication.default.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 {}
      @public
    */
    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
    @public
    */
    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
      @public
    */
    setupForTesting: function () {
      _emberTestingSetup_for_testing.default();

      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
      @private
    */
    helperContainer: null,

    /**
      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
      @public
    */
    injectTestHelpers: function (helperContainer) {
      if (helperContainer) {
        this.helperContainer = helperContainer;
      } else {
        this.helperContainer = window;
      }

      this.reopen({
        willDestroy: function () {
          this._super.apply(this, arguments);
          this.removeTestHelpers();
        }
      });

      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 () {
      if (!this.helperContainer) {
        return;
      }

      for (var name in helpers) {
        this.helperContainer[name] = this.originalMethods[name];
        delete Test.Promise.prototype[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 () {
      for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }

      if (isAsync) {
        return callback.apply(this, args);
      } else {
        return this.then(function () {
          return callback.apply(this, args);
        });
      }
    };
  }

  Test.Promise = function () {
    _emberRuntimeExtRsvp.default.Promise.apply(this, arguments);
    Test.lastPromise = this;
  };

  Test.Promise.prototype = Object.create(_emberRuntimeExtRsvp.default.Promise.prototype);
  Test.Promise.prototype.constructor = Test.Promise;
  Test.Promise.resolve = Test.resolve;

  // Patch `then` to isolate async methods
  // specifically `Ember.Test.lastPromise`
  var originalThen = _emberRuntimeExtRsvp.default.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
  function isolate(fn, val) {
    var value, lastPromise;

    // Reset lastPromise for nested helpers
    Test.lastPromise = null;

    value = fn(val);

    lastPromise = Test.lastPromise;
    Test.lastPromise = null;

    // 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 {
      return run(function () {
        return Test.resolve(lastPromise).then(function () {
          return value;
        });
      });
    }
  }

  exports.default = Test;
});
enifed('ember-views/compat/attrs-proxy', ['exports', 'ember-metal/mixin', 'ember-metal/symbol', 'ember-metal/property_events'], function (exports, _emberMetalMixin, _emberMetalSymbol, _emberMetalProperty_events) {
  'use strict';

  exports.deprecation = deprecation;

  function deprecation(key) {
    return 'You tried to look up an attribute directly on the component. This is deprecated. Use attrs.' + key + ' instead.';
  }

  var MUTABLE_CELL = _emberMetalSymbol.default('MUTABLE_CELL');

  exports.MUTABLE_CELL = MUTABLE_CELL;
  function isCell(val) {
    return val && val[MUTABLE_CELL];
  }

  var AttrsProxyMixin = {
    attrs: null,

    getAttr: function (key) {
      var attrs = this.attrs;
      if (!attrs) {
        return;
      }
      return this.getAttrFor(attrs, key);
    },

    getAttrFor: function (attrs, key) {
      var val = attrs[key];
      return isCell(val) ? val.value : val;
    },

    setAttr: function (key, value) {
      var attrs = this.attrs;
      var val = attrs[key];

      if (!isCell(val)) {
        throw new Error('You can\'t update attrs.' + key + ', because it\'s not mutable');
      }

      val.update(value);
    },

    _propagateAttrsToThis: function (attrs) {
      this._isDispatchingAttrs = true;
      this.setProperties(attrs);
      this._isDispatchingAttrs = false;
    }
  };

  AttrsProxyMixin[_emberMetalProperty_events.PROPERTY_DID_CHANGE] = function (key) {
    if (this._isAngleBracket) {
      return;
    }
    if (this._isDispatchingAttrs) {
      return;
    }

    if (this._currentState) {
      this._currentState.legacyPropertyDidChange(this, key);
    }
  };

  exports.default = _emberMetalMixin.Mixin.create(AttrsProxyMixin);
});
enifed('ember-views/component_lookup', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-runtime/system/object', 'ember-htmlbars/system/lookup-helper', 'container/owner'], function (exports, _emberMetalCore, _emberMetalDebug, _emberRuntimeSystemObject, _emberHtmlbarsSystemLookupHelper, _containerOwner) {
  'use strict';

  exports.default = _emberRuntimeSystemObject.default.extend({
    invalidName: function (name) {
      if (!_emberHtmlbarsSystemLookupHelper.CONTAINS_DASH_CACHE.get(name)) {
        _emberMetalDebug.assert('You cannot use \'' + name + '\' as a component name. Component names must contain a hyphen.');
        return true;
      }
    },

    lookupFactory: function (name, owner) {
      owner = owner || _containerOwner.getOwner(this);

      var fullName = 'component:' + name;
      var templateFullName = 'template:components/' + name;
      var templateRegistered = owner && owner.hasRegistration(templateFullName);

      if (templateRegistered) {
        owner.inject(fullName, 'layout', templateFullName);
      }

      var Component = owner._lookupFactory(fullName);

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

    componentFor: function (name, owner, options) {
      if (this.invalidName(name)) {
        return;
      }

      var fullName = 'component:' + name;
      return owner._lookupFactory(fullName, options);
    },

    layoutFor: function (name, owner, options) {
      if (this.invalidName(name)) {
        return;
      }

      var templateFullName = 'template:components/' + name;
      return owner.lookup(templateFullName, options);
    }
  });
});
enifed('ember-views/components/component', ['exports', 'ember-metal/debug', 'ember-metal/environment', 'ember-runtime/mixins/target_action_support', 'ember-views/views/view', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/is_none', 'ember-metal/utils', 'ember-metal/computed', 'ember-views/compat/attrs-proxy', 'container/owner'], function (exports, _emberMetalDebug, _emberMetalEnvironment, _emberRuntimeMixinsTarget_action_support, _emberViewsViewsView, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalIs_none, _emberMetalUtils, _emberMetalComputed, _emberViewsCompatAttrsProxy, _containerOwner) {
  'use strict';

  function validateAction(component, actionName) {
    if (actionName && actionName[_emberViewsCompatAttrsProxy.MUTABLE_CELL]) {
      actionName = actionName.value;
    }
    _emberMetalDebug.assert('The default action was triggered on the component ' + component.toString() + ', but the action name (' + actionName + ') was not a string.', _emberMetalIs_none.default(actionName) || typeof actionName === 'string' || typeof actionName === 'function');
    return actionName;
  }

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

  /**
    An `Ember.Component` is a view that is completely
    isolated. Properties accessed 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 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 component's 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
    @uses Ember.ViewTargetActionSupport
    @public
  */
  var Component = _emberViewsViewsView.default.extend(_emberRuntimeMixinsTarget_action_support.default, {
    isComponent: true,
    /*
      This is set so that the proto inspection in appendTemplatedView does not
      think that it should set the component's `context` to that of the parent view.
    */
    controller: null,
    context: null,

    instrumentName: 'component',
    instrumentDisplay: _emberMetalComputed.computed(function () {
      if (this._debugContainerKey) {
        return '{{' + this._debugContainerKey.split(':')[1] + '}}';
      }
    }),

    init: function () {
      var _this = this;

      this._super.apply(this, arguments);
      _emberMetalProperty_set.set(this, 'controller', this);
      _emberMetalProperty_set.set(this, 'context', this);

      if (!this.layout && this.layoutName && _containerOwner.getOwner(this)) {
        var layoutName = _emberMetalProperty_get.get(this, 'layoutName');

        this.layout = this.templateForName(layoutName);
      }

      // If a `defaultLayout` was specified move it to the `layout` prop.
      // `layout` is no longer a CP, so this just ensures that the `defaultLayout`
      // logic is supported with a deprecation
      if (this.defaultLayout && !this.layout) {
        _emberMetalDebug.deprecate('Specifying `defaultLayout` to ' + this + ' is deprecated. Please use `layout` instead.', false, {
          id: 'ember-views.component.defaultLayout',
          until: '3.0.0',
          url: 'http://emberjs.com/deprecations/v2.x/#toc_ember-component-defaultlayout'
        });

        this.layout = this.defaultLayout;
      }

      // If in a tagless component, assert that no event handlers are defined
      _emberMetalDebug.assert('You can not define a function that handles DOM events in the `' + this + '` tagless component since it doesn\'t have any DOM element.', this.tagName !== '' || !_emberMetalEnvironment.default.hasDOM || !(function () {
        var eventDispatcher = _containerOwner.getOwner(_this).lookup('event_dispatcher:main');
        var events = eventDispatcher && eventDispatcher._finalEvents || {};

        for (var key in events) {
          var methodName = events[key];

          if (typeof _this[methodName] === 'function') {
            return true; // indicate that the assertion should be triggered
          }
        }
      })());
    },

    template: null,
    layoutName: null,
    layout: null,

    /**
      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
      @private
    */
    targetObject: _emberMetalComputed.computed('controller', function (key) {
      if (this._targetObject) {
        return this._targetObject;
      }
      if (this._controller) {
        return this._controller;
      }
      var parentView = _emberMetalProperty_get.get(this, 'parentView');
      return parentView ? _emberMetalProperty_get.get(parentView, 'controller') : null;
    }),

    /**
      Calls an action passed to a component.
       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/components/play-button.js
      export default Ember.Component.extend({
        click() {
          if (this.get('isPlaying')) {
            this.sendAction('play');
          } else {
            this.sendAction('stop');
          }
        }
      });
      ```
       The actions "play" and "stop" must be passed to this `play-button` component:
       ```handlebars
      {{! app/templates/application.hbs }}
      {{play-button play=(action "musicStarted") stop=(action "musicStopped")}}
      ```
       When the component receives a browser `click` event it translate this
      interaction into application-specific semantics ("play" or "stop") and
      calls the specified action.
       ```javascript
      // app/controller/application.js
      export default Ember.Controller.extend({
        actions: {
          musicStarted() {
            // called when the play button is clicked
            // and the music started playing
          },
          musicStopped() {
            // called when the play button is clicked
            // and the music stopped playing
          }
        }
      });
      ```
       If no action is passed to `sendAction` a default name of "action"
      is assumed.
       ```javascript
      // app/components/next-button.js
      export default Ember.Component.extend({
        click() {
          this.sendAction();
        }
      });
      ```
       ```handlebars
      {{! app/templates/application.hbs }}
      {{next-button action=(action "playNextSongInAlbum")}}
      ```
       ```javascript
      // app/controllers/application.js
      App.ApplicationController = Ember.Controller.extend({
        actions: {
          playNextSongInAlbum() {
            ...
          }
        }
      });
      ```
       @method sendAction
      @param [action] {String} the action to call
      @param [params] {*} arguments for the action
      @public
    */
    sendAction: function (action) {
      for (var _len = arguments.length, contexts = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
        contexts[_key - 1] = arguments[_key];
      }

      var actionName;

      // Send the default action
      if (action === undefined) {
        action = 'action';
      }
      actionName = _emberMetalProperty_get.get(this, 'attrs.' + action) || _emberMetalProperty_get.get(this, action);
      actionName = validateAction(this, actionName);

      // If no action name for that action could be found, just abort.
      if (actionName === undefined) {
        return;
      }

      if (typeof actionName === 'function') {
        actionName.apply(undefined, contexts);
      } else {
        this.triggerAction({
          action: actionName,
          actionContext: contexts
        });
      }
    },

    send: function (actionName) {
      for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
        args[_key2 - 1] = arguments[_key2];
      }

      var target;
      var action = this.actions && this.actions[actionName];

      if (action) {
        var shouldBubble = action.apply(this, args) === true;
        if (!shouldBubble) {
          return;
        }
      }

      if (target = _emberMetalProperty_get.get(this, 'target')) {
        var _target;

        _emberMetalDebug.assert('The `target` for ' + this + ' (' + target + ') does not have a `send` method', typeof target.send === 'function');
        (_target = target).send.apply(_target, arguments);
      } else {
        if (!action) {
          throw new Error(_emberMetalUtils.inspect(this) + ' had no action handler for: ' + actionName);
        }
      }
    }

    /**
      Returns true when the component was invoked with a block template.
       Example (`hasBlock` will be `false`):
       ```hbs
      {{! templates/application.hbs }}
       {{foo-bar}}
       {{! templates/components/foo-bar.hbs }}
      {{#if hasBlock}}
        This will not be printed, because no block was provided
      {{/if}}
      ```
       Example (`hasBlock` will be `true`):
       ```hbs
      {{! templates/application.hbs }}
       {{#foo-bar}}
        Hi!
      {{/foo-bar}}
       {{! templates/components/foo-bar.hbs }}
      {{#if hasBlock}}
        This will be printed because a block was provided
        {{yield}}
      {{/if}}
      ```
       This helper accepts an argument with the name of the block we want to check the presence of.
      This is useful for checking for the presence of the optional inverse block in components.
       ```hbs
      {{! templates/application.hbs }}
       {{#foo-bar}}
        Hi!
      {{else}}
        What's up?
      {{/foo-bar}}
       {{! templates/components/foo-bar.hbs }}
      {{yield}}
      {{#if (hasBlock "inverse")}}
        {{yield to="inverse"}}
      {{else}}
        How are you?
      {{/if}}
      ```
       @public
      @property hasBlock
      @param {String} [blockName="default"] The name of the block to check presence of.
      @returns Boolean
      @since 1.13.0
    */

    /**
      Returns true when the component was invoked with a block parameter
      supplied.
       Example (`hasBlockParams` will be `false`):
       ```hbs
      {{! templates/application.hbs }}
       {{#foo-bar}}
        No block parameter.
      {{/foo-bar}}
       {{! templates/components/foo-bar.hbs }}
      {{#if hasBlockParams}}
        This will not be printed, because no block was provided
        {{yield this}}
      {{/if}}
      ```
       Example (`hasBlockParams` will be `true`):
       ```hbs
      {{! templates/application.hbs }}
       {{#foo-bar as |foo|}}
        Hi!
      {{/foo-bar}}
       {{! templates/components/foo-bar.hbs }}
      {{#if hasBlockParams}}
        This will be printed because a block was provided
        {{yield this}}
      {{/if}}
      ```
      @public
      @property hasBlockParams
      @returns Boolean
      @since 1.13.0
    */

    /**
      Enables components to take a list of parameters as arguments
       For example a component that takes two parameters with the names
      `name` and `age`:
       ```javascript
      let MyComponent = Ember.Component.extend;
      MyComponent.reopenClass({
        positionalParams: ['name', 'age']
      });
      ```
       It can then be invoked like this:
       ```hbs
      {{my-component "John" 38}}
      ```
       The parameters can be refered to just like named parameters:
       ```hbs
      Name: {{attrs.name}}, Age: {{attrs.age}}.
      ```
       Using a string instead of an array allows for an arbitrary number of
      parameters:
       ```javascript
      let MyComponent = Ember.Component.extend;
      MyComponent.reopenClass({
        positionalParams: 'names'
      });
      ```
       It can then be invoked like this:
       ```hbs
      {{my-component "John" "Michael" "Scott"}}
      ```
       The parameters can then be refered to by enumerating over the list:
       ```hbs
      {{#each attrs.names as |name|}}{{name}}{{/each}}
      ```
       @static
      @public
      @property positionalParams
      @since 1.13.0
    */

    /**
      Called when the attributes passed into the component have been updated.
      Called both during the initial render of a container and during a rerender.
      Can be used in place of an observer; code placed here will be executed
      every time any attribute updates.
       @method didReceiveAttrs
      @public
      @since 1.13.0
    */

    /**
      Called when the attributes passed into the component have been updated.
      Called both during the initial render of a container and during a rerender.
      Can be used in place of an observer; code placed here will be executed
      every time any attribute updates.
       @event didReceiveAttrs
      @public
      @since 1.13.0
    */

    /**
      Called after a component has been rendered, both on initial render and
      in subsequent rerenders.
       @method didRender
      @public
      @since 1.13.0
    */

    /**
      Called after a component has been rendered, both on initial render and
      in subsequent rerenders.
       @event didRender
      @public
      @since 1.13.0
    */

    /**
      Called before a component has been rendered, both on initial render and
      in subsequent rerenders.
       @method willRender
      @public
      @since 1.13.0
    */

    /**
      Called before a component has been rendered, both on initial render and
      in subsequent rerenders.
       @event willRender
      @public
      @since 1.13.0
    */

    /**
      Called when the attributes passed into the component have been changed.
      Called only during a rerender, not during an initial render.
       @method didUpdateAttrs
      @public
      @since 1.13.0
    */

    /**
      Called when the attributes passed into the component have been changed.
      Called only during a rerender, not during an initial render.
       @event didUpdateAttrs
      @public
      @since 1.13.0
    */

    /**
      Called when the component is about to update and rerender itself.
      Called only during a rerender, not during an initial render.
       @method willUpdate
      @public
      @since 1.13.0
    */

    /**
      Called when the component is about to update and rerender itself.
      Called only during a rerender, not during an initial render.
       @event willUpdate
      @public
      @since 1.13.0
    */

    /**
      Called when the component has updated and rerendered itself.
      Called only during a rerender, not during an initial render.
       @event didUpdate
      @public
      @since 1.13.0
    */

    /**
      Called when the component has updated and rerendered itself.
      Called only during a rerender, not during an initial render.
       @event didUpdate
      @public
      @since 1.13.0
    */
  });

  Component.reopenClass({
    isComponentFactory: true
  });

  exports.default = Component;
});
enifed('ember-views/index', ['exports', 'ember-runtime', 'ember-views/system/jquery', 'ember-views/system/utils', 'ember-views/system/ext', 'ember-metal-views', 'ember-views/components/component', 'ember-views/system/event_dispatcher', 'ember-views/mixins/view_target_action_support', 'ember-views/component_lookup', 'ember-views/views/checkbox', 'ember-views/mixins/text_support', 'ember-views/views/text_field', 'ember-views/views/text_area'], function (exports, _emberRuntime, _emberViewsSystemJquery, _emberViewsSystemUtils, _emberViewsSystemExt, _emberMetalViews, _emberViewsComponentsComponent, _emberViewsSystemEvent_dispatcher, _emberViewsMixinsView_target_action_support, _emberViewsComponent_lookup, _emberViewsViewsCheckbox, _emberViewsMixinsText_support, _emberViewsViewsText_field, _emberViewsViewsText_area) {
  /**
  @module ember
  @submodule ember-views
  */

  // BEGIN IMPORTS
  'use strict';

  // END IMPORTS

  /**
    Alias for jQuery

    @method $
    @for Ember
   @public
  */

  // BEGIN EXPORTS
  _emberRuntime.default.$ = _emberViewsSystemJquery.default;

  _emberRuntime.default.ViewTargetActionSupport = _emberViewsMixinsView_target_action_support.default;

  var ViewUtils = _emberRuntime.default.ViewUtils = {};
  ViewUtils.isSimpleClick = _emberViewsSystemUtils.isSimpleClick;
  ViewUtils.getViewClientRects = _emberViewsSystemUtils.getViewClientRects;
  ViewUtils.getViewBoundingClientRect = _emberViewsSystemUtils.getViewBoundingClientRect;

  _emberRuntime.default._Renderer = _emberMetalViews.Renderer;

  _emberRuntime.default.Checkbox = _emberViewsViewsCheckbox.default;
  _emberRuntime.default.TextField = _emberViewsViewsText_field.default;
  _emberRuntime.default.TextArea = _emberViewsViewsText_area.default;

  _emberRuntime.default.TextSupport = _emberViewsMixinsText_support.default;
  _emberRuntime.default.ComponentLookup = _emberViewsComponent_lookup.default;
  _emberRuntime.default.Component = _emberViewsComponentsComponent.default;
  _emberRuntime.default.EventDispatcher = _emberViewsSystemEvent_dispatcher.default;

  // END EXPORTS

  exports.default = _emberRuntime.default;
});
// for the side effect of extending Ember.run.queues
enifed('ember-views/mixins/aria_role_support', ['exports', 'ember-metal/mixin'], function (exports, _emberMetalMixin) {
  /**
   @module ember
   @submodule ember-views
  */

  'use strict';

  /**
   @class AriaRoleSupport
   @namespace Ember
   @private
  */
  exports.default = _emberMetalMixin.Mixin.create({
    attributeBindings: ['ariaRole:role'],

    /**
     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
     @public
    */
    ariaRole: null
  });
});
enifed('ember-views/mixins/class_names_support', ['exports', 'ember-metal/debug', 'ember-metal/mixin', 'ember-runtime/system/native_array'], function (exports, _emberMetalDebug, _emberMetalMixin, _emberRuntimeSystemNative_array) {
  /**
  @module ember
  @submodule ember-views
  */
  'use strict';

  var EMPTY_ARRAY = [];

  /**
    @class ClassNamesSupport
    @namespace Ember
    @private
  */
  exports.default = _emberMetalMixin.Mixin.create({
    concatenatedProperties: ['classNames', 'classNameBindings'],

    init: function () {
      this._super.apply(this, arguments);

      _emberMetalDebug.assert('Only arrays are allowed for \'classNameBindings\'', Array.isArray(this.classNameBindings));
      this.classNameBindings = _emberRuntimeSystemNative_array.A(this.classNameBindings.slice());

      _emberMetalDebug.assert('Only arrays of static class strings are allowed for \'classNames\'. For dynamic classes, use \'classNameBindings\'.', Array.isArray(this.classNames));
      this.classNames = _emberRuntimeSystemNative_array.A(this.classNames.slice());
    },

    /**
      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']
      @public
    */
    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 []
      @public
    */
    classNameBindings: EMPTY_ARRAY
  });
});
enifed('ember-views/mixins/instrumentation_support', ['exports', 'ember-metal/mixin', 'ember-metal/property_get'], function (exports, _emberMetalMixin, _emberMetalProperty_get) {
  /**
  @module ember
  @submodule ember-views
  */
  'use strict';

  /**
    @class InstrumentationSupport
    @namespace Ember
    @public
  */
  var InstrumentationSupport = _emberMetalMixin.Mixin.create({
    /**
      Used to identify this view during debugging
       @property instrumentDisplay
      @type String
      @public
    */
    instrumentDisplay: '',

    instrumentName: 'view',

    instrumentDetails: function (hash) {
      hash.template = _emberMetalProperty_get.get(this, 'templateName');
      this._super(hash);
    }
  });

  exports.default = InstrumentationSupport;
});
enifed('ember-views/mixins/legacy_child_views_support', ['exports', 'ember-metal/mixin', 'ember-metal/property_get', 'ember-metal/property_set', 'container/owner'], function (exports, _emberMetalMixin, _emberMetalProperty_get, _emberMetalProperty_set, _containerOwner) {
  'use strict';

  exports.default = _emberMetalMixin.Mixin.create({
    linkChild: function (instance) {
      if (!instance[_containerOwner.OWNER]) {
        _containerOwner.setOwner(instance, _containerOwner.getOwner(this));
      }

      if (_emberMetalProperty_get.get(instance, 'parentView') !== this) {
        // linkChild should be idempotent
        _emberMetalProperty_set.set(instance, 'parentView', this);
        instance.trigger('parentViewDidChange');
      }
      instance.ownerView = this.ownerView;
    },

    unlinkChild: function (instance) {
      _emberMetalProperty_set.set(instance, 'parentView', null);
      instance.trigger('parentViewDidChange');
    }
  });
});
enifed('ember-views/mixins/legacy_view_support', ['exports', 'ember-metal/debug', 'ember-metal/mixin', 'ember-metal/property_get'], function (exports, _emberMetalDebug, _emberMetalMixin, _emberMetalProperty_get) {
  /**
  @module ember
  @submodule ember-views
  */
  'use strict';

  /**
    @class LegacyViewSupport
    @namespace Ember
    @private
  */
  var LegacyViewSupport = _emberMetalMixin.Mixin.create({
    mutateChildViews: function (callback) {
      var childViews = _emberMetalProperty_get.get(this, 'childViews');
      var idx = childViews.length;
      var view;

      while (--idx >= 0) {
        view = childViews[idx];
        callback(this, view, idx);
      }

      return this;
    },

    /**
      Removes all children from the `parentView`.
       @method removeAllChildren
      @return {Ember.View} receiver
      @private
    */
    removeAllChildren: function () {
      return this.mutateChildViews(function (parentView, view) {
        parentView.removeChild(view);
      });
    },

    destroyAllChildren: function () {
      return this.mutateChildViews(function (parentView, view) {
        view.destroy();
      });
    },

    /**
      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
      @deprecated
      @private
    */
    nearestChildOf: function (klass) {
      _emberMetalDebug.deprecate('nearestChildOf has been deprecated.', false, { id: 'ember-views.nearest-child-of', until: '3.0.0' });

      var view = _emberMetalProperty_get.get(this, 'parentView');

      while (view) {
        if (_emberMetalProperty_get.get(view, 'parentView') instanceof klass) {
          return view;
        }
        view = _emberMetalProperty_get.get(view, 'parentView');
      }
    },

    /**
      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
      @private
    */
    nearestInstanceOf: function (klass) {
      _emberMetalDebug.deprecate('nearestInstanceOf is deprecated and will be removed from future releases. Use nearestOfType.', false, { id: 'ember-views.nearest-instance-of', until: '3.0.0' });

      var view = _emberMetalProperty_get.get(this, 'parentView');

      while (view) {
        if (view instanceof klass) {
          return view;
        }
        view = _emberMetalProperty_get.get(view, 'parentView');
      }
    },

    /**
      If a value that affects template rendering changes, the view should be
      re-rendered to reflect the new value.
       @method _contextDidChange
      @private
      @private
    */
    _contextDidChange: _emberMetalMixin.observer('context', function () {
      this.rerender();
    })
  });

  exports.default = LegacyViewSupport;
});
enifed('ember-views/mixins/template_rendering_support', ['exports', 'ember-metal/mixin'], function (exports, _emberMetalMixin) {
  /**
  @module ember
  @submodule ember-views
  */
  'use strict';

  // Circular dep
  var _renderView;

  /**
    @class TemplateRenderingSupport
    @namespace Ember
    @private
  */
  var TemplateRenderingSupport = _emberMetalMixin.Mixin.create({
    /**
      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 renderBlock
      @param {Ember.RenderBuffer} buffer The render buffer
      @private
    */

    renderBlock: function (block, renderNode) {
      if (_renderView === undefined) {
        _renderView = require('ember-htmlbars/system/render-view');
      }

      return _renderView.renderHTMLBarsBlock(this, block, renderNode);
    }
  });

  exports.default = TemplateRenderingSupport;
});
enifed('ember-views/mixins/text_support', ['exports', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/mixin', 'ember-runtime/mixins/target_action_support'], function (exports, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalMixin, _emberRuntimeMixinsTarget_action_support) {
  /**
  @module ember
  @submodule ember-views
  */

  'use strict';

  var KEY_EVENTS = {
    13: 'insertNewline',
    27: 'cancel'
  };

  /**
    `TextSupport` is a shared mixin used by both `Ember.TextField` and
    `Ember.TextArea`. `TextSupport` adds a number of methods that allow you to
    specify a controller action to invoke when a certain event is fired on your
    text field or textarea. The specifed controller action would get the current
    value of the field passed in as the only argument unless the value of
    the field is empty. In that case, the instance of the field itself is passed
    in as the only argument.

    Let's use the pressing of the escape key as an example. If you wanted to
    invoke a controller action when a user presses the escape key while on your
    field, you would use the `escape-press` attribute on your field like so:

    ```handlebars
      {{! application.hbs}}

      {{input escape-press='alertUser'}}
    ```

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

        App.ApplicationController = Ember.Controller.extend({
          actions: {
            alertUser: function ( currentValue ) {
              alert( 'escape pressed, current value: ' + currentValue );
            }
          }
        });
    ```

    The following chart is a visual representation of what takes place when the
    escape key is pressed in this scenario:

    ```
    The Template
    +---------------------------+
    |                           |
    | escape-press='alertUser'  |
    |                           |          TextSupport Mixin
    +----+----------------------+          +-------------------------------+
         |                                 | cancel method                 |
         |      escape button pressed      |                               |
         +-------------------------------> | checks for the `escape-press` |
                                           | attribute and pulls out the   |
         +-------------------------------+ | `alertUser` value             |
         |     action name 'alertUser'     +-------------------------------+
         |     sent to controller
         v
    Controller
    +------------------------------------------ +
    |                                           |
    |  actions: {                               |
    |     alertUser: function( currentValue ){  |
    |       alert( 'the esc key was pressed!' ) |
    |     }                                     |
    |  }                                        |
    |                                           |
    +-------------------------------------------+
    ```

    Here are the events that we currently support along with the name of the
    attribute you would need to use on your field. To reiterate, you would use the
    attribute name like so:

    ```handlebars
      {{input attribute-name='controllerAction'}}
    ```

    ```
    +--------------------+----------------+
    |                    |                |
    | event              | attribute name |
    +--------------------+----------------+
    | new line inserted  | insert-newline |
    |                    |                |
    | enter key pressed  | insert-newline |
    |                    |                |
    | cancel key pressed | escape-press   |
    |                    |                |
    | focusin            | focus-in       |
    |                    |                |
    | focusout           | focus-out      |
    |                    |                |
    | keypress           | key-press      |
    |                    |                |
    | keyup              | key-up         |
    |                    |                |
    | keydown            | key-down       |
    +--------------------+----------------+
    ```

    @class TextSupport
    @namespace Ember
    @uses Ember.TargetActionSupport
    @extends Ember.Mixin
    @private
  */
  var TextSupport = _emberMetalMixin.Mixin.create(_emberRuntimeMixinsTarget_action_support.default, {
    value: '',

    attributeBindings: ['autocapitalize', 'autocorrect', 'autofocus', 'disabled', 'form', 'maxlength', 'placeholder', 'readonly', 'required', 'selectionDirection', 'spellcheck', 'tabindex', 'title'],
    placeholder: null,
    disabled: false,
    maxlength: null,

    init: function () {
      this._super.apply(this, arguments);
      this.on('paste', this, this._elementValueDidChange);
      this.on('cut', this, this._elementValueDidChange);
      this.on('input', this, this._elementValueDidChange);
    },

    /**
      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
      @private
    */
    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
      @private
    */
    onEvent: 'enter',

    /**
      Whether the `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
      @private
    */
    bubbles: false,

    interpretKeyEvents: function (event) {
      var map = KEY_EVENTS;
      var method = map[event.keyCode];

      this._elementValueDidChange();
      if (method) {
        return this[method](event);
      }
    },

    _elementValueDidChange: function () {
      // Using readDOMAttr will ensure that HTMLBars knows the last
      // value.
      _emberMetalProperty_set.set(this, 'value', this.readDOMAttr('value'));
    },

    change: function (event) {
      this._elementValueDidChange(event);
    },

    /**
      Allows you to specify a controller action to invoke when either the `enter`
      key is pressed or, in the case of the field being a textarea, when a newline
      is inserted. To use this method, give your field an `insert-newline`
      attribute. The value of that attribute should be the name of the action
      in your controller that you wish to invoke.
       For an example on how to use the `insert-newline` attribute, please
      reference the example near the top of this file.
       @method insertNewline
      @param {Event} event
      @private
    */
    insertNewline: function (event) {
      sendAction('enter', this, event);
      sendAction('insert-newline', this, event);
    },

    /**
      Allows you to specify a controller action to invoke when the escape button
      is pressed. To use this method, give your field an `escape-press`
      attribute. The value of that attribute should be the name of the action
      in your controller that you wish to invoke.
       For an example on how to use the `escape-press` attribute, please reference
      the example near the top of this file.
       @method cancel
      @param {Event} event
      @private
    */
    cancel: function (event) {
      sendAction('escape-press', this, event);
    },

    /**
      Allows you to specify a controller action to invoke when a field receives
      focus. To use this method, give your field a `focus-in` attribute. The value
      of that attribute should be the name of the action in your controller
      that you wish to invoke.
       For an example on how to use the `focus-in` attribute, please reference the
      example near the top of this file.
       @method focusIn
      @param {Event} event
      @private
    */
    focusIn: function (event) {
      sendAction('focus-in', this, event);
    },

    /**
      Allows you to specify a controller action to invoke when a field loses
      focus. To use this method, give your field a `focus-out` attribute. The value
      of that attribute should be the name of the action in your controller
      that you wish to invoke.
       For an example on how to use the `focus-out` attribute, please reference the
      example near the top of this file.
       @method focusOut
      @param {Event} event
      @private
    */
    focusOut: function (event) {
      this._elementValueDidChange(event);
      sendAction('focus-out', this, event);
    },

    /**
      Allows you to specify a controller action to invoke when a key is pressed.
      To use this method, give your field a `key-press` attribute. The value of
      that attribute should be the name of the action in your controller you
      that wish to invoke.
       For an example on how to use the `key-press` attribute, please reference the
      example near the top of this file.
       @method keyPress
      @param {Event} event
      @private
    */
    keyPress: function (event) {
      sendAction('key-press', this, event);
    },

    /**
      Allows you to specify a controller action to invoke when a key-up event is
      fired. To use this method, give your field a `key-up` attribute. The value
      of that attribute should be the name of the action in your controller
      that you wish to invoke.
       For an example on how to use the `key-up` attribute, please reference the
      example near the top of this file.
       @method keyUp
      @param {Event} event
      @private
    */
    keyUp: function (event) {
      this.interpretKeyEvents(event);

      this.sendAction('key-up', _emberMetalProperty_get.get(this, 'value'), event);
    },

    /**
      Allows you to specify a controller action to invoke when a key-down event is
      fired. To use this method, give your field a `key-down` attribute. The value
      of that attribute should be the name of the action in your controller that
      you wish to invoke.
       For an example on how to use the `key-down` attribute, please reference the
      example near the top of this file.
       @method keyDown
      @param {Event} event
      @private
    */
    keyDown: function (event) {
      this.sendAction('key-down', _emberMetalProperty_get.get(this, 'value'), event);
    }
  });

  // 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 = _emberMetalProperty_get.get(view, 'attrs.' + eventName) || _emberMetalProperty_get.get(view, eventName);
    var on = _emberMetalProperty_get.get(view, 'onEvent');
    var value = _emberMetalProperty_get.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 (!_emberMetalProperty_get.get(view, 'bubbles')) {
        event.stopPropagation();
      }
    }
  }

  exports.default = TextSupport;
});
enifed('ember-views/mixins/view_child_views_support', ['exports', 'ember-metal/debug', 'ember-metal/mixin', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/set_properties', 'ember-runtime/system/native_array', 'container/owner'], function (exports, _emberMetalDebug, _emberMetalMixin, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalSet_properties, _emberRuntimeSystemNative_array, _containerOwner) {
  /**
  @module ember
  @submodule ember-views
  */
  'use strict';

  var EMPTY_ARRAY = [];

  exports.default = _emberMetalMixin.Mixin.create({
    /**
      Array of child views. You should never edit this array directly.
      Instead, use `appendChild` and `removeFromParent`.
       @property childViews
      @type Array
      @default []
      @private
    */
    childViews: EMPTY_ARRAY,

    init: function () {
      this._super.apply(this, arguments);

      // setup child views. be sure to clone the child views array first
      // 2.0TODO: Remove Ember.A() here
      this.childViews = _emberRuntimeSystemNative_array.A(this.childViews.slice());
      this.ownerView = this.ownerView || this;
    },

    appendChild: function (view) {
      this.linkChild(view);
      this.childViews.push(view);
    },

    destroyChild: function (view) {
      view.destroy();
    },

    /**
      Removes the child view from the parent view.
       @method removeChild
      @param {Ember.View} view
      @return {Ember.View} receiver
      @private
    */
    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
      this.unlinkChild(view);

      // remove view from childViews array.
      var childViews = _emberMetalProperty_get.get(this, 'childViews');

      var index = childViews.indexOf(view);
      if (index !== -1) {
        childViews.splice(index, 1);
      }

      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 {Object} [attrs] Attributes to add
      @return {Ember.View} new instance
      @private
    */
    createChildView: function (maybeViewClass) {
      var attrs = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

      if (!maybeViewClass) {
        throw new TypeError('createChildViews first argument must exist');
      }

      var owner = _containerOwner.getOwner(this);

      if (maybeViewClass.isView && maybeViewClass.parentView === this && _containerOwner.getOwner(maybeViewClass) === owner) {
        return maybeViewClass;
      }

      var view;

      attrs.parentView = this;
      attrs.renderer = this.renderer;
      attrs._viewRegistry = this._viewRegistry;

      if (maybeViewClass.isViewFactory) {
        _containerOwner.setOwner(attrs, owner);

        view = maybeViewClass.create(attrs);

        if (view.viewName) {
          _emberMetalProperty_set.set(this, view.viewName, view);
        }
      } else if ('string' === typeof maybeViewClass) {
        var fullName = 'view:' + maybeViewClass;
        var ViewKlass = owner._lookupFactory(fullName);

        _emberMetalDebug.assert('Could not find view: \'' + fullName + '\'', !!ViewKlass);

        view = ViewKlass.create(attrs);
      } else {
        view = maybeViewClass;
        _emberMetalDebug.assert('You must pass instance or subclass of View', view.isView);

        _containerOwner.setOwner(attrs, owner);
        _emberMetalSet_properties.default(view, attrs);
      }

      this.linkChild(view);

      return view;
    },

    linkChild: function (instance) {
      if (!instance[_containerOwner.OWNER]) {
        _containerOwner.setOwner(instance, _containerOwner.getOwner(this));
      }

      instance.parentView = this;
      instance.ownerView = this.ownerView;
    },

    unlinkChild: function (instance) {
      instance.parentView = null;
    }
  });
});
enifed('ember-views/mixins/view_context_support', ['exports', 'ember-metal/mixin', 'ember-metal/computed', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-views/mixins/legacy_view_support', 'ember-metal/events'], function (exports, _emberMetalMixin, _emberMetalComputed, _emberMetalProperty_get, _emberMetalProperty_set, _emberViewsMixinsLegacy_view_support, _emberMetalEvents) {
  /**
  @module ember
  @submodule ember-views
  */
  'use strict';

  var ViewContextSupport = _emberMetalMixin.Mixin.create(_emberViewsMixinsLegacy_view_support.default, {
    /**
      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
      @private
    */
    context: _emberMetalComputed.computed({
      get: function () {
        return _emberMetalProperty_get.get(this, '_context');
      },
      set: function (key, value) {
        _emberMetalProperty_set.set(this, '_context', value);
        return value;
      }
    }),

    /**
      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
       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: _emberMetalComputed.computed({
      get: function () {
        var parentView, controller;

        if (controller = _emberMetalProperty_get.get(this, 'controller')) {
          return controller;
        }

        parentView = this.parentView;
        if (parentView) {
          return _emberMetalProperty_get.get(parentView, '_context');
        }
        return null;
      },
      set: function (key, value) {
        return value;
      }
    }),

    _controller: null,

    /**
      The controller managing this view. If this property is set, it will be
      made available for use by the template.
       @property controller
      @type Object
      @private
    */
    controller: _emberMetalComputed.computed({
      get: function () {
        if (this._controller) {
          return this._controller;
        }

        return this.parentView ? _emberMetalProperty_get.get(this.parentView, 'controller') : null;
      },
      set: function (_, value) {
        this._controller = value;
        return value;
      }
    }),

    _legacyControllerDidChange: _emberMetalMixin.observer('controller', function () {
      this.childViews.forEach(function (view) {
        return view.notifyPropertyChange('controller');
      });
    }),

    _notifyControllerChange: _emberMetalEvents.on('parentViewDidChange', function () {
      this.notifyPropertyChange('controller');
    })
  });

  exports.default = ViewContextSupport;
});
enifed('ember-views/mixins/view_state_support', ['exports', 'ember-metal/debug', 'ember-metal/mixin'], function (exports, _emberMetalDebug, _emberMetalMixin) {
  'use strict';

  var ViewStateSupport = _emberMetalMixin.Mixin.create({
    transitionTo: function (state) {
      _emberMetalDebug.deprecate('Ember.View#transitionTo has been deprecated, it is for internal use only', false, { id: 'ember-views.view-transition-to', until: '2.4.0' });
      this._transitionTo(state);
    },

    _transitionTo: function (state) {
      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);
      }
    }
  });

  exports.default = ViewStateSupport;
});
enifed('ember-views/mixins/view_support', ['exports', 'ember-metal/debug', 'ember-metal/error', 'ember-metal/property_get', 'ember-metal/run_loop', 'ember-metal/observer', 'ember-metal/utils', 'ember-metal/computed', 'ember-metal/mixin', 'ember-runtime/system/core_object', 'ember-metal/symbol', 'container/owner', 'ember-views/system/jquery'], function (exports, _emberMetalDebug, _emberMetalError, _emberMetalProperty_get, _emberMetalRun_loop, _emberMetalObserver, _emberMetalUtils, _emberMetalComputed, _emberMetalMixin, _emberRuntimeSystemCore_object, _emberMetalSymbol, _containerOwner, _emberViewsSystemJquery) {
  'use strict';

  var _Mixin$create;

  var INIT_WAS_CALLED = _emberMetalSymbol.default('INIT_WAS_CALLED');

  function K() {
    return this;
  }

  exports.default = _emberMetalMixin.Mixin.create((_Mixin$create = {
    concatenatedProperties: ['attributeBindings'],

    /**
      @property isView
      @type Boolean
      @default true
      @static
      @private
    */
    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
      @private
    */
    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
      @private
    */
    layoutName: null,

    /**
      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
      @private
    */
    template: _emberMetalComputed.computed({
      get: function () {
        var templateName = _emberMetalProperty_get.get(this, 'templateName');
        var template = this.templateForName(templateName, 'template');
        _emberMetalDebug.assert('You specified the templateName ' + templateName + ' for ' + this + ', but it did not exist.', !templateName || !!template);
        return template || _emberMetalProperty_get.get(this, 'defaultTemplate');
      },
      set: function (key, value) {
        if (value !== undefined) {
          return value;
        }
        return _emberMetalProperty_get.get(this, key);
      }
    }),

    /**
      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
      @private
    */
    layout: _emberMetalComputed.computed({
      get: function (key) {
        var layoutName = _emberMetalProperty_get.get(this, 'layoutName');
        var layout = this.templateForName(layoutName, 'layout');

        _emberMetalDebug.assert('You specified the layoutName ' + layoutName + ' for ' + this + ', but it did not exist.', !layoutName || !!layout);

        return layout || _emberMetalProperty_get.get(this, 'defaultLayout');
      },

      set: function (key, value) {
        return value;
      }
    }),

    templateForName: function (name, type) {
      if (!name) {
        return;
      }
      _emberMetalDebug.assert('templateNames are not allowed to contain periods: ' + name, name.indexOf('.') === -1);

      var owner = _containerOwner.getOwner(this);

      if (!owner) {
        throw new _emberMetalError.default('Container was not found when looking up a views template. ' + 'This is most likely due to manually instantiating an Ember.View. ' + 'See: http://git.io/EKPpnA');
      }

      return owner.lookup('template:' + name);
    },

    /**
      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
      @private
    */
    nearestOfType: function (klass) {
      var view = _emberMetalProperty_get.get(this, 'parentView');
      var isOfType = klass instanceof _emberMetalMixin.Mixin ? function (view) {
        return klass.detect(view);
      } : function (view) {
        return klass.detect(view.constructor);
      };

      while (view) {
        if (isOfType(view)) {
          return view;
        }
        view = _emberMetalProperty_get.get(view, 'parentView');
      }
    },

    /**
      Return the nearest ancestor that has a given property.
       @method nearestWithProperty
      @param {String} property A property name
      @return Ember.View
      @private
    */
    nearestWithProperty: function (property) {
      var view = _emberMetalProperty_get.get(this, 'parentView');

      while (view) {
        if (property in view) {
          return view;
        }
        view = _emberMetalProperty_get.get(view, 'parentView');
      }
    },

    /**
      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
      @public
    */
    rerender: function () {
      return this._currentState.rerender(this);
    },

    // ..........................................................
    // ELEMENT SUPPORT
    //

    /**
      Returns the current DOM element for the view.
       @property element
      @type DOMElement
      @public
    */
    element: null,

    /**
      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
      @public
    */
    $: function (sel) {
      _emberMetalDebug.assert('You cannot access this.$() on a component with `tagName: \'\'` specified.', this.tagName !== '');
      return this._currentState.$(this, sel);
    },

    forEachChildView: function (callback) {
      var childViews = this.childViews;

      if (!childViews) {
        return this;
      }

      var len = childViews.length;
      var 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. 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
      @private
    */
    appendTo: function (selector) {
      var $ = this._environment ? this._environment.options.jQuery : _emberViewsSystemJquery.default;

      if ($) {
        var target = $(selector);

        _emberMetalDebug.assert('You tried to append to (' + selector + ') but that isn\'t in the DOM', target.length > 0);
        _emberMetalDebug.assert('You cannot append to an existing Ember.View.', !target.is('.ember-view') && !target.parents().is('.ember-view'));

        this.renderer.appendTo(this, target[0]);
      } else {
        var target = selector;

        _emberMetalDebug.assert('You tried to append to a selector string (' + selector + ') in an environment without jQuery', typeof target !== 'string');
        _emberMetalDebug.assert('You tried to append to a non-Element (' + selector + ') in an environment without jQuery', typeof selector.appendChild === 'function');

        this.renderer.appendTo(this, target);
      }

      return this;
    },

    /**
      @private
       Creates a new DOM element, renders the view into it, then returns the
      element.
       By default, the element created and rendered into will be a `BODY` element,
      since this is the default context that views are rendered into when being
      inserted directly into the DOM.
       ```js
      var element = view.renderToElement();
      element.tagName; // => "BODY"
      ```
       You can override the kind of element rendered into and returned by
      specifying an optional tag name as the first argument.
       ```js
      var element = view.renderToElement('table');
      element.tagName; // => "TABLE"
      ```
       This method is useful if you want to render the view into an element that
      is not in the document's body. Instead, a new `body` element, detached from
      the DOM is returned. FastBoot uses this to serialize the rendered view into
      a string for transmission over the network.
       ```js
      app.visit('/').then(function(instance) {
        var element;
        Ember.run(function() {
          element = renderToElement(instance);
        });
         res.send(serialize(element));
      });
      ```
       @method renderToElement
      @param {String} tagName The tag of the element to create and render into. Defaults to "body".
      @return {HTMLBodyElement} element
      @private
    */
    renderToElement: function (tagName) {
      tagName = tagName || 'body';

      var element = this.renderer._dom.createElement(tagName);

      this.renderer.appendTo(this, element);
      return element;
    },

    /**
      Replaces the content of the specified parent element with this view's
      element. If the view does not have an HTML representation yet,
      the element will be generated 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
      @private
    */
    replaceIn: function (selector) {
      var target = _emberViewsSystemJquery.default(selector);

      _emberMetalDebug.assert('You tried to replace in (' + selector + ') but that isn\'t in the DOM', target.length > 0);
      _emberMetalDebug.assert('You cannot replace an existing Ember.View.', !target.is('.ember-view') && !target.parents().is('.ember-view'));

      this.renderer.replaceIn(this, target[0]);

      return this;
    },

    /**
      Appends the view's element to the document body. If the view does
      not have an HTML representation yet
      the element will be generated 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
      @private
    */
    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
      @private
    */
    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();
      }

      // Set flag to avoid future renders
      this._willInsert = false;
    },

    /**
      The HTML `id` of the view's element in the DOM. You can provide this
      value yourself but it must be unique (just as in HTML):
       ```handlebars
        {{my-component elementId="a-really-cool-id"}}
      ```
       If not manually set a default value will be provided by the framework.
       Once rendered an element's `elementId` is considered immutable and you
      should never change it. If you need to compute a dynamic value for the
      `elementId`, you should do this when the component or element is being
      instantiated:
       ```javascript
        export default Ember.Component.extend({
          setElementId: Ember.on('init', function() {
            var index = this.get('index');
            this.set('elementId', 'component-id' + index);
          })
        });
      ```
       @property elementId
      @type String
      @public
    */
    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
      @private
    */
    findElementInParentElement: function (parentElem) {
      var id = '#' + this.elementId;
      return _emberViewsSystemJquery.default(id)[0] || _emberViewsSystemJquery.default(id, parentElem)[0];
    },

    /**
      Creates a DOM representation of the view and all of its child views by
      recursively calling the `render()` method. Once the element is created,
      it sets the `element` property of the view to the rendered element.
       After the element has been inserted into the DOM, `didInsertElement` will
      be called on this view and all of its child views.
       @method createElement
      @return {Ember.View} receiver
      @private
    */
    createElement: function () {
      if (this.element) {
        return this;
      }

      this.renderer.createElement(this);

      return this;
    },

    /**
      Called when a view is going to insert an element into the DOM.
       @event willInsertElement
      @public
    */
    willInsertElement: 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.
       When a view has children, didInsertElement will be called on the
      child view(s) first, bubbling upwards through the hierarchy.
       @event didInsertElement
      @public
    */
    didInsertElement: 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
      @public
    */
    willClearRender: K,

    /**
      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
      @private
    */
    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.
       Please note: any property changes made during this event will have no
      effect on object observers.
       @event willDestroyElement
      @public
    */
    willDestroyElement: K,

    /**
      Called when the parentView property has changed.
       @event parentViewDidChange
      @private
    */
    parentViewDidChange: K,

    // ..........................................................
    // 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
      @public
    */

    // We leave this null by default so we can tell the difference between
    // the default case and a user-specified tag.
    tagName: null,

    /*
      Used to specify a default tagName that can be overridden when extending
      or invoking from a template.
       @property _defaultTagName
      @private
    */

    /**
      Normally, Ember's component model is "write-only". The component takes a
      bunch of attributes that it got passed in, and uses them to render its
      template.
       One nice thing about this model is that if you try to set a value to the
      same thing as last time, Ember (through HTMLBars) will avoid doing any
      work on the DOM.
       This is not just a performance optimization. If an attribute has not
      changed, it is important not to clobber the element's "hidden state".
      For example, if you set an input's `value` to the same value as before,
      it will clobber selection state and cursor position. In other words,
      setting an attribute is not **always** idempotent.
       This method provides a way to read an element's attribute and also
      update the last value Ember knows about at the same time. This makes
      setting an attribute idempotent.
       In particular, what this means is that if you get an `<input>` element's
      `value` attribute and then re-render the template with the same value,
      it will avoid clobbering the cursor and selection position.
       Since most attribute sets are idempotent in the browser, you typically
      can get away with reading attributes using jQuery, but the most reliable
      way to do so is through this method.
       @method readDOMAttr
      @param {String} name the name of the attribute
      @return String
      @public
    */
    readDOMAttr: function (name) {
      var attr = this._renderNode.childNodes.filter(function (node) {
        return node.attrName === name;
      })[0];
      if (!attr) {
        return null;
      }
      return attr.getContent();
    },

    // .......................................................
    // 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._super.apply(this, arguments);

      if (!this.elementId) {
        this.elementId = _emberMetalUtils.guidFor(this);
      }

      this.scheduledRevalidation = false;

      this[INIT_WAS_CALLED] = true;

      if (typeof this.didInitAttrs === 'function') {
        _emberMetalDebug.deprecate('[DEPRECATED] didInitAttrs called in ' + this.toString() + '.', false, {
          id: 'ember-views.did-init-attrs',
          until: '3.0.0',
          url: 'http://emberjs.com/deprecations/v2.x#toc_ember-component-didinitattrs'
        });
      }

      _emberMetalDebug.assert('Using a custom `.render` function is no longer supported.', !this.render);
    }

  }, _Mixin$create[_emberRuntimeSystemCore_object.POST_INIT] = function () {
    this._super.apply(this, arguments);

    _emberMetalDebug.assert('You must call `this._super(...arguments);` when implementing `init` in a component. Please update ' + this + ' to call `this._super` from `init`.', this[INIT_WAS_CALLED]);

    this.renderer.componentInitAttrs(this, this.attrs || {});
  }, _Mixin$create.__defineNonEnumerable = function (property) {
    this[property.name] = property.descriptor.value;
  }, _Mixin$create.revalidate = function () {
    this.renderer.revalidateTopLevelView(this);
    this.scheduledRevalidation = false;
  }, _Mixin$create.scheduleRevalidate = function (node, label, manualRerender) {
    if (node && !this._dispatching && this.env.renderedNodes.has(node)) {
      if (manualRerender) {
        _emberMetalDebug.deprecate('You manually rerendered ' + label + ' (a parent component) from a child component during the rendering process. This rarely worked in Ember 1.x and will be removed in Ember 3.0', false, { id: 'ember-views.manual-parent-rerender', until: '3.0.0' });
      } else {
        _emberMetalDebug.deprecate('You modified ' + label + ' twice in a single render. This was unreliable in Ember 1.x and will be removed in Ember 3.0', false, { id: 'ember-views.render-double-modify', until: '3.0.0' });
      }
      _emberMetalRun_loop.default.scheduleOnce('render', this, this.revalidate);
      return;
    }

    _emberMetalDebug.deprecate('A property of ' + this + ' was modified inside the ' + this._dispatching + ' hook. You should never change properties on components, services or models during ' + this._dispatching + ' because it causes significant performance degradation.', !this._dispatching, { id: 'ember-views.dispatching-modify-property', until: '3.0.0' });

    if (!this.scheduledRevalidation || this._dispatching) {
      this.scheduledRevalidation = true;
      _emberMetalRun_loop.default.scheduleOnce('render', this, this.revalidate);
    }
  }, _Mixin$create.templateRenderer = null, _Mixin$create.removeFromParent = function () {
    var parent = this.parentView;

    // Remove DOM element from parent
    this.remove();

    if (parent) {
      parent.removeChild(this);
    }
    return this;
  }, _Mixin$create.destroy = function () {
    // get parentView before calling super because it'll be destroyed
    var parentView = this.parentView;
    var viewName = this.viewName;

    if (!this._super.apply(this, arguments)) {
      return;
    }

    // remove from non-virtual parent view if viewName was specified
    if (viewName && parentView) {
      parentView.set(viewName, null);
    }

    // Destroy HTMLbars template
    if (this.lastResult) {
      this.lastResult.destroy();
    }

    return this;
  }, _Mixin$create.handleEvent = function (eventName, evt) {
    return this._currentState.handleEvent(this, eventName, evt);
  }, _Mixin$create._register = function () {
    _emberMetalDebug.assert('Attempted to register a view with an id already in use: ' + this.elementId, !this._viewRegistry[this.elementId]);
    this._viewRegistry[this.elementId] = this;
  }, _Mixin$create._unregister = function () {
    delete this._viewRegistry[this.elementId];
  }, _Mixin$create.registerObserver = function (root, path, target, observer) {
    if (!observer && 'function' === typeof target) {
      observer = target;
      target = null;
    }

    if (!root || typeof root !== 'object') {
      return;
    }

    var scheduledObserver = this._wrapAsScheduled(observer);

    _emberMetalObserver.addObserver(root, path, target, scheduledObserver);

    this.one('willClearRender', function () {
      _emberMetalObserver.removeObserver(root, path, target, scheduledObserver);
    });
  }, _Mixin$create._wrapAsScheduled = function (fn) {
    var view = this;
    var stateCheckedFn = function () {
      view._currentState.invokeObserver(this, fn);
    };
    var scheduledFn = function () {
      _emberMetalRun_loop.default.scheduleOnce('render', this, stateCheckedFn);
    };
    return scheduledFn;
  }, _Mixin$create));
});
/*
 This is a special hook implemented in CoreObject, that allows Views/Components
 to have a way to ensure that `init` fires before `didInitAttrs` / `didReceiveAttrs`
 (so that `this._super` in init does not trigger `didReceiveAttrs` before the classes
 own `init` is finished).
  @method __postInitInitialization
 @private
 */

/**
  Removes the view from its `parentView`, if one is found. Otherwise
  does nothing.
   @method removeFromParent
  @return {Ember.View} receiver
  @private
*/

/**
  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
  @private
*/

// .......................................................
// EVENT HANDLING
//

/**
  Handle events from `Ember.EventDispatcher`
   @method handleEvent
  @param eventName {String}
  @param evt {Event}
  @private
*/

/**
  Registers the view in the view registry, keyed on the view's `elementId`.
  This is used by the EventDispatcher to locate the view in response to
  events.
   This method should only be called once the view has been inserted into the
  DOM.
   @method _register
  @private
*/

/**
  Removes the view from the view registry. This should be called when the
  view is removed from DOM.
   @method _unregister
  @private
*/
enifed('ember-views/mixins/view_target_action_support', ['exports', 'ember-metal/mixin', 'ember-runtime/mixins/target_action_support', 'ember-metal/alias'], function (exports, _emberMetalMixin, _emberRuntimeMixinsTarget_action_support, _emberMetalAlias) {
  'use strict';

  /**
  `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
  @private
  */
  exports.default = _emberMetalMixin.Mixin.create(_emberRuntimeMixinsTarget_action_support.default, {
    /**
     @property target
     @private
    */
    target: _emberMetalAlias.default('controller'),
    /**
     @property actionContext
     @private
    */
    actionContext: _emberMetalAlias.default('context')
  });
});
enifed('ember-views/mixins/visibility_support', ['exports', 'ember-metal/mixin', 'ember-metal/property_get', 'ember-metal/run_loop'], function (exports, _emberMetalMixin, _emberMetalProperty_get, _emberMetalRun_loop) {
  /**
   @module ember
   @submodule ember-views
  */
  'use strict';

  function K() {
    return this;
  }

  /**
   @class VisibilitySupport
   @namespace Ember
   @public
  */
  var VisibilitySupport = _emberMetalMixin.Mixin.create({
    /**
      If `false`, the view will appear hidden in DOM.
       @property isVisible
      @type Boolean
      @default null
      @public
    */
    isVisible: true,

    becameVisible: K,
    becameHidden: K,

    /**
      When the view's `isVisible` property changes, toggle the visibility
      element of the actual DOM element.
       @method _isVisibleDidChange
      @private
    */
    _isVisibleDidChange: _emberMetalMixin.observer('isVisible', function () {
      if (this._isVisible === _emberMetalProperty_get.get(this, 'isVisible')) {
        return;
      }
      _emberMetalRun_loop.default.scheduleOnce('render', this, this._toggleVisibility);
    }),

    _toggleVisibility: function () {
      var $el = this.$();
      var isVisible = _emberMetalProperty_get.get(this, 'isVisible');

      if (this._isVisible === isVisible) {
        return;
      }

      // It's important to keep these in sync, even if we don't yet have
      // an element in the DOM to manipulate:
      this._isVisible = isVisible;

      if (!$el) {
        return;
      }

      $el.toggle(isVisible);

      if (this._isAncestorHidden()) {
        return;
      }

      if (isVisible) {
        this._notifyBecameVisible();
      } else {
        this._notifyBecameHidden();
      }
    },

    _notifyBecameVisible: function () {
      this.trigger('becameVisible');

      this.forEachChildView(function (view) {
        var isVisible = _emberMetalProperty_get.get(view, 'isVisible');

        if (isVisible || isVisible === null) {
          view._notifyBecameVisible();
        }
      });
    },

    _notifyBecameHidden: function () {
      this.trigger('becameHidden');
      this.forEachChildView(function (view) {
        var isVisible = _emberMetalProperty_get.get(view, 'isVisible');

        if (isVisible || isVisible === null) {
          view._notifyBecameHidden();
        }
      });
    },

    _isAncestorHidden: function () {
      var parent = _emberMetalProperty_get.get(this, 'parentView');

      while (parent) {
        if (_emberMetalProperty_get.get(parent, 'isVisible') === false) {
          return true;
        }

        parent = _emberMetalProperty_get.get(parent, 'parentView');
      }

      return false;
    }
  });

  exports.default = VisibilitySupport;
});
enifed('ember-views/streams/class_name_binding', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/utils', 'ember-metal/streams/utils', 'ember-runtime/system/string'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalUtils, _emberMetalStreamsUtils, _emberRuntimeSystemString) {
  'use strict';

  exports.parsePropertyPath = parsePropertyPath;
  exports.classStringForValue = classStringForValue;
  exports.streamifyClassNameBinding = streamifyClassNameBinding;

  /**
    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
  */

  function parsePropertyPath(path) {
    var split = path.split(':');
    var propertyPath = split[0];
    var classNames = '';
    var 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
  */

  function classStringForValue(path, val, className, falsyClassName) {
    if (_emberMetalUtils.isArray(val)) {
      val = _emberMetalProperty_get.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 _emberRuntimeSystemString.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;
          }
  }

  function streamifyClassNameBinding(view, classNameBinding, prefix) {
    prefix = prefix || '';
    _emberMetalDebug.assert('classNameBindings must not have spaces in them. Multiple class name bindings can be provided as elements of an array, e.g. [\'foo\', \':bar\']', classNameBinding.indexOf(' ') === -1);
    var parsedPath = parsePropertyPath(classNameBinding);
    if (parsedPath.path === '') {
      return classStringForValue(parsedPath.path, true, parsedPath.className, parsedPath.falsyClassName);
    } else {
      var pathValue = view.getStream(prefix + parsedPath.path);
      return _emberMetalStreamsUtils.chain(pathValue, function () {
        return classStringForValue(parsedPath.path, _emberMetalStreamsUtils.read(pathValue), parsedPath.className, parsedPath.falsyClassName);
      });
    }
  }
});
enifed('ember-views/streams/should_display', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-runtime/utils', 'ember-metal/streams/stream', 'ember-metal/streams/utils'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberRuntimeUtils, _emberMetalStreamsStream, _emberMetalStreamsUtils) {
  'use strict';

  exports.default = shouldDisplay;

  var ShouldDisplayStream = _emberMetalStreamsStream.default.extend({
    init: function (predicate) {
      _emberMetalDebug.assert('ShouldDisplayStream error: predicate must be a stream', _emberMetalStreamsUtils.isStream(predicate));

      var isTruthy = predicate.get('isTruthy');

      this.init();
      this.predicate = predicate;
      this.isTruthy = isTruthy;
      this.lengthDep = null;

      this.addDependency(predicate);
      this.addDependency(isTruthy);
    },

    compute: function () {
      var truthy = _emberMetalStreamsUtils.read(this.isTruthy);

      if (typeof truthy === 'boolean') {
        return truthy;
      }

      if (this.lengthDep) {
        return this.lengthDep.getValue() !== 0;
      } else {
        return !!_emberMetalStreamsUtils.read(this.predicate);
      }
    },

    revalidate: function () {
      if (_emberRuntimeUtils.isArray(_emberMetalStreamsUtils.read(this.predicate))) {
        if (!this.lengthDep) {
          this.lengthDep = this.addMutableDependency(this.predicate.get('length'));
        }
      } else {
        if (this.lengthDep) {
          this.lengthDep.destroy();
          this.lengthDep = null;
        }
      }
    }
  });

  function shouldDisplay(predicate) {
    if (_emberMetalStreamsUtils.isStream(predicate)) {
      return new ShouldDisplayStream(predicate);
    }

    var type = typeof predicate;

    if (type === 'boolean') {
      return predicate;
    }

    if (type && type === 'object' && predicate !== null) {
      var isTruthy = _emberMetalProperty_get.get(predicate, 'isTruthy');
      if (typeof isTruthy === 'boolean') {
        return isTruthy;
      }
    }

    if (_emberRuntimeUtils.isArray(predicate)) {
      return _emberMetalProperty_get.get(predicate, 'length') !== 0;
    } else {
      return !!predicate;
    }
  }
});
enifed('ember-views/streams/utils', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/streams/utils', 'ember-runtime/mixins/controller'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalStreamsUtils, _emberRuntimeMixinsController) {
  'use strict';

  exports.readViewFactory = readViewFactory;
  exports.readComponentFactory = readComponentFactory;
  exports.readUnwrappedModel = readUnwrappedModel;

  function readViewFactory(object, owner) {
    var value = _emberMetalStreamsUtils.read(object);
    var viewClass;

    if (typeof value === 'string') {
      _emberMetalDebug.assert('View requires an owner to resolve views not passed in through the context', !!owner);
      viewClass = owner._lookupFactory('view:' + value);
    } else {
      viewClass = value;
    }

    _emberMetalDebug.assert(value + ' must be a subclass or an instance of Ember.View, not ' + viewClass, (function (viewClass) {
      return viewClass && (viewClass.isViewFactory || viewClass.isView || viewClass.isComponentFactory || viewClass.isComponent);
    })(viewClass));

    return viewClass;
  }

  function readComponentFactory(nameOrStream, owner) {
    var name = _emberMetalStreamsUtils.read(nameOrStream);
    var componentLookup = owner.lookup('component-lookup:main');
    _emberMetalDebug.assert('Could not find \'component-lookup:main\' on the provided container, ' + 'which is necessary for performing component lookups', componentLookup);

    return componentLookup.lookupFactory(name, owner);
  }

  function readUnwrappedModel(object) {
    if (_emberMetalStreamsUtils.isStream(object)) {
      var result = object.value();

      // If the path is exactly `controller` then we don't unwrap it.
      if (object.label !== 'controller') {
        while (_emberRuntimeMixinsController.default.detect(result)) {
          result = _emberMetalProperty_get.get(result, 'model');
        }
      }

      return result;
    } else {
      return object;
    }
  }
});
enifed("ember-views/system/action_manager", ["exports"], function (exports) {
  /**
  @module ember
  @submodule ember-views
  */

  "use strict";

  function ActionManager() {}

  /**
    Global action id hash.

    @private
    @property registeredActions
    @type Object
  */
  ActionManager.registeredActions = {};

  exports.default = ActionManager;
});
enifed('ember-views/system/build-component-template', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/assign', 'htmlbars-runtime', 'ember-htmlbars/hooks/get-value', 'ember-metal/streams/utils'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalAssign, _htmlbarsRuntime, _emberHtmlbarsHooksGetValue, _emberMetalStreamsUtils) {
  'use strict';

  exports.default = buildComponentTemplate;
  exports.buildHTMLTemplate = buildHTMLTemplate;

  function buildComponentTemplate(_ref, attrs, content) {
    var component = _ref.component;
    var tagName = _ref.tagName;
    var layout = _ref.layout;
    var isAngleBracket = _ref.isAngleBracket;
    var isComponentElement = _ref.isComponentElement;
    var outerAttrs = _ref.outerAttrs;

    var blockToRender, meta;

    if (component === undefined) {
      component = null;
    }

    if (layout && layout.raw) {
      var yieldTo = createContentBlocks(content.templates, content.scope, content.self, component);
      blockToRender = createLayoutBlock(layout.raw, yieldTo, content.self, component, attrs);
      meta = layout.raw.meta;
    } else if (content.templates && content.templates.default) {
      blockToRender = createContentBlock(content.templates.default, content.scope, content.self, component);
      meta = content.templates.default.meta;
    }

    if (component && !component._isAngleBracket || isComponentElement) {
      tagName = tagName || tagNameFor(component);

      // If this is not a tagless component, we need to create the wrapping
      // element. We use `manualElement` to create a template that represents
      // the wrapping element and yields to the previous block.
      if (tagName !== '') {
        if (isComponentElement) {
          attrs = mergeAttrs(attrs, outerAttrs);
        }
        var attributes = normalizeComponentAttributes(component, isAngleBracket, attrs);
        var elementTemplate = _htmlbarsRuntime.internal.manualElement(tagName, attributes);
        elementTemplate.meta = meta;

        blockToRender = createElementBlock(elementTemplate, blockToRender, component);
      } else {
        validateTaglessComponent(component);
      }
    }

    // tagName is one of:
    //   * `undefined` if no component is present
    //   * the falsy value "" if set explicitly on the component
    //   * an actual tagName set explicitly on the component
    return { createdElement: !!tagName, block: blockToRender };
  }

  function buildHTMLTemplate(tagName, _attrs, content) {
    var attrs = {};

    for (var prop in _attrs) {
      var val = _attrs[prop];

      if (typeof val === 'string') {
        attrs[prop] = val;
      } else {
        attrs[prop] = ['value', val];
      }
    }

    var childTemplate = content.templates.default;
    var elementTemplate = _htmlbarsRuntime.internal.manualElement(tagName, attrs, childTemplate.isEmpty);

    if (childTemplate.isEmpty) {
      return blockFor(elementTemplate, { scope: content.scope });
    } else {
      var blockToRender = blockFor(content.templates.default, content);
      return blockFor(elementTemplate, { yieldTo: blockToRender, scope: content.scope });
    }
  }

  function mergeAttrs(innerAttrs, outerAttrs) {
    var result = _emberMetalAssign.default({}, innerAttrs, outerAttrs);

    if (innerAttrs.class && outerAttrs.class) {
      result.class = ['subexpr', '-join-classes', [['value', innerAttrs.class], ['value', outerAttrs.class]], []];
    }

    return result;
  }

  function blockFor(template, options) {
    _emberMetalDebug.assert('BUG: Must pass a template to blockFor', !!template);
    return _htmlbarsRuntime.internal.blockFor(_htmlbarsRuntime.render, template, options);
  }

  function createContentBlock(template, scope, self, component) {
    _emberMetalDebug.assert('BUG: buildComponentTemplate can take a scope or a self, but not both', !(scope && self));

    return blockFor(template, {
      scope: scope,
      self: self,
      options: { view: component }
    });
  }

  function createContentBlocks(templates, scope, self, component) {
    if (!templates) {
      return;
    }
    var output = {};
    for (var name in templates) {
      if (templates.hasOwnProperty(name)) {
        var template = templates[name];
        if (template) {
          output[name] = createContentBlock(templates[name], scope, self, component);
        }
      }
    }
    return output;
  }

  function createLayoutBlock(template, yieldTo, self, component, attrs) {
    return blockFor(template, {
      yieldTo: yieldTo,

      // If we have an old-style Controller with a template it will be
      // passed as our `self` argument, and it should be the context for
      // the template. Otherwise, we must have a real Component and it
      // should be its own template context.
      self: self || component,

      options: { view: component, attrs: attrs }
    });
  }

  function createElementBlock(template, yieldTo, component) {
    return blockFor(template, {
      yieldTo: yieldTo,
      self: component,
      options: { view: component }
    });
  }

  function tagNameFor(view) {
    var tagName = view.tagName;

    if (tagName !== null && typeof tagName === 'object' && tagName.isDescriptor) {
      tagName = _emberMetalProperty_get.get(view, 'tagName');
      _emberMetalDebug.deprecate('In the future using a computed property to define tagName will not be permitted. That value will be respected, but changing it will not update the element.', !tagName, { id: 'ember-views.computed-tag-name', until: '2.0.0' });
    }

    if (tagName === null || tagName === undefined) {
      tagName = view._defaultTagName || 'div';
    }

    return tagName;
  }

  // Takes a component and builds a normalized set of attribute
  // bindings consumable by HTMLBars' `attribute` hook.
  function normalizeComponentAttributes(component, isAngleBracket, attrs) {
    var normalized = {};
    var attributeBindings = component.attributeBindings;
    var streamBasePath = component.isComponent ? '' : 'view.';
    var i, l;

    if (attrs.id && _emberHtmlbarsHooksGetValue.default(attrs.id)) {
      // Do not allow binding to the `id`
      normalized.id = _emberHtmlbarsHooksGetValue.default(attrs.id);
      component.elementId = normalized.id;
    } else {
      normalized.id = component.elementId;
    }

    if (attributeBindings) {
      for (i = 0, l = attributeBindings.length; i < l; i++) {
        var attr = attributeBindings[i];
        var colonIndex = attr.indexOf(':');

        var attrName, expression;
        if (colonIndex !== -1) {
          var attrProperty = attr.substring(0, colonIndex);
          attrName = attr.substring(colonIndex + 1);
          expression = ['get', '' + streamBasePath + attrProperty];
        } else if (attrs[attr]) {
          // TODO: For compatibility with 1.x, we probably need to `set`
          // the component's attribute here if it is a CP, but we also
          // probably want to suspend observers and allow the
          // willUpdateAttrs logic to trigger observers at the correct time.
          attrName = attr;
          expression = ['value', attrs[attr]];
        } else {
          attrName = attr;
          expression = ['get', '' + streamBasePath + attr];
        }

        _emberMetalDebug.assert('You cannot use class as an attributeBinding, use classNameBindings instead.', attrName !== 'class');

        normalized[attrName] = expression;
      }
    }

    if (isAngleBracket) {
      for (var prop in attrs) {
        var val = attrs[prop];
        if (!val) {
          continue;
        }

        if (typeof val === 'string' || val.isConcat) {
          normalized[prop] = ['value', val];
        }
      }
    }

    if (attrs.tagName) {
      component.tagName = attrs.tagName;
    }

    var normalizedClass = normalizeClass(component, attrs, streamBasePath);

    if (normalizedClass) {
      normalized.class = normalizedClass;
    }

    if (_emberMetalProperty_get.get(component, 'isVisible') === false) {
      var hiddenStyle = ['subexpr', '-html-safe', ['display: none;'], []];
      var existingStyle = normalized.style;

      if (existingStyle) {
        normalized.style = ['subexpr', 'concat', [existingStyle, ' ', hiddenStyle], []];
      } else {
        normalized.style = hiddenStyle;
      }
    }

    return normalized;
  }

  function normalizeClass(component, attrs, streamBasePath) {
    var i, l;
    var normalizedClass = [];
    var classNames = _emberMetalProperty_get.get(component, 'classNames');
    var classNameBindings = _emberMetalProperty_get.get(component, 'classNameBindings');

    if (attrs.class) {
      if (_emberMetalStreamsUtils.isStream(attrs.class)) {
        normalizedClass.push(['subexpr', '-normalize-class', [['value', attrs.class.path], ['value', attrs.class]], []]);
      } else {
        normalizedClass.push(attrs.class);
      }
    }

    if (attrs.classBinding) {
      normalizeClasses(attrs.classBinding.split(' '), normalizedClass, streamBasePath);
    }

    if (classNames) {
      for (i = 0, l = classNames.length; i < l; i++) {
        normalizedClass.push(classNames[i]);
      }
    }

    if (classNameBindings) {
      normalizeClasses(classNameBindings, normalizedClass, streamBasePath);
    }

    if (normalizeClass.length) {
      return ['subexpr', '-join-classes', normalizedClass, []];
    }
  }

  function normalizeClasses(classes, output, streamBasePath) {
    var i, l;

    for (i = 0, l = classes.length; i < l; i++) {
      var className = classes[i];
      _emberMetalDebug.assert('classNameBindings must not have spaces in them. Multiple class name bindings can be provided as elements of an array, e.g. [\'foo\', \':bar\']', className.indexOf(' ') === -1);

      var _className$split = className.split(':');

      var propName = _className$split[0];
      var activeClass = _className$split[1];
      var inactiveClass = _className$split[2];

      // Legacy :class microsyntax for static class names
      if (propName === '') {
        output.push(activeClass);
        continue;
      }

      var prop = '' + streamBasePath + propName;

      output.push(['subexpr', '-normalize-class', [
      // params
      ['value', propName], ['get', prop]], [
      // hash
      'activeClass', activeClass, 'inactiveClass', inactiveClass]]);
    }
  }

  function validateTaglessComponent(component) {
    _emberMetalDebug.assert('You cannot use `classNameBindings` on a tag-less component: ' + component.toString(), (function () {
      var classNameBindings = component.classNameBindings;
      return !classNameBindings || classNameBindings.length === 0;
    })());
  }
});
enifed('ember-views/system/event_dispatcher', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/is_none', 'ember-metal/run_loop', 'ember-runtime/system/object', 'ember-views/system/jquery', 'ember-views/system/action_manager', 'ember-views/views/view', 'ember-metal/assign', 'container/owner', 'ember-metal/environment'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalIs_none, _emberMetalRun_loop, _emberRuntimeSystemObject, _emberViewsSystemJquery, _emberViewsSystemAction_manager, _emberViewsViewsView, _emberMetalAssign, _containerOwner, _emberMetalEnvironment) {
  /**
  @module ember
  @submodule ember-views
  */

  'use strict';

  var ROOT_ELEMENT_CLASS = 'ember-application';
  var ROOT_ELEMENT_SELECTOR = '.' + ROOT_ELEMENT_CLASS;

  /**
    `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 = _emberRuntimeSystemObject.default.extend({

    /**
      The set of events names (and associated handler function names) to be setup
      and dispatched by the `EventDispatcher`. Modifications to this list can be done
      at setup time, generally via the `Ember.Application.customEvents` hash.
       To add new events to be listened to:
       ```javascript
      var App = Ember.Application.create({
        customEvents: {
          paste: 'paste'
        }
      });
      ```
       To prevent default events from being listened to:
       ```javascript
      var App = Ember.Application.create({
        customEvents: {
          mouseenter: null,
          mouseleave: null
        }
      });
      ```
      @property events
      @type Object
      @private
    */
    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'
      @since 1.7.0
      @private
    */
    canDispatchToEventManager: true,

    init: function () {
      this._super();
      _emberMetalDebug.assert('EventDispatcher should never be instantiated in fastboot mode. Please report this as an Ember bug.', _emberMetalEnvironment.default.hasDOM);
    },

    /**
      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 {Object}
    */
    setup: function (addedEvents, rootElement) {
      var event;
      var events = this._finalEvents = _emberMetalAssign.default({}, _emberMetalProperty_get.get(this, 'events'), addedEvents);

      if (!_emberMetalIs_none.default(rootElement)) {
        _emberMetalProperty_set.set(this, 'rootElement', rootElement);
      }

      rootElement = _emberViewsSystemJquery.default(_emberMetalProperty_get.get(this, 'rootElement'));

      _emberMetalDebug.assert('You cannot use the same root element (' + (rootElement.selector || rootElement[0].tagName) + ') multiple times in an Ember.Application', !rootElement.is(ROOT_ELEMENT_SELECTOR));
      _emberMetalDebug.assert('You cannot make a new Ember.Application using a root element that is a descendent of an existing Ember.Application', !rootElement.closest(ROOT_ELEMENT_SELECTOR).length);
      _emberMetalDebug.assert('You cannot make a new Ember.Application using a root element that is an ancestor of an existing Ember.Application', !rootElement.find(ROOT_ELEMENT_SELECTOR).length);

      rootElement.addClass(ROOT_ELEMENT_CLASS);

      _emberMetalDebug.assert('Unable to add \'' + ROOT_ELEMENT_CLASS + '\' class to rootElement. Make sure you set rootElement to the body or an element in the body.', rootElement.is(ROOT_ELEMENT_SELECTOR));

      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;

      var owner = _containerOwner.getOwner(this);
      var viewRegistry = owner && owner.lookup('-view-registry:main') || _emberViewsViewsView.default.views;

      if (eventName === null) {
        return;
      }

      rootElement.on(event + '.ember', '.ember-view', function (evt, triggeringManager) {
        var view = viewRegistry[this.id];
        var 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) {
        var actionId = _emberViewsSystemJquery.default(evt.currentTarget).attr('data-ember-action');
        var actions = _emberViewsSystemAction_manager.default.registeredActions[actionId];

        // We have to check for actions 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 (!actions) {
          return;
        }

        for (var index = 0, _length = actions.length; index < _length; index++) {
          var action = actions[index];

          if (action && action.eventName === eventName) {
            return action.handler(evt);
          }
        }
      });
    },

    _findNearestEventManager: function (view, eventName) {
      var manager = null;

      while (view) {
        manager = _emberMetalProperty_get.get(view, 'eventManager');
        if (manager && manager[eventName]) {
          break;
        }

        view = _emberMetalProperty_get.get(view, 'parentView');
      }

      return manager;
    },

    _dispatchEvent: function (object, evt, eventName, view) {
      var result = true;

      var handler = object[eventName];
      if (typeof handler === 'function') {
        result = _emberMetalRun_loop.default(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 view.handleEvent(eventName, evt);
    },

    destroy: function () {
      var rootElement = _emberMetalProperty_get.get(this, 'rootElement');
      _emberViewsSystemJquery.default(rootElement).off('.ember', '**').removeClass(ROOT_ELEMENT_CLASS);
      return this._super.apply(this, arguments);
    },

    toString: function () {
      return '(EventDispatcher)';
    }
  });
});
enifed('ember-views/system/ext', ['exports', 'ember-metal/run_loop'], function (exports, _emberMetalRun_loop) {
  /**
  @module ember
  @submodule ember-views
  */

  'use strict';

  // Add a new named queue for rendering views that happens
  // after bindings have synced, and a queue for scheduling actions
  // that should occur after view rendering.
  _emberMetalRun_loop.default._addQueue('render', 'actions');
  _emberMetalRun_loop.default._addQueue('afterRender', 'render');
});
enifed('ember-views/system/jquery', ['exports', 'ember-metal/core', 'ember-metal/environment'], function (exports, _emberMetalCore, _emberMetalEnvironment) {
  'use strict';

  var jQuery;

  if (_emberMetalEnvironment.default.hasDOM) {
    // mainContext is set in `package/loader/lib/main.js` to the `this` context before entering strict mode
    jQuery = _emberMetalCore.default.imports && _emberMetalCore.default.imports.jQuery || mainContext && mainContext.jQuery; //jshint ignore:line
    if (!jQuery && typeof require === 'function') {
      jQuery = require('jquery');
    }

    if (jQuery) {
      // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
      var dragEvents = ['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
      dragEvents.forEach(function (eventName) {
        jQuery.event.fixHooks[eventName] = {
          props: ['dataTransfer']
        };
      });
    }
  }

  exports.default = jQuery;
});

// ES6TODO: the functions on EnumerableUtils need their own exports
enifed('ember-views/system/lookup_partial', ['exports', 'ember-metal/debug', 'ember-metal/error'], function (exports, _emberMetalDebug, _emberMetalError) {
  'use strict';

  exports.default = lookupPartial;

  function lookupPartial(env, templateName) {
    if (templateName == null) {
      return;
    }

    var nameParts = templateName.split('/');
    var lastPart = nameParts[nameParts.length - 1];

    nameParts[nameParts.length - 1] = '_' + lastPart;

    var underscoredName = nameParts.join('/');
    var template = templateFor(env, underscoredName, templateName);

    _emberMetalDebug.assert('Unable to find partial with name "' + templateName + '"', !!template);

    return template;
  }

  function templateFor(env, underscored, name) {
    if (!name) {
      return;
    }
    _emberMetalDebug.assert('templateNames are not allowed to contain periods: ' + name, name.indexOf('.') === -1);

    if (!env.owner) {
      throw new _emberMetalError.default('Container was not found when looking up a views template. ' + 'This is most likely due to manually instantiating an Ember.View. ' + 'See: http://git.io/EKPpnA');
    }

    return env.owner.lookup('template:' + underscored) || env.owner.lookup('template:' + name);
  }
});
enifed('ember-views/system/platform', ['exports', 'ember-metal/environment'], function (exports, _emberMetalEnvironment) {
  'use strict';

  // 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 = _emberMetalEnvironment.default.hasDOM && (function () {
    var div = document.createElement('div');
    var el = document.createElement('input');

    el.setAttribute('name', 'foo');
    div.appendChild(el);

    return !!div.innerHTML.match('foo');
  })();
  exports.canSetNameOnInputs = canSetNameOnInputs;
});
enifed("ember-views/system/utils", ["exports"], function (exports) {
  /**
  @module ember
  @submodule ember-views
  */

  "use strict";

  exports.isSimpleClick = isSimpleClick;
  exports.getViewClientRects = getViewClientRects;
  exports.getViewBoundingClientRect = getViewBoundingClientRect;

  function isSimpleClick(event) {
    var modifier = event.shiftKey || event.metaKey || event.altKey || event.ctrlKey;
    var secondaryClick = event.which > 1; // IE9 may return undefined

    return !modifier && !secondaryClick;
  }

  /**
    @private
    @method getViewRange
    @param {Ember.View} view
  */
  function getViewRange(view) {
    var range = document.createRange();
    range.setStartBefore(view._renderNode.firstNode);
    range.setEndAfter(view._renderNode.lastNode);
    return range;
  }

  /**
    `getViewClientRects` provides information about the position of the border
    box edges of a view relative to the viewport.

    It is only intended to be used by development tools like the Ember Inspector
    and may not work on older browsers.

    @private
    @method getViewClientRects
    @param {Ember.View} view
  */

  function getViewClientRects(view) {
    var range = getViewRange(view);
    return range.getClientRects();
  }

  /**
    `getViewBoundingClientRect` provides information about the position of the
    bounding border box edges of a view relative to the viewport.

    It is only intended to be used by development tools like the Ember Inpsector
    and may not work on older browsers.

    @private
    @method getViewBoundingClientRect
    @param {Ember.View} view
  */

  function getViewBoundingClientRect(view) {
    var range = getViewRange(view);
    return range.getBoundingClientRect();
  }
});
enifed('ember-views/views/checkbox', ['exports', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-views/components/component'], function (exports, _emberMetalProperty_get, _emberMetalProperty_set, _emberViewsComponentsComponent) {
  'use strict';

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

  /**
    The internal class used to create text inputs when the `{{input}}`
    helper is used with `type` of `checkbox`.

    See [Ember.Templates.helpers.input](/api/classes/Ember.Templates.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.Component
    @public
  */
  exports.default = _emberViewsComponentsComponent.default.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,

    didInsertElement: function () {
      this._super.apply(this, arguments);
      _emberMetalProperty_get.get(this, 'element').indeterminate = !!_emberMetalProperty_get.get(this, 'indeterminate');
    },

    change: function () {
      _emberMetalProperty_set.set(this, 'checked', this.$().prop('checked'));
    }
  });
});
enifed('ember-views/views/core_view', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-runtime/system/object', 'ember-runtime/mixins/evented', 'ember-runtime/mixins/action_handler', 'ember-runtime/utils', 'ember-metal-views', 'ember-views/views/states', 'htmlbars-runtime', 'require'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberRuntimeSystemObject, _emberRuntimeMixinsEvented, _emberRuntimeMixinsAction_handler, _emberRuntimeUtils, _emberMetalViews, _emberViewsViewsStates, _htmlbarsRuntime, _require) {
  'use strict';

  // Normally, the renderer is injected by the container when the view is looked
  // up. However, if someone creates a view without looking it up via the
  // container (e.g. `Ember.View.create().append()`) then we create a fallback
  // DOM renderer that is shared. In general, this path should be avoided since
  // views created this way cannot run in a node environment.
  var renderer;

  /**
    `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 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
    @deprecated Use `Ember.View` instead.
    @uses Ember.Evented
    @uses Ember.ActionHandler
    @private
  */
  var CoreView = _emberRuntimeSystemObject.default.extend(_emberRuntimeMixinsEvented.default, _emberRuntimeMixinsAction_handler.default, {
    isView: true,

    _states: _emberViewsViewsStates.cloneStates(_emberViewsViewsStates.states),

    init: function () {
      this._super.apply(this, arguments);
      this._state = 'preRender';
      this._currentState = this._states.preRender;
      this._isVisible = _emberMetalProperty_get.get(this, 'isVisible');

      // Fallback for legacy cases where the view was created directly
      // via `create()` instead of going through the container.
      if (!this.renderer) {
        var DOMHelper = domHelper();
        renderer = renderer || _emberMetalViews.InteractiveRenderer.create({ dom: new DOMHelper() });
        this.renderer = renderer;
      }

      this._destroyingSubtreeForView = null;
      this._dispatching = null;
    },

    /**
      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
      @private
    */
    parentView: null,

    instrumentName: 'core_view',

    instrumentDetails: function (hash) {
      hash.object = this.toString();
      hash.containerKey = this._debugContainerKey;
      hash.view = this;
    },

    /**
      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);
      }
    },

    has: function (name) {
      return _emberRuntimeUtils.typeOf(this[name]) === 'function' || this._super(name);
    },

    destroy: function () {
      if (!this._super.apply(this, arguments)) {
        return;
      }

      this._currentState.cleanup(this);

      // If the destroyingSubtreeForView property is not set but we have an
      // associated render node, it means this view is being destroyed from user
      // code and not via a change in the templating layer (like an {{if}}
      // becoming falsy, for example).  In this case, it is our responsibility to
      // make sure that any render nodes created as part of the rendering process
      // are cleaned up.
      if (!this.ownerView._destroyingSubtreeForView && this._renderNode) {
        _emberMetalDebug.assert('BUG: Render node exists without concomitant env.', this.ownerView.env);
        _htmlbarsRuntime.internal.clearMorph(this._renderNode, this.ownerView.env, true);
      }

      return this;
    }
  });

  _emberRuntimeMixinsAction_handler.deprecateUnderscoreActions(CoreView);

  CoreView.reopenClass({
    isViewFactory: true
  });

  var _domHelper;
  function domHelper() {
    return _domHelper = _domHelper || _require.default('ember-htmlbars/system/dom-helper').default;
  }

  exports.default = CoreView;
});
enifed('ember-views/views/states', ['exports', 'ember-metal/assign', 'ember-views/views/states/default', 'ember-views/views/states/pre_render', 'ember-views/views/states/has_element', 'ember-views/views/states/in_dom', 'ember-views/views/states/destroying'], function (exports, _emberMetalAssign, _emberViewsViewsStatesDefault, _emberViewsViewsStatesPre_render, _emberViewsViewsStatesHas_element, _emberViewsViewsStatesIn_dom, _emberViewsViewsStatesDestroying) {
  'use strict';

  exports.cloneStates = cloneStates;

  function cloneStates(from) {
    var into = {};

    into._default = {};
    into.preRender = Object.create(into._default);
    into.destroying = Object.create(into._default);
    into.hasElement = Object.create(into._default);
    into.inDOM = Object.create(into.hasElement);

    for (var stateName in from) {
      if (!from.hasOwnProperty(stateName)) {
        continue;
      }
      _emberMetalAssign.default(into[stateName], from[stateName]);
    }

    return into;
  }

  var states = {
    _default: _emberViewsViewsStatesDefault.default,
    preRender: _emberViewsViewsStatesPre_render.default,
    inDOM: _emberViewsViewsStatesIn_dom.default,
    hasElement: _emberViewsViewsStatesHas_element.default,
    destroying: _emberViewsViewsStatesDestroying.default
  };
  exports.states = states;
});
enifed('ember-views/views/states/default', ['exports', 'ember-metal/error', 'ember-metal/property_get', 'ember-views/compat/attrs-proxy'], function (exports, _emberMetalError, _emberMetalProperty_get, _emberViewsCompatAttrsProxy) {
  'use strict';

  /**
  @module ember
  @submodule ember-views
  */
  exports.default = {
    // appendChild is only legal while rendering the buffer.
    appendChild: function () {
      throw new _emberMetalError.default('You can\'t use appendChild outside of the rendering process');
    },

    $: function () {
      return undefined;
    },

    getElement: function () {
      return null;
    },

    legacyPropertyDidChange: function (view, key) {
      var attrs = view.attrs;
      if (attrs && key in attrs) {
        var possibleCell = attrs[key];

        if (possibleCell && possibleCell[_emberViewsCompatAttrsProxy.MUTABLE_CELL]) {
          var value = _emberMetalProperty_get.get(view, key);
          if (value === possibleCell.value) {
            return;
          }
          possibleCell.update(value);
        }
      }
    },

    // Handle events from `Ember.EventDispatcher`
    handleEvent: function () {
      return true; // continue event propagation
    },

    cleanup: function () {},
    destroyElement: function () {},

    rerender: function (view) {
      view.renderer.ensureViewNotRendering(view);
    },
    invokeObserver: function () {}
  };
});
enifed('ember-views/views/states/destroying', ['exports', 'ember-metal/assign', 'ember-views/views/states/default', 'ember-metal/error'], function (exports, _emberMetalAssign, _emberViewsViewsStatesDefault, _emberMetalError) {
  'use strict';

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

  var destroying = Object.create(_emberViewsViewsStatesDefault.default);

  _emberMetalAssign.default(destroying, {
    appendChild: function () {
      throw new _emberMetalError.default('You can\'t call appendChild on a view being destroyed');
    },
    rerender: function () {
      throw new _emberMetalError.default('You can\'t call rerender on a view being destroyed');
    },
    destroyElement: function () {
      throw new _emberMetalError.default('You can\'t call destroyElement on a view being destroyed');
    }
  });

  exports.default = destroying;
});
enifed('ember-views/views/states/has_element', ['exports', 'ember-views/views/states/default', 'ember-metal/assign', 'ember-views/system/jquery', 'ember-metal/run_loop', 'ember-metal/instrumentation', 'ember-metal/property_get'], function (exports, _emberViewsViewsStatesDefault, _emberMetalAssign, _emberViewsSystemJquery, _emberMetalRun_loop, _emberMetalInstrumentation, _emberMetalProperty_get) {
  'use strict';

  var hasElement = Object.create(_emberViewsViewsStatesDefault.default);

  _emberMetalAssign.default(hasElement, {
    $: function (view, sel) {
      var elem = view.element;
      return sel ? _emberViewsSystemJquery.default(sel, elem) : _emberViewsSystemJquery.default(elem);
    },

    getElement: function (view) {
      var parent = _emberMetalProperty_get.get(view, 'parentView');
      if (parent) {
        parent = _emberMetalProperty_get.get(parent, 'element');
      }
      if (parent) {
        return view.findElementInParentElement(parent);
      }
      return _emberViewsSystemJquery.default('#' + _emberMetalProperty_get.get(view, 'elementId'))[0];
    },

    // once the view has been inserted into the DOM, rerendering is
    // deferred to allow bindings to synchronize.
    rerender: function (view) {
      view.renderer.ensureViewNotRendering(view);
      view.renderer.rerender(view);
    },

    cleanup: function (view) {
      view._currentState.destroyElement(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.renderer.remove(view, false);
      return view;
    },

    // Handle events from `Ember.EventDispatcher`
    handleEvent: function (view, eventName, event) {
      if (view.has(eventName)) {
        // Handler should be able to re-dispatch events, so we don't
        // preventDefault or stopPropagation.
        return _emberMetalInstrumentation.flaggedInstrument('interaction.' + eventName, { event: event, view: view }, function () {
          return _emberMetalRun_loop.default.join(view, view.trigger, eventName, event);
        });
      } else {
        return true; // continue event propagation
      }
    },

    invokeObserver: function (target, observer) {
      observer.call(target);
    }
  });

  exports.default = hasElement;
});

/**
@module ember
@submodule ember-views
*/
enifed('ember-views/views/states/in_dom', ['exports', 'ember-metal/debug', 'ember-metal/assign', 'ember-metal/error', 'ember-metal/observer', 'ember-views/views/states/has_element'], function (exports, _emberMetalDebug, _emberMetalAssign, _emberMetalError, _emberMetalObserver, _emberViewsViewsStatesHas_element) {
  'use strict';

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

  var inDOM = Object.create(_emberViewsViewsStatesHas_element.default);

  _emberMetalAssign.default(inDOM, {
    enter: function (view) {
      // Register the view for event handling. This hash is used by
      // Ember.EventDispatcher to dispatch incoming events.
      if (view.tagName !== '') {
        view._register();
      }

      _emberMetalDebug.runInDebug(function () {
        _emberMetalObserver._addBeforeObserver(view, 'elementId', function () {
          throw new _emberMetalError.default('Changing a view\'s elementId after creation is not allowed');
        });
      });
    },

    exit: function (view) {
      view._unregister();
    }
  });

  exports.default = inDOM;
});
enifed('ember-views/views/states/pre_render', ['exports', 'ember-views/views/states/default', 'ember-metal/assign'], function (exports, _emberViewsViewsStatesDefault, _emberMetalAssign) {
  'use strict';

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

  var preRender = Object.create(_emberViewsViewsStatesDefault.default);

  _emberMetalAssign.default(preRender, {
    legacyPropertyDidChange: function (view, key) {}
  });

  exports.default = preRender;
});
enifed('ember-views/views/text_area', ['exports', 'ember-views/components/component', 'ember-views/mixins/text_support'], function (exports, _emberViewsComponentsComponent, _emberViewsMixinsText_support) {
  /**
  @module ember
  @submodule ember-views
  */
  'use strict';

  /**
    The internal class used to create textarea element when the `{{textarea}}`
    helper is used.

    See [Ember.Templates.helpers.textarea](/api/classes/Ember.Templates.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
    @public
  */
  exports.default = _emberViewsComponentsComponent.default.extend(_emberViewsMixinsText_support.default, {
    instrumentDisplay: '{{textarea}}',

    classNames: ['ember-text-area'],

    tagName: 'textarea',
    attributeBindings: ['rows', 'cols', 'name', 'selectionEnd', 'selectionStart', 'wrap', 'lang', 'dir', 'value'],
    rows: null,
    cols: null
  });
});
enifed('ember-views/views/text_field', ['exports', 'ember-metal/computed', 'ember-metal/environment', 'ember-views/components/component', 'ember-views/mixins/text_support', 'ember-metal/empty_object'], function (exports, _emberMetalComputed, _emberMetalEnvironment, _emberViewsComponentsComponent, _emberViewsMixinsText_support, _emberMetalEmpty_object) {
  /**
  @module ember
  @submodule ember-views
  */
  'use strict';

  var inputTypeTestElement;
  var inputTypes = new _emberMetalEmpty_object.default();
  function canSetTypeOfInput(type) {
    if (type in inputTypes) {
      return inputTypes[type];
    }

    // if running in outside of a browser always return the
    // original type
    if (!_emberMetalEnvironment.default.hasDOM) {
      inputTypes[type] = type;

      return type;
    }

    if (!inputTypeTestElement) {
      inputTypeTestElement = document.createElement('input');
    }

    try {
      inputTypeTestElement.type = type;
    } catch (e) {}

    return inputTypes[type] = inputTypeTestElement.type === type;
  }

  /**

    The internal class used to create text inputs when the `{{input}}`
    helper is used with `type` of `text`.

    See [Ember.Templates.helpers.input](/api/classes/Ember.Templates.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
    @public
  */
  exports.default = _emberViewsComponentsComponent.default.extend(_emberViewsMixinsText_support.default, {
    instrumentDisplay: '{{input type="text"}}',

    classNames: ['ember-text-field'],
    tagName: 'input',
    attributeBindings: ['accept', 'autocomplete', 'autosave', 'dir', 'formaction', 'formenctype', 'formmethod', 'formnovalidate', 'formtarget', 'height', 'inputmode', 'lang', 'list', 'max', 'min', 'multiple', 'name', 'pattern', 'size', 'step', 'type', 'value', 'width'],

    defaultLayout: null,

    /**
      The `value` attribute of the input element. As the user inputs text, this
      property is updated live.
       @property value
      @type String
      @default ""
      @public
    */
    value: '',

    /**
      The `type` attribute of the input element.
       @property type
      @type String
      @default "text"
      @public
    */
    type: _emberMetalComputed.computed({
      get: function () {
        return 'text';
      },

      set: function (key, value) {
        var type = 'text';

        if (canSetTypeOfInput(value)) {
          type = value;
        }

        return type;
      }
    }),

    /**
      The `size` of the text field in characters.
       @property size
      @type String
      @default null
      @public
    */
    size: null,

    /**
      The `pattern` attribute of input element.
       @property pattern
      @type String
      @default null
      @public
    */
    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
      @public
    */
    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
      @public
    */
    max: null
  });
});
enifed('ember-views/views/view', ['exports', 'ember-views/system/ext', 'ember-views/views/core_view', 'ember-views/mixins/view_context_support', 'ember-views/mixins/view_child_views_support', 'ember-views/mixins/legacy_child_views_support', 'ember-views/mixins/view_state_support', 'ember-views/mixins/template_rendering_support', 'ember-views/mixins/class_names_support', 'ember-views/mixins/legacy_view_support', 'ember-views/mixins/instrumentation_support', 'ember-views/mixins/aria_role_support', 'ember-views/mixins/visibility_support', 'ember-views/compat/attrs-proxy', 'ember-views/mixins/view_support'], function (exports, _emberViewsSystemExt, _emberViewsViewsCore_view, _emberViewsMixinsView_context_support, _emberViewsMixinsView_child_views_support, _emberViewsMixinsLegacy_child_views_support, _emberViewsMixinsView_state_support, _emberViewsMixinsTemplate_rendering_support, _emberViewsMixinsClass_names_support, _emberViewsMixinsLegacy_view_support, _emberViewsMixinsInstrumentation_support, _emberViewsMixinsAria_role_support, _emberViewsMixinsVisibility_support, _emberViewsCompatAttrsProxy, _emberViewsMixinsView_support) {
  // jQuery, Ember.lookup,
  // Ember.ENV
  'use strict';

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

  /**
    `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: Ember.computed(function() {
        if (someLogic) { return 'from-b'; }
      })
    });
    ```

    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 representation 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 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>
    ```

    Namespaced attributes (e.g. `xlink:href`) are supported, but have to be
    mapped, since `:` is not a valid character for properties in Javascript:

    ```javascript
    UseView = Ember.View.extend({
      tagName: 'use',
      attributeBindings: ['xlinkHref:xlink:href'],
      xlinkHref: '#triangle'
    });
    ```
    Will result in view instances with an HTML representation of:

    ```html
    <use xlink:href="#triangle"></use>
    ```

    If the return value of an `attributeBindings` monitored property is a boolean
    the property's value will be set as a coerced string:

    ```javascript
    MyTextInput = Ember.View.extend({
      tagName: 'input',
      attributeBindings: ['disabled'],
      disabled: false
    });
    ```

    Will result in a view instance with an HTML representation of:

    ```html
    <input id="ember1" class="ember-view" disabled="false" />
    ```

    `attributeBindings` can refer to computed properties:

    ```javascript
    MyTextInput = Ember.View.extend({
      tagName: 'input',
      attributeBindings: ['disabled'],
      disabled: Ember.computed(function() {
        if (someLogic) {
          return true;
        } else {
          return false;
        }
      })
    });
    ```

    To prevent setting an attribute altogether, use `null` or `undefined` as the
    return value of the `attributeBindings` monitored property:

    ```javascript
    MyTextInput = Ember.View.extend({
      tagName: 'form',
      attributeBindings: ['novalidate'],
      novalidate: null
    });
    ```

    Updates to 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
    template.

    ```javascript
    AView = Ember.View.extend({
      template: Ember.HTMLBars.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 routes, 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 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}}` 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.HTMLBars.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.HTMLBars.compile('I was the default')
    });

    aView = AView.create({
      template: Ember.HTMLBars.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.HTMLBars.compile('Hello {{excitedGreeting}}')
    });

    aController = Ember.Object.create({
      firstName: 'Barry',
      excitedGreeting: Ember.computed('content.firstName', function() {
        return this.get('content.firstName') + '!!!';
      })
    });

    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 template.

    A view's layout can be set directly with the `layout` property or reference
    an existing template by name with the `layoutName` property.

    A template used as a layout must contain a single use of the
    `{{yield}}` helper. The HTML contents of a view's rendered `template` will be
    inserted at this location:

    ```javascript
    AViewWithLayout = Ember.View.extend({
      layout: Ember.HTMLBars.compile("<div class='my-decorative-class'>{{yield}}</div>"),
      template: Ember.HTMLBars.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.Templates.helpers.yield](/api/classes/Ember.Templates.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 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
    descendant views.

    ```javascript
    AView = Ember.View.extend({
      eventManager: Ember.Object.create({
        doubleClick: function(event, view) {
          // will be called when an instance's
          // rendered element or any rendering
          // of this view's descendant
          // 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 descendant. 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 descendant.

    ```javascript
    var App = Ember.Application.create();
    App.OuterView = Ember.View.extend({
      template: Ember.HTMLBars.compile("outer {{#view 'inner'}}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 occurred
        }
      })
    });

    App.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.
      }
    });
    ```

    ### `{{action}}` Helper

    See [Ember.Templates.helpers.action](/api/classes/Ember.Templates.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`

    ## `{{view}}` Helper

    Other `Ember.View` instances can be included as part of a view's template by
    using the `{{view}}` helper. See [Ember.Templates.helpers.view](/api/classes/Ember.Templates.helpers.html#method_view)
    for additional information.

    @class View
    @namespace Ember
    @extends Ember.CoreView
    @deprecated See http://emberjs.com/deprecations/v1.x/#toc_ember-view
    @uses Ember.ViewSupport
    @uses Ember.ViewContextSupport
    @uses Ember.ViewChildViewsSupport
    @uses Ember.TemplateRenderingSupport
    @uses Ember.ClassNamesSupport
    @uses Ember.AttributeBindingsSupport
    @uses Ember.LegacyViewSupport
    @uses Ember.InstrumentationSupport
    @uses Ember.VisibilitySupport
    @uses Ember.AriaRoleSupport
    @public
  */
  // jscs:disable validateIndentation
  var View = _emberViewsViewsCore_view.default.extend(_emberViewsMixinsView_context_support.default, _emberViewsMixinsView_child_views_support.default, _emberViewsMixinsLegacy_child_views_support.default, _emberViewsMixinsView_state_support.default, _emberViewsMixinsTemplate_rendering_support.default, _emberViewsMixinsClass_names_support.default, _emberViewsMixinsLegacy_view_support.default, _emberViewsMixinsInstrumentation_support.default, _emberViewsMixinsVisibility_support.default, _emberViewsCompatAttrsProxy.default, _emberViewsMixinsAria_role_support.default, _emberViewsMixinsView_support.default, {
    init: function () {
      this._super.apply(this, arguments);

      if (!this._viewRegistry) {
        this._viewRegistry = View.views;
      }
    },

    /**
      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 (parsedPath) {
      return View._classStringForValue(parsedPath.path, parsedPath.stream.value(), parsedPath.className, parsedPath.falsyClassName);
    }
  });

  // jscs:enable validateIndentation

  /*
    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.

  View.reopenClass({
    /**
      Global views hash
       @property views
      @static
      @type Object
      @private
    */
    views: {}
  });

  exports.default = View;
  exports.ViewContextSupport = _emberViewsMixinsView_context_support.default;
  exports.ViewChildViewsSupport = _emberViewsMixinsView_child_views_support.default;
  exports.ViewStateSupport = _emberViewsMixinsView_state_support.default;
  exports.TemplateRenderingSupport = _emberViewsMixinsTemplate_rendering_support.default;
  exports.ClassNamesSupport = _emberViewsMixinsClass_names_support.default;
});
// for the side effect of extending Ember.run.queues
enifed('ember/index', ['exports', 'ember-metal', 'ember-runtime', 'ember-views', 'ember-routing', 'ember-application', 'ember-extension-support', 'ember-htmlbars', 'ember-routing-htmlbars', 'ember-routing-views', 'require', 'ember-runtime/system/lazy_load'], function (exports, _emberMetal, _emberRuntime, _emberViews, _emberRouting, _emberApplication, _emberExtensionSupport, _emberHtmlbars, _emberRoutingHtmlbars, _emberRoutingViews, _require, _emberRuntimeSystemLazy_load) {
  // require the main entry points for each of these packages
  // this is so that the global exports occur properly
  'use strict';

  if (_require.has('ember-template-compiler')) {
    _require.default('ember-template-compiler');
  }

  // do this to ensure that Ember.Test is defined properly on the global
  // if it is present.
  if (_require.has('ember-testing')) {
    _require.default('ember-testing');
  }

  _emberRuntimeSystemLazy_load.runLoadHooks('Ember');

  /**
  @module ember
  */
});
enifed('htmlbars-runtime', ['exports', 'htmlbars-runtime/hooks', 'htmlbars-runtime/render', 'htmlbars-util/morph-utils', 'htmlbars-util/template-utils'], function (exports, _htmlbarsRuntimeHooks, _htmlbarsRuntimeRender, _htmlbarsUtilMorphUtils, _htmlbarsUtilTemplateUtils) {
  'use strict';

  var internal = {
    blockFor: _htmlbarsUtilTemplateUtils.blockFor,
    manualElement: _htmlbarsRuntimeRender.manualElement,
    hostBlock: _htmlbarsRuntimeHooks.hostBlock,
    continueBlock: _htmlbarsRuntimeHooks.continueBlock,
    hostYieldWithShadowTemplate: _htmlbarsRuntimeHooks.hostYieldWithShadowTemplate,
    visitChildren: _htmlbarsUtilMorphUtils.visitChildren,
    validateChildMorphs: _htmlbarsUtilMorphUtils.validateChildMorphs,
    clearMorph: _htmlbarsUtilTemplateUtils.clearMorph
  };

  exports.hooks = _htmlbarsRuntimeHooks.default;
  exports.render = _htmlbarsRuntimeRender.default;
  exports.internal = internal;
});
enifed('htmlbars-runtime/expression-visitor', ['exports'], function (exports) {
  /**
    # Expression Nodes:

    These nodes are not directly responsible for any part of the DOM, but are
    eventually passed to a Statement Node.

    * get
    * subexpr
    * concat
  */

  'use strict';

  exports.acceptParams = acceptParams;
  exports.acceptHash = acceptHash;

  function acceptParams(nodes, env, scope) {
    var array = [];

    for (var i = 0, l = nodes.length; i < l; i++) {
      array.push(acceptExpression(nodes[i], env, scope).value);
    }

    return array;
  }

  function acceptHash(pairs, env, scope) {
    var object = {};

    for (var i = 0, l = pairs.length; i < l; i += 2) {
      var key = pairs[i];
      var value = pairs[i + 1];
      object[key] = acceptExpression(value, env, scope).value;
    }

    return object;
  }

  function acceptExpression(node, env, scope) {
    var ret = { value: null };

    // Primitive literals are unambiguously non-array representations of
    // themselves.
    if (typeof node !== 'object' || node === null) {
      ret.value = node;
    } else {
      ret.value = evaluateNode(node, env, scope);
    }

    return ret;
  }

  function evaluateNode(node, env, scope) {
    switch (node[0]) {
      // can be used by manualElement
      case 'value':
        return node[1];
      case 'get':
        return evaluateGet(node, env, scope);
      case 'subexpr':
        return evaluateSubexpr(node, env, scope);
      case 'concat':
        return evaluateConcat(node, env, scope);
    }
  }

  function evaluateGet(node, env, scope) {
    var path = node[1];

    return env.hooks.get(env, scope, path);
  }

  function evaluateSubexpr(node, env, scope) {
    var path = node[1];
    var rawParams = node[2];
    var rawHash = node[3];

    var params = acceptParams(rawParams, env, scope);
    var hash = acceptHash(rawHash, env, scope);

    return env.hooks.subexpr(env, scope, path, params, hash);
  }

  function evaluateConcat(node, env, scope) {
    var rawParts = node[1];

    var parts = acceptParams(rawParts, env, scope);

    return env.hooks.concat(env, parts);
  }
});
enifed("htmlbars-runtime/hooks", ["exports", "htmlbars-runtime/render", "morph-range/morph-list", "htmlbars-util/object-utils", "htmlbars-util/morph-utils", "htmlbars-util/template-utils"], function (exports, _htmlbarsRuntimeRender, _morphRangeMorphList, _htmlbarsUtilObjectUtils, _htmlbarsUtilMorphUtils, _htmlbarsUtilTemplateUtils) {
  "use strict";

  exports.wrap = wrap;
  exports.wrapForHelper = wrapForHelper;
  exports.createScope = createScope;
  exports.createFreshScope = createFreshScope;
  exports.bindShadowScope = bindShadowScope;
  exports.createChildScope = createChildScope;
  exports.bindSelf = bindSelf;
  exports.updateSelf = updateSelf;
  exports.bindLocal = bindLocal;
  exports.updateLocal = updateLocal;
  exports.bindBlock = bindBlock;
  exports.block = block;
  exports.continueBlock = continueBlock;
  exports.hostBlock = hostBlock;
  exports.handleRedirect = handleRedirect;
  exports.handleKeyword = handleKeyword;
  exports.linkRenderNode = linkRenderNode;
  exports.inline = inline;
  exports.keyword = keyword;
  exports.invokeHelper = invokeHelper;
  exports.classify = classify;
  exports.partial = partial;
  exports.range = range;
  exports.element = element;
  exports.attribute = attribute;
  exports.subexpr = subexpr;
  exports.get = get;
  exports.getRoot = getRoot;
  exports.getBlock = getBlock;
  exports.getChild = getChild;
  exports.getValue = getValue;
  exports.getCellOrValue = getCellOrValue;
  exports.component = component;
  exports.concat = concat;
  exports.hasHelper = hasHelper;
  exports.lookupHelper = lookupHelper;
  exports.bindScope = bindScope;
  exports.updateScope = updateScope;

  /**
    HTMLBars delegates the runtime behavior of a template to
    hooks provided by the host environment. These hooks explain
    the lexical environment of a Handlebars template, the internal
    representation of references, and the interaction between an
    HTMLBars template and the DOM it is managing.

    While HTMLBars host hooks have access to all of this internal
    machinery, templates and helpers have access to the abstraction
    provided by the host hooks.

    ## The Lexical Environment

    The default lexical environment of an HTMLBars template includes:

    * Any local variables, provided by *block arguments*
    * The current value of `self`

    ## Simple Nesting

    Let's look at a simple template with a nested block:

    ```hbs
    <h1>{{title}}</h1>

    {{#if author}}
      <p class="byline">{{author}}</p>
    {{/if}}
    ```

    In this case, the lexical environment at the top-level of the
    template does not change inside of the `if` block. This is
    achieved via an implementation of `if` that looks like this:

    ```js
    registerHelper('if', function(params) {
      if (!!params[0]) {
        return this.yield();
      }
    });
    ```

    A call to `this.yield` invokes the child template using the
    current lexical environment.

    ## Block Arguments

    It is possible for nested blocks to introduce new local
    variables:

    ```hbs
    {{#count-calls as |i|}}
    <h1>{{title}}</h1>
    <p>Called {{i}} times</p>
    {{/count}}
    ```

    In this example, the child block inherits its surrounding
    lexical environment, but augments it with a single new
    variable binding.

    The implementation of `count-calls` supplies the value of
    `i`, but does not otherwise alter the environment:

    ```js
    var count = 0;
    registerHelper('count-calls', function() {
      return this.yield([ ++count ]);
    });
    ```
  */

  function wrap(template) {
    if (template === null) {
      return null;
    }

    return {
      meta: template.meta,
      arity: template.arity,
      raw: template,
      render: function (self, env, options, blockArguments) {
        var scope = env.hooks.createFreshScope();

        var contextualElement = options && options.contextualElement;
        var renderOptions = new _htmlbarsRuntimeRender.RenderOptions(null, self, blockArguments, contextualElement);

        return _htmlbarsRuntimeRender.default(template, env, scope, renderOptions);
      }
    };
  }

  function wrapForHelper(template, env, scope, morph, renderState, visitor) {
    if (!template) {
      return {};
    }

    var yieldArgs = yieldTemplate(template, env, scope, morph, renderState, visitor);

    return {
      meta: template.meta,
      arity: template.arity,
      'yield': yieldArgs, // quoted since it's a reserved word, see issue #420
      yieldItem: yieldItem(template, env, scope, morph, renderState, visitor),
      raw: template,

      render: function (self, blockArguments) {
        yieldArgs(blockArguments, self);
      }
    };
  }

  // Called by a user-land helper to render a template.
  function yieldTemplate(template, env, parentScope, morph, renderState, visitor) {
    return function (blockArguments, self) {
      // Render state is used to track the progress of the helper (since it
      // may call into us multiple times). As the user-land helper calls
      // into library code, we track what needs to be cleaned up after the
      // helper has returned.
      //
      // Here, we remember that a template has been yielded and so we do not
      // need to remove the previous template. (If no template is yielded
      // this render by the helper, we assume nothing should be shown and
      // remove any previous rendered templates.)
      renderState.morphToClear = null;

      // In this conditional is true, it means that on the previous rendering pass
      // the helper yielded multiple items via `yieldItem()`, but this time they
      // are yielding a single template. In that case, we mark the morph list for
      // cleanup so it is removed from the DOM.
      if (morph.morphList) {
        _htmlbarsUtilTemplateUtils.clearMorphList(morph.morphList, morph, env);
        renderState.morphListToClear = null;
      }

      var scope = parentScope;

      if (morph.lastYielded && isStableTemplate(template, morph.lastYielded)) {
        return morph.lastResult.revalidateWith(env, undefined, self, blockArguments, visitor);
      }

      // Check to make sure that we actually **need** a new scope, and can't
      // share the parent scope. Note that we need to move this check into
      // a host hook, because the host's notion of scope may require a new
      // scope in more cases than the ones we can determine statically.
      if (self !== undefined || parentScope === null || template.arity) {
        scope = env.hooks.createChildScope(parentScope);
      }

      morph.lastYielded = { self: self, template: template, shadowTemplate: null };

      // Render the template that was selected by the helper
      var renderOptions = new _htmlbarsRuntimeRender.RenderOptions(morph, self, blockArguments);
      _htmlbarsRuntimeRender.default(template, env, scope, renderOptions);
    };
  }

  function yieldItem(template, env, parentScope, morph, renderState, visitor) {
    // Initialize state that tracks multiple items being
    // yielded in.
    var currentMorph = null;

    // Candidate morphs for deletion.
    var candidates = {};

    // Reuse existing MorphList if this is not a first-time
    // render.
    var morphList = morph.morphList;
    if (morphList) {
      currentMorph = morphList.firstChildMorph;
    }

    // Advances the currentMorph pointer to the morph in the previously-rendered
    // list that matches the yielded key. While doing so, it marks any morphs
    // that it advances past as candidates for deletion. Assuming those morphs
    // are not yielded in later, they will be removed in the prune step during
    // cleanup.
    // Note that this helper function assumes that the morph being seeked to is
    // guaranteed to exist in the previous MorphList; if this is called and the
    // morph does not exist, it will result in an infinite loop
    function advanceToKey(key) {
      var seek = currentMorph;

      while (seek.key !== key) {
        candidates[seek.key] = seek;
        seek = seek.nextMorph;
      }

      currentMorph = seek.nextMorph;
      return seek;
    }

    return function (_key, blockArguments, self) {
      if (typeof _key !== 'string') {
        throw new Error("You must provide a string key when calling `yieldItem`; you provided " + _key);
      }

      // At least one item has been yielded, so we do not wholesale
      // clear the last MorphList but instead apply a prune operation.
      renderState.morphListToClear = null;
      morph.lastYielded = null;

      var morphList, morphMap;

      if (!morph.morphList) {
        morph.morphList = new _morphRangeMorphList.default();
        morph.morphMap = {};
        morph.setMorphList(morph.morphList);
      }

      morphList = morph.morphList;
      morphMap = morph.morphMap;

      // A map of morphs that have been yielded in on this
      // rendering pass. Any morphs that do not make it into
      // this list will be pruned from the MorphList during the cleanup
      // process.
      var handledMorphs = renderState.handledMorphs;
      var key = undefined;

      if (_key in handledMorphs) {
        // In this branch we are dealing with a duplicate key. The strategy
        // is to take the original key and append a counter to it that is
        // incremented every time the key is reused. In order to greatly
        // reduce the chance of colliding with another valid key we also add
        // an extra string "--z8mS2hvDW0A--" to the new key.
        var collisions = renderState.collisions;
        if (collisions === undefined) {
          collisions = renderState.collisions = {};
        }
        var count = collisions[_key] | 0;
        collisions[_key] = ++count;

        key = _key + '--z8mS2hvDW0A--' + count;
      } else {
        key = _key;
      }

      if (currentMorph && currentMorph.key === key) {
        yieldTemplate(template, env, parentScope, currentMorph, renderState, visitor)(blockArguments, self);
        currentMorph = currentMorph.nextMorph;
        handledMorphs[key] = currentMorph;
      } else if (morphMap[key] !== undefined) {
        var foundMorph = morphMap[key];

        if (key in candidates) {
          // If we already saw this morph, move it forward to this position
          morphList.insertBeforeMorph(foundMorph, currentMorph);
        } else {
          // Otherwise, move the pointer forward to the existing morph for this key
          advanceToKey(key);
        }

        handledMorphs[foundMorph.key] = foundMorph;
        yieldTemplate(template, env, parentScope, foundMorph, renderState, visitor)(blockArguments, self);
      } else {
        var childMorph = _htmlbarsRuntimeRender.createChildMorph(env.dom, morph);
        childMorph.key = key;
        morphMap[key] = handledMorphs[key] = childMorph;
        morphList.insertBeforeMorph(childMorph, currentMorph);
        yieldTemplate(template, env, parentScope, childMorph, renderState, visitor)(blockArguments, self);
      }

      renderState.morphListToPrune = morphList;
      morph.childNodes = null;
    };
  }

  function isStableTemplate(template, lastYielded) {
    return !lastYielded.shadowTemplate && template === lastYielded.template;
  }
  function optionsFor(template, inverse, env, scope, morph, visitor) {
    // If there was a template yielded last time, set morphToClear so it will be cleared
    // if no template is yielded on this render.
    var morphToClear = morph.lastResult ? morph : null;
    var renderState = new _htmlbarsUtilTemplateUtils.RenderState(morphToClear, morph.morphList || null);

    return {
      templates: {
        template: wrapForHelper(template, env, scope, morph, renderState, visitor),
        inverse: wrapForHelper(inverse, env, scope, morph, renderState, visitor)
      },
      renderState: renderState
    };
  }

  function thisFor(options) {
    return {
      arity: options.template.arity,
      'yield': options.template.yield, // quoted since it's a reserved word, see issue #420
      yieldItem: options.template.yieldItem,
      yieldIn: options.template.yieldIn
    };
  }

  /**
    Host Hook: createScope

    @param {Scope?} parentScope
    @return Scope

    Corresponds to entering a new HTMLBars block.

    This hook is invoked when a block is entered with
    a new `self` or additional local variables.

    When invoked for a top-level template, the
    `parentScope` is `null`, and this hook should return
    a fresh Scope.

    When invoked for a child template, the `parentScope`
    is the scope for the parent environment.

    Note that the `Scope` is an opaque value that is
    passed to other host hooks. For example, the `get`
    hook uses the scope to retrieve a value for a given
    scope and variable name.
  */

  function createScope(env, parentScope) {
    if (parentScope) {
      return env.hooks.createChildScope(parentScope);
    } else {
      return env.hooks.createFreshScope();
    }
  }

  function createFreshScope() {
    // because `in` checks have unpredictable performance, keep a
    // separate dictionary to track whether a local was bound.
    // See `bindLocal` for more information.
    return { self: null, blocks: {}, locals: {}, localPresent: {} };
  }

  /**
    Host Hook: bindShadowScope

    @param {Scope?} parentScope
    @return Scope

    Corresponds to rendering a new template into an existing
    render tree, but with a new top-level lexical scope. This
    template is called the "shadow root".

    If a shadow template invokes `{{yield}}`, it will render
    the block provided to the shadow root in the original
    lexical scope.

    ```hbs
    {{!-- post template --}}
    <p>{{props.title}}</p>
    {{yield}}

    {{!-- blog template --}}
    {{#post title="Hello world"}}
      <p>by {{byline}}</p>
      <article>This is my first post</article>
    {{/post}}

    {{#post title="Goodbye world"}}
      <p>by {{byline}}</p>
      <article>This is my last post</article>
    {{/post}}
    ```

    ```js
    helpers.post = function(params, hash, options) {
      options.template.yieldIn(postTemplate, { props: hash });
    };

    blog.render({ byline: "Yehuda Katz" });
    ```

    Produces:

    ```html
    <p>Hello world</p>
    <p>by Yehuda Katz</p>
    <article>This is my first post</article>

    <p>Goodbye world</p>
    <p>by Yehuda Katz</p>
    <article>This is my last post</article>
    ```

    In short, `yieldIn` creates a new top-level scope for the
    provided template and renders it, making the original block
    available to `{{yield}}` in that template.
  */

  function bindShadowScope(env /*, parentScope, shadowScope */) {
    return env.hooks.createFreshScope();
  }

  function createChildScope(parent) {
    var scope = Object.create(parent);
    scope.locals = Object.create(parent.locals);
    scope.localPresent = Object.create(parent.localPresent);
    scope.blocks = Object.create(parent.blocks);
    return scope;
  }

  /**
    Host Hook: bindSelf

    @param {Scope} scope
    @param {any} self

    Corresponds to entering a template.

    This hook is invoked when the `self` value for a scope is ready to be bound.

    The host must ensure that child scopes reflect the change to the `self` in
    future calls to the `get` hook.
  */

  function bindSelf(env, scope, self) {
    scope.self = self;
  }

  function updateSelf(env, scope, self) {
    env.hooks.bindSelf(env, scope, self);
  }

  /**
    Host Hook: bindLocal

    @param {Environment} env
    @param {Scope} scope
    @param {String} name
    @param {any} value

    Corresponds to entering a template with block arguments.

    This hook is invoked when a local variable for a scope has been provided.

    The host must ensure that child scopes reflect the change in future calls
    to the `get` hook.
  */

  function bindLocal(env, scope, name, value) {
    scope.localPresent[name] = true;
    scope.locals[name] = value;
  }

  function updateLocal(env, scope, name, value) {
    env.hooks.bindLocal(env, scope, name, value);
  }

  /**
    Host Hook: bindBlock

    @param {Environment} env
    @param {Scope} scope
    @param {Function} block

    Corresponds to entering a shadow template that was invoked by a block helper with
    `yieldIn`.

    This hook is invoked with an opaque block that will be passed along
    to the shadow template, and inserted into the shadow template when
    `{{yield}}` is used. Optionally provide a non-default block name
    that can be targeted by `{{yield to=blockName}}`.
  */

  function bindBlock(env, scope, block) {
    var name = arguments.length <= 3 || arguments[3] === undefined ? 'default' : arguments[3];

    scope.blocks[name] = block;
  }

  /**
    Host Hook: block

    @param {RenderNode} renderNode
    @param {Environment} env
    @param {Scope} scope
    @param {String} path
    @param {Array} params
    @param {Object} hash
    @param {Block} block
    @param {Block} elseBlock

    Corresponds to:

    ```hbs
    {{#helper param1 param2 key1=val1 key2=val2}}
      {{!-- child template --}}
    {{/helper}}
    ```

    This host hook is a workhorse of the system. It is invoked
    whenever a block is encountered, and is responsible for
    resolving the helper to call, and then invoke it.

    The helper should be invoked with:

    - `{Array} params`: the parameters passed to the helper
      in the template.
    - `{Object} hash`: an object containing the keys and values passed
      in the hash position in the template.

    The values in `params` and `hash` will already be resolved
    through a previous call to the `get` host hook.

    The helper should be invoked with a `this` value that is
    an object with one field:

    `{Function} yield`: when invoked, this function executes the
    block with the current scope. It takes an optional array of
    block parameters. If block parameters are supplied, HTMLBars
    will invoke the `bindLocal` host hook to bind the supplied
    values to the block arguments provided by the template.

    In general, the default implementation of `block` should work
    for most host environments. It delegates to other host hooks
    where appropriate, and properly invokes the helper with the
    appropriate arguments.
  */

  function block(morph, env, scope, path, params, hash, template, inverse, visitor) {
    if (handleRedirect(morph, env, scope, path, params, hash, template, inverse, visitor)) {
      return;
    }

    continueBlock(morph, env, scope, path, params, hash, template, inverse, visitor);
  }

  function continueBlock(morph, env, scope, path, params, hash, template, inverse, visitor) {
    hostBlock(morph, env, scope, template, inverse, null, visitor, function (options) {
      var helper = env.hooks.lookupHelper(env, scope, path);
      return env.hooks.invokeHelper(morph, env, scope, visitor, params, hash, helper, options.templates, thisFor(options.templates));
    });
  }

  function hostBlock(morph, env, scope, template, inverse, shadowOptions, visitor, callback) {
    var options = optionsFor(template, inverse, env, scope, morph, visitor);
    _htmlbarsUtilTemplateUtils.renderAndCleanup(morph, env, options, shadowOptions, callback);
  }

  function handleRedirect(morph, env, scope, path, params, hash, template, inverse, visitor) {
    if (!path) {
      return false;
    }

    var redirect = env.hooks.classify(env, scope, path);
    if (redirect) {
      switch (redirect) {
        case 'component':
          env.hooks.component(morph, env, scope, path, params, hash, { default: template, inverse: inverse }, visitor);break;
        case 'inline':
          env.hooks.inline(morph, env, scope, path, params, hash, visitor);break;
        case 'block':
          env.hooks.block(morph, env, scope, path, params, hash, template, inverse, visitor);break;
        default:
          throw new Error("Internal HTMLBars redirection to " + redirect + " not supported");
      }
      return true;
    }

    if (handleKeyword(path, morph, env, scope, params, hash, template, inverse, visitor)) {
      return true;
    }

    return false;
  }

  function handleKeyword(path, morph, env, scope, params, hash, template, inverse, visitor) {
    var keyword = env.hooks.keywords[path];
    if (!keyword) {
      return false;
    }

    if (typeof keyword === 'function') {
      return keyword(morph, env, scope, params, hash, template, inverse, visitor);
    }

    if (keyword.willRender) {
      keyword.willRender(morph, env);
    }

    var lastState, newState;
    if (keyword.setupState) {
      lastState = _htmlbarsUtilObjectUtils.shallowCopy(morph.getState());
      newState = morph.setState(keyword.setupState(lastState, env, scope, params, hash));
    }

    if (keyword.childEnv) {
      // Build the child environment...
      env = keyword.childEnv(morph.getState(), env);

      // ..then save off the child env builder on the render node. If the render
      // node tree is re-rendered and this node is not dirty, the child env
      // builder will still be invoked so that child dirty render nodes still get
      // the correct child env.
      morph.buildChildEnv = keyword.childEnv;
    }

    var firstTime = !morph.rendered;

    if (keyword.isEmpty) {
      var isEmpty = keyword.isEmpty(morph.getState(), env, scope, params, hash);

      if (isEmpty) {
        if (!firstTime) {
          _htmlbarsUtilTemplateUtils.clearMorph(morph, env, false);
        }
        return true;
      }
    }

    if (firstTime) {
      if (keyword.render) {
        keyword.render(morph, env, scope, params, hash, template, inverse, visitor);
      }
      morph.rendered = true;
      return true;
    }

    var isStable;
    if (keyword.isStable) {
      isStable = keyword.isStable(lastState, newState);
    } else {
      isStable = stableState(lastState, newState);
    }

    if (isStable) {
      if (keyword.rerender) {
        var newEnv = keyword.rerender(morph, env, scope, params, hash, template, inverse, visitor);
        env = newEnv || env;
      }
      _htmlbarsUtilMorphUtils.validateChildMorphs(env, morph, visitor);
      return true;
    } else {
      _htmlbarsUtilTemplateUtils.clearMorph(morph, env, false);
    }

    // If the node is unstable, re-render from scratch
    if (keyword.render) {
      keyword.render(morph, env, scope, params, hash, template, inverse, visitor);
      morph.rendered = true;
      return true;
    }
  }

  function stableState(oldState, newState) {
    if (_htmlbarsUtilObjectUtils.keyLength(oldState) !== _htmlbarsUtilObjectUtils.keyLength(newState)) {
      return false;
    }

    for (var prop in oldState) {
      if (oldState[prop] !== newState[prop]) {
        return false;
      }
    }

    return true;
  }

  function linkRenderNode() /* morph, env, scope, params, hash */{
    return;
  }

  /**
    Host Hook: inline

    @param {RenderNode} renderNode
    @param {Environment} env
    @param {Scope} scope
    @param {String} path
    @param {Array} params
    @param {Hash} hash

    Corresponds to:

    ```hbs
    {{helper param1 param2 key1=val1 key2=val2}}
    ```

    This host hook is similar to the `block` host hook, but it
    invokes helpers that do not supply an attached block.

    Like the `block` hook, the helper should be invoked with:

    - `{Array} params`: the parameters passed to the helper
      in the template.
    - `{Object} hash`: an object containing the keys and values passed
      in the hash position in the template.

    The values in `params` and `hash` will already be resolved
    through a previous call to the `get` host hook.

    In general, the default implementation of `inline` should work
    for most host environments. It delegates to other host hooks
    where appropriate, and properly invokes the helper with the
    appropriate arguments.

    The default implementation of `inline` also makes `partial`
    a keyword. Instead of invoking a helper named `partial`,
    it invokes the `partial` host hook.
  */

  function inline(morph, env, scope, path, params, hash, visitor) {
    if (handleRedirect(morph, env, scope, path, params, hash, null, null, visitor)) {
      return;
    }

    var value = undefined,
        hasValue = undefined;
    if (morph.linkedResult) {
      value = env.hooks.getValue(morph.linkedResult);
      hasValue = true;
    } else {
      var options = optionsFor(null, null, env, scope, morph);

      var helper = env.hooks.lookupHelper(env, scope, path);
      var result = env.hooks.invokeHelper(morph, env, scope, visitor, params, hash, helper, options.templates, thisFor(options.templates));

      if (result && result.link) {
        morph.linkedResult = result.value;
        _htmlbarsUtilMorphUtils.linkParams(env, scope, morph, '@content-helper', [morph.linkedResult], null);
      }

      if (result && 'value' in result) {
        value = env.hooks.getValue(result.value);
        hasValue = true;
      }
    }

    if (hasValue) {
      if (morph.lastValue !== value) {
        morph.setContent(value);
      }
      morph.lastValue = value;
    }
  }

  function keyword(path, morph, env, scope, params, hash, template, inverse, visitor) {
    handleKeyword(path, morph, env, scope, params, hash, template, inverse, visitor);
  }

  function invokeHelper(morph, env, scope, visitor, _params, _hash, helper, templates, context) {
    var params = normalizeArray(env, _params);
    var hash = normalizeObject(env, _hash);
    return { value: helper.call(context, params, hash, templates) };
  }

  function normalizeArray(env, array) {
    var out = new Array(array.length);

    for (var i = 0, l = array.length; i < l; i++) {
      out[i] = env.hooks.getCellOrValue(array[i]);
    }

    return out;
  }

  function normalizeObject(env, object) {
    var out = {};

    for (var prop in object) {
      out[prop] = env.hooks.getCellOrValue(object[prop]);
    }

    return out;
  }

  function classify() /* env, scope, path */{
    return null;
  }

  var keywords = {
    partial: function (morph, env, scope, params) {
      var value = env.hooks.partial(morph, env, scope, params[0]);
      morph.setContent(value);
      return true;
    },

    // quoted since it's a reserved word, see issue #420
    'yield': function (morph, env, scope, params, hash, template, inverse, visitor) {
      // the current scope is provided purely for the creation of shadow
      // scopes; it should not be provided to user code.

      var to = env.hooks.getValue(hash.to) || 'default';
      var block = env.hooks.getBlock(scope, to);

      if (block) {
        block.invoke(env, params, hash.self, morph, scope, visitor);
      }
      return true;
    },

    hasBlock: function (morph, env, scope, params) {
      var name = env.hooks.getValue(params[0]) || 'default';
      return !!env.hooks.getBlock(scope, name);
    },

    hasBlockParams: function (morph, env, scope, params) {
      var name = env.hooks.getValue(params[0]) || 'default';
      var block = env.hooks.getBlock(scope, name);
      return !!(block && block.arity);
    }

  };

  exports.keywords = keywords;
  /**
    Host Hook: partial

    @param {RenderNode} renderNode
    @param {Environment} env
    @param {Scope} scope
    @param {String} path

    Corresponds to:

    ```hbs
    {{partial "location"}}
    ```

    This host hook is invoked by the default implementation of
    the `inline` hook. This makes `partial` a keyword in an
    HTMLBars environment using the default `inline` host hook.

    It is implemented as a host hook so that it can retrieve
    the named partial out of the `Environment`. Helpers, in
    contrast, only have access to the values passed in to them,
    and not to the ambient lexical environment.

    The host hook should invoke the referenced partial with
    the ambient `self`.
  */

  function partial(renderNode, env, scope, path) {
    var template = env.partials[path];
    return template.render(scope.self, env, {}).fragment;
  }

  /**
    Host hook: range

    @param {RenderNode} renderNode
    @param {Environment} env
    @param {Scope} scope
    @param {any} value

    Corresponds to:

    ```hbs
    {{content}}
    {{{unescaped}}}
    ```

    This hook is responsible for updating a render node
    that represents a range of content with a value.
  */

  function range(morph, env, scope, path, value, visitor) {
    if (handleRedirect(morph, env, scope, path, [], {}, null, null, visitor)) {
      return;
    }

    value = env.hooks.getValue(value);

    if (morph.lastValue !== value) {
      morph.setContent(value);
    }

    morph.lastValue = value;
  }

  /**
    Host hook: element

    @param {RenderNode} renderNode
    @param {Environment} env
    @param {Scope} scope
    @param {String} path
    @param {Array} params
    @param {Hash} hash

    Corresponds to:

    ```hbs
    <div {{bind-attr foo=bar}}></div>
    ```

    This hook is responsible for invoking a helper that
    modifies an element.

    Its purpose is largely legacy support for awkward
    idioms that became common when using the string-based
    Handlebars engine.

    Most of the uses of the `element` hook are expected
    to be superseded by component syntax and the
    `attribute` hook.
  */

  function element(morph, env, scope, path, params, hash, visitor) {
    if (handleRedirect(morph, env, scope, path, params, hash, null, null, visitor)) {
      return;
    }

    var helper = env.hooks.lookupHelper(env, scope, path);
    if (helper) {
      env.hooks.invokeHelper(null, env, scope, null, params, hash, helper, { element: morph.element });
    }
  }

  /**
    Host hook: attribute

    @param {RenderNode} renderNode
    @param {Environment} env
    @param {String} name
    @param {any} value

    Corresponds to:

    ```hbs
    <div foo={{bar}}></div>
    ```

    This hook is responsible for updating a render node
    that represents an element's attribute with a value.

    It receives the name of the attribute as well as an
    already-resolved value, and should update the render
    node with the value if appropriate.
  */

  function attribute(morph, env, scope, name, value) {
    value = env.hooks.getValue(value);

    if (morph.lastValue !== value) {
      morph.setContent(value);
    }

    morph.lastValue = value;
  }

  function subexpr(env, scope, helperName, params, hash) {
    var helper = env.hooks.lookupHelper(env, scope, helperName);
    var result = env.hooks.invokeHelper(null, env, scope, null, params, hash, helper, {});
    if (result && 'value' in result) {
      return env.hooks.getValue(result.value);
    }
  }

  /**
    Host Hook: get

    @param {Environment} env
    @param {Scope} scope
    @param {String} path

    Corresponds to:

    ```hbs
    {{foo.bar}}
      ^

    {{helper foo.bar key=value}}
             ^           ^
    ```

    This hook is the "leaf" hook of the system. It is used to
    resolve a path relative to the current scope.
  */

  function get(env, scope, path) {
    if (path === '') {
      return scope.self;
    }

    var keys = path.split('.');
    var value = env.hooks.getRoot(scope, keys[0])[0];

    for (var i = 1; i < keys.length; i++) {
      if (value) {
        value = env.hooks.getChild(value, keys[i]);
      } else {
        break;
      }
    }

    return value;
  }

  function getRoot(scope, key) {
    if (scope.localPresent[key]) {
      return [scope.locals[key]];
    } else if (scope.self) {
      return [scope.self[key]];
    } else {
      return [undefined];
    }
  }

  function getBlock(scope, key) {
    return scope.blocks[key];
  }

  function getChild(value, key) {
    return value[key];
  }

  function getValue(reference) {
    return reference;
  }

  function getCellOrValue(reference) {
    return reference;
  }

  function component(morph, env, scope, tagName, params, attrs, templates, visitor) {
    if (env.hooks.hasHelper(env, scope, tagName)) {
      return env.hooks.block(morph, env, scope, tagName, params, attrs, templates.default, templates.inverse, visitor);
    }

    componentFallback(morph, env, scope, tagName, attrs, templates.default);
  }

  function concat(env, params) {
    var value = "";
    for (var i = 0, l = params.length; i < l; i++) {
      value += env.hooks.getValue(params[i]);
    }
    return value;
  }

  function componentFallback(morph, env, scope, tagName, attrs, template) {
    var element = env.dom.createElement(tagName);
    for (var name in attrs) {
      element.setAttribute(name, env.hooks.getValue(attrs[name]));
    }
    var fragment = _htmlbarsRuntimeRender.default(template, env, scope, {}).fragment;
    element.appendChild(fragment);
    morph.setNode(element);
  }

  function hasHelper(env, scope, helperName) {
    return env.helpers[helperName] !== undefined;
  }

  function lookupHelper(env, scope, helperName) {
    return env.helpers[helperName];
  }

  function bindScope() /* env, scope */{
    // this function is used to handle host-specified extensions to scope
    // other than `self`, `locals` and `block`.
  }

  function updateScope(env, scope) {
    env.hooks.bindScope(env, scope);
  }

  exports.default = {
    // fundamental hooks that you will likely want to override
    bindLocal: bindLocal,
    bindSelf: bindSelf,
    bindScope: bindScope,
    classify: classify,
    component: component,
    concat: concat,
    createFreshScope: createFreshScope,
    getChild: getChild,
    getRoot: getRoot,
    getBlock: getBlock,
    getValue: getValue,
    getCellOrValue: getCellOrValue,
    keywords: keywords,
    linkRenderNode: linkRenderNode,
    partial: partial,
    subexpr: subexpr,

    // fundamental hooks with good default behavior
    bindBlock: bindBlock,
    bindShadowScope: bindShadowScope,
    updateLocal: updateLocal,
    updateSelf: updateSelf,
    updateScope: updateScope,
    createChildScope: createChildScope,
    hasHelper: hasHelper,
    lookupHelper: lookupHelper,
    invokeHelper: invokeHelper,
    cleanupRenderNode: null,
    destroyRenderNode: null,
    willCleanupTree: null,
    didCleanupTree: null,
    willRenderNode: null,
    didRenderNode: null,

    // derived hooks
    attribute: attribute,
    block: block,
    createScope: createScope,
    element: element,
    get: get,
    inline: inline,
    range: range,
    keyword: keyword
  };
});
enifed("htmlbars-runtime/morph", ["exports", "morph-range"], function (exports, _morphRange) {
  "use strict";

  var guid = 1;

  function HTMLBarsMorph(domHelper, contextualElement) {
    this.super$constructor(domHelper, contextualElement);

    this._state = undefined;
    this.ownerNode = null;
    this.isDirty = false;
    this.isSubtreeDirty = false;
    this.lastYielded = null;
    this.lastResult = null;
    this.lastValue = null;
    this.buildChildEnv = null;
    this.morphList = null;
    this.morphMap = null;
    this.key = null;
    this.linkedParams = null;
    this.linkedResult = null;
    this.childNodes = null;
    this.rendered = false;
    this.guid = "range" + guid++;
    this.seen = false;
  }

  HTMLBarsMorph.empty = function (domHelper, contextualElement) {
    var morph = new HTMLBarsMorph(domHelper, contextualElement);
    morph.clear();
    return morph;
  };

  HTMLBarsMorph.create = function (domHelper, contextualElement, node) {
    var morph = new HTMLBarsMorph(domHelper, contextualElement);
    morph.setNode(node);
    return morph;
  };

  HTMLBarsMorph.attach = function (domHelper, contextualElement, firstNode, lastNode) {
    var morph = new HTMLBarsMorph(domHelper, contextualElement);
    morph.setRange(firstNode, lastNode);
    return morph;
  };

  var prototype = HTMLBarsMorph.prototype = Object.create(_morphRange.default.prototype);
  prototype.constructor = HTMLBarsMorph;
  prototype.super$constructor = _morphRange.default;

  prototype.getState = function () {
    if (!this._state) {
      this._state = {};
    }

    return this._state;
  };

  prototype.setState = function (newState) {
    /*jshint -W093 */

    return this._state = newState;
  };

  exports.default = HTMLBarsMorph;
});
enifed("htmlbars-runtime/node-visitor", ["exports", "htmlbars-util/morph-utils", "htmlbars-runtime/expression-visitor"], function (exports, _htmlbarsUtilMorphUtils, _htmlbarsRuntimeExpressionVisitor) {
  "use strict";

  /**
    Node classification:

    # Primary Statement Nodes:

    These nodes are responsible for a render node that represents a morph-range.

    * block
    * inline
    * content
    * element
    * component

    # Leaf Statement Nodes:

    This node is responsible for a render node that represents a morph-attr.

    * attribute
  */

  function linkParamsAndHash(env, scope, morph, path, params, hash) {
    if (morph.linkedParams) {
      params = morph.linkedParams.params;
      hash = morph.linkedParams.hash;
    } else {
      params = params && _htmlbarsRuntimeExpressionVisitor.acceptParams(params, env, scope);
      hash = hash && _htmlbarsRuntimeExpressionVisitor.acceptHash(hash, env, scope);
    }

    _htmlbarsUtilMorphUtils.linkParams(env, scope, morph, path, params, hash);
    return [params, hash];
  }

  var AlwaysDirtyVisitor = {

    block: function (node, morph, env, scope, template, visitor) {
      var path = node[1];
      var params = node[2];
      var hash = node[3];
      var templateId = node[4];
      var inverseId = node[5];

      var paramsAndHash = linkParamsAndHash(env, scope, morph, path, params, hash);

      morph.isDirty = morph.isSubtreeDirty = false;
      env.hooks.block(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1], templateId === null ? null : template.templates[templateId], inverseId === null ? null : template.templates[inverseId], visitor);
    },

    inline: function (node, morph, env, scope, visitor) {
      var path = node[1];
      var params = node[2];
      var hash = node[3];

      var paramsAndHash = linkParamsAndHash(env, scope, morph, path, params, hash);

      morph.isDirty = morph.isSubtreeDirty = false;
      env.hooks.inline(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1], visitor);
    },

    content: function (node, morph, env, scope, visitor) {
      var path = node[1];

      morph.isDirty = morph.isSubtreeDirty = false;

      if (isHelper(env, scope, path)) {
        env.hooks.inline(morph, env, scope, path, [], {}, visitor);
        if (morph.linkedResult) {
          _htmlbarsUtilMorphUtils.linkParams(env, scope, morph, '@content-helper', [morph.linkedResult], null);
        }
        return;
      }

      var params = undefined;
      if (morph.linkedParams) {
        params = morph.linkedParams.params;
      } else {
        params = [env.hooks.get(env, scope, path)];
      }

      _htmlbarsUtilMorphUtils.linkParams(env, scope, morph, '@range', params, null);
      env.hooks.range(morph, env, scope, path, params[0], visitor);
    },

    element: function (node, morph, env, scope, visitor) {
      var path = node[1];
      var params = node[2];
      var hash = node[3];

      var paramsAndHash = linkParamsAndHash(env, scope, morph, path, params, hash);

      morph.isDirty = morph.isSubtreeDirty = false;
      env.hooks.element(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1], visitor);
    },

    attribute: function (node, morph, env, scope) {
      var name = node[1];
      var value = node[2];

      var paramsAndHash = linkParamsAndHash(env, scope, morph, '@attribute', [value], null);

      morph.isDirty = morph.isSubtreeDirty = false;
      env.hooks.attribute(morph, env, scope, name, paramsAndHash[0][0]);
    },

    component: function (node, morph, env, scope, template, visitor) {
      var path = node[1];
      var attrs = node[2];
      var templateId = node[3];
      var inverseId = node[4];

      var paramsAndHash = linkParamsAndHash(env, scope, morph, path, [], attrs);
      var templates = {
        default: template.templates[templateId],
        inverse: template.templates[inverseId]
      };

      morph.isDirty = morph.isSubtreeDirty = false;
      env.hooks.component(morph, env, scope, path, paramsAndHash[0], paramsAndHash[1], templates, visitor);
    },

    attributes: function (node, morph, env, scope, parentMorph, visitor) {
      var template = node[1];

      env.hooks.attributes(morph, env, scope, template, parentMorph, visitor);
    }

  };

  exports.AlwaysDirtyVisitor = AlwaysDirtyVisitor;
  exports.default = {
    block: function (node, morph, env, scope, template, visitor) {
      dirtyCheck(env, morph, visitor, function (visitor) {
        AlwaysDirtyVisitor.block(node, morph, env, scope, template, visitor);
      });
    },

    inline: function (node, morph, env, scope, visitor) {
      dirtyCheck(env, morph, visitor, function (visitor) {
        AlwaysDirtyVisitor.inline(node, morph, env, scope, visitor);
      });
    },

    content: function (node, morph, env, scope, visitor) {
      dirtyCheck(env, morph, visitor, function (visitor) {
        AlwaysDirtyVisitor.content(node, morph, env, scope, visitor);
      });
    },

    element: function (node, morph, env, scope, template, visitor) {
      dirtyCheck(env, morph, visitor, function (visitor) {
        AlwaysDirtyVisitor.element(node, morph, env, scope, template, visitor);
      });
    },

    attribute: function (node, morph, env, scope, template) {
      dirtyCheck(env, morph, null, function () {
        AlwaysDirtyVisitor.attribute(node, morph, env, scope, template);
      });
    },

    component: function (node, morph, env, scope, template, visitor) {
      dirtyCheck(env, morph, visitor, function (visitor) {
        AlwaysDirtyVisitor.component(node, morph, env, scope, template, visitor);
      });
    },

    attributes: function (node, morph, env, scope, parentMorph, visitor) {
      AlwaysDirtyVisitor.attributes(node, morph, env, scope, parentMorph, visitor);
    }
  };

  function dirtyCheck(_env, morph, visitor, callback) {
    var isDirty = morph.isDirty;
    var isSubtreeDirty = morph.isSubtreeDirty;
    var env = _env;

    if (isSubtreeDirty) {
      visitor = AlwaysDirtyVisitor;
    }

    if (isDirty || isSubtreeDirty) {
      callback(visitor);
    } else {
      if (morph.buildChildEnv) {
        env = morph.buildChildEnv(morph.getState(), env);
      }
      _htmlbarsUtilMorphUtils.validateChildMorphs(env, morph, visitor);
    }
  }

  function isHelper(env, scope, path) {
    return env.hooks.keywords[path] !== undefined || env.hooks.hasHelper(env, scope, path);
  }
});
enifed("htmlbars-runtime/render", ["exports", "htmlbars-util/morph-utils", "htmlbars-runtime/node-visitor", "htmlbars-runtime/morph", "htmlbars-util/template-utils", "htmlbars-util/void-tag-names"], function (exports, _htmlbarsUtilMorphUtils, _htmlbarsRuntimeNodeVisitor, _htmlbarsRuntimeMorph, _htmlbarsUtilTemplateUtils, _htmlbarsUtilVoidTagNames) {
  "use strict";

  exports.default = render;
  exports.RenderOptions = RenderOptions;
  exports.manualElement = manualElement;
  exports.attachAttributes = attachAttributes;
  exports.createChildMorph = createChildMorph;
  exports.getCachedFragment = getCachedFragment;

  var svgNamespace = "http://www.w3.org/2000/svg";

  function render(template, env, scope, options) {
    var dom = env.dom;
    var contextualElement;

    if (options) {
      if (options.renderNode) {
        contextualElement = options.renderNode.contextualElement;
      } else if (options.contextualElement) {
        contextualElement = options.contextualElement;
      }
    }

    dom.detectNamespace(contextualElement);

    var renderResult = RenderResult.build(env, scope, template, options, contextualElement);
    renderResult.render();

    return renderResult;
  }

  function RenderOptions(renderNode, self, blockArguments, contextualElement) {
    this.renderNode = renderNode || null;
    this.self = self;
    this.blockArguments = blockArguments || null;
    this.contextualElement = contextualElement || null;
  }

  function RenderResult(env, scope, options, rootNode, ownerNode, nodes, fragment, template, shouldSetContent) {
    this.root = rootNode;
    this.fragment = fragment;

    this.nodes = nodes;
    this.template = template;
    this.statements = template.statements.slice();
    this.env = env;
    this.scope = scope;
    this.shouldSetContent = shouldSetContent;

    if (options.self !== undefined) {
      this.bindSelf(options.self);
    }
    if (options.blockArguments !== undefined) {
      this.bindLocals(options.blockArguments);
    }

    this.initializeNodes(ownerNode);
  }

  RenderResult.build = function (env, scope, template, options, contextualElement) {
    var dom = env.dom;
    var fragment = getCachedFragment(template, env);
    var nodes = template.buildRenderNodes(dom, fragment, contextualElement);

    var rootNode, ownerNode, shouldSetContent;

    if (options && options.renderNode) {
      rootNode = options.renderNode;
      ownerNode = rootNode.ownerNode;
      shouldSetContent = true;
    } else {
      rootNode = dom.createMorph(null, fragment.firstChild, fragment.lastChild, contextualElement);
      ownerNode = rootNode;
      rootNode.ownerNode = ownerNode;
      shouldSetContent = false;
    }

    if (rootNode.childNodes) {
      _htmlbarsUtilMorphUtils.visitChildren(rootNode.childNodes, function (node) {
        _htmlbarsUtilTemplateUtils.clearMorph(node, env, true);
      });
    }

    rootNode.childNodes = nodes;
    return new RenderResult(env, scope, options, rootNode, ownerNode, nodes, fragment, template, shouldSetContent);
  };

  function manualElement(tagName, attributes, _isEmpty) {
    var statements = [];

    for (var key in attributes) {
      if (typeof attributes[key] === 'string') {
        continue;
      }
      statements.push(["attribute", key, attributes[key]]);
    }

    var isEmpty = _isEmpty || _htmlbarsUtilVoidTagNames.default[tagName];

    if (!isEmpty) {
      statements.push(['content', 'yield']);
    }

    var template = {
      arity: 0,
      cachedFragment: null,
      hasRendered: false,
      buildFragment: function buildFragment(dom) {
        var el0 = dom.createDocumentFragment();
        if (tagName === 'svg') {
          dom.setNamespace(svgNamespace);
        }
        var el1 = dom.createElement(tagName);

        for (var key in attributes) {
          if (typeof attributes[key] !== 'string') {
            continue;
          }
          dom.setAttribute(el1, key, attributes[key]);
        }

        if (!isEmpty) {
          var el2 = dom.createComment("");
          dom.appendChild(el1, el2);
        }

        dom.appendChild(el0, el1);

        return el0;
      },
      buildRenderNodes: function buildRenderNodes(dom, fragment) {
        var element = dom.childAt(fragment, [0]);
        var morphs = [];

        for (var key in attributes) {
          if (typeof attributes[key] === 'string') {
            continue;
          }
          morphs.push(dom.createAttrMorph(element, key));
        }

        if (!isEmpty) {
          morphs.push(dom.createMorphAt(element, 0, 0));
        }

        return morphs;
      },
      statements: statements,
      locals: [],
      templates: []
    };

    return template;
  }

  function attachAttributes(attributes) {
    var statements = [];

    for (var key in attributes) {
      if (typeof attributes[key] === 'string') {
        continue;
      }
      statements.push(["attribute", key, attributes[key]]);
    }

    var template = {
      arity: 0,
      cachedFragment: null,
      hasRendered: false,
      buildFragment: function buildFragment(dom) {
        var el0 = this.element;
        if (el0.namespaceURI === "http://www.w3.org/2000/svg") {
          dom.setNamespace(svgNamespace);
        }
        for (var key in attributes) {
          if (typeof attributes[key] !== 'string') {
            continue;
          }
          dom.setAttribute(el0, key, attributes[key]);
        }

        return el0;
      },
      buildRenderNodes: function buildRenderNodes(dom) {
        var element = this.element;
        var morphs = [];

        for (var key in attributes) {
          if (typeof attributes[key] === 'string') {
            continue;
          }
          morphs.push(dom.createAttrMorph(element, key));
        }

        return morphs;
      },
      statements: statements,
      locals: [],
      templates: [],
      element: null
    };

    return template;
  }

  RenderResult.prototype.initializeNodes = function (ownerNode) {
    var childNodes = this.root.childNodes;

    for (var i = 0, l = childNodes.length; i < l; i++) {
      childNodes[i].ownerNode = ownerNode;
    }
  };

  RenderResult.prototype.render = function () {
    this.root.lastResult = this;
    this.root.rendered = true;
    this.populateNodes(_htmlbarsRuntimeNodeVisitor.AlwaysDirtyVisitor);

    if (this.shouldSetContent && this.root.setContent) {
      this.root.setContent(this.fragment);
    }
  };

  RenderResult.prototype.dirty = function () {
    _htmlbarsUtilMorphUtils.visitChildren([this.root], function (node) {
      node.isDirty = true;
    });
  };

  RenderResult.prototype.revalidate = function (env, self, blockArguments, scope) {
    this.revalidateWith(env, scope, self, blockArguments, _htmlbarsRuntimeNodeVisitor.default);
  };

  RenderResult.prototype.rerender = function (env, self, blockArguments, scope) {
    this.revalidateWith(env, scope, self, blockArguments, _htmlbarsRuntimeNodeVisitor.AlwaysDirtyVisitor);
  };

  RenderResult.prototype.revalidateWith = function (env, scope, self, blockArguments, visitor) {
    if (env !== undefined) {
      this.env = env;
    }
    if (scope !== undefined) {
      this.scope = scope;
    }
    this.updateScope();

    if (self !== undefined) {
      this.updateSelf(self);
    }
    if (blockArguments !== undefined) {
      this.updateLocals(blockArguments);
    }

    this.populateNodes(visitor);
  };

  RenderResult.prototype.destroy = function () {
    var rootNode = this.root;
    _htmlbarsUtilTemplateUtils.clearMorph(rootNode, this.env, true);
  };

  RenderResult.prototype.populateNodes = function (visitor) {
    var env = this.env;
    var scope = this.scope;
    var template = this.template;
    var nodes = this.nodes;
    var statements = this.statements;
    var i, l;

    for (i = 0, l = statements.length; i < l; i++) {
      var statement = statements[i];
      var morph = nodes[i];

      if (env.hooks.willRenderNode) {
        env.hooks.willRenderNode(morph, env, scope);
      }

      switch (statement[0]) {
        case 'block':
          visitor.block(statement, morph, env, scope, template, visitor);break;
        case 'inline':
          visitor.inline(statement, morph, env, scope, visitor);break;
        case 'content':
          visitor.content(statement, morph, env, scope, visitor);break;
        case 'element':
          visitor.element(statement, morph, env, scope, template, visitor);break;
        case 'attribute':
          visitor.attribute(statement, morph, env, scope);break;
        case 'component':
          visitor.component(statement, morph, env, scope, template, visitor);break;
      }

      if (env.hooks.didRenderNode) {
        env.hooks.didRenderNode(morph, env, scope);
      }
    }
  };

  RenderResult.prototype.bindScope = function () {
    this.env.hooks.bindScope(this.env, this.scope);
  };

  RenderResult.prototype.updateScope = function () {
    this.env.hooks.updateScope(this.env, this.scope);
  };

  RenderResult.prototype.bindSelf = function (self) {
    this.env.hooks.bindSelf(this.env, this.scope, self);
  };

  RenderResult.prototype.updateSelf = function (self) {
    this.env.hooks.updateSelf(this.env, this.scope, self);
  };

  RenderResult.prototype.bindLocals = function (blockArguments) {
    var localNames = this.template.locals;

    for (var i = 0, l = localNames.length; i < l; i++) {
      this.env.hooks.bindLocal(this.env, this.scope, localNames[i], blockArguments[i]);
    }
  };

  RenderResult.prototype.updateLocals = function (blockArguments) {
    var localNames = this.template.locals;

    for (var i = 0, l = localNames.length; i < l; i++) {
      this.env.hooks.updateLocal(this.env, this.scope, localNames[i], blockArguments[i]);
    }
  };

  function initializeNode(node, owner) {
    node.ownerNode = owner;
  }

  function createChildMorph(dom, parentMorph, contextualElement) {
    var morph = _htmlbarsRuntimeMorph.default.empty(dom, contextualElement || parentMorph.contextualElement);
    initializeNode(morph, parentMorph.ownerNode);
    return morph;
  }

  function getCachedFragment(template, env) {
    var dom = env.dom,
        fragment;
    if (env.useFragmentCache && dom.canClone) {
      if (template.cachedFragment === null) {
        fragment = template.buildFragment(dom);
        if (template.hasRendered) {
          template.cachedFragment = fragment;
        } else {
          template.hasRendered = true;
        }
      }
      if (template.cachedFragment) {
        fragment = dom.cloneNode(template.cachedFragment, true);
      }
    } else if (!fragment) {
      fragment = template.buildFragment(dom);
    }

    return fragment;
  }
});
enifed('htmlbars-util', ['exports', 'htmlbars-util/safe-string', 'htmlbars-util/handlebars/utils', 'htmlbars-util/namespaces', 'htmlbars-util/morph-utils'], function (exports, _htmlbarsUtilSafeString, _htmlbarsUtilHandlebarsUtils, _htmlbarsUtilNamespaces, _htmlbarsUtilMorphUtils) {
  'use strict';

  exports.SafeString = _htmlbarsUtilSafeString.default;
  exports.escapeExpression = _htmlbarsUtilHandlebarsUtils.escapeExpression;
  exports.getAttrNamespace = _htmlbarsUtilNamespaces.getAttrNamespace;
  exports.validateChildMorphs = _htmlbarsUtilMorphUtils.validateChildMorphs;
  exports.linkParams = _htmlbarsUtilMorphUtils.linkParams;
  exports.dump = _htmlbarsUtilMorphUtils.dump;
});
enifed('htmlbars-util/array-utils', ['exports'], function (exports) {
  'use strict';

  exports.forEach = forEach;
  exports.map = map;

  function forEach(array, callback, binding) {
    var i, l;
    if (binding === undefined) {
      for (i = 0, l = array.length; i < l; i++) {
        callback(array[i], i, array);
      }
    } else {
      for (i = 0, l = array.length; i < l; i++) {
        callback.call(binding, array[i], i, array);
      }
    }
  }

  function map(array, callback) {
    var output = [];
    var i, l;

    for (i = 0, l = array.length; i < l; i++) {
      output.push(callback(array[i], i, array));
    }

    return output;
  }

  var getIdx;
  if (Array.prototype.indexOf) {
    getIdx = function (array, obj, from) {
      return array.indexOf(obj, from);
    };
  } else {
    getIdx = function (array, obj, from) {
      if (from === undefined || from === null) {
        from = 0;
      } else if (from < 0) {
        from = Math.max(0, array.length + from);
      }
      for (var i = from, l = array.length; i < l; i++) {
        if (array[i] === obj) {
          return i;
        }
      }
      return -1;
    };
  }

  var isArray = Array.isArray || function (array) {
    return Object.prototype.toString.call(array) === '[object Array]';
  };

  exports.isArray = isArray;
  var indexOfArray = getIdx;
  exports.indexOfArray = indexOfArray;
});
enifed('htmlbars-util/handlebars/safe-string', ['exports'], function (exports) {
  // Build out our basic SafeString type
  'use strict';

  function SafeString(string) {
    this.string = string;
  }

  SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
    return '' + this.string;
  };

  exports.default = SafeString;
});
enifed('htmlbars-util/handlebars/utils', ['exports'], function (exports) {
  'use strict';

  exports.extend = extend;
  exports.indexOf = indexOf;
  exports.escapeExpression = escapeExpression;
  exports.isEmpty = isEmpty;
  exports.blockParams = blockParams;
  exports.appendContextPath = appendContextPath;
  var escape = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '`': '&#x60;'
  };

  var badChars = /[&<>"'`]/g,
      possible = /[&<>"'`]/;

  function escapeChar(chr) {
    return escape[chr];
  }

  function extend(obj /* , ...source */) {
    for (var i = 1; i < arguments.length; i++) {
      for (var key in arguments[i]) {
        if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
          obj[key] = arguments[i][key];
        }
      }
    }

    return obj;
  }

  var toString = Object.prototype.toString;

  exports.toString = toString;
  // Sourced from lodash
  // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
  /*eslint-disable func-style, no-var */
  var isFunction = function (value) {
    return typeof value === 'function';
  };
  // fallback for older versions of Chrome and Safari
  /* istanbul ignore next */
  if (isFunction(/x/)) {
    exports.isFunction = isFunction = function (value) {
      return typeof value === 'function' && toString.call(value) === '[object Function]';
    };
  }
  var isFunction;
  exports.isFunction = isFunction;
  /*eslint-enable func-style, no-var */

  /* istanbul ignore next */
  var isArray = Array.isArray || function (value) {
    return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
  };

  exports.isArray = isArray;
  // Older IE versions do not directly support indexOf so we must implement our own, sadly.

  function indexOf(array, value) {
    for (var i = 0, len = array.length; i < len; i++) {
      if (array[i] === value) {
        return i;
      }
    }
    return -1;
  }

  function escapeExpression(string) {
    if (typeof string !== 'string') {
      // don't escape SafeStrings, since they're already safe
      if (string && string.toHTML) {
        return string.toHTML();
      } else if (string == null) {
        return '';
      } else if (!string) {
        return string + '';
      }

      // Force a string conversion as this will be done by the append regardless and
      // the regex test will do this transparently behind the scenes, causing issues if
      // an object's to string has escaped characters in it.
      string = '' + string;
    }

    if (!possible.test(string)) {
      return string;
    }
    return string.replace(badChars, escapeChar);
  }

  function isEmpty(value) {
    if (!value && value !== 0) {
      return true;
    } else if (isArray(value) && value.length === 0) {
      return true;
    } else {
      return false;
    }
  }

  function blockParams(params, ids) {
    params.path = ids;
    return params;
  }

  function appendContextPath(contextPath, id) {
    return (contextPath ? contextPath + '.' : '') + id;
  }
});
enifed("htmlbars-util/morph-utils", ["exports"], function (exports) {
  /*globals console*/

  "use strict";

  exports.visitChildren = visitChildren;
  exports.validateChildMorphs = validateChildMorphs;
  exports.linkParams = linkParams;
  exports.dump = dump;

  function visitChildren(nodes, callback) {
    if (!nodes || nodes.length === 0) {
      return;
    }

    nodes = nodes.slice();

    while (nodes.length) {
      var node = nodes.pop();
      callback(node);

      if (node.childNodes) {
        nodes.push.apply(nodes, node.childNodes);
      } else if (node.firstChildMorph) {
        var current = node.firstChildMorph;

        while (current) {
          nodes.push(current);
          current = current.nextMorph;
        }
      } else if (node.morphList) {
        var current = node.morphList.firstChildMorph;

        while (current) {
          nodes.push(current);
          current = current.nextMorph;
        }
      }
    }
  }

  function validateChildMorphs(env, morph, visitor) {
    var morphList = morph.morphList;
    if (morph.morphList) {
      var current = morphList.firstChildMorph;

      while (current) {
        var next = current.nextMorph;
        validateChildMorphs(env, current, visitor);
        current = next;
      }
    } else if (morph.lastResult) {
      morph.lastResult.revalidateWith(env, undefined, undefined, undefined, visitor);
    } else if (morph.childNodes) {
      // This means that the childNodes were wired up manually
      for (var i = 0, l = morph.childNodes.length; i < l; i++) {
        validateChildMorphs(env, morph.childNodes[i], visitor);
      }
    }
  }

  function linkParams(env, scope, morph, path, params, hash) {
    if (morph.linkedParams) {
      return;
    }

    if (env.hooks.linkRenderNode(morph, env, scope, path, params, hash)) {
      morph.linkedParams = { params: params, hash: hash };
    }
  }

  function dump(node) {
    console.group(node, node.isDirty);

    if (node.childNodes) {
      map(node.childNodes, dump);
    } else if (node.firstChildMorph) {
      var current = node.firstChildMorph;

      while (current) {
        dump(current);
        current = current.nextMorph;
      }
    } else if (node.morphList) {
      dump(node.morphList);
    }

    console.groupEnd();
  }

  function map(nodes, cb) {
    for (var i = 0, l = nodes.length; i < l; i++) {
      cb(nodes[i]);
    }
  }
});
enifed('htmlbars-util/namespaces', ['exports'], function (exports) {
  // ref http://dev.w3.org/html5/spec-LC/namespaces.html
  'use strict';

  exports.getAttrNamespace = getAttrNamespace;
  var defaultNamespaces = {
    html: 'http://www.w3.org/1999/xhtml',
    mathml: 'http://www.w3.org/1998/Math/MathML',
    svg: 'http://www.w3.org/2000/svg',
    xlink: 'http://www.w3.org/1999/xlink',
    xml: 'http://www.w3.org/XML/1998/namespace'
  };

  function getAttrNamespace(attrName, detectedNamespace) {
    if (detectedNamespace) {
      return detectedNamespace;
    }

    var namespace;

    var colonIndex = attrName.indexOf(':');
    if (colonIndex !== -1) {
      var prefix = attrName.slice(0, colonIndex);
      namespace = defaultNamespaces[prefix];
    }

    return namespace || null;
  }
});
enifed("htmlbars-util/object-utils", ["exports"], function (exports) {
  "use strict";

  exports.merge = merge;
  exports.shallowCopy = shallowCopy;
  exports.keySet = keySet;
  exports.keyLength = keyLength;

  function merge(options, defaults) {
    for (var prop in defaults) {
      if (options.hasOwnProperty(prop)) {
        continue;
      }
      options[prop] = defaults[prop];
    }
    return options;
  }

  function shallowCopy(obj) {
    return merge({}, obj);
  }

  function keySet(obj) {
    var set = {};

    for (var prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        set[prop] = true;
      }
    }

    return set;
  }

  function keyLength(obj) {
    var count = 0;

    for (var prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        count++;
      }
    }

    return count;
  }
});
enifed("htmlbars-util/quoting", ["exports"], function (exports) {
  "use strict";

  exports.hash = hash;
  exports.repeat = repeat;
  function escapeString(str) {
    str = str.replace(/\\/g, "\\\\");
    str = str.replace(/"/g, '\\"');
    str = str.replace(/\n/g, "\\n");
    return str;
  }

  exports.escapeString = escapeString;

  function string(str) {
    return '"' + escapeString(str) + '"';
  }

  exports.string = string;

  function array(a) {
    return "[" + a + "]";
  }

  exports.array = array;

  function hash(pairs) {
    return "{" + pairs.join(", ") + "}";
  }

  function repeat(chars, times) {
    var str = "";
    while (times--) {
      str += chars;
    }
    return str;
  }
});
enifed('htmlbars-util/safe-string', ['exports', 'htmlbars-util/handlebars/safe-string'], function (exports, _htmlbarsUtilHandlebarsSafeString) {
  'use strict';

  exports.default = _htmlbarsUtilHandlebarsSafeString.default;
});
enifed("htmlbars-util/template-utils", ["exports", "htmlbars-util/morph-utils", "htmlbars-runtime/render"], function (exports, _htmlbarsUtilMorphUtils, _htmlbarsRuntimeRender) {
  "use strict";

  exports.RenderState = RenderState;
  exports.blockFor = blockFor;
  exports.renderAndCleanup = renderAndCleanup;
  exports.clearMorph = clearMorph;
  exports.clearMorphList = clearMorphList;

  function RenderState(renderNode, morphList) {
    // The morph list that is no longer needed and can be
    // destroyed.
    this.morphListToClear = morphList;

    // The morph list that needs to be pruned of any items
    // that were not yielded on a subsequent render.
    this.morphListToPrune = null;

    // A map of morphs for each item yielded in during this
    // rendering pass. Any morphs in the DOM but not in this map
    // will be pruned during cleanup.
    this.handledMorphs = {};
    this.collisions = undefined;

    // The morph to clear once rendering is complete. By
    // default, we set this to the previous morph (to catch
    // the case where nothing is yielded; in that case, we
    // should just clear the morph). Otherwise this gets set
    // to null if anything is rendered.
    this.morphToClear = renderNode;

    this.shadowOptions = null;
  }

  function Block(render, template, blockOptions) {
    this.render = render;
    this.template = template;
    this.blockOptions = blockOptions;
    this.arity = template.arity;
  }

  Block.prototype.invoke = function (env, blockArguments, _self, renderNode, parentScope, visitor) {
    if (renderNode.lastResult) {
      renderNode.lastResult.revalidateWith(env, undefined, _self, blockArguments, visitor);
    } else {
      this._firstRender(env, blockArguments, _self, renderNode, parentScope);
    }
  };

  Block.prototype._firstRender = function (env, blockArguments, _self, renderNode, parentScope) {
    var options = { renderState: new RenderState(renderNode) };
    var render = this.render;
    var template = this.template;
    var scope = this.blockOptions.scope;

    var shadowScope = scope ? env.hooks.createChildScope(scope) : env.hooks.createFreshScope();

    env.hooks.bindShadowScope(env, parentScope, shadowScope, this.blockOptions.options);

    if (_self !== undefined) {
      env.hooks.bindSelf(env, shadowScope, _self);
    } else if (this.blockOptions.self !== undefined) {
      env.hooks.bindSelf(env, shadowScope, this.blockOptions.self);
    }

    bindBlocks(env, shadowScope, this.blockOptions.yieldTo);

    renderAndCleanup(renderNode, env, options, null, function () {
      options.renderState.morphToClear = null;
      var renderOptions = new _htmlbarsRuntimeRender.RenderOptions(renderNode, undefined, blockArguments);
      render(template, env, shadowScope, renderOptions);
    });
  };

  function blockFor(render, template, blockOptions) {
    return new Block(render, template, blockOptions);
  }

  function bindBlocks(env, shadowScope, blocks) {
    if (!blocks) {
      return;
    }
    if (blocks instanceof Block) {
      env.hooks.bindBlock(env, shadowScope, blocks);
    } else {
      for (var name in blocks) {
        if (blocks.hasOwnProperty(name)) {
          env.hooks.bindBlock(env, shadowScope, blocks[name], name);
        }
      }
    }
  }

  function renderAndCleanup(morph, env, options, shadowOptions, callback) {
    // The RenderState object is used to collect information about what the
    // helper or hook being invoked has yielded. Once it has finished either
    // yielding multiple items (via yieldItem) or a single template (via
    // yieldTemplate), we detect what was rendered and how it differs from
    // the previous render, cleaning up old state in DOM as appropriate.
    var renderState = options.renderState;
    renderState.collisions = undefined;
    renderState.shadowOptions = shadowOptions;

    // Invoke the callback, instructing it to save information about what it
    // renders into RenderState.
    var result = callback(options);

    // The hook can opt-out of cleanup if it handled cleanup itself.
    if (result && result.handled) {
      return;
    }

    var morphMap = morph.morphMap;

    // Walk the morph list, clearing any items that were yielded in a previous
    // render but were not yielded during this render.
    var morphList = renderState.morphListToPrune;
    if (morphList) {
      var handledMorphs = renderState.handledMorphs;
      var item = morphList.firstChildMorph;

      while (item) {
        var next = item.nextMorph;

        // If we don't see the key in handledMorphs, it wasn't
        // yielded in and we can safely remove it from DOM.
        if (!(item.key in handledMorphs)) {
          morphMap[item.key] = undefined;
          clearMorph(item, env, true);
          item.destroy();
        }

        item = next;
      }
    }

    morphList = renderState.morphListToClear;
    if (morphList) {
      clearMorphList(morphList, morph, env);
    }

    var toClear = renderState.morphToClear;
    if (toClear) {
      clearMorph(toClear, env);
    }
  }

  function clearMorph(morph, env, destroySelf) {
    var cleanup = env.hooks.cleanupRenderNode;
    var destroy = env.hooks.destroyRenderNode;
    var willCleanup = env.hooks.willCleanupTree;
    var didCleanup = env.hooks.didCleanupTree;

    function destroyNode(node) {
      if (cleanup) {
        cleanup(node);
      }
      if (destroy) {
        destroy(node);
      }
    }

    if (willCleanup) {
      willCleanup(env, morph, destroySelf);
    }
    if (cleanup) {
      cleanup(morph);
    }
    if (destroySelf && destroy) {
      destroy(morph);
    }

    _htmlbarsUtilMorphUtils.visitChildren(morph.childNodes, destroyNode);

    // TODO: Deal with logical children that are not in the DOM tree
    morph.clear();
    if (didCleanup) {
      didCleanup(env, morph, destroySelf);
    }

    morph.lastResult = null;
    morph.lastYielded = null;
    morph.childNodes = null;
  }

  function clearMorphList(morphList, morph, env) {
    var item = morphList.firstChildMorph;

    while (item) {
      var next = item.nextMorph;
      morph.morphMap[item.key] = undefined;
      clearMorph(item, env, true);
      item.destroy();

      item = next;
    }

    // Remove the MorphList from the morph.
    morphList.clear();
    morph.morphList = null;
  }
});
enifed("htmlbars-util/void-tag-names", ["exports", "htmlbars-util/array-utils"], function (exports, _htmlbarsUtilArrayUtils) {
  "use strict";

  // The HTML elements in this list are speced by
  // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements,
  // and will be forced to close regardless of if they have a
  // self-closing /> at the end.
  var voidTagNames = "area base br col command embed hr img input keygen link meta param source track wbr";
  var voidMap = {};

  _htmlbarsUtilArrayUtils.forEach(voidTagNames.split(" "), function (tagName) {
    voidMap[tagName] = true;
  });

  exports.default = voidMap;
});
enifed("morph-attr", ["exports", "morph-attr/sanitize-attribute-value", "dom-helper/prop", "dom-helper/build-html-dom", "htmlbars-util"], function (exports, _morphAttrSanitizeAttributeValue, _domHelperProp, _domHelperBuildHtmlDom, _htmlbarsUtil) {
  "use strict";

  function getProperty() {
    return this.domHelper.getPropertyStrict(this.element, this.attrName);
  }

  function updateProperty(value) {
    if (this._renderedInitially === true || !_domHelperProp.isAttrRemovalValue(value)) {
      var element = this.element;
      var attrName = this.attrName;

      if (attrName === 'value' && element.tagName === 'INPUT' && element.value === value) {
        // Do nothing. Attempts to avoid accidently changing the input cursor location.
        // See https://github.com/tildeio/htmlbars/pull/447 for more details.
      } else {
          // do not render if initial value is undefined or null
          this.domHelper.setPropertyStrict(element, attrName, value);
        }
    }

    this._renderedInitially = true;
  }

  function getAttribute() {
    return this.domHelper.getAttribute(this.element, this.attrName);
  }

  function updateAttribute(value) {
    if (_domHelperProp.isAttrRemovalValue(value)) {
      this.domHelper.removeAttribute(this.element, this.attrName);
    } else {
      this.domHelper.setAttribute(this.element, this.attrName, value);
    }
  }

  function getAttributeNS() {
    return this.domHelper.getAttributeNS(this.element, this.namespace, this.attrName);
  }

  function updateAttributeNS(value) {
    if (_domHelperProp.isAttrRemovalValue(value)) {
      this.domHelper.removeAttribute(this.element, this.attrName);
    } else {
      this.domHelper.setAttributeNS(this.element, this.namespace, this.attrName, value);
    }
  }

  var UNSET = { unset: true };

  var guid = 1;

  AttrMorph.create = function (element, attrName, domHelper, namespace) {
    var ns = _htmlbarsUtil.getAttrNamespace(attrName, namespace);

    if (ns) {
      return new AttributeNSAttrMorph(element, attrName, domHelper, ns);
    } else {
      return createNonNamespacedAttrMorph(element, attrName, domHelper);
    }
  };

  function createNonNamespacedAttrMorph(element, attrName, domHelper) {
    var _normalizeProperty = _domHelperProp.normalizeProperty(element, attrName);

    var normalized = _normalizeProperty.normalized;
    var type = _normalizeProperty.type;

    if (element.namespaceURI === _domHelperBuildHtmlDom.svgNamespace || attrName === 'style' || type === 'attr') {
      return new AttributeAttrMorph(element, normalized, domHelper);
    } else {
      return new PropertyAttrMorph(element, normalized, domHelper);
    }
  }

  function AttrMorph(element, attrName, domHelper) {
    this.element = element;
    this.domHelper = domHelper;
    this.attrName = attrName;
    this._state = undefined;
    this.isDirty = false;
    this.isSubtreeDirty = false;
    this.escaped = true;
    this.lastValue = UNSET;
    this.lastResult = null;
    this.lastYielded = null;
    this.childNodes = null;
    this.linkedParams = null;
    this.linkedResult = null;
    this.guid = "attr" + guid++;
    this.seen = false;
    this.ownerNode = null;
    this.rendered = false;
    this._renderedInitially = false;
    this.namespace = undefined;
    this.didInit();
  }

  AttrMorph.prototype.getState = function () {
    if (!this._state) {
      this._state = {};
    }

    return this._state;
  };

  AttrMorph.prototype.setState = function (newState) {
    /*jshint -W093 */

    return this._state = newState;
  };

  AttrMorph.prototype.didInit = function () {};
  AttrMorph.prototype.willSetContent = function () {};

  AttrMorph.prototype.setContent = function (value) {
    this.willSetContent(value);

    if (this.lastValue === value) {
      return;
    }
    this.lastValue = value;

    if (this.escaped) {
      var sanitized = _morphAttrSanitizeAttributeValue.sanitizeAttributeValue(this.domHelper, this.element, this.attrName, value);
      this._update(sanitized, this.namespace);
    } else {
      this._update(value, this.namespace);
    }
  };

  AttrMorph.prototype.getContent = function () {
    var value = this.lastValue = this._get();
    return value;
  };

  // renderAndCleanup calls `clear` on all items in the morph map
  // just before calling `destroy` on the morph.
  //
  // As a future refactor this could be changed to set the property
  // back to its original/default value.
  AttrMorph.prototype.clear = function () {};

  AttrMorph.prototype.destroy = function () {
    this.element = null;
    this.domHelper = null;
  };

  AttrMorph.prototype._$superAttrMorph = AttrMorph;

  function PropertyAttrMorph(element, attrName, domHelper) {
    this._$superAttrMorph(element, attrName, domHelper);
  }

  PropertyAttrMorph.prototype = Object.create(AttrMorph.prototype);
  PropertyAttrMorph.prototype._update = updateProperty;
  PropertyAttrMorph.prototype._get = getProperty;

  function AttributeNSAttrMorph(element, attrName, domHelper, namespace) {
    this._$superAttrMorph(element, attrName, domHelper);
    this.namespace = namespace;
  }

  AttributeNSAttrMorph.prototype = Object.create(AttrMorph.prototype);
  AttributeNSAttrMorph.prototype._update = updateAttributeNS;
  AttributeNSAttrMorph.prototype._get = getAttributeNS;

  function AttributeAttrMorph(element, attrName, domHelper) {
    this._$superAttrMorph(element, attrName, domHelper);
  }

  AttributeAttrMorph.prototype = Object.create(AttrMorph.prototype);
  AttributeAttrMorph.prototype._update = updateAttribute;
  AttributeAttrMorph.prototype._get = getAttribute;

  exports.default = AttrMorph;
  exports.sanitizeAttributeValue = _morphAttrSanitizeAttributeValue.sanitizeAttributeValue;
});
enifed('morph-attr/sanitize-attribute-value', ['exports'], function (exports) {
  /* jshint scripturl:true */

  'use strict';

  exports.sanitizeAttributeValue = sanitizeAttributeValue;
  var badProtocols = {
    'javascript:': true,
    'vbscript:': true
  };

  var badTags = {
    'A': true,
    'BODY': true,
    'LINK': true,
    'IMG': true,
    'IFRAME': true,
    'BASE': true,
    'FORM': true
  };

  var badTagsForDataURI = {
    'EMBED': true
  };

  var badAttributes = {
    'href': true,
    'src': true,
    'background': true,
    'action': true
  };

  exports.badAttributes = badAttributes;
  var badAttributesForDataURI = {
    'src': true
  };

  function sanitizeAttributeValue(dom, element, attribute, value) {
    var tagName;

    if (!element) {
      tagName = null;
    } else {
      tagName = element.tagName.toUpperCase();
    }

    if (value && value.toHTML) {
      return value.toHTML();
    }

    if ((tagName === null || badTags[tagName]) && badAttributes[attribute]) {
      var protocol = dom.protocolForURL(value);
      if (badProtocols[protocol] === true) {
        return 'unsafe:' + value;
      }
    }

    if (badTagsForDataURI[tagName] && badAttributesForDataURI[attribute]) {
      return 'unsafe:' + value;
    }

    return value;
  }
});
enifed('morph-range', ['exports', 'morph-range/utils'], function (exports, _morphRangeUtils) {
  'use strict';

  // constructor just initializes the fields
  // use one of the static initializers to create a valid morph.
  function Morph(domHelper, contextualElement) {
    this.domHelper = domHelper;
    // context if content if current content is detached
    this.contextualElement = contextualElement;
    // inclusive range of morph
    // these should be nodeType 1, 3, or 8
    this.firstNode = null;
    this.lastNode = null;

    // flag to force text to setContent to be treated as html
    this.parseTextAsHTML = false;

    // morph list graph
    this.parentMorphList = null;
    this.previousMorph = null;
    this.nextMorph = null;
  }

  Morph.empty = function (domHelper, contextualElement) {
    var morph = new Morph(domHelper, contextualElement);
    morph.clear();
    return morph;
  };

  Morph.create = function (domHelper, contextualElement, node) {
    var morph = new Morph(domHelper, contextualElement);
    morph.setNode(node);
    return morph;
  };

  Morph.attach = function (domHelper, contextualElement, firstNode, lastNode) {
    var morph = new Morph(domHelper, contextualElement);
    morph.setRange(firstNode, lastNode);
    return morph;
  };

  Morph.prototype.setContent = function Morph$setContent(content) {
    if (content === null || content === undefined) {
      return this.clear();
    }

    var type = typeof content;
    switch (type) {
      case 'string':
        if (this.parseTextAsHTML) {
          return this.domHelper.setMorphHTML(this, content);
        }
        return this.setText(content);
      case 'object':
        if (typeof content.nodeType === 'number') {
          return this.setNode(content);
        }
        /* Handlebars.SafeString */
        if (typeof content.toHTML === 'function') {
          return this.setHTML(content.toHTML());
        }
        if (this.parseTextAsHTML) {
          return this.setHTML(content.toString());
        }
      /* falls through */
      case 'boolean':
      case 'number':
        return this.setText(content.toString());
      case 'function':
        raiseCannotBindToFunction(content);
      default:
        throw new TypeError('unsupported content');
    }
  };

  function raiseCannotBindToFunction(content) {
    var functionName = content.name;
    var message;

    if (functionName) {
      message = 'Unsupported Content: Cannot bind to function `' + functionName + '`';
    } else {
      message = 'Unsupported Content: Cannot bind to function';
    }

    throw new TypeError(message);
  }

  Morph.prototype.clear = function Morph$clear() {
    var node = this.setNode(this.domHelper.createComment(''));
    return node;
  };

  Morph.prototype.setText = function Morph$setText(text) {
    var firstNode = this.firstNode;
    var lastNode = this.lastNode;

    if (firstNode && lastNode === firstNode && firstNode.nodeType === 3) {
      firstNode.nodeValue = text;
      return firstNode;
    }

    return this.setNode(text ? this.domHelper.createTextNode(text) : this.domHelper.createComment(''));
  };

  Morph.prototype.setNode = function Morph$setNode(newNode) {
    var firstNode, lastNode;
    switch (newNode.nodeType) {
      case 3:
        firstNode = newNode;
        lastNode = newNode;
        break;
      case 11:
        firstNode = newNode.firstChild;
        lastNode = newNode.lastChild;
        if (firstNode === null) {
          firstNode = this.domHelper.createComment('');
          newNode.appendChild(firstNode);
          lastNode = firstNode;
        }
        break;
      default:
        firstNode = newNode;
        lastNode = newNode;
        break;
    }

    this.setRange(firstNode, lastNode);

    return newNode;
  };

  Morph.prototype.setRange = function (firstNode, lastNode) {
    var previousFirstNode = this.firstNode;
    if (previousFirstNode !== null) {

      var parentNode = previousFirstNode.parentNode;
      if (parentNode !== null) {
        _morphRangeUtils.insertBefore(parentNode, firstNode, lastNode, previousFirstNode);
        _morphRangeUtils.clear(parentNode, previousFirstNode, this.lastNode);
      }
    }

    this.firstNode = firstNode;
    this.lastNode = lastNode;

    if (this.parentMorphList) {
      this._syncFirstNode();
      this._syncLastNode();
    }
  };

  Morph.prototype.destroy = function Morph$destroy() {
    this.unlink();

    var firstNode = this.firstNode;
    var lastNode = this.lastNode;
    var parentNode = firstNode && firstNode.parentNode;

    this.firstNode = null;
    this.lastNode = null;

    _morphRangeUtils.clear(parentNode, firstNode, lastNode);
  };

  Morph.prototype.unlink = function Morph$unlink() {
    var parentMorphList = this.parentMorphList;
    var previousMorph = this.previousMorph;
    var nextMorph = this.nextMorph;

    if (previousMorph) {
      if (nextMorph) {
        previousMorph.nextMorph = nextMorph;
        nextMorph.previousMorph = previousMorph;
      } else {
        previousMorph.nextMorph = null;
        parentMorphList.lastChildMorph = previousMorph;
      }
    } else {
      if (nextMorph) {
        nextMorph.previousMorph = null;
        parentMorphList.firstChildMorph = nextMorph;
      } else if (parentMorphList) {
        parentMorphList.lastChildMorph = parentMorphList.firstChildMorph = null;
      }
    }

    this.parentMorphList = null;
    this.nextMorph = null;
    this.previousMorph = null;

    if (parentMorphList && parentMorphList.mountedMorph) {
      if (!parentMorphList.firstChildMorph) {
        // list is empty
        parentMorphList.mountedMorph.clear();
        return;
      } else {
        parentMorphList.firstChildMorph._syncFirstNode();
        parentMorphList.lastChildMorph._syncLastNode();
      }
    }
  };

  Morph.prototype.setHTML = function (text) {
    var fragment = this.domHelper.parseHTML(text, this.contextualElement);
    return this.setNode(fragment);
  };

  Morph.prototype.setMorphList = function Morph$appendMorphList(morphList) {
    morphList.mountedMorph = this;
    this.clear();

    var originalFirstNode = this.firstNode;

    if (morphList.firstChildMorph) {
      this.firstNode = morphList.firstChildMorph.firstNode;
      this.lastNode = morphList.lastChildMorph.lastNode;

      var current = morphList.firstChildMorph;

      while (current) {
        var next = current.nextMorph;
        current.insertBeforeNode(originalFirstNode, null);
        current = next;
      }
      originalFirstNode.parentNode.removeChild(originalFirstNode);
    }
  };

  Morph.prototype._syncFirstNode = function Morph$syncFirstNode() {
    var morph = this;
    var parentMorphList;
    while (parentMorphList = morph.parentMorphList) {
      if (parentMorphList.mountedMorph === null) {
        break;
      }
      if (morph !== parentMorphList.firstChildMorph) {
        break;
      }
      if (morph.firstNode === parentMorphList.mountedMorph.firstNode) {
        break;
      }

      parentMorphList.mountedMorph.firstNode = morph.firstNode;

      morph = parentMorphList.mountedMorph;
    }
  };

  Morph.prototype._syncLastNode = function Morph$syncLastNode() {
    var morph = this;
    var parentMorphList;
    while (parentMorphList = morph.parentMorphList) {
      if (parentMorphList.mountedMorph === null) {
        break;
      }
      if (morph !== parentMorphList.lastChildMorph) {
        break;
      }
      if (morph.lastNode === parentMorphList.mountedMorph.lastNode) {
        break;
      }

      parentMorphList.mountedMorph.lastNode = morph.lastNode;

      morph = parentMorphList.mountedMorph;
    }
  };

  Morph.prototype.insertBeforeNode = function Morph$insertBeforeNode(parentNode, refNode) {
    _morphRangeUtils.insertBefore(parentNode, this.firstNode, this.lastNode, refNode);
  };

  Morph.prototype.appendToNode = function Morph$appendToNode(parentNode) {
    _morphRangeUtils.insertBefore(parentNode, this.firstNode, this.lastNode, null);
  };

  exports.default = Morph;
});
enifed('morph-range/morph-list', ['exports', 'morph-range/utils'], function (exports, _morphRangeUtils) {
  'use strict';

  function MorphList() {
    // morph graph
    this.firstChildMorph = null;
    this.lastChildMorph = null;

    this.mountedMorph = null;
  }

  var prototype = MorphList.prototype;

  prototype.clear = function MorphList$clear() {
    var current = this.firstChildMorph;

    while (current) {
      var next = current.nextMorph;
      current.previousMorph = null;
      current.nextMorph = null;
      current.parentMorphList = null;
      current = next;
    }

    this.firstChildMorph = this.lastChildMorph = null;
  };

  prototype.destroy = function MorphList$destroy() {};

  prototype.appendMorph = function MorphList$appendMorph(morph) {
    this.insertBeforeMorph(morph, null);
  };

  prototype.insertBeforeMorph = function MorphList$insertBeforeMorph(morph, referenceMorph) {
    if (morph.parentMorphList !== null) {
      morph.unlink();
    }
    if (referenceMorph && referenceMorph.parentMorphList !== this) {
      throw new Error('The morph before which the new morph is to be inserted is not a child of this morph.');
    }

    var mountedMorph = this.mountedMorph;

    if (mountedMorph) {

      var parentNode = mountedMorph.firstNode.parentNode;
      var referenceNode = referenceMorph ? referenceMorph.firstNode : mountedMorph.lastNode.nextSibling;

      _morphRangeUtils.insertBefore(parentNode, morph.firstNode, morph.lastNode, referenceNode);

      // was not in list mode replace current content
      if (!this.firstChildMorph) {
        _morphRangeUtils.clear(this.mountedMorph.firstNode.parentNode, this.mountedMorph.firstNode, this.mountedMorph.lastNode);
      }
    }

    morph.parentMorphList = this;

    var previousMorph = referenceMorph ? referenceMorph.previousMorph : this.lastChildMorph;
    if (previousMorph) {
      previousMorph.nextMorph = morph;
      morph.previousMorph = previousMorph;
    } else {
      this.firstChildMorph = morph;
    }

    if (referenceMorph) {
      referenceMorph.previousMorph = morph;
      morph.nextMorph = referenceMorph;
    } else {
      this.lastChildMorph = morph;
    }

    this.firstChildMorph._syncFirstNode();
    this.lastChildMorph._syncLastNode();
  };

  prototype.removeChildMorph = function MorphList$removeChildMorph(morph) {
    if (morph.parentMorphList !== this) {
      throw new Error("Cannot remove a morph from a parent it is not inside of");
    }

    morph.destroy();
  };

  exports.default = MorphList;
});
enifed('morph-range/morph-list.umd', ['exports', 'morph-range/morph-list'], function (exports, _morphRangeMorphList) {
  'use strict';

  (function (root, factory) {
    if (typeof define === 'function' && define.amd) {
      define([], factory);
    } else if (typeof exports === 'object') {
      module.exports = factory();
    } else {
      root.MorphList = factory();
    }
  })(undefined, function () {
    return _morphRangeMorphList.default;
  });
});
enifed("morph-range/utils", ["exports"], function (exports) {
  // inclusive of both nodes
  "use strict";

  exports.clear = clear;
  exports.insertBefore = insertBefore;

  function clear(parentNode, firstNode, lastNode) {
    if (!parentNode) {
      return;
    }

    var node = firstNode;
    var nextNode;
    do {
      nextNode = node.nextSibling;
      parentNode.removeChild(node);
      if (node === lastNode) {
        break;
      }
      node = nextNode;
    } while (node);
  }

  function insertBefore(parentNode, firstNode, lastNode, refNode) {
    var node = firstNode;
    var nextNode;
    do {
      nextNode = node.nextSibling;
      parentNode.insertBefore(node, refNode);
      if (node === lastNode) {
        break;
      }
      node = nextNode;
    } while (node);
  }
});
enifed('route-recognizer', ['exports', 'route-recognizer/dsl'], function (exports, _routeRecognizerDsl) {
  '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;
  }

  function decodeQueryParamPart(part) {
    // http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
    part = part.replace(/\+/gm, '%20');
    return decodeURIComponent(part);
  }

  // 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 = encodeURIComponent(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 = decodeQueryParamPart(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] ? decodeQueryParamPart(pair[1]) : '';
        }
        if (isArray) {
          queryParams[key].push(value);
        } else {
          queryParams[key] = value;
        }
      }
      return queryParams;
    },

    recognize: function (path) {
      var states = [this.rootState],
          pathLen,
          i,
          l,
          queryStart,
          queryParams = {},
          isSlashDropped = false;

      queryStart = path.indexOf('?');
      if (queryStart !== -1) {
        var queryString = path.substr(queryStart + 1, path.length);
        path = path.substr(0, queryStart);
        queryParams = this.parseQueryString(queryString);
      }

      path = decodeURI(path);

      // 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);
      }
    }
  };

  RouteRecognizer.prototype.map = _routeRecognizerDsl.default;

  RouteRecognizer.VERSION = '0.1.5';

  exports.default = RouteRecognizer;
});
enifed("route-recognizer/dsl", ["exports"], function (exports) {
  "use strict";

  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);
        }
      }
    }
  }

  exports.default = 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);
  };
});
enifed('router', ['exports', 'router/router'], function (exports, _routerRouter) {
  'use strict';

  exports.default = _routerRouter.default;
});
enifed('router/handler-info', ['exports', 'router/utils', 'rsvp/promise'], function (exports, _routerUtils, _rsvpPromise) {
  'use strict';

  function HandlerInfo(_props) {
    var props = _props || {};
    _routerUtils.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 _routerUtils.promiseLabel("'" + this.name + "' " + label);
    },

    getUnresolved: function () {
      return this;
    },

    serialize: function () {
      return this.params || {};
    },

    resolve: function (shouldContinue, payload) {
      var checkForAbort = _routerUtils.bind(this, this.checkForAbort, shouldContinue),
          beforeModel = _routerUtils.bind(this, this.runBeforeModelHook, payload),
          model = _routerUtils.bind(this, this.getModel, payload),
          afterModel = _routerUtils.bind(this, this.runAfterModelHook, payload),
          becomeResolved = _routerUtils.bind(this, this.becomeResolved, payload);

      return _rsvpPromise.default.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 result = _routerUtils.applyHook(this.handler, hookName, args);

      if (result && result.isTransition) {
        result = null;
      }

      return _rsvpPromise.default.resolve(result, this.promiseLabel("Resolve value returned from one of the model hooks"));
    },

    // overridden by subclasses
    getModel: null,

    checkForAbort: function (shouldContinue, promiseValue) {
      return _rsvpPromise.default.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;
});
enifed('router/handler-info/factory', ['exports', 'router/handler-info/resolved-handler-info', 'router/handler-info/unresolved-handler-info-by-object', 'router/handler-info/unresolved-handler-info-by-param'], function (exports, _routerHandlerInfoResolvedHandlerInfo, _routerHandlerInfoUnresolvedHandlerInfoByObject, _routerHandlerInfoUnresolvedHandlerInfoByParam) {
  'use strict';

  handlerInfoFactory.klasses = {
    resolved: _routerHandlerInfoResolvedHandlerInfo.default,
    param: _routerHandlerInfoUnresolvedHandlerInfoByParam.default,
    object: _routerHandlerInfoUnresolvedHandlerInfoByObject.default
  };

  function handlerInfoFactory(name, props) {
    var Ctor = handlerInfoFactory.klasses[name],
        handlerInfo = new Ctor(props || {});
    handlerInfo.factory = handlerInfoFactory;
    return handlerInfo;
  }

  exports.default = handlerInfoFactory;
});
enifed('router/handler-info/resolved-handler-info', ['exports', 'router/handler-info', 'router/utils', 'rsvp/promise'], function (exports, _routerHandlerInfo, _routerUtils, _rsvpPromise) {
  'use strict';

  var ResolvedHandlerInfo = _routerUtils.subclass(_routerHandlerInfo.default, {
    resolve: function (shouldContinue, payload) {
      // A ResolvedHandlerInfo just resolved with itself.
      if (payload && payload.resolvedModels) {
        payload.resolvedModels[this.name] = this.context;
      }
      return _rsvpPromise.default.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;
});
enifed('router/handler-info/unresolved-handler-info-by-object', ['exports', 'router/handler-info', 'router/utils', 'rsvp/promise'], function (exports, _routerHandlerInfo, _routerUtils, _rsvpPromise) {
  'use strict';

  var UnresolvedHandlerInfoByObject = _routerUtils.subclass(_routerHandlerInfo.default, {
    getModel: function (payload) {
      this.log(payload, this.name + ": resolving provided model");
      return _rsvpPromise.default.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 (_routerUtils.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;
});
enifed('router/handler-info/unresolved-handler-info-by-param', ['exports', 'router/handler-info', 'router/utils'], function (exports, _routerHandlerInfo, _routerUtils) {
  'use strict';

  // Generated by URL transitions and non-dynamic route segments in named Transitions.
  var UnresolvedHandlerInfoByParam = _routerUtils.subclass(_routerHandlerInfo.default, {
    initialize: function (props) {
      this.params = props.params || {};
    },

    getModel: function (payload) {
      var fullParams = this.params;
      if (payload && payload.queryParams) {
        fullParams = {};
        _routerUtils.merge(fullParams, this.params);
        fullParams.queryParams = payload.queryParams;
      }

      var handler = this.handler;
      var hookName = _routerUtils.resolveHook(handler, 'deserialize') || _routerUtils.resolveHook(handler, 'model');

      return this.runSharedModelHook(payload, hookName, [fullParams]);
    }
  });

  exports.default = UnresolvedHandlerInfoByParam;
});
enifed('router/router', ['exports', 'route-recognizer', 'rsvp/promise', 'router/utils', 'router/transition-state', 'router/transition', 'router/transition-intent/named-transition-intent', 'router/transition-intent/url-transition-intent', 'router/handler-info'], function (exports, _routeRecognizer, _rsvpPromise, _routerUtils, _routerTransitionState, _routerTransition, _routerTransitionIntentNamedTransitionIntent, _routerTransitionIntentUrlTransitionIntent, _routerHandlerInfo) {
  'use strict';

  var pop = Array.prototype.pop;

  function Router(_options) {
    var options = _options || {};
    this.getHandler = options.getHandler || this.getHandler;
    this.updateURL = options.updateURL || this.updateURL;
    this.replaceURL = options.replaceURL || this.replaceURL;
    this.didTransition = options.didTransition || this.didTransition;
    this.willTransition = options.willTransition || this.willTransition;
    this.delegate = options.delegate || this.delegate;
    this.triggerEvent = options.triggerEvent || this.triggerEvent;
    this.log = options.log || this.log;

    this.recognizer = new _routeRecognizer.default();
    this.reset();
  }

  function getTransitionByIntent(intent, isIntermediate) {
    var wasTransitioning = !!this.activeTransition;
    var oldState = wasTransitioning ? this.activeTransition.state : this.state;
    var newTransition;

    var newState = intent.applyToState(oldState, this.recognizer, this.getHandler, isIntermediate);
    var queryParamChangelist = _routerUtils.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 this.activeTransition || new _routerTransition.Transition(this);
    }

    if (isIntermediate) {
      setupContexts(this, newState);
      return;
    }

    // Create a new transition to the destination route.
    newTransition = new _routerTransition.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, _routerUtils.promiseLabel("Settle transition promise when transition is finalized"));

    if (!wasTransitioning) {
      notifyExistingHandlers(this, newState, newTransition);
    }

    fireQueryParamDidChange(this, newState, queryParamChangelist);

    return newTransition;
  }

  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);
    },

    getHandler: function () {},

    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 _routerTransition.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, _routerUtils.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) {
      try {
        return getTransitionByIntent.apply(this, arguments);
      } catch (e) {
        return new _routerTransition.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) {
        _routerUtils.forEach(this.state.handlerInfos.slice().reverse(), function (handlerInfo) {
          var handler = handlerInfo.handler;
          _routerUtils.callHook(handler, 'exit');
        });
      }

      this.state = new _routerTransitionState.default();
      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 = _routerUtils.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) {
      return 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 || {};
      }

      _routerUtils.log(this, "Starting a refresh transition");
      var intent = new _routerTransitionIntentNamedTransitionIntent.default({
        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 = _routerUtils.extractQueryParams(_routerUtils.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 _routerTransitionIntentNamedTransitionIntent.default({ 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();
        _routerUtils.merge(params, handlerParams);
      }
      params.queryParams = queryParams;

      return this.recognizer.generate(handlerName, params);
    },

    applyIntent: function (handlerName, contexts) {
      var intent = new _routerTransitionIntentNamedTransitionIntent.default({
        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, _state) {
      var state = _state || this.state,
          targetHandlerInfos = 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 testState = new _routerTransitionState.default();
      testState.handlerInfos = targetHandlerInfos.slice(0, index + 1);
      recogHandlers = recogHandlers.slice(0, index + 1);

      var intent = new _routerTransitionIntentNamedTransitionIntent.default({
        name: targetHandler,
        contexts: contexts
      });

      var newState = intent.applyToHandlers(testState, recogHandlers, this.getHandler, targetHandler, true, true);

      var handlersEqual = handlerInfosEqual(newState.handlerInfos, testState.handlerInfos);
      if (!queryParams || !handlersEqual) {
        return handlersEqual;
      }

      // Get a hash of QPs that will still be active on new route
      var activeQPsOnNewHandler = {};
      _routerUtils.merge(activeQPsOnNewHandler, queryParams);

      var activeQueryParams = state.queryParams;
      for (var key in activeQueryParams) {
        if (activeQueryParams.hasOwnProperty(key) && activeQPsOnNewHandler.hasOwnProperty(key)) {
          activeQPsOnNewHandler[key] = activeQueryParams[key];
        }
      }

      return handlersEqual && !_routerUtils.getChangelist(activeQPsOnNewHandler, queryParams);
    },

    isActive: function (handlerName) {
      var partitionedArgs = _routerUtils.extractQueryParams(_routerUtils.slice.call(arguments, 1));
      return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]);
    },

    trigger: function (name) {
      var args = _routerUtils.slice.call(arguments);
      _routerUtils.trigger(this, this.currentHandlerInfos, false, args);
    },

    /**
      Hook point for logging transition status updates.
       @param {String} message The message to log.
    */
    log: null
  };

  /**
    @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;
      _routerUtils.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);
    var i, l, handler;

    for (i = 0, l = partition.exited.length; i < l; i++) {
      handler = partition.exited[i].handler;
      delete handler.context;

      _routerUtils.callHook(handler, 'reset', true, transition);
      _routerUtils.callHook(handler, 'exit', transition);
    }

    var oldState = router.oldState = router.state;
    router.state = newState;
    var currentHandlerInfos = router.currentHandlerInfos = partition.unchanged.slice();

    try {
      for (i = 0, l = partition.reset.length; i < l; i++) {
        handler = partition.reset[i].handler;
        _routerUtils.callHook(handler, 'reset', false, transition);
      }

      for (i = 0, l = partition.updatedContext.length; i < l; i++) {
        handlerEnteredOrUpdated(currentHandlerInfos, partition.updatedContext[i], false, transition);
      }

      for (i = 0, l = partition.entered.length; i < l; i++) {
        handlerEnteredOrUpdated(currentHandlerInfos, partition.entered[i], 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) {
      _routerUtils.callHook(handler, 'enter', transition);
    }
    if (transition && transition.isAborted) {
      throw new _routerTransition.TransitionAborted();
    }

    handler.context = context;
    _routerUtils.callHook(handler, 'contextDidChange');

    _routerUtils.callHook(handler, 'setup', context, transition);
    if (transition && transition.isAborted) {
      throw new _routerTransition.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 = false,
        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];
      _routerUtils.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 {
      _routerUtils.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 _rsvpPromise.default.reject(_routerTransition.logAbort(transition));
      }

      updateURL(transition, newState, transition.intent.url);

      transition.isActive = false;
      router.activeTransition = null;

      _routerUtils.trigger(router, router.currentHandlerInfos, true, ['didTransition']);

      if (router.didTransition) {
        router.didTransition(router.currentHandlerInfos);
      }

      _routerUtils.log(router, transition.sequence, "TRANSITION COMPLETE.");

      // Resolve with the final handler.
      return handlerInfos[handlerInfos.length - 1].handler;
    } catch (e) {
      if (!(e instanceof _routerTransition.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) {

      _routerUtils.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 _routerTransitionIntentNamedTransitionIntent.default({
        name: handlerInfos[handlerInfos.length - 1].name,
        contexts: [],
        queryParams: queryParams
      });
    } else if (name.charAt(0) === '/') {

      _routerUtils.log(router, "Attempting URL transition to " + name);
      intent = new _routerTransitionIntentUrlTransitionIntent.default({ url: name });
    } else {

      _routerUtils.log(router, "Attempting transition to " + name);
      intent = new _routerTransitionIntentNamedTransitionIntent.default({
        name: args[0],
        contexts: _routerUtils.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 = [];
    _routerUtils.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,
        oldHandlerLen,
        oldHandler,
        newHandler;

    oldHandlerLen = oldHandlers.length;
    for (i = 0; i < oldHandlerLen; 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, oldHandlerLen);
      leavingChecker = function (name) {
        for (var h = 0, len = leaving.length; h < len; h++) {
          if (leaving[h].name === name) {
            return true;
          }
        }
        return false;
      };
    }

    _routerUtils.trigger(router, oldHandlers, true, ['willTransition', newTransition]);

    if (router.willTransition) {
      router.willTransition(oldHandlers, newState.handlerInfos, newTransition);
    }
  }

  exports.default = Router;
});
enifed('router/transition-intent', ['exports', 'router/utils'], function (exports, _routerUtils) {
  'use strict';

  function TransitionIntent(props) {
    this.initialize(props);

    // TODO: wat
    this.data = this.data || {};
  }

  TransitionIntent.prototype = {
    initialize: null,
    applyToState: null
  };

  exports.default = TransitionIntent;
});
enifed('router/transition-intent/named-transition-intent', ['exports', 'router/transition-intent', 'router/transition-state', 'router/handler-info/factory', 'router/utils'], function (exports, _routerTransitionIntent, _routerTransitionState, _routerHandlerInfoFactory, _routerUtils) {
  'use strict';

  exports.default = _routerUtils.subclass(_routerTransitionIntent.default, {
    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 = _routerUtils.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, len;
      var newState = new _routerTransitionState.default();
      var objects = this.contexts.slice(0);

      var invalidateIndex = handlers.length;

      // Pivot handlers are provided for refresh transitions
      if (this.pivotHandler) {
        for (i = 0, len = handlers.length; i < len; ++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);
      }

      _routerUtils.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 (_routerUtils.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 _routerHandlerInfoFactory.default('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 (_routerUtils.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 _routerHandlerInfoFactory.default('param', {
        name: name,
        handler: handler,
        params: params
      });
    }
  });
});
enifed('router/transition-intent/url-transition-intent', ['exports', 'router/transition-intent', 'router/transition-state', 'router/handler-info/factory', 'router/utils', 'router/unrecognized-url-error'], function (exports, _routerTransitionIntent, _routerTransitionState, _routerHandlerInfoFactory, _routerUtils, _routerUnrecognizedUrlError) {
  'use strict';

  exports.default = _routerUtils.subclass(_routerTransitionIntent.default, {
    url: null,

    initialize: function (props) {
      this.url = props.url;
    },

    applyToState: function (oldState, recognizer, getHandler) {
      var newState = new _routerTransitionState.default();

      var results = recognizer.recognize(this.url),
          queryParams = {},
          i,
          len;

      if (!results) {
        throw new _routerUnrecognizedUrlError.default(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 _routerUnrecognizedUrlError.default(this.url);
        }

        var newHandlerInfo = _routerHandlerInfoFactory.default('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;
        }
      }

      _routerUtils.merge(newState.queryParams, results.queryParams);

      return newState;
    }
  });
});
enifed('router/transition-state', ['exports', 'router/handler-info', 'router/utils', 'rsvp/promise'], function (exports, _routerHandlerInfo, _routerUtils, _rsvpPromise) {
  'use strict';

  function TransitionState(other) {
    this.handlerInfos = [];
    this.queryParams = {};
    this.params = {};
  }

  TransitionState.prototype = {
    handlerInfos: null,
    queryParams: null,
    params: null,

    promiseLabel: function (label) {
      var targetName = '';
      _routerUtils.forEach(this.handlerInfos, function (handlerInfo) {
        if (targetName !== '') {
          targetName += '.';
        }
        targetName += handlerInfo.name;
      });
      return _routerUtils.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;
      _routerUtils.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 _rsvpPromise.default.resolve(null, this.promiseLabel("Start transition")).then(resolveOneHandlerInfo, null, this.promiseLabel('Resolve handler'))['catch'](handleError, this.promiseLabel('Handle error'));

      function innerShouldContinue() {
        return _rsvpPromise.default.resolve(shouldContinue(), currentState.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 _rsvpPromise.default.reject(reason);
        }, currentState.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 _rsvpPromise.default.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;
          _routerUtils.callHook(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, currentState.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, currentState.promiseLabel('Proceed'));
      }
    }
  };

  exports.default = TransitionState;
});
enifed('router/transition', ['exports', 'rsvp/promise', 'router/handler-info', 'router/utils'], function (exports, _rsvpPromise, _routerHandlerInfo, _routerUtils) {
  'use strict';

  /**
    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.

    @class Transition
    @constructor
    @param {Object} router
    @param {Object} intent
    @param {Object} state
    @param {Object} error
    @private
   */
  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 = _rsvpPromise.default.reject(error);
      this.error = 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[len - 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 _rsvpPromise.default.reject(logAbort(transition));
        } else {
          transition.trigger('error', result.error, transition, result.handlerWithError);
          transition.abort();
          return _rsvpPromise.default.reject(result.error);
        }
      }, _routerUtils.promiseLabel('Handle Abort'));
    } else {
      this.promise = _rsvpPromise.default.resolve(this.state);
      this.params = {};
    }

    function checkForAbort() {
      if (transition.isAborted) {
        return _rsvpPromise.default.reject(undefined, _routerUtils.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;
    },

    /**
      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.
       @property promise
      @type {Object}
      @public
     */
    promise: null,

    /**
      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.

      @property data
      @type {Object}
      @public
     */
    data: null,

    /**
      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.
       @method then
      @param {Function} onFulfilled
      @param {Function} onRejected
      @param {String} label optional string for labeling the promise.
      Useful for tooling.
      @return {Promise}
      @public
     */
    then: function (onFulfilled, onRejected, label) {
      return this.promise.then(onFulfilled, onRejected, label);
    },

    /**
       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.
       @method catch
      @param {Function} onRejection
      @param {String} label optional string for labeling the promise.
      Useful for tooling.
      @return {Promise}
      @public
     */
    catch: function (onRejection, label) {
      return this.promise.catch(onRejection, label);
    },

    /**
       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.
       @method finally
      @param {Function} callback
      @param {String} label optional string for labeling the promise.
      Useful for tooling.
      @return {Promise}
      @public
     */
    finally: function (callback, label) {
      return this.promise.finally(callback, label);
    },

    /**
      Aborts the Transition. Note you can also implicitly abort a transition
      by initiating another transition while a previous one is underway.
       @method abort
      @return {Transition} this transition
      @public
     */
    abort: function () {
      if (this.isAborted) {
        return this;
      }
      _routerUtils.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;
    },

    /**
       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.
       @method retry
      @return {Transition} new transition
      @public
     */
    retry: function () {
      // TODO: add tests for merged state retry()s
      this.abort();
      return this.router.transitionByIntent(this.intent, false);
    },

    /**
       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).
       @method method
      @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
      @public
     */
    method: function (method) {
      this.urlMethod = method;
      return this;
    },

    /**
       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`
       @method trigger
      @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error
      @param {String} name the name of the event to fire
      @public
     */
    trigger: function (ignoreFailure) {
      var args = _routerUtils.slice.call(arguments);
      if (typeof ignoreFailure === 'boolean') {
        args.shift();
      } else {
        // Throw errors on unhandled trigger events by default
        ignoreFailure = false;
      }
      _routerUtils.trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args);
    },

    /**
      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.
       @method followRedirects
      @return {Promise} a promise that fulfills with the same
        value that the final redirecting transition fulfills with
      @public
     */
    followRedirects: function () {
      var router = this.router;
      return this.promise['catch'](function (reason) {
        if (router.activeTransition) {
          return router.activeTransition.followRedirects();
        }
        return _rsvpPromise.default.reject(reason);
      });
    },

    toString: function () {
      return "Transition (sequence " + this.sequence + ")";
    },

    /**
      @private
     */
    log: function (message) {
      _routerUtils.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) {
    _routerUtils.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;
});
enifed("router/unrecognized-url-error", ["exports", "router/utils"], function (exports, _routerUtils) {
  "use strict";

  /**
    Promise reject reasons passed to promise rejection
    handlers for failed transitions.
   */
  function UnrecognizedURLError(message) {
    this.message = message || "UnrecognizedURLError";
    this.name = "UnrecognizedURLError";
    Error.call(this);
  }

  UnrecognizedURLError.prototype = _routerUtils.oCreate(Error.prototype);

  exports.default = UnrecognizedURLError;
});
enifed('router/utils', ['exports'], function (exports) {
  'use strict';

  exports.extractQueryParams = extractQueryParams;
  exports.log = log;
  exports.bind = bind;
  exports.forEach = forEach;
  exports.trigger = trigger;
  exports.getChangelist = getChangelist;
  exports.promiseLabel = promiseLabel;
  exports.subclass = subclass;
  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];
    }
  }

  /**
    @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);
    }
  }

  function bind(context, fn) {
    var boundArgs = arguments;
    return function (value) {
      var args = slice.call(boundArgs, 2);
      args.push(value);
      return fn.apply(context, args);
    };
  }

  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++) {}
  }

  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 + "'.");
    }
  }

  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;
  }

  function promiseLabel(label) {
    return 'Router: ' + label;
  }

  function subclass(parentConstructor, proto) {
    function C(props) {
      parentConstructor.call(this, props || {});
    }
    C.prototype = oCreate(parentConstructor.prototype);
    merge(C.prototype, proto);
    return C;
  }

  function resolveHook(obj, hookName) {
    if (!obj) {
      return;
    }
    var underscored = "_" + hookName;
    return obj[underscored] && underscored || obj[hookName] && hookName;
  }

  function callHook(obj, _hookName, arg1, arg2) {
    var hookName = resolveHook(obj, _hookName);
    return hookName && obj[hookName].call(obj, arg1, arg2);
  }

  function applyHook(obj, _hookName, args) {
    var hookName = resolveHook(obj, _hookName);
    if (hookName) {
      if (args.length === 0) {
        return obj[hookName].call(obj);
      } else if (args.length === 1) {
        return obj[hookName].call(obj, args[0]);
      } else if (args.length === 2) {
        return obj[hookName].call(obj, args[0], args[1]);
      } else {
        return obj[hookName].apply(obj, args);
      }
    }
  }

  exports.merge = merge;
  exports.slice = slice;
  exports.isParam = isParam;
  exports.coerceQueryParamsToString = coerceQueryParamsToString;
  exports.callHook = callHook;
  exports.resolveHook = resolveHook;
  exports.applyHook = applyHook;
});
enifed('rsvp', ['exports', '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'], function (exports, _rsvpPromise, _rsvpEvents, _rsvpNode, _rsvpAll, _rsvpAllSettled, _rsvpRace, _rsvpHash, _rsvpHashSettled, _rsvpRethrow, _rsvpDefer, _rsvpConfig, _rsvpMap, _rsvpResolve, _rsvpReject, _rsvpFilter, _rsvpAsap) {
  'use strict';

  // defaults
  _rsvpConfig.config.async = _rsvpAsap.default;
  _rsvpConfig.config.after = function (cb) {
    setTimeout(cb, 0);
  };
  var cast = _rsvpResolve.default;
  function async(callback, arg) {
    _rsvpConfig.config.async(callback, arg);
  }

  function on() {
    _rsvpConfig.config['on'].apply(_rsvpConfig.config, arguments);
  }

  function off() {
    _rsvpConfig.config['off'].apply(_rsvpConfig.config, arguments);
  }

  // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`
  if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {
    var callbacks = window['__PROMISE_INSTRUMENTATION__'];
    _rsvpConfig.configure('instrument', true);
    for (var eventName in callbacks) {
      if (callbacks.hasOwnProperty(eventName)) {
        on(eventName, callbacks[eventName]);
      }
    }
  }

  exports.cast = cast;
  exports.Promise = _rsvpPromise.default;
  exports.EventTarget = _rsvpEvents.default;
  exports.all = _rsvpAll.default;
  exports.allSettled = _rsvpAllSettled.default;
  exports.race = _rsvpRace.default;
  exports.hash = _rsvpHash.default;
  exports.hashSettled = _rsvpHashSettled.default;
  exports.rethrow = _rsvpRethrow.default;
  exports.defer = _rsvpDefer.default;
  exports.denodeify = _rsvpNode.default;
  exports.configure = _rsvpConfig.configure;
  exports.on = on;
  exports.off = off;
  exports.resolve = _rsvpResolve.default;
  exports.reject = _rsvpReject.default;
  exports.async = async;
  exports.map = _rsvpMap.default;
  exports.filter = _rsvpFilter.default;
});
enifed('rsvp.umd', ['exports', 'rsvp/platform', 'rsvp'], function (exports, _rsvpPlatform, _rsvp) {
  'use strict';

  var RSVP = {
    'race': _rsvp.race,
    'Promise': _rsvp.Promise,
    'allSettled': _rsvp.allSettled,
    'hash': _rsvp.hash,
    'hashSettled': _rsvp.hashSettled,
    'denodeify': _rsvp.denodeify,
    'on': _rsvp.on,
    'off': _rsvp.off,
    'map': _rsvp.map,
    'filter': _rsvp.filter,
    'resolve': _rsvp.resolve,
    'reject': _rsvp.reject,
    'all': _rsvp.all,
    'rethrow': _rsvp.rethrow,
    'defer': _rsvp.defer,
    'EventTarget': _rsvp.EventTarget,
    'configure': _rsvp.configure,
    'async': _rsvp.async
  };

  /* global define:true module:true window: true */
  if (typeof define === 'function' && define['amd']) {
    define(function () {
      return RSVP;
    });
  } else if (typeof module !== 'undefined' && module['exports']) {
    module['exports'] = RSVP;
  } else if (typeof _rsvpPlatform.default !== 'undefined') {
    _rsvpPlatform.default['RSVP'] = RSVP;
  }
});
enifed('rsvp/-internal', ['exports', 'rsvp/utils', 'rsvp/instrument', 'rsvp/config'], function (exports, _rsvpUtils, _rsvpInstrument, _rsvpConfig) {
  'use strict';

  function withOwnPromise() {
    return new TypeError('A promises callback cannot return that same promise.');
  }

  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) {
    _rsvpConfig.config.async(function (promise) {
      var sealed = false;
      var error = tryThen(then, thenable, function (value) {
        if (sealed) {
          return;
        }
        sealed = true;
        if (thenable !== value) {
          resolve(promise, value);
        } else {
          fulfill(promise, value);
        }
      }, function (reason) {
        if (sealed) {
          return;
        }
        sealed = true;

        reject(promise, reason);
      }, 'Settle: ' + (promise._label || ' unknown promise'));

      if (!sealed && error) {
        sealed = true;
        reject(promise, error);
      }
    }, promise);
  }

  function handleOwnThenable(promise, thenable) {
    if (thenable._state === FULFILLED) {
      fulfill(promise, thenable._result);
    } else if (thenable._state === REJECTED) {
      thenable._onError = null;
      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.constructor === 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 (_rsvpUtils.isFunction(then)) {
        handleForeignThenable(promise, maybeThenable, then);
      } else {
        fulfill(promise, maybeThenable);
      }
    }
  }

  function resolve(promise, value) {
    if (promise === value) {
      fulfill(promise, value);
    } else if (_rsvpUtils.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 (_rsvpConfig.config.instrument) {
        _rsvpInstrument.default('fulfilled', promise);
      }
    } else {
      _rsvpConfig.config.async(publish, promise);
    }
  }

  function reject(promise, reason) {
    if (promise._state !== PENDING) {
      return;
    }
    promise._state = REJECTED;
    promise._result = reason;
    _rsvpConfig.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) {
      _rsvpConfig.config.async(publish, parent);
    }
  }

  function publish(promise) {
    var subscribers = promise._subscribers;
    var settled = promise._state;

    if (_rsvpConfig.config.instrument) {
      _rsvpInstrument.default(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 = _rsvpUtils.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, withOwnPromise());
        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) {
    var resolved = false;
    try {
      resolver(function resolvePromise(value) {
        if (resolved) {
          return;
        }
        resolved = true;
        resolve(promise, value);
      }, function rejectPromise(reason) {
        if (resolved) {
          return;
        }
        resolved = true;
        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;
  exports.PENDING = PENDING;
});
enifed('rsvp/all-settled', ['exports', 'rsvp/enumerator', 'rsvp/promise', 'rsvp/utils'], function (exports, _rsvpEnumerator, _rsvpPromise, _rsvpUtils) {
  'use strict';

  exports.default = allSettled;

  function AllSettled(Constructor, entries, label) {
    this._superConstructor(Constructor, entries, false, /* don't abort on reject */label);
  }

  AllSettled.prototype = _rsvpUtils.o_create(_rsvpEnumerator.default.prototype);
  AllSettled.prototype._superConstructor = _rsvpEnumerator.default;
  AllSettled.prototype._makeResult = _rsvpEnumerator.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} entries
    @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.
  */

  function allSettled(entries, label) {
    return new AllSettled(_rsvpPromise.default, entries, label).promise;
  }
});
enifed("rsvp/all", ["exports", "rsvp/promise"], function (exports, _rsvpPromise) {
  "use strict";

  exports.default = all;

  /**
    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.
  */

  function all(array, label) {
    return _rsvpPromise.default.all(array, label);
  }
});
enifed('rsvp/asap', ['exports'], function (exports) {
  'use strict';

  exports.default = asap;
  var len = 0;
  var toString = ({}).toString;
  var vertxNext;

  function asap(callback, arg) {
    queue[len] = callback;
    queue[len + 1] = arg;
    len += 2;
    if (len === 2) {
      // If len 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 browserWindow = typeof window !== 'undefined' ? window : undefined;
  var browserGlobal = browserWindow || {};
  var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
  var isNode = typeof window === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]';

  // test for web worker but not in IE10
  var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';

  // node
  function useNextTick() {
    var nextTick = process.nextTick;
    // node version 0.10.x displays a deprecation warning when nextTick is used recursively
    // setImmediate should be used instead instead
    var version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/);
    if (Array.isArray(version) && version[1] === '0' && version[2] === '10') {
      nextTick = setImmediate;
    }
    return function () {
      nextTick(flush);
    };
  }

  // vertx
  function useVertxTimer() {
    return function () {
      vertxNext(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 < len; i += 2) {
      var callback = queue[i];
      var arg = queue[i + 1];

      callback(arg);

      queue[i] = undefined;
      queue[i + 1] = undefined;
    }

    len = 0;
  }

  function attemptVertex() {
    try {
      var r = require;
      var vertx = r('vertx');
      vertxNext = vertx.runOnLoop || vertx.runOnContext;
      return useVertxTimer();
    } catch (e) {
      return useSetTimeout();
    }
  }

  var scheduleFlush;
  // Decide what async method to use to triggering processing of queued callbacks:
  if (isNode) {
    scheduleFlush = useNextTick();
  } else if (BrowserMutationObserver) {
    scheduleFlush = useMutationObserver();
  } else if (isWorker) {
    scheduleFlush = useMessageChannel();
  } else if (browserWindow === undefined && typeof require === 'function') {
    scheduleFlush = attemptVertex();
  } else {
    scheduleFlush = useSetTimeout();
  }
});
enifed('rsvp/config', ['exports', 'rsvp/events'], function (exports, _rsvpEvents) {
  'use strict';

  var config = {
    instrument: false
  };

  _rsvpEvents.default['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;
});
enifed('rsvp/defer', ['exports', 'rsvp/promise'], function (exports, _rsvpPromise) {
  'use strict';

  exports.default = defer;

  /**
    `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!");

     deferred.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}
   */

  function defer(label) {
    var deferred = {};

    deferred['promise'] = new _rsvpPromise.default(function (resolve, reject) {
      deferred['resolve'] = resolve;
      deferred['reject'] = reject;
    }, label);

    return deferred;
  }
});
enifed('rsvp/enumerator', ['exports', 'rsvp/utils', 'rsvp/-internal'], function (exports, _rsvpUtils, _rsvpInternal) {
  'use strict';

  exports.makeSettledResult = makeSettledResult;

  function makeSettledResult(state, position, value) {
    if (state === _rsvpInternal.FULFILLED) {
      return {
        state: 'fulfilled',
        value: value
      };
    } else {
      return {
        state: 'rejected',
        reason: value
      };
    }
  }

  function Enumerator(Constructor, input, abortOnReject, label) {
    var enumerator = this;

    enumerator._instanceConstructor = Constructor;
    enumerator.promise = new Constructor(_rsvpInternal.noop, label);
    enumerator._abortOnReject = abortOnReject;

    if (enumerator._validateInput(input)) {
      enumerator._input = input;
      enumerator.length = input.length;
      enumerator._remaining = input.length;

      enumerator._init();

      if (enumerator.length === 0) {
        _rsvpInternal.fulfill(enumerator.promise, enumerator._result);
      } else {
        enumerator.length = enumerator.length || 0;
        enumerator._enumerate();
        if (enumerator._remaining === 0) {
          _rsvpInternal.fulfill(enumerator.promise, enumerator._result);
        }
      }
    } else {
      _rsvpInternal.reject(enumerator.promise, enumerator._validationError());
    }
  }

  exports.default = Enumerator;

  Enumerator.prototype._validateInput = function (input) {
    return _rsvpUtils.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);
  };

  Enumerator.prototype._enumerate = function () {
    var enumerator = this;
    var length = enumerator.length;
    var promise = enumerator.promise;
    var input = enumerator._input;

    for (var i = 0; promise._state === _rsvpInternal.PENDING && i < length; i++) {
      enumerator._eachEntry(input[i], i);
    }
  };

  Enumerator.prototype._eachEntry = function (entry, i) {
    var enumerator = this;
    var c = enumerator._instanceConstructor;
    if (_rsvpUtils.isMaybeThenable(entry)) {
      if (entry.constructor === c && entry._state !== _rsvpInternal.PENDING) {
        entry._onError = null;
        enumerator._settledAt(entry._state, i, entry._result);
      } else {
        enumerator._willSettleAt(c.resolve(entry), i);
      }
    } else {
      enumerator._remaining--;
      enumerator._result[i] = enumerator._makeResult(_rsvpInternal.FULFILLED, i, entry);
    }
  };

  Enumerator.prototype._settledAt = function (state, i, value) {
    var enumerator = this;
    var promise = enumerator.promise;

    if (promise._state === _rsvpInternal.PENDING) {
      enumerator._remaining--;

      if (enumerator._abortOnReject && state === _rsvpInternal.REJECTED) {
        _rsvpInternal.reject(promise, value);
      } else {
        enumerator._result[i] = enumerator._makeResult(state, i, value);
      }
    }

    if (enumerator._remaining === 0) {
      _rsvpInternal.fulfill(promise, enumerator._result);
    }
  };

  Enumerator.prototype._makeResult = function (state, i, value) {
    return value;
  };

  Enumerator.prototype._willSettleAt = function (promise, i) {
    var enumerator = this;

    _rsvpInternal.subscribe(promise, undefined, function (value) {
      enumerator._settledAt(_rsvpInternal.FULFILLED, i, value);
    }, function (reason) {
      enumerator._settledAt(_rsvpInternal.REJECTED, i, reason);
    });
  };
});
enifed('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 = {

    /**
      `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For
      Example:
       ```javascript
      var object = {};
       RSVP.EventTarget.mixin(object);
       object.on('finished', function(event) {
        // handle event
      });
       object.trigger('finished', { detail: value });
      ```
       `EventTarget.mixin` also works with prototypes:
       ```javascript
      var Person = function() {};
      RSVP.EventTarget.mixin(Person.prototype);
       var yehuda = new Person();
      var tom = new Person();
       yehuda.on('poke', function(event) {
        console.log('Yehuda says OW');
      });
       tom.on('poke', function(event) {
        console.log('Tom says OW');
      });
       yehuda.trigger('poke');
      tom.trigger('poke');
      ```
       @method mixin
      @for RSVP.EventTarget
      @private
      @param {Object} object object to extend with EventTarget methods
    */
    'mixin': function (object) {
      object['on'] = this['on'];
      object['off'] = this['off'];
      object['trigger'] = this['trigger'];
      object._promiseCallbacks = undefined;
      return object;
    },

    /**
      Registers a callback to be executed when `eventName` is triggered
       ```javascript
      object.on('event', function(eventInfo){
        // handle the event
      });
       object.trigger('event');
      ```
       @method on
      @for RSVP.EventTarget
      @private
      @param {String} eventName name of the event to listen for
      @param {Function} callback function to be called when the event is triggered.
    */
    'on': function (eventName, callback) {
      if (typeof callback !== 'function') {
        throw new TypeError('Callback must be a function');
      }

      var allCallbacks = callbacksFor(this),
          callbacks;

      callbacks = allCallbacks[eventName];

      if (!callbacks) {
        callbacks = allCallbacks[eventName] = [];
      }

      if (indexOf(callbacks, callback) === -1) {
        callbacks.push(callback);
      }
    },

    /**
      You can use `off` to stop firing a particular callback for an event:
       ```javascript
      function doStuff() { // do stuff! }
      object.on('stuff', doStuff);
       object.trigger('stuff'); // doStuff will be called
       // Unregister ONLY the doStuff callback
      object.off('stuff', doStuff);
      object.trigger('stuff'); // doStuff will NOT be called
      ```
       If you don't pass a `callback` argument to `off`, ALL callbacks for the
      event will not be executed when the event fires. For example:
       ```javascript
      var callback1 = function(){};
      var callback2 = function(){};
       object.on('stuff', callback1);
      object.on('stuff', callback2);
       object.trigger('stuff'); // callback1 and callback2 will be executed.
       object.off('stuff');
      object.trigger('stuff'); // callback1 and callback2 will not be executed!
      ```
       @method off
      @for RSVP.EventTarget
      @private
      @param {String} eventName event to stop listening to
      @param {Function} callback optional argument. If given, only the function
      given will be removed from the event's callback queue. If no `callback`
      argument is given, all callbacks will be removed from the event's callback
      queue.
    */
    '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);
      }
    },

    /**
      Use `trigger` to fire custom events. For example:
       ```javascript
      object.on('foo', function(){
        console.log('foo event happened!');
      });
      object.trigger('foo');
      // 'foo event happened!' logged to the console
      ```
       You can also pass a value as a second argument to `trigger` that will be
      passed as an argument to all event listeners for the event:
       ```javascript
      object.on('foo', function(value){
        console.log(value.name);
      });
       object.trigger('foo', { name: 'bar' });
      // 'bar' logged to the console
      ```
       @method trigger
      @for RSVP.EventTarget
      @private
      @param {String} eventName name of the event to be triggered
      @param {*} options optional value to be passed to any event handlers for
      the given `eventName`
    */
    'trigger': function (eventName, options) {
      var allCallbacks = callbacksFor(this),
          callbacks,
          callback;

      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);
        }
      }
    }
  };
});
enifed('rsvp/filter', ['exports', 'rsvp/promise', 'rsvp/utils'], function (exports, _rsvpPromise, _rsvpUtils) {
  'use strict';

  exports.default = filter;

  /**
   `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}
  */

  function filter(promises, filterFn, label) {
    return _rsvpPromise.default.all(promises, label).then(function (values) {
      if (!_rsvpUtils.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 _rsvpPromise.default.all(filtered, label).then(function (filtered) {
        var results = new Array(length);
        var newLength = 0;

        for (var i = 0; i < length; i++) {
          if (filtered[i]) {
            results[newLength] = values[i];
            newLength++;
          }
        }

        results.length = newLength;

        return results;
      });
    });
  }
});
enifed('rsvp/hash-settled', ['exports', 'rsvp/promise', 'rsvp/enumerator', 'rsvp/promise-hash', 'rsvp/utils'], function (exports, _rsvpPromise, _rsvpEnumerator, _rsvpPromiseHash, _rsvpUtils) {
  'use strict';

  exports.default = hashSettled;

  function HashSettled(Constructor, object, label) {
    this._superConstructor(Constructor, object, false, label);
  }

  HashSettled.prototype = _rsvpUtils.o_create(_rsvpPromiseHash.default.prototype);
  HashSettled.prototype._superConstructor = _rsvpEnumerator.default;
  HashSettled.prototype._makeResult = _rsvpEnumerator.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} object
    @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
  */

  function hashSettled(object, label) {
    return new HashSettled(_rsvpPromise.default, object, label).promise;
  }
});
enifed('rsvp/hash', ['exports', 'rsvp/promise', 'rsvp/promise-hash'], function (exports, _rsvpPromise, _rsvpPromiseHash) {
  'use strict';

  exports.default = hash;

  /**
    `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} object
    @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.
  */

  function hash(object, label) {
    return new _rsvpPromiseHash.default(_rsvpPromise.default, object, label).promise;
  }
});
enifed('rsvp/instrument', ['exports', 'rsvp/config', 'rsvp/utils'], function (exports, _rsvpConfig, _rsvpUtils) {
  'use strict';

  exports.default = instrument;

  var queue = [];

  function scheduleFlush() {
    setTimeout(function () {
      var entry;
      for (var i = 0; i < queue.length; i++) {
        entry = queue[i];

        var payload = entry.payload;

        payload.guid = payload.key + payload.id;
        payload.childGuid = payload.key + payload.childId;
        if (payload.error) {
          payload.stack = payload.error.stack;
        }

        _rsvpConfig.config['trigger'](entry.name, entry.payload);
      }
      queue.length = 0;
    }, 50);
  }

  function instrument(eventName, promise, child) {
    if (1 === queue.push({
      name: eventName,
      payload: {
        key: promise._guidKey,
        id: promise._id,
        eventName: eventName,
        detail: promise._result,
        childId: child && child._id,
        label: promise._label,
        timeStamp: _rsvpUtils.now(),
        error: _rsvpConfig.config["instrument-with-stack"] ? new Error(promise._label) : null
      } })) {
      scheduleFlush();
    }
  }
});
enifed('rsvp/map', ['exports', 'rsvp/promise', 'rsvp/utils'], function (exports, _rsvpPromise, _rsvpUtils) {
  'use strict';

  exports.default = map;

  /**
   `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
  */

  function map(promises, mapFn, label) {
    return _rsvpPromise.default.all(promises, label).then(function (values) {
      if (!_rsvpUtils.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 _rsvpPromise.default.all(results, label);
    });
  }
});
enifed('rsvp/node', ['exports', 'rsvp/promise', 'rsvp/-internal', 'rsvp/utils'], function (exports, _rsvpPromise, _rsvpInternal, _rsvpUtils) {
  'use strict';

  exports.default = denodeify;

  function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }

  function Result() {
    this.value = undefined;
  }

  var ERROR = new Result();
  var GET_THEN_ERROR = new Result();

  function getThen(obj) {
    try {
      return obj.then;
    } catch (error) {
      ERROR.value = error;
      return ERROR;
    }
  }

  function tryApply(f, s, a) {
    try {
      f.apply(s, a);
    } catch (error) {
      ERROR.value = error;
      return ERROR;
    }
  }

  function makeObject(_, argumentNames) {
    var obj = {};
    var name;
    var i;
    var length = _.length;
    var args = new Array(length);

    for (var x = 0; x < length; x++) {
      args[x] = _[x];
    }

    for (i = 0; i < argumentNames.length; i++) {
      name = argumentNames[i];
      obj[name] = args[i + 1];
    }

    return obj;
  }

  function arrayResult(_) {
    var length = _.length;
    var args = new Array(length - 1);

    for (var i = 1; i < length; i++) {
      args[i - 1] = _[i];
    }

    return args;
  }

  function wrapThenable(then, promise) {
    return {
      then: function (onFulFillment, onRejection) {
        return then.call(promise, onFulFillment, onRejection);
      }
    };
  }

  /**
    `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} [options] 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
  */

  function denodeify(nodeFunc, options) {
    var fn = function () {
      var self = this;
      var l = arguments.length;
      var args = new Array(l + 1);
      var arg;
      var promiseInput = false;

      for (var i = 0; i < l; ++i) {
        arg = arguments[i];

        if (!promiseInput) {
          // TODO: clean this up
          promiseInput = needsPromiseInput(arg);
          if (promiseInput === GET_THEN_ERROR) {
            var p = new _rsvpPromise.default(_rsvpInternal.noop);
            _rsvpInternal.reject(p, GET_THEN_ERROR.value);
            return p;
          } else if (promiseInput && promiseInput !== true) {
            arg = wrapThenable(promiseInput, arg);
          }
        }
        args[i] = arg;
      }

      var promise = new _rsvpPromise.default(_rsvpInternal.noop);

      args[l] = function (err, val) {
        if (err) _rsvpInternal.reject(promise, err);else if (options === undefined) _rsvpInternal.resolve(promise, val);else if (options === true) _rsvpInternal.resolve(promise, arrayResult(arguments));else if (_rsvpUtils.isArray(options)) _rsvpInternal.resolve(promise, makeObject(arguments, options));else _rsvpInternal.resolve(promise, val);
      };

      if (promiseInput) {
        return handlePromiseInput(promise, args, nodeFunc, self);
      } else {
        return handleValueInput(promise, args, nodeFunc, self);
      }
    };

    _defaults(fn, nodeFunc);

    return fn;
  }

  function handleValueInput(promise, args, nodeFunc, self) {
    var result = tryApply(nodeFunc, self, args);
    if (result === ERROR) {
      _rsvpInternal.reject(promise, result.value);
    }
    return promise;
  }

  function handlePromiseInput(promise, args, nodeFunc, self) {
    return _rsvpPromise.default.all(args).then(function (args) {
      var result = tryApply(nodeFunc, self, args);
      if (result === ERROR) {
        _rsvpInternal.reject(promise, result.value);
      }
      return promise;
    });
  }

  function needsPromiseInput(arg) {
    if (arg && typeof arg === 'object') {
      if (arg.constructor === _rsvpPromise.default) {
        return true;
      } else {
        return getThen(arg);
      }
    } else {
      return false;
    }
  }
});
enifed('rsvp/platform', ['exports'], function (exports) {
  'use strict';

  var platform;

  /* global self */
  if (typeof self === 'object') {
    platform = self;

    /* global global */
  } else if (typeof global === 'object') {
      platform = global;
    } else {
      throw new Error('no global: `self` or `global` found');
    }

  exports.default = platform;
});
enifed('rsvp/promise-hash', ['exports', 'rsvp/enumerator', 'rsvp/-internal', 'rsvp/utils'], function (exports, _rsvpEnumerator, _rsvpInternal, _rsvpUtils) {
  'use strict';

  function PromiseHash(Constructor, object, label) {
    this._superConstructor(Constructor, object, true, label);
  }

  exports.default = PromiseHash;

  PromiseHash.prototype = _rsvpUtils.o_create(_rsvpEnumerator.default.prototype);
  PromiseHash.prototype._superConstructor = _rsvpEnumerator.default;
  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 enumerator = this;
    var promise = enumerator.promise;
    var input = enumerator._input;
    var results = [];

    for (var key in input) {
      if (promise._state === _rsvpInternal.PENDING && Object.prototype.hasOwnProperty.call(input, key)) {
        results.push({
          position: key,
          entry: input[key]
        });
      }
    }

    var length = results.length;
    enumerator._remaining = length;
    var result;

    for (var i = 0; promise._state === _rsvpInternal.PENDING && i < length; i++) {
      result = results[i];
      enumerator._eachEntry(result.entry, result.position);
    }
  };
});
enifed('rsvp/promise', ['exports', 'rsvp/config', 'rsvp/instrument', 'rsvp/utils', 'rsvp/-internal', 'rsvp/promise/all', 'rsvp/promise/race', 'rsvp/promise/resolve', 'rsvp/promise/reject'], function (exports, _rsvpConfig, _rsvpInstrument, _rsvpUtils, _rsvpInternal, _rsvpPromiseAll, _rsvpPromiseRace, _rsvpPromiseResolve, _rsvpPromiseReject) {
  'use strict';

  exports.default = Promise;

  var guidKey = 'rsvp_' + _rsvpUtils.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.");
  }

  /**
    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) {
    var promise = this;

    promise._id = counter++;
    promise._label = label;
    promise._state = undefined;
    promise._result = undefined;
    promise._subscribers = [];

    if (_rsvpConfig.config.instrument) {
      _rsvpInstrument.default('created', promise);
    }

    if (_rsvpInternal.noop !== resolver) {
      if (!_rsvpUtils.isFunction(resolver)) {
        needsResolver();
      }

      if (!(promise instanceof Promise)) {
        needsNew();
      }

      _rsvpInternal.initializePromise(promise, resolver);
    }
  }

  Promise.cast = _rsvpPromiseResolve.default; // deprecated
  Promise.all = _rsvpPromiseAll.default;
  Promise.race = _rsvpPromiseRace.default;
  Promise.resolve = _rsvpPromiseResolve.default;
  Promise.reject = _rsvpPromiseReject.default;

  Promise.prototype = {
    constructor: Promise,

    _guidKey: guidKey,

    _onError: function (reason) {
      var promise = this;
      _rsvpConfig.config.after(function () {
        if (promise._onError) {
          _rsvpConfig.config['trigger']('error', reason);
        }
      });
    },

    /**
      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.

      ```js
      findUser().then(function(user){
        // user is available
      }, function(reason){
        // user is unavailable, and you are given the reason why
      });
      ```

      Chaining
      --------

      The return value of `then` is itself a promise.  This second, 'downstream'
      promise is resolved with the return value of the first promise's fulfillment
      or rejection handler, or rejected if the handler throws an exception.

      ```js
      findUser().then(function (user) {
        return user.name;
      }, function (reason) {
        return 'default name';
      }).then(function (userName) {
        // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
        // will be `'default name'`
      });

      findUser().then(function (user) {
        throw new Error('Found user, but still unhappy');
      }, function (reason) {
        throw new Error('`findUser` rejected and we're unhappy');
      }).then(function (value) {
        // never reached
      }, function (reason) {
        // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
        // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
      });
      ```
      If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.

      ```js
      findUser().then(function (user) {
        throw new PedagogicalException('Upstream error');
      }).then(function (value) {
        // never reached
      }).then(function (value) {
        // never reached
      }, function (reason) {
        // The `PedgagocialException` is propagated all the way down to here
      });
      ```

      Assimilation
      ------------

      Sometimes the value you want to propagate to a downstream promise can only be
      retrieved asynchronously. This can be achieved by returning a promise in the
      fulfillment or rejection handler. The downstream promise will then be pending
      until the returned promise is settled. This is called *assimilation*.

      ```js
      findUser().then(function (user) {
        return findCommentsByAuthor(user);
      }).then(function (comments) {
        // The user's comments are now available
      });
      ```

      If the assimliated promise rejects, then the downstream promise will also reject.

      ```js
      findUser().then(function (user) {
        return findCommentsByAuthor(user);
      }).then(function (comments) {
        // If `findCommentsByAuthor` fulfills, we'll have the value here
      }, function (reason) {
        // If `findCommentsByAuthor` rejects, we'll have the reason here
      });
      ```

      Simple Example
      --------------

      Synchronous Example

      ```javascript
      var result;

      try {
        result = findResult();
        // success
      } catch(reason) {
        // failure
      }
      ```

      Errback Example

      ```js
      findResult(function(result, err){
        if (err) {
          // failure
        } else {
          // success
        }
      });
      ```

      Promise Example;

      ```javascript
      findResult().then(function(result){
        // success
      }, function(reason){
        // failure
      });
      ```

      Advanced Example
      --------------

      Synchronous Example

      ```javascript
      var author, books;

      try {
        author = findAuthor();
        books  = findBooksByAuthor(author);
        // success
      } catch(reason) {
        // failure
      }
      ```

      Errback Example

      ```js

      function foundBooks(books) {

      }

      function failure(reason) {

      }

      findAuthor(function(author, err){
        if (err) {
          failure(err);
          // failure
        } else {
          try {
            findBoooksByAuthor(author, function(books, err) {
              if (err) {
                failure(err);
              } else {
                try {
                  foundBooks(books);
                } catch(reason) {
                  failure(reason);
                }
              }
            });
          } catch(error) {
            failure(err);
          }
          // success
        }
      });
      ```

      Promise Example;

      ```javascript
      findAuthor().
        then(findBooksByAuthor).
        then(function(books){
          // found books
      }).catch(function(reason){
        // something went wrong
      });
      ```

      @method then
      @param {Function} onFulfillment
      @param {Function} onRejection
      @param {String} label optional string for labeling the promise.
      Useful for tooling.
      @return {Promise}
    */
    then: function (onFulfillment, onRejection, label) {
      var parent = this;
      var state = parent._state;

      if (state === _rsvpInternal.FULFILLED && !onFulfillment || state === _rsvpInternal.REJECTED && !onRejection) {
        if (_rsvpConfig.config.instrument) {
          _rsvpInstrument.default('chained', parent, parent);
        }
        return parent;
      }

      parent._onError = null;

      var child = new parent.constructor(_rsvpInternal.noop, label);
      var result = parent._result;

      if (_rsvpConfig.config.instrument) {
        _rsvpInstrument.default('chained', parent, child);
      }

      if (state) {
        var callback = arguments[state - 1];
        _rsvpConfig.config.async(function () {
          _rsvpInternal.invokeCallback(state, child, callback, result);
        });
      } else {
        _rsvpInternal.subscribe(parent, child, onFulfillment, onRejection);
      }

      return child;
    },

    /**
      `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
      as the catch block of a try/catch statement.

      ```js
      function findAuthor(){
        throw new Error('couldn't find that author');
      }

      // synchronous
      try {
        findAuthor();
      } catch(reason) {
        // something went wrong
      }

      // async with promises
      findAuthor().catch(function(reason){
        // something went wrong
      });
      ```

      @method catch
      @param {Function} onRejection
      @param {String} label optional string for labeling the promise.
      Useful for tooling.
      @return {Promise}
    */
    'catch': function (onRejection, label) {
      return this.then(undefined, onRejection, label);
    },

    /**
      `finally` will be invoked regardless of the promise's fate just as native
      try/catch/finally behaves

      Synchronous example:

      ```js
      findAuthor() {
        if (Math.random() > 0.5) {
          throw new Error();
        }
        return new Author();
      }

      try {
        return findAuthor(); // succeed or fail
      } catch(error) {
        return findOtherAuther();
      } finally {
        // always runs
        // doesn't affect the return value
      }
      ```

      Asynchronous example:

      ```js
      findAuthor().catch(function(reason){
        return findOtherAuther();
      }).finally(function(){
        // author was either found, or not
      });
      ```

      @method finally
      @param {Function} callback
      @param {String} label optional string for labeling the promise.
      Useful for tooling.
      @return {Promise}
    */
    'finally': function (callback, label) {
      var promise = this;
      var constructor = promise.constructor;

      return promise.then(function (value) {
        return constructor.resolve(callback()).then(function () {
          return value;
        });
      }, function (reason) {
        return constructor.resolve(callback()).then(function () {
          throw reason;
        });
      }, label);
    }
  };
});
enifed('rsvp/promise/all', ['exports', 'rsvp/enumerator'], function (exports, _rsvpEnumerator) {
  'use strict';

  exports.default = all;

  /**
    `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
  */

  function all(entries, label) {
    return new _rsvpEnumerator.default(this, entries, true, /* abort on reject */label).promise;
  }
});
enifed('rsvp/promise/race', ['exports', 'rsvp/utils', 'rsvp/-internal'], function (exports, _rsvpUtils, _rsvpInternal) {
  'use strict';

  exports.default = race;

  /**
    `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} entries 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.
  */

  function race(entries, label) {
    /*jshint validthis:true */
    var Constructor = this;

    var promise = new Constructor(_rsvpInternal.noop, label);

    if (!_rsvpUtils.isArray(entries)) {
      _rsvpInternal.reject(promise, new TypeError('You must pass an array to race.'));
      return promise;
    }

    var length = entries.length;

    function onFulfillment(value) {
      _rsvpInternal.resolve(promise, value);
    }

    function onRejection(reason) {
      _rsvpInternal.reject(promise, reason);
    }

    for (var i = 0; promise._state === _rsvpInternal.PENDING && i < length; i++) {
      _rsvpInternal.subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
    }

    return promise;
  }
});
enifed('rsvp/promise/reject', ['exports', 'rsvp/-internal'], function (exports, _rsvpInternal) {
  'use strict';

  exports.default = 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 {*} 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`.
  */

  function reject(reason, label) {
    /*jshint validthis:true */
    var Constructor = this;
    var promise = new Constructor(_rsvpInternal.noop, label);
    _rsvpInternal.reject(promise, reason);
    return promise;
  }
});
enifed('rsvp/promise/resolve', ['exports', 'rsvp/-internal'], function (exports, _rsvpInternal) {
  'use strict';

  exports.default = 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 {*} object 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`
  */

  function resolve(object, label) {
    /*jshint validthis:true */
    var Constructor = this;

    if (object && typeof object === 'object' && object.constructor === Constructor) {
      return object;
    }

    var promise = new Constructor(_rsvpInternal.noop, label);
    _rsvpInternal.resolve(promise, object);
    return promise;
  }
});
enifed('rsvp/race', ['exports', 'rsvp/promise'], function (exports, _rsvpPromise) {
  'use strict';

  exports.default = race;

  /**
    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.
   */

  function race(array, label) {
    return _rsvpPromise.default.race(array, label);
  }
});
enifed('rsvp/reject', ['exports', 'rsvp/promise'], function (exports, _rsvpPromise) {
  'use strict';

  exports.default = reject;

  /**
    This is a convenient alias for `RSVP.Promise.reject`.

    @method reject
    @static
    @for RSVP
    @param {*} 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`.
  */

  function reject(reason, label) {
    return _rsvpPromise.default.reject(reason, label);
  }
});
enifed('rsvp/resolve', ['exports', 'rsvp/promise'], function (exports, _rsvpPromise) {
  'use strict';

  exports.default = resolve;

  /**
    This is a convenient alias for `RSVP.Promise.resolve`.

    @method resolve
    @static
    @for RSVP
    @param {*} 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`
  */

  function resolve(value, label) {
    return _rsvpPromise.default.resolve(value, label);
  }
});
enifed("rsvp/rethrow", ["exports"], function (exports) {
  /**
    `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
  */
  "use strict";

  exports.default = rethrow;

  function rethrow(reason) {
    setTimeout(function () {
      throw reason;
    });
    throw reason;
  }
});
enifed('rsvp/utils', ['exports'], function (exports) {
  'use strict';

  exports.objectOrFunction = objectOrFunction;
  exports.isFunction = isFunction;
  exports.isMaybeThenable = isMaybeThenable;

  function objectOrFunction(x) {
    return typeof x === 'function' || typeof x === 'object' && x !== null;
  }

  function isFunction(x) {
    return typeof x === 'function';
  }

  function isMaybeThenable(x) {
    return typeof x === 'object' && x !== null;
  }

  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;
  function F() {}

  var o_create = Object.create || function (o) {
    if (arguments.length > 1) {
      throw new Error('Second argument not supported');
    }
    if (typeof o !== 'object') {
      throw new TypeError('Argument must be an object');
    }
    F.prototype = o;
    return new F();
  };
  exports.o_create = o_create;
});
enifed("vertex", ["exports"], function (exports) {
  /**
   * DAG Vertex
   *
   * @class Vertex
   * @constructor
   */

  "use strict";

  exports.default = Vertex;

  function Vertex(name) {
    this.name = name;
    this.incoming = {};
    this.incomingNames = [];
    this.hasOutgoing = false;
    this.value = null;
  }
});
enifed("visit", ["exports"], function (exports) {
  "use strict";

  exports.default = visit;

  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();
  }
});
requireModule("ember");

}());

;(function() {
/* globals define, Ember, jQuery */

  function processEmberShims() {
    var shims = {
      'ember': {
        'default': Ember
      },
      'ember-application': {
        'default': Ember.Application
      },
      'ember-array': {
        'default': Ember.Array
      },
      'ember-array/mutable': {
        'default': Ember.MutableArray
      },
      'ember-array/utils': {
        'A':            Ember.A,
        'isEmberArray': Ember.isArray,
        'wrap':         Ember.makeArray
      },
      'ember-component': {
        'default': Ember.Component
      },
      'ember-components/checkbox': {
        'default': Ember.Checkbox
      },
      'ember-components/text-area': {
        'default': Ember.TextArea
      },
      'ember-components/text-field': {
        'default': Ember.TextField
      },
      'ember-controller': {
        'default': Ember.Controller
      },
      'ember-controller/inject': {
        'default': Ember.inject.controller
      },
      'ember-controller/proxy': {
        'default': Ember.ArrayProxy
      },
      'ember-controllers/sortable': {
        'default': Ember.SortableMixin
      },
      'ember-debug': {
        'log':      Ember.debug,
        'inspect':  Ember.inspect,
        'run':      Ember.runInDebug,
        'warn':     Ember.warn
      },
      'ember-debug/container-debug-adapter': {
        'default': Ember.ContainerDebugAdapter
      },
      'ember-debug/data-adapter': {
        'default': Ember.DataAdapter
      },
      'ember-deprecations': {
        'deprecate':      Ember.deprecate,
        'deprecateFunc':  Ember.deprecateFunc
      },
      'ember-enumerable': {
        'default': Ember.Enumerable
      },
      'ember-evented': {
        'default': Ember.Evented
      },
      'ember-evented/on': {
        'default': Ember.on
      },
      'ember-globals-resolver': {
        'default': Ember.DefaultResolver
      },
      'ember-helper': {
        'default':  Ember.Helper,
        'helper':   Ember.Helper && Ember.Helper.helper
      },
      'ember-instrumentation': {
        'instrument':   Ember.Instrumentation.instrument,
        'reset':        Ember.Instrumentation.reset,
        'subscribe':    Ember.Instrumentation.subscribe,
        'unsubscribe':  Ember.Instrumentation.unsubscribe
      },
      'ember-locations/hash': {
        'default': Ember.HashLocation
      },
      'ember-locations/history': {
        'default': Ember.HistoryLocation
      },
      'ember-locations/none': {
        'default': Ember.NoneLocation
      },
      'ember-map': {
        'default':      Ember.Map,
        'withDefault':  Ember.MapWithDefault
      },
      'ember-metal/destroy': {
        'default': Ember.destroy
      },
      'ember-metal/events': {
        'addListener':    Ember.addListener,
        'removeListener': Ember.removeListener,
        'send':           Ember.sendEvent
      },
      'ember-metal/get': {
        'default': Ember.get,
        'getProperties': Ember.getProperties
      },
      'ember-metal/mixin': {
        'default': Ember.Mixin
      },
      'ember-metal/observer': {
        'default':        Ember.observer,
        'addObserver':    Ember.addObserver,
        'removeObserver': Ember.removeObserver
      },
      'ember-metal/on-load': {
        'default':  Ember.onLoad,
        'run':      Ember.runLoadHooks
      },
      'ember-metal/set': {
        'default':        Ember.set,
        'setProperties':  Ember.setProperties,
        'trySet':         Ember.trySet
      },
      'ember-metal/utils': {
        'aliasMethod':  Ember.aliasMethod,
        'assert':       Ember.assert,
        'cacheFor':     Ember.cacheFor,
        'copy':         Ember.copy,
        'guidFor':      Ember.guidFor
      },
      'ember-object': {
        'default': Ember.Object
      },
      'ember-platform': {
        'assign':         Ember.merge,
        'create':         Ember.create,
        'defineProperty': Ember.platform.defineProperty,
        'hasAccessors':   Ember.platform.hasPropertyAccessors,
        'keys':           Ember.keys
      },
      'ember-route': {
        'default': Ember.Route
      },
      'ember-router': {
        'default': Ember.Router
      },
      'ember-runloop': {
        'default':      Ember.run,
        'begin':        Ember.run.begin,
        'bind':         Ember.run.bind,
        'cancel':       Ember.run.cancel,
        'debounce':     Ember.run.debounce,
        'end':          Ember.run.end,
        'join':         Ember.run.join,
        'later':        Ember.run.later,
        'next':         Ember.run.next,
        'once':         Ember.run.once,
        'schedule':     Ember.run.schedule,
        'scheduleOnce': Ember.run.scheduleOnce,
        'throttle':     Ember.run.throttle
      },
      'ember-service': {
        'default': Ember.Service
      },
      'ember-service/inject': {
        'default': Ember.inject.service
      },
      'ember-set/ordered': {
        'default': Ember.OrderedSet
      },
      'ember-string': {
        'camelize':     Ember.String.camelize,
        'capitalize':   Ember.String.capitalize,
        'classify':     Ember.String.classify,
        'dasherize':    Ember.String.dasherize,
        'decamelize':   Ember.String.decamelize,
        'fmt':          Ember.String.fmt,
        'htmlSafe':     Ember.String.htmlSafe,
        'loc':          Ember.String.loc,
        'underscore':   Ember.String.underscore,
        'w':            Ember.String.w
      },
      'ember-utils': {
        'isBlank':    Ember.isBlank,
        'isEmpty':    Ember.isEmpty,
        'isNone':     Ember.isNone,
        'isPresent':  Ember.isPresent,
        'tryInvoke':  Ember.tryInvoke,
        'typeOf':     Ember.typeOf
      }
    };

    // populate `ember/computed` named exports
    shims['ember-computed'] = {
      'default': Ember.computed
    };
    var computedMacros = [
      "empty","notEmpty", "none", "not", "bool", "match",
      "equal", "gt", "gte", "lt", "lte", "alias", "oneWay",
      "reads", "readOnly", "deprecatingAlias",
      "and", "or", "collect", "sum", "min", "max",
      "map", "sort", "setDiff", "mapBy", "mapProperty",
      "filter", "filterBy", "filterProperty", "uniq",
      "union", "intersect"
    ];
    for (var i = 0, l = computedMacros.length; i < l; i++) {
      var key = computedMacros[i];
      shims['ember-computed'][key] = Ember.computed[key];
    }

    for (var moduleName in shims) {
      generateModule(moduleName, shims[moduleName]);
    }
  }

  function processTestShims() {
    if (Ember.Test) {
      var testShims = {
        'ember-test': {
          'default': Ember.Test
        },
        'ember-test/adapter': {
          'default': Ember.Test.Adapter
        },
        'ember-test/qunit-adapter': {
          'default': Ember.Test.QUnitAdapter
        }
      };

      for (var moduleName in testShims) {
        generateModule(moduleName, testShims[moduleName]);
      }
    }
  }

  function generateModule(name, values) {
    define(name, [], function() {
      'use strict';

      return values;
    });
  }

  processEmberShims();
  processTestShims();
  generateModule('jquery', { 'default': self.jQuery });
  generateModule('rsvp', { 'default': Ember.RSVP });
})();

;/* globals define */
define('ember/load-initializers', ['exports', 'ember-load-initializers', 'ember'], function(exports, loadInitializers, Ember) {
  Ember['default'].deprecate(
    'Usage of `' + 'ember/load-initializers' + '` module is deprecated, please update to `ember-load-initializers`.',
    false,
    { id: 'ember-load-initializers.legacy-shims', until: '3.0.0' }
  );

  exports['default'] = loadInitializers['default'];
});

;/* globals define */

function createDeprecatedModule(moduleId) {
  define(moduleId, ['exports', 'ember-resolver/resolver', 'ember'], function(exports, Resolver, Ember) {
    Ember['default'].deprecate(
      'Usage of `' + moduleId + '` module is deprecated, please update to `ember-resolver`.',
      false,
      { id: 'ember-resolver.legacy-shims', until: '3.0.0' }
    );

    exports['default'] = Resolver['default'];
  });
}

createDeprecatedModule('ember/resolver');
createDeprecatedModule('resolver');

;define('ember-ajax/errors', ['exports', 'ember'], function (exports, _ember) {
  'use strict';

  exports.AjaxError = AjaxError;
  exports.InvalidError = InvalidError;
  exports.UnauthorizedError = UnauthorizedError;
  exports.ForbiddenError = ForbiddenError;

  var EmberError = _ember['default'].Error;

  /**
    @class AjaxError
    @namespace DS
  */

  function AjaxError(errors) {
    var message = arguments.length <= 1 || arguments[1] === undefined ? 'Ajax operation failed' : arguments[1];

    EmberError.call(this, message);

    this.errors = errors || [{
      title: 'Ajax Error',
      detail: message
    }];
  }

  AjaxError.prototype = Object.create(EmberError.prototype);

  function InvalidError(errors) {
    AjaxError.call(this, errors, 'Request was rejected because it was invalid');
  }

  InvalidError.prototype = Object.create(AjaxError.prototype);

  function UnauthorizedError(errors) {
    AjaxError.call(this, errors, 'Ajax authorization failed');
  }

  UnauthorizedError.prototype = Object.create(AjaxError.prototype);

  function ForbiddenError(errors) {
    AjaxError.call(this, errors, 'Request was rejected because user is not permitted to perform this operation.');
  }

  ForbiddenError.prototype = Object.create(AjaxError.prototype);
});
define('ember-ajax/index', ['exports', 'ember-ajax/request'], function (exports, _emberAjaxRequest) {
  'use strict';

  Object.defineProperty(exports, 'default', {
    enumerable: true,
    get: function get() {
      return _emberAjaxRequest['default'];
    }
  });
});
define('ember-ajax/make-promise', ['exports', 'ember'], function (exports, _ember) {
  'use strict';

  exports['default'] = makePromise;

  var run = _ember['default'].run;
  var RSVP = _ember['default'].RSVP;

  function makePromise(settings) {
    var type = settings.type || 'GET';
    return new RSVP.Promise(function (resolve, reject) {
      settings.success = makeSuccess(resolve);
      settings.error = makeError(reject);
      _ember['default'].$.ajax(settings);
    }, 'ember-ajax: ' + type + ' to ' + settings.url);
  }

  function makeSuccess(resolve) {
    return function success(response, textStatus, jqXHR) {
      run(null, resolve, {
        response: response,
        textStatus: textStatus,
        jqXHR: jqXHR
      });
    };
  }

  function makeError(reject) {
    return function error(jqXHR, textStatus, errorThrown) {
      run(null, reject, {
        jqXHR: jqXHR,
        textStatus: textStatus,
        errorThrown: errorThrown
      });
    };
  }
});
define('ember-ajax/raw', ['exports', 'ember-ajax/make-promise', 'ember-ajax/utils/parse-args', 'ember'], function (exports, _emberAjaxMakePromise, _emberAjaxUtilsParseArgs, _ember) {
  'use strict';

  var _slicedToArray = (function () {
    function sliceIterator(arr, i) {
      var _arr = [];var _n = true;var _d = false;var _e = undefined;try {
        for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
          _arr.push(_s.value);if (i && _arr.length === i) break;
        }
      } catch (err) {
        _d = true;_e = err;
      } finally {
        try {
          if (!_n && _i['return']) _i['return']();
        } finally {
          if (_d) throw _e;
        }
      }return _arr;
    }return function (arr, i) {
      if (Array.isArray(arr)) {
        return arr;
      } else if (Symbol.iterator in Object(arr)) {
        return sliceIterator(arr, i);
      } else {
        throw new TypeError('Invalid attempt to destructure non-iterable instance');
      }
    };
  })();

  exports['default'] = raw;

  var deprecate = _ember['default'].deprecate;

  /*
   * Same as `request` except it resolves an object with `{response, textStatus,
   * jqXHR}`, useful if you need access to the jqXHR object for headers, etc.
   */
  function raw() {
    deprecate('ember-ajax/raw is deprecated and will be removed in ember-ajax@2.0.0', false, { id: 'ember-ajax.raw' });

    var _parseArgs$apply = _emberAjaxUtilsParseArgs['default'].apply(null, arguments);

    var _parseArgs$apply2 = _slicedToArray(_parseArgs$apply, 3);

    var url = _parseArgs$apply2[0];
    var type = _parseArgs$apply2[1];
    var settings = _parseArgs$apply2[2];

    if (!settings) {
      settings = {};
    }
    settings.url = url;
    settings.type = type;
    return (0, _emberAjaxMakePromise['default'])(settings);
  }
});
define('ember-ajax/request', ['exports', 'ember-ajax/raw', 'ember'], function (exports, _emberAjaxRaw, _ember) {
  'use strict';

  exports['default'] = request;

  var deprecate = _ember['default'].deprecate;

  /*
   * jQuery.ajax wrapper, supports the same signature except providing
   * `success` and `error` handlers will throw an error (use promises instead)
   * and it resolves only the response (no access to jqXHR or textStatus).
   */
  function request() {
    deprecate('ember-ajax/request is deprecated and will be removed in ember-ajax@2.0.0', false, { id: 'ember-ajax.raw' });
    return _emberAjaxRaw['default'].apply(undefined, arguments).then(function (result) {
      return result.response;
    }, null, 'ember-ajax: unwrap raw ajax response');
  }
});
define('ember-ajax/services/ajax', ['exports', 'ember', 'ember-ajax/errors', 'ember-ajax/utils/parse-response-headers'], function (exports, _ember, _emberAjaxErrors, _emberAjaxUtilsParseResponseHeaders) {
  'use strict';

  var deprecate = _ember['default'].deprecate;
  var get = _ember['default'].get;
  var isBlank = _ember['default'].isBlank;

  /**
    ### Headers customization

    Some APIs require HTTP headers, e.g. to provide an API key. Arbitrary
    headers can be set as key/value pairs on the `RESTAdapter`'s `headers`
    object and Ember Data will send them along with each ajax request.

    ```app/services/ajax
    import AjaxService from 'ember-ajax/services/ajax';

    export default AjaxService.extend({
      headers: {
        "API_KEY": "secret key",
        "ANOTHER_HEADER": "Some header value"
      }
    });
    ```

    `headers` can also be used as a computed property to support dynamic
    headers.

    ```app/services/ajax.js
    import Ember from 'ember';
    import AjaxService from 'ember-ajax/services/ajax';

    export default AjaxService.extend({
      session: Ember.inject.service(),
      headers: Ember.computed("session.authToken", function() {
        return {
          "API_KEY": this.get("session.authToken"),
          "ANOTHER_HEADER": "Some header value"
        };
      })
    });
    ```

    In some cases, your dynamic headers may require data from some
    object outside of Ember's observer system (for example
    `document.cookie`). You can use the
    [volatile](/api/classes/Ember.ComputedProperty.html#method_volatile)
    function to set the property into a non-cached mode causing the headers to
    be recomputed with every request.

    ```app/services/ajax.js
    import Ember from 'ember';
    import AjaxService from 'ember-ajax/services/ajax';

    export default AjaxService.extend({
      session: Ember.inject.service(),
      headers: Ember.computed("session.authToken", function() {
        return {
          "API_KEY": Ember.get(document.cookie.match(/apiKey\=([^;]*)/), "1"),
          "ANOTHER_HEADER": "Some header value"
        };
      }).volatile()
    });
    ```

  **/
  exports['default'] = _ember['default'].Service.extend({

    request: function request(url, options) {
      var _this = this;

      var opts;

      if (arguments.length > 2 || typeof options === 'string') {
        deprecate('ember-ajax/ajax#request calling request with `type` is deprecated and will be removed in ember-ajax@1.0.0. If you want to specify a type pass an object like {type: \'DELETE\'}', false, { id: 'ember-ajax.service.request' });

        if (arguments.length > 2) {
          opts = arguments[2];
          opts.type = options;
        } else {
          opts = { type: options };
        }
      } else {
        opts = options;
      }

      var hash = this.options(url, opts);

      return new _ember['default'].RSVP.Promise(function (resolve, reject) {

        hash.success = function (payload, textStatus, jqXHR) {
          var response = _this.handleResponse(jqXHR.status, (0, _emberAjaxUtilsParseResponseHeaders['default'])(jqXHR.getAllResponseHeaders()), payload);

          if (response instanceof _emberAjaxErrors.AjaxError) {
            reject(response);
          } else {
            resolve(response);
          }
        };

        hash.error = function (jqXHR, textStatus, errorThrown) {
          var error = undefined;

          if (!(error instanceof Error)) {
            if (errorThrown instanceof Error) {
              error = errorThrown;
            } else {
              error = _this.handleResponse(jqXHR.status, (0, _emberAjaxUtilsParseResponseHeaders['default'])(jqXHR.getAllResponseHeaders()), _this.parseErrorResponse(jqXHR.responseText) || errorThrown);
            }
          }
          reject(error);
        };

        _ember['default'].$.ajax(hash);
      }, 'ember-ajax: ' + hash.type + ' to ' + url);
    },

    // calls `request()` but forces `options.type` to `POST`
    post: function post(url, options) {
      return this.request(url, this._addTypeToOptionsFor(options, 'POST'));
    },

    // calls `request()` but forces `options.type` to `PUT`
    put: function put(url, options) {
      return this.request(url, this._addTypeToOptionsFor(options, 'PUT'));
    },

    // calls `request()` but forces `options.type` to `PATCH`
    patch: function patch(url, options) {
      return this.request(url, this._addTypeToOptionsFor(options, 'PATCH'));
    },

    // calls `request()` but forces `options.type` to `DELETE`
    del: function del(url, options) {
      return this.request(url, this._addTypeToOptionsFor(options, 'DELETE'));
    },

    // forcibly manipulates the options hash to include the HTTP method on the type key
    _addTypeToOptionsFor: function _addTypeToOptionsFor(options, method) {
      options = options || {};
      options.type = method;
      return options;
    },

    /**
      @method options
      @private
      @param {String} url
      @param {Object} options
      @return {Object}
    */
    options: function options(url, _options) {
      var hash = _options || {};
      hash.url = this._buildURL(url);
      hash.type = hash.type || 'GET';
      hash.dataType = hash.dataType || 'json';
      hash.context = this;

      var headers = get(this, 'headers');
      if (headers !== undefined) {
        hash.beforeSend = function (xhr) {
          Object.keys(headers).forEach(function (key) {
            return xhr.setRequestHeader(key, headers[key]);
          });
        };
      }

      return hash;
    },

    _buildURL: function _buildURL(url) {
      var host = get(this, 'host');
      if (isBlank(host)) {
        return url;
      }
      var startsWith = String.prototype.startsWith || function (searchString, position) {
        position = position || 0;
        return this.indexOf(searchString, position) === position;
      };
      if (startsWith.call(url, '/')) {
        return '' + host + url;
      } else {
        return host + '/' + url;
      }
    },

    /**
     Takes an ajax response, and returns the json payload or an error.
      By default this hook just returns the json payload passed to it.
     You might want to override it in two cases:
      1. Your API might return useful results in the response headers.
     Response headers are passed in as the second argument.
      2. Your API might return errors as successful responses with status code
     200 and an Errors text or object.
     @method handleResponse
     @param  {Number} status
     @param  {Object} headers
     @param  {Object} payload
     @return {Object | DS.AdapterError} response
    */
    handleResponse: function handleResponse(status, headers, payload) {
      if (this.isSuccess(status, headers, payload)) {
        return payload;
      } else if (this.isUnauthorized(status, headers, payload)) {
        return new _emberAjaxErrors.UnauthorizedError(payload.errors);
      } else if (this.isForbidden(status, headers, payload)) {
        return new _emberAjaxErrors.ForbiddenError(payload.errors);
      } else if (this.isInvalid(status, headers, payload)) {
        return new _emberAjaxErrors.InvalidError(payload.errors);
      }

      var errors = this.normalizeErrorResponse(status, headers, payload);

      return new _emberAjaxErrors.AjaxError(errors);
    },

    /**
     Default `handleResponse` implementation uses this hook to decide if the
     response is a an authorized error.
     @method isUnauthorized
     @param  {Number} status
     @param  {Object} headers
     @param  {Object} payload
     @return {Boolean}
    */
    isUnauthorized: function isUnauthorized(status /*, headers, payload */) {
      return status === 401;
    },

    /**
       Default `handleResponse` implementation uses this hook to decide if the
       response is a forbidden error.
       @method isForbidden
       @param  {Number} status
       @param  {Object} headers
       @param  {Object} payload
       @return {Boolean}
     */
    isForbidden: function isForbidden(status /*, headers, payload */) {
      return status === 403;
    },

    /**
      Default `handleResponse` implementation uses this hook to decide if the
      response is a an invalid error.
      @method isInvalid
      @param  {Number} status
      @param  {Object} headers
      @param  {Object} payload
      @return {Boolean}
    */
    isInvalid: function isInvalid(status /*, headers, payload */) {
      return status === 422;
    },

    /**
     Default `handleResponse` implementation uses this hook to decide if the
     response is a success.
     @method isSuccess
     @param  {Number} status
     @param  {Object} headers
     @param  {Object} payload
     @return {Boolean}
    */
    isSuccess: function isSuccess(status /*, headers, payload */) {
      return status >= 200 && status < 300 || status === 304;
    },

    /**
      @method parseErrorResponse
      @private
      @param {String} responseText
      @return {Object}
    */
    parseErrorResponse: function parseErrorResponse(responseText) {
      var json = responseText;

      try {
        json = _ember['default'].$.parseJSON(responseText);
      } catch (e) {}

      return json;
    },

    /**
      @method normalizeErrorResponse
      @private
      @param  {Number} status
      @param  {Object} headers
      @param  {Object} payload
      @return {Object} errors payload
    */
    normalizeErrorResponse: function normalizeErrorResponse(status, headers, payload) {
      if (payload && typeof payload === 'object' && payload.errors) {
        return payload.errors;
      } else {
        return [{
          status: '' + status,
          title: "The backend responded with an error",
          detail: '' + payload
        }];
      }
    }
  });
});
define("ember-ajax/utils/parse-args", ["exports"], function (exports) {
  "use strict";

  var _slicedToArray = (function () {
    function sliceIterator(arr, i) {
      var _arr = [];var _n = true;var _d = false;var _e = undefined;try {
        for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
          _arr.push(_s.value);if (i && _arr.length === i) break;
        }
      } catch (err) {
        _d = true;_e = err;
      } finally {
        try {
          if (!_n && _i["return"]) _i["return"]();
        } finally {
          if (_d) throw _e;
        }
      }return _arr;
    }return function (arr, i) {
      if (Array.isArray(arr)) {
        return arr;
      } else if (Symbol.iterator in Object(arr)) {
        return sliceIterator(arr, i);
      } else {
        throw new TypeError("Invalid attempt to destructure non-iterable instance");
      }
    };
  })();

  exports["default"] = parseArgs;

  function parseArgs() {
    var args = [].slice.apply(arguments);
    if (args.length === 1) {
      if (typeof args[0] === "string") {
        var _args = _slicedToArray(args, 1);

        var url = _args[0];

        return [url];
      } else {
        var _args2 = _slicedToArray(args, 1);

        var options = _args2[0];
        var url = options.url;

        delete options.url;
        var type = options.type || options.method;
        delete options.type;
        delete options.method;
        return [url, type, options];
      }
    }
    if (args.length === 2) {
      var _args3 = _slicedToArray(args, 1);

      var url = _args3[0];

      if (typeof args[1] === 'object') {
        var options = args[1];
        var type = options.type || options.method;
        delete options.type;
        delete options.method;
        return [url, type, options];
      } else {
        var type = args[1];
        return [url, type];
      }
    }
    return args;
  }
});
define('ember-ajax/utils/parse-response-headers', ['exports'], function (exports) {
  'use strict';

  exports['default'] = parseResponseHeaders;

  function parseResponseHeaders(headerStr) {
    var headers = Object.create(null);
    if (!headerStr) {
      return headers;
    }

    var headerPairs = headerStr.split('\r\n');
    for (var i = 0; i < headerPairs.length; i++) {
      var headerPair = headerPairs[i];
      // Can't use split() here because it does the wrong thing
      // if the header value has the string ": " in it.
      var index = headerPair.indexOf(': ');
      if (index > 0) {
        var key = headerPair.substring(0, index);
        var val = headerPair.substring(index + 2);
        headers[key] = val;
      }
    }

    return headers;
  }
});
define('ember-cli-app-version/components/app-version', ['exports', 'ember', 'ember-cli-app-version/templates/app-version'], function (exports, _ember, _emberCliAppVersionTemplatesAppVersion) {
  'use strict';

  exports['default'] = _ember['default'].Component.extend({
    tagName: 'span',
    layout: _emberCliAppVersionTemplatesAppVersion['default']
  });
});
define('ember-cli-app-version/initializer-factory', ['exports', 'ember'], function (exports, _ember) {
  'use strict';

  exports['default'] = initializerFactory;

  var classify = _ember['default'].String.classify;

  function initializerFactory(name, version) {
    var registered = false;

    return function () {
      if (!registered && name && version) {
        var appName = classify(name);
        _ember['default'].libraries.register(appName, version);
        registered = true;
      }
    };
  }
});
define("ember-cli-app-version/templates/app-version", ["exports"], function (exports) {
  "use strict";

  exports["default"] = Ember.HTMLBars.template((function () {
    return {
      meta: {
        "fragmentReason": {
          "name": "missing-wrapper",
          "problems": ["wrong-type"]
        },
        "revision": "Ember@2.6.2",
        "loc": {
          "source": null,
          "start": {
            "line": 1,
            "column": 0
          },
          "end": {
            "line": 2,
            "column": 0
          }
        },
        "moduleName": "modules/ember-cli-app-version/templates/app-version.hbs"
      },
      isEmpty: false,
      arity: 0,
      cachedFragment: null,
      hasRendered: false,
      buildFragment: function buildFragment(dom) {
        var el0 = dom.createDocumentFragment();
        var el1 = dom.createComment("");
        dom.appendChild(el0, el1);
        var el1 = dom.createTextNode("\n");
        dom.appendChild(el0, el1);
        return el0;
      },
      buildRenderNodes: function buildRenderNodes(dom, fragment, contextualElement) {
        var morphs = new Array(1);
        morphs[0] = dom.createMorphAt(fragment, 0, 0, contextualElement);
        dom.insertBoundary(fragment, 0);
        return morphs;
      },
      statements: [["content", "version", ["loc", [null, [1, 0], [1, 11]]]]],
      locals: [],
      templates: []
    };
  })());
});
define("ember-inflector/index", ["exports", "ember", "ember-inflector/lib/system", "ember-inflector/lib/ext/string"], function (exports, _ember, _emberInflectorLibSystem, _emberInflectorLibExtString) {
  /* global define, module */

  "use strict";

  _emberInflectorLibSystem.Inflector.defaultRules = _emberInflectorLibSystem.defaultRules;
  _ember["default"].Inflector = _emberInflectorLibSystem.Inflector;

  _ember["default"].String.pluralize = _emberInflectorLibSystem.pluralize;
  _ember["default"].String.singularize = _emberInflectorLibSystem.singularize;exports["default"] = _emberInflectorLibSystem.Inflector;
  exports.pluralize = _emberInflectorLibSystem.pluralize;
  exports.singularize = _emberInflectorLibSystem.singularize;
  exports.defaultRules = _emberInflectorLibSystem.defaultRules;

  if (typeof define !== 'undefined' && define.amd) {
    define('ember-inflector', ['exports'], function (__exports__) {
      __exports__['default'] = _emberInflectorLibSystem.Inflector;
      return _emberInflectorLibSystem.Inflector;
    });
  } else if (typeof module !== 'undefined' && module['exports']) {
    module['exports'] = _emberInflectorLibSystem.Inflector;
  }
});
define('ember-inflector/lib/ext/string', ['exports', 'ember', 'ember-inflector/lib/system/string'], function (exports, _ember, _emberInflectorLibSystemString) {
  'use strict';

  if (_ember['default'].EXTEND_PROTOTYPES === true || _ember['default'].EXTEND_PROTOTYPES.String) {
    /**
      See {{#crossLink "Ember.String/pluralize"}}{{/crossLink}}
       @method pluralize
      @for String
    */
    String.prototype.pluralize = function () {
      return (0, _emberInflectorLibSystemString.pluralize)(this);
    };

    /**
      See {{#crossLink "Ember.String/singularize"}}{{/crossLink}}
       @method singularize
      @for String
    */
    String.prototype.singularize = function () {
      return (0, _emberInflectorLibSystemString.singularize)(this);
    };
  }
});
define('ember-inflector/lib/helpers/pluralize', ['exports', 'ember-inflector', 'ember-inflector/lib/utils/make-helper'], function (exports, _emberInflector, _emberInflectorLibUtilsMakeHelper) {
  'use strict';

  /**
   *
   * If you have Ember Inflector (such as if Ember Data is present),
   * pluralize a word. For example, turn "ox" into "oxen".
   *
   * Example:
   *
   * {{pluralize count myProperty}}
   * {{pluralize 1 "oxen"}}
   * {{pluralize myProperty}}
   * {{pluralize "ox"}}
   *
   * @for Ember.HTMLBars.helpers
   * @method pluralize
   * @param {Number|Property} [count] count of objects
   * @param {String|Property} word word to pluralize
  */
  exports['default'] = (0, _emberInflectorLibUtilsMakeHelper['default'])(function (params) {
    var count = undefined,
        word = undefined;

    if (params.length === 1) {
      word = params[0];
      return (0, _emberInflector.pluralize)(word);
    } else {
      count = params[0];
      word = params[1];

      if (parseFloat(count) !== 1) {
        word = (0, _emberInflector.pluralize)(word);
      }

      return count + " " + word;
    }
  });
});
define('ember-inflector/lib/helpers/singularize', ['exports', 'ember-inflector', 'ember-inflector/lib/utils/make-helper'], function (exports, _emberInflector, _emberInflectorLibUtilsMakeHelper) {
  'use strict';

  /**
   *
   * If you have Ember Inflector (such as if Ember Data is present),
   * singularize a word. For example, turn "oxen" into "ox".
   *
   * Example:
   *
   * {{singularize myProperty}}
   * {{singularize "oxen"}}
   *
   * @for Ember.HTMLBars.helpers
   * @method singularize
   * @param {String|Property} word word to singularize
  */
  exports['default'] = (0, _emberInflectorLibUtilsMakeHelper['default'])(function (params) {
    return (0, _emberInflector.singularize)(params[0]);
  });
});
define("ember-inflector/lib/system", ["exports", "ember-inflector/lib/system/inflector", "ember-inflector/lib/system/string", "ember-inflector/lib/system/inflections"], function (exports, _emberInflectorLibSystemInflector, _emberInflectorLibSystemString, _emberInflectorLibSystemInflections) {
  "use strict";

  _emberInflectorLibSystemInflector["default"].inflector = new _emberInflectorLibSystemInflector["default"](_emberInflectorLibSystemInflections["default"]);

  exports.Inflector = _emberInflectorLibSystemInflector["default"];
  exports.singularize = _emberInflectorLibSystemString.singularize;
  exports.pluralize = _emberInflectorLibSystemString.pluralize;
  exports.defaultRules = _emberInflectorLibSystemInflections["default"];
});
define('ember-inflector/lib/system/inflections', ['exports'], function (exports) {
  'use strict';

  exports['default'] = {
    plurals: [[/$/, 's'], [/s$/i, 's'], [/^(ax|test)is$/i, '$1es'], [/(octop|vir)us$/i, '$1i'], [/(octop|vir)i$/i, '$1i'], [/(alias|status)$/i, '$1es'], [/(bu)s$/i, '$1ses'], [/(buffal|tomat)o$/i, '$1oes'], [/([ti])um$/i, '$1a'], [/([ti])a$/i, '$1a'], [/sis$/i, 'ses'], [/(?:([^f])fe|([lr])f)$/i, '$1$2ves'], [/(hive)$/i, '$1s'], [/([^aeiouy]|qu)y$/i, '$1ies'], [/(x|ch|ss|sh)$/i, '$1es'], [/(matr|vert|ind)(?:ix|ex)$/i, '$1ices'], [/^(m|l)ouse$/i, '$1ice'], [/^(m|l)ice$/i, '$1ice'], [/^(ox)$/i, '$1en'], [/^(oxen)$/i, '$1'], [/(quiz)$/i, '$1zes']],

    singular: [[/s$/i, ''], [/(ss)$/i, '$1'], [/(n)ews$/i, '$1ews'], [/([ti])a$/i, '$1um'], [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '$1sis'], [/(^analy)(sis|ses)$/i, '$1sis'], [/([^f])ves$/i, '$1fe'], [/(hive)s$/i, '$1'], [/(tive)s$/i, '$1'], [/([lr])ves$/i, '$1f'], [/([^aeiouy]|qu)ies$/i, '$1y'], [/(s)eries$/i, '$1eries'], [/(m)ovies$/i, '$1ovie'], [/(x|ch|ss|sh)es$/i, '$1'], [/^(m|l)ice$/i, '$1ouse'], [/(bus)(es)?$/i, '$1'], [/(o)es$/i, '$1'], [/(shoe)s$/i, '$1'], [/(cris|test)(is|es)$/i, '$1is'], [/^(a)x[ie]s$/i, '$1xis'], [/(octop|vir)(us|i)$/i, '$1us'], [/(alias|status)(es)?$/i, '$1'], [/^(ox)en/i, '$1'], [/(vert|ind)ices$/i, '$1ex'], [/(matr)ices$/i, '$1ix'], [/(quiz)zes$/i, '$1'], [/(database)s$/i, '$1']],

    irregularPairs: [['person', 'people'], ['man', 'men'], ['child', 'children'], ['sex', 'sexes'], ['move', 'moves'], ['cow', 'kine'], ['zombie', 'zombies']],

    uncountable: ['equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep', 'jeans', 'police']
  };
});
define('ember-inflector/lib/system/inflector', ['exports', 'ember'], function (exports, _ember) {
  'use strict';

  var capitalize = _ember['default'].String.capitalize;

  var BLANK_REGEX = /^\s*$/;
  var LAST_WORD_DASHED_REGEX = /([\w/-]+[_/\s-])([a-z\d]+$)/;
  var LAST_WORD_CAMELIZED_REGEX = /([\w/\s-]+)([A-Z][a-z\d]*$)/;
  var CAMELIZED_REGEX = /[A-Z][a-z\d]*$/;

  function loadUncountable(rules, uncountable) {
    for (var i = 0, length = uncountable.length; i < length; i++) {
      rules.uncountable[uncountable[i].toLowerCase()] = true;
    }
  }

  function loadIrregular(rules, irregularPairs) {
    var pair;

    for (var i = 0, length = irregularPairs.length; i < length; i++) {
      pair = irregularPairs[i];

      //pluralizing
      rules.irregular[pair[0].toLowerCase()] = pair[1];
      rules.irregular[pair[1].toLowerCase()] = pair[1];

      //singularizing
      rules.irregularInverse[pair[1].toLowerCase()] = pair[0];
      rules.irregularInverse[pair[0].toLowerCase()] = pair[0];
    }
  }

  /**
    Inflector.Ember provides a mechanism for supplying inflection rules for your
    application. Ember includes a default set of inflection rules, and provides an
    API for providing additional rules.

    Examples:

    Creating an inflector with no rules.

    ```js
    var inflector = new Ember.Inflector();
    ```

    Creating an inflector with the default ember ruleset.

    ```js
    var inflector = new Ember.Inflector(Ember.Inflector.defaultRules);

    inflector.pluralize('cow'); //=> 'kine'
    inflector.singularize('kine'); //=> 'cow'
    ```

    Creating an inflector and adding rules later.

    ```javascript
    var inflector = Ember.Inflector.inflector;

    inflector.pluralize('advice'); // => 'advices'
    inflector.uncountable('advice');
    inflector.pluralize('advice'); // => 'advice'

    inflector.pluralize('formula'); // => 'formulas'
    inflector.irregular('formula', 'formulae');
    inflector.pluralize('formula'); // => 'formulae'

    // you would not need to add these as they are the default rules
    inflector.plural(/$/, 's');
    inflector.singular(/s$/i, '');
    ```

    Creating an inflector with a nondefault ruleset.

    ```javascript
    var rules = {
      plurals:  [ /$/, 's' ],
      singular: [ /\s$/, '' ],
      irregularPairs: [
        [ 'cow', 'kine' ]
      ],
      uncountable: [ 'fish' ]
    };

    var inflector = new Ember.Inflector(rules);
    ```

    @class Inflector
    @namespace Ember
  */
  function Inflector(ruleSet) {
    ruleSet = ruleSet || {};
    ruleSet.uncountable = ruleSet.uncountable || makeDictionary();
    ruleSet.irregularPairs = ruleSet.irregularPairs || makeDictionary();

    var rules = this.rules = {
      plurals: ruleSet.plurals || [],
      singular: ruleSet.singular || [],
      irregular: makeDictionary(),
      irregularInverse: makeDictionary(),
      uncountable: makeDictionary()
    };

    loadUncountable(rules, ruleSet.uncountable);
    loadIrregular(rules, ruleSet.irregularPairs);

    this.enableCache();
  }

  if (!Object.create && !Object.create(null).hasOwnProperty) {
    throw new Error("This browser does not support Object.create(null), please polyfil with es5-sham: http://git.io/yBU2rg");
  }

  function makeDictionary() {
    var cache = Object.create(null);
    cache['_dict'] = null;
    delete cache['_dict'];
    return cache;
  }

  Inflector.prototype = {
    /**
      @public
       As inflections can be costly, and commonly the same subset of words are repeatedly
      inflected an optional cache is provided.
       @method enableCache
    */
    enableCache: function enableCache() {
      this.purgeCache();

      this.singularize = function (word) {
        this._cacheUsed = true;
        return this._sCache[word] || (this._sCache[word] = this._singularize(word));
      };

      this.pluralize = function (word) {
        this._cacheUsed = true;
        return this._pCache[word] || (this._pCache[word] = this._pluralize(word));
      };
    },

    /**
      @public
       @method purgedCache
    */
    purgeCache: function purgeCache() {
      this._cacheUsed = false;
      this._sCache = makeDictionary();
      this._pCache = makeDictionary();
    },

    /**
      @public
      disable caching
       @method disableCache;
    */
    disableCache: function disableCache() {
      this._sCache = null;
      this._pCache = null;
      this.singularize = function (word) {
        return this._singularize(word);
      };

      this.pluralize = function (word) {
        return this._pluralize(word);
      };
    },

    /**
      @method plural
      @param {RegExp} regex
      @param {String} string
    */
    plural: function plural(regex, string) {
      if (this._cacheUsed) {
        this.purgeCache();
      }
      this.rules.plurals.push([regex, string.toLowerCase()]);
    },

    /**
      @method singular
      @param {RegExp} regex
      @param {String} string
    */
    singular: function singular(regex, string) {
      if (this._cacheUsed) {
        this.purgeCache();
      }
      this.rules.singular.push([regex, string.toLowerCase()]);
    },

    /**
      @method uncountable
      @param {String} regex
    */
    uncountable: function uncountable(string) {
      if (this._cacheUsed) {
        this.purgeCache();
      }
      loadUncountable(this.rules, [string.toLowerCase()]);
    },

    /**
      @method irregular
      @param {String} singular
      @param {String} plural
    */
    irregular: function irregular(singular, plural) {
      if (this._cacheUsed) {
        this.purgeCache();
      }
      loadIrregular(this.rules, [[singular, plural]]);
    },

    /**
      @method pluralize
      @param {String} word
    */
    pluralize: function pluralize(word) {
      return this._pluralize(word);
    },

    _pluralize: function _pluralize(word) {
      return this.inflect(word, this.rules.plurals, this.rules.irregular);
    },
    /**
      @method singularize
      @param {String} word
    */
    singularize: function singularize(word) {
      return this._singularize(word);
    },

    _singularize: function _singularize(word) {
      return this.inflect(word, this.rules.singular, this.rules.irregularInverse);
    },

    /**
      @protected
       @method inflect
      @param {String} word
      @param {Object} typeRules
      @param {Object} irregular
    */
    inflect: function inflect(word, typeRules, irregular) {
      var inflection, substitution, result, lowercase, wordSplit, firstPhrase, lastWord, isBlank, isCamelized, rule, isUncountable;

      isBlank = !word || BLANK_REGEX.test(word);

      isCamelized = CAMELIZED_REGEX.test(word);
      firstPhrase = "";

      if (isBlank) {
        return word;
      }

      lowercase = word.toLowerCase();
      wordSplit = LAST_WORD_DASHED_REGEX.exec(word) || LAST_WORD_CAMELIZED_REGEX.exec(word);

      if (wordSplit) {
        firstPhrase = wordSplit[1];
        lastWord = wordSplit[2].toLowerCase();
      }

      isUncountable = this.rules.uncountable[lowercase] || this.rules.uncountable[lastWord];

      if (isUncountable) {
        return word;
      }

      for (rule in this.rules.irregular) {
        if (lowercase.match(rule + "$")) {
          substitution = irregular[rule];

          if (isCamelized && irregular[lastWord]) {
            substitution = capitalize(substitution);
            rule = capitalize(rule);
          }

          return word.replace(rule, substitution);
        }
      }

      for (var i = typeRules.length, min = 0; i > min; i--) {
        inflection = typeRules[i - 1];
        rule = inflection[0];

        if (rule.test(word)) {
          break;
        }
      }

      inflection = inflection || [];

      rule = inflection[0];
      substitution = inflection[1];

      result = word.replace(rule, substitution);

      return result;
    }
  };

  exports['default'] = Inflector;
});
define('ember-inflector/lib/system/string', ['exports', 'ember-inflector/lib/system/inflector'], function (exports, _emberInflectorLibSystemInflector) {
  'use strict';

  function pluralize(word) {
    return _emberInflectorLibSystemInflector['default'].inflector.pluralize(word);
  }

  function singularize(word) {
    return _emberInflectorLibSystemInflector['default'].inflector.singularize(word);
  }

  exports.pluralize = pluralize;
  exports.singularize = singularize;
});
define('ember-inflector/lib/utils/make-helper', ['exports', 'ember'], function (exports, _ember) {
  'use strict';

  exports['default'] = makeHelper;

  function makeHelper(helperFunction) {
    if (_ember['default'].Helper) {
      return _ember['default'].Helper.helper(helperFunction);
    }
    if (_ember['default'].HTMLBars) {
      return _ember['default'].HTMLBars.makeBoundHelper(helperFunction);
    }
    return _ember['default'].Handlebars.makeBoundHelper(helperFunction);
  }
});
define('ember-load-initializers/index', ['exports', 'ember'], function (exports, _ember) {
  'use strict';

  exports['default'] = function (app, prefix) {
    var regex = new RegExp('^' + prefix + '\/((?:instance-)?initializers)\/');
    var getKeys = Object.keys || _ember['default'].keys;

    getKeys(requirejs._eak_seen).map(function (moduleName) {
      return {
        moduleName: moduleName,
        matches: regex.exec(moduleName)
      };
    }).filter(function (dep) {
      return dep.matches && dep.matches.length === 2;
    }).forEach(function (dep) {
      var moduleName = dep.moduleName;

      var module = require(moduleName, null, null, true);
      if (!module) {
        throw new Error(moduleName + ' must export an initializer.');
      }

      var initializerType = _ember['default'].String.camelize(dep.matches[1].substring(0, dep.matches[1].length - 1));
      var initializer = module['default'];
      if (!initializer.name) {
        var initializerName = moduleName.match(/[^\/]+\/?$/)[0];
        initializer.name = initializerName;
      }

      if (app[initializerType]) {
        app[initializerType](initializer);
      }
    });
  };
});
define('ember-resolver/container-debug-adapter', ['exports', 'ember', 'ember-resolver/utils/module-registry'], function (exports, _ember, _emberResolverUtilsModuleRegistry) {
  'use strict';

  var ContainerDebugAdapter = _ember['default'].ContainerDebugAdapter;

  var ModulesContainerDebugAdapter = null;

  function getPod(type, key, prefix) {
    var match = key.match(new RegExp('^/?' + prefix + '/(.+)/' + type + '$'));
    if (match) {
      return match[1];
    }
  }

  // Support Ember < 1.5-beta.4
  // TODO: Remove this after 1.5.0 is released
  if (typeof ContainerDebugAdapter !== 'undefined') {

    /*
     * This module defines a subclass of Ember.ContainerDebugAdapter that adds two
     * important features:
     *
     *  1) is able provide injections to classes that implement `extend`
     *     (as is typical with Ember).
     */

    ModulesContainerDebugAdapter = ContainerDebugAdapter.extend({
      _moduleRegistry: null,

      init: function init() {
        this._super.apply(this, arguments);

        if (!this._moduleRegistry) {
          this._moduleRegistry = new _emberResolverUtilsModuleRegistry['default']();
        }
      },

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

      /**
        The resolver instance of the application
        being debugged. This property will be injected
        on creation.
         @property resolver
        @default 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 canCatalogEntriesByType() /* type */{
        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 classes.
      */
      catalogEntriesByType: function catalogEntriesByType(type) {
        var moduleNames = this._moduleRegistry.moduleNames();
        var types = _ember['default'].A();

        var prefix = this.namespace.modulePrefix;

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

          if (key.indexOf(type) !== -1) {
            // Check if it's a pod module
            var name = getPod(type, key, this.namespace.podModulePrefix || prefix);
            if (!name) {
              // Not pod
              name = key.split(type + 's/').pop();

              // Support for different prefix (such as ember-cli addons).
              // Uncomment the code below when
              // https://github.com/ember-cli/ember-resolver/pull/80 is merged.

              //var match = key.match('^/?(.+)/' + type);
              //if (match && match[1] !== prefix) {
              // Different prefix such as an addon
              //name = match[1] + '@' + name;
              //}
            }
            types.addObject(name);
          }
        }
        return types;
      }
    });
  }

  exports['default'] = ModulesContainerDebugAdapter;
});
define('ember-resolver/index', ['exports', 'ember-resolver/resolver'], function (exports, _emberResolverResolver) {
  'use strict';

  Object.defineProperty(exports, 'default', {
    enumerable: true,
    get: function get() {
      return _emberResolverResolver['default'];
    }
  });
});
define('ember-resolver/resolver', ['exports', 'ember', 'ember-resolver/utils/module-registry', 'ember-resolver/utils/class-factory', 'ember-resolver/utils/make-dictionary'], function (exports, _ember, _emberResolverUtilsModuleRegistry, _emberResolverUtilsClassFactory, _emberResolverUtilsMakeDictionary) {
  /*globals require */

  'use strict';

  /*
   * This module defines a subclass of Ember.DefaultResolver that adds two
   * important features:
   *
   *  1) The resolver makes the container aware of es6 modules via the AMD
   *     output. The loader's _moduleEntries is consulted so that classes can be
   *     resolved directly via the module loader, without needing a manual
   *     `import`.
   *  2) is able to provide injections to classes that implement `extend`
   *     (as is typical with Ember).
   */

  var _Ember$String = _ember['default'].String;
  var underscore = _Ember$String.underscore;
  var classify = _Ember$String.classify;
  var dasherize = _Ember$String.dasherize;
  var get = _ember['default'].get;
  var DefaultResolver = _ember['default'].DefaultResolver;

  function parseName(fullName) {
    /*jshint validthis:true */

    if (fullName.parsedName === true) {
      return fullName;
    }

    var prefix, type, name;
    var fullNameParts = fullName.split('@');

    // HTMLBars uses helper:@content-helper which collides
    // with ember-cli namespace detection.
    // This will be removed in a future release of HTMLBars.
    if (fullName !== 'helper:@content-helper' && fullNameParts.length === 2) {
      var prefixParts = fullNameParts[0].split(':');

      if (prefixParts.length === 2) {
        prefix = prefixParts[1];
        type = prefixParts[0];
        name = fullNameParts[1];
      } else {
        var nameParts = fullNameParts[1].split(':');

        prefix = fullNameParts[0];
        type = nameParts[0];
        name = nameParts[1];
      }
    } else {
      fullNameParts = fullName.split(':');
      type = fullNameParts[0];
      name = fullNameParts[1];
    }

    var fullNameWithoutType = name;
    var namespace = get(this, 'namespace');
    var root = namespace;

    return {
      parsedName: true,
      fullName: fullName,
      prefix: prefix || this.prefix({ type: type }),
      type: type,
      fullNameWithoutType: fullNameWithoutType,
      name: name,
      root: root,
      resolveMethodName: "resolve" + classify(type)
    };
  }

  function resolveOther(parsedName) {
    /*jshint validthis:true */

    _ember['default'].assert('`modulePrefix` must be defined', this.namespace.modulePrefix);

    var normalizedModuleName = this.findModuleName(parsedName);

    if (normalizedModuleName) {
      var defaultExport = this._extractDefaultExport(normalizedModuleName, parsedName);

      if (defaultExport === undefined) {
        throw new Error(" Expected to find: '" + parsedName.fullName + "' within '" + normalizedModuleName + "' but got 'undefined'. Did you forget to `export default` within '" + normalizedModuleName + "'?");
      }

      if (this.shouldWrapInClassFactory(defaultExport, parsedName)) {
        defaultExport = (0, _emberResolverUtilsClassFactory['default'])(defaultExport);
      }

      return defaultExport;
    } else {
      return this._super(parsedName);
    }
  }

  // Ember.DefaultResolver docs:
  //   https://github.com/emberjs/ember.js/blob/master/packages/ember-application/lib/system/resolver.js
  var Resolver = DefaultResolver.extend({
    resolveOther: resolveOther,
    parseName: parseName,
    resolveTemplate: resolveOther,
    pluralizedTypes: null,
    moduleRegistry: null,

    makeToString: function makeToString(factory, fullName) {
      return '' + this.namespace.modulePrefix + '@' + fullName + ':';
    },

    shouldWrapInClassFactory: function shouldWrapInClassFactory() /* module, parsedName */{
      return false;
    },

    init: function init() {
      this._super();
      this.moduleBasedResolver = true;

      if (!this._moduleRegistry) {
        this._moduleRegistry = new _emberResolverUtilsModuleRegistry['default']();
      }

      this._normalizeCache = (0, _emberResolverUtilsMakeDictionary['default'])();

      this.pluralizedTypes = this.pluralizedTypes || (0, _emberResolverUtilsMakeDictionary['default'])();

      if (!this.pluralizedTypes.config) {
        this.pluralizedTypes.config = 'config';
      }
      this._deprecatedPodModulePrefix = false;
    },

    normalize: function normalize(fullName) {
      return this._normalizeCache[fullName] || (this._normalizeCache[fullName] = this._normalize(fullName));
    },

    _normalize: function _normalize(fullName) {
      // A) Convert underscores to dashes
      // B) Convert camelCase to dash-case, except for helpers where we want to avoid shadowing camelCase expressions
      // C) replace `.` with `/` in order to make nested controllers work in the following cases
      //      1. `needs: ['posts/post']`
      //      2. `{{render "posts/post"}}`
      //      3. `this.render('posts/post')` from Route

      var split = fullName.split(':');
      if (split.length > 1) {
        if (split[0] === 'helper') {
          return split[0] + ':' + split[1].replace(/_/g, '-');
        } else {
          return split[0] + ':' + dasherize(split[1].replace(/\./g, '/'));
        }
      } else {
        return fullName;
      }
    },

    pluralize: function pluralize(type) {
      return this.pluralizedTypes[type] || (this.pluralizedTypes[type] = type + 's');
    },

    podBasedLookupWithPrefix: function podBasedLookupWithPrefix(podPrefix, parsedName) {
      var fullNameWithoutType = parsedName.fullNameWithoutType;

      if (parsedName.type === 'template') {
        fullNameWithoutType = fullNameWithoutType.replace(/^components\//, '');
      }

      return podPrefix + '/' + fullNameWithoutType + '/' + parsedName.type;
    },

    podBasedModuleName: function podBasedModuleName(parsedName) {
      var podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix;

      return this.podBasedLookupWithPrefix(podPrefix, parsedName);
    },

    podBasedComponentsInSubdir: function podBasedComponentsInSubdir(parsedName) {
      var podPrefix = this.namespace.podModulePrefix || this.namespace.modulePrefix;
      podPrefix = podPrefix + '/components';

      if (parsedName.type === 'component' || parsedName.fullNameWithoutType.match(/^components/)) {
        return this.podBasedLookupWithPrefix(podPrefix, parsedName);
      }
    },

    resolveEngine: function resolveEngine(parsedName) {
      var engineName = parsedName.fullNameWithoutType;
      var engineModule = engineName + '/engine';

      if (this._moduleRegistry.has(engineModule)) {
        return this._extractDefaultExport(engineModule);
      }
    },

    resolveRouteMap: function resolveRouteMap(parsedName) {
      var engineName = parsedName.fullNameWithoutType;
      var engineRoutesModule = engineName + '/routes';

      if (this._moduleRegistry.has(engineRoutesModule)) {
        var routeMap = this._extractDefaultExport(engineRoutesModule);

        _ember['default'].assert('The route map for ' + engineName + ' should be wrapped by \'buildRoutes\' before exporting.', routeMap.isRouteMap);

        return routeMap;
      }
    },

    mainModuleName: function mainModuleName(parsedName) {
      // if router:main or adapter:main look for a module with just the type first
      var tmpModuleName = parsedName.prefix + '/' + parsedName.type;

      if (parsedName.fullNameWithoutType === 'main') {
        return tmpModuleName;
      }
    },

    defaultModuleName: function defaultModuleName(parsedName) {
      return parsedName.prefix + '/' + this.pluralize(parsedName.type) + '/' + parsedName.fullNameWithoutType;
    },

    prefix: function prefix(parsedName) {
      var tmpPrefix = this.namespace.modulePrefix;

      if (this.namespace[parsedName.type + 'Prefix']) {
        tmpPrefix = this.namespace[parsedName.type + 'Prefix'];
      }

      return tmpPrefix;
    },

    /**
      A listing of functions to test for moduleName's based on the provided
     `parsedName`. This allows easy customization of additional module based
     lookup patterns.
      @property moduleNameLookupPatterns
     @returns {Ember.Array}
     */
    moduleNameLookupPatterns: _ember['default'].computed(function () {
      return [this.podBasedModuleName, this.podBasedComponentsInSubdir, this.mainModuleName, this.defaultModuleName];
    }),

    findModuleName: function findModuleName(parsedName, loggingDisabled) {
      var moduleNameLookupPatterns = this.get('moduleNameLookupPatterns');
      var moduleName;

      for (var index = 0, _length = moduleNameLookupPatterns.length; index < _length; index++) {
        var item = moduleNameLookupPatterns[index];

        var tmpModuleName = item.call(this, parsedName);

        // allow treat all dashed and all underscored as the same thing
        // supports components with dashes and other stuff with underscores.
        if (tmpModuleName) {
          tmpModuleName = this.chooseModuleName(tmpModuleName, parsedName);
        }

        if (tmpModuleName && this._moduleRegistry.has(tmpModuleName)) {
          moduleName = tmpModuleName;
        }

        if (!loggingDisabled) {
          this._logLookup(moduleName, parsedName, tmpModuleName);
        }

        if (moduleName) {
          return moduleName;
        }
      }
    },

    chooseModuleName: function chooseModuleName(moduleName, parsedName) {
      var _this = this;

      var underscoredModuleName = underscore(moduleName);

      if (moduleName !== underscoredModuleName && this._moduleRegistry.has(moduleName) && this._moduleRegistry.has(underscoredModuleName)) {
        throw new TypeError("Ambiguous module names: `" + moduleName + "` and `" + underscoredModuleName + "`");
      }

      if (this._moduleRegistry.has(moduleName)) {
        return moduleName;
      } else if (this._moduleRegistry.has(underscoredModuleName)) {
        return underscoredModuleName;
      }
      // workaround for dasherized partials:
      // something/something/-something => something/something/_something
      var partializedModuleName = moduleName.replace(/\/-([^\/]*)$/, '/_$1');

      if (this._moduleRegistry.has(partializedModuleName)) {
        _ember['default'].deprecate('Modules should not contain underscores. ' + 'Attempted to lookup "' + moduleName + '" which ' + 'was not found. Please rename "' + partializedModuleName + '" ' + 'to "' + moduleName + '" instead.', false, { id: 'ember-resolver.underscored-modules', until: '3.0.0' });

        return partializedModuleName;
      }
      _ember['default'].runInDebug(function () {
        var isCamelCaseHelper = parsedName.type === 'helper' && !!moduleName.match(/[a-z]+[A-Z]+/);
        if (isCamelCaseHelper) {
          _this._camelCaseHelperWarnedNames = _this._camelCaseHelperWarnedNames || [];
          var alreadyWarned = _this._camelCaseHelperWarnedNames.indexOf(parsedName.fullName) > -1;
          if (!alreadyWarned && _this._moduleRegistry.has(dasherize(moduleName))) {
            _this._camelCaseHelperWarnedNames.push(parsedName.fullName);
            _ember['default'].warn('Attempted to lookup "' + parsedName.fullName + '" which ' + 'was not found. In previous versions of ember-resolver, a bug would have ' + 'caused the module at "' + dasherize(moduleName) + '" to be ' + 'returned for this camel case helper name. This has been fixed. ' + 'Use the dasherized name to resolve the module that would have been ' + 'returned in previous versions.', false, { id: 'ember-resolver.camelcase-helper-names', until: '3.0.0' });
          }
        }
      });
    },

    // used by Ember.DefaultResolver.prototype._logLookup
    lookupDescription: function lookupDescription(fullName) {
      var parsedName = this.parseName(fullName);

      var moduleName = this.findModuleName(parsedName, true);

      return moduleName;
    },

    // only needed until 1.6.0-beta.2 can be required
    _logLookup: function _logLookup(found, parsedName, description) {
      if (!_ember['default'].ENV.LOG_MODULE_RESOLVER && !parsedName.root.LOG_RESOLVER) {
        return;
      }

      var symbol, padding;

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

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

      if (!description) {
        description = this.lookupDescription(parsedName);
      }

      _ember['default'].Logger.info(symbol, parsedName.fullName, padding, description);
    },

    knownForType: function knownForType(type) {
      var moduleKeys = this._moduleRegistry.moduleNames();

      var items = (0, _emberResolverUtilsMakeDictionary['default'])();
      for (var index = 0, length = moduleKeys.length; index < length; index++) {
        var moduleName = moduleKeys[index];
        var fullname = this.translateToContainerFullname(type, moduleName);

        if (fullname) {
          items[fullname] = true;
        }
      }

      return items;
    },

    translateToContainerFullname: function translateToContainerFullname(type, moduleName) {
      var prefix = this.prefix({ type: type });

      // Note: using string manipulation here rather than regexes for better performance.
      // pod modules
      // '^' + prefix + '/(.+)/' + type + '$'
      var podPrefix = prefix + '/';
      var podSuffix = '/' + type;
      var start = moduleName.indexOf(podPrefix);
      var end = moduleName.indexOf(podSuffix);

      if (start === 0 && end === moduleName.length - podSuffix.length && moduleName.length > podPrefix.length + podSuffix.length) {
        return type + ':' + moduleName.slice(start + podPrefix.length, end);
      }

      // non-pod modules
      // '^' + prefix + '/' + pluralizedType + '/(.+)$'
      var pluralizedType = this.pluralize(type);
      var nonPodPrefix = prefix + '/' + pluralizedType + '/';

      if (moduleName.indexOf(nonPodPrefix) === 0 && moduleName.length > nonPodPrefix.length) {
        return type + ':' + moduleName.slice(nonPodPrefix.length);
      }
    },

    _extractDefaultExport: function _extractDefaultExport(normalizedModuleName) {
      var module = require(normalizedModuleName, null, null, true /* force sync */);

      if (module && module['default']) {
        module = module['default'];
      }

      return module;
    }
  });

  Resolver.reopenClass({
    moduleBasedResolver: true
  });

  exports['default'] = Resolver;
});
define('ember-resolver/utils/class-factory', ['exports'], function (exports) {
  'use strict';

  exports['default'] = classFactory;

  function classFactory(klass) {
    return {
      create: function create(injections) {
        if (typeof klass.extend === 'function') {
          return klass.extend(injections);
        } else {
          return klass;
        }
      }
    };
  }
});
define("ember-resolver/utils/create", ["exports", "ember"], function (exports, _ember) {
  "use strict";

  var create = Object.create || _ember["default"].create;
  if (!(create && !create(null).hasOwnProperty)) {
    throw new Error("This browser does not support Object.create(null), please polyfil with es5-sham: http://git.io/yBU2rg");
  }

  exports["default"] = create;
});
define('ember-resolver/utils/make-dictionary', ['exports', 'ember-resolver/utils/create'], function (exports, _emberResolverUtilsCreate) {
  'use strict';

  exports['default'] = makeDictionary;

  function makeDictionary() {
    var cache = (0, _emberResolverUtilsCreate['default'])(null);
    cache['_dict'] = null;
    delete cache['_dict'];
    return cache;
  }
});
define('ember-resolver/utils/module-registry', ['exports', 'ember'], function (exports, _ember) {
  /*globals requirejs, require */

  'use strict';

  if (typeof requirejs.entries === 'undefined') {
    requirejs.entries = requirejs._eak_seen;
  }

  function ModuleRegistry(entries) {
    this._entries = entries || requirejs.entries;
  }

  ModuleRegistry.prototype.moduleNames = function ModuleRegistry_moduleNames() {
    return (Object.keys || _ember['default'].keys)(this._entries);
  };

  ModuleRegistry.prototype.has = function ModuleRegistry_has(moduleName) {
    return moduleName in this._entries;
  };

  ModuleRegistry.prototype.get = function ModuleRegistry_get(moduleName) {
    var exportName = arguments.length <= 1 || arguments[1] === undefined ? 'default' : arguments[1];

    var module = require(moduleName);
    return module && module[exportName];
  };

  exports['default'] = ModuleRegistry;
});
;/* jshint ignore:start */



/* jshint ignore:end */
//# sourceMappingURL=vendor.map
