UNPKG

ya-ember-precompile

Version:

Precompile ember handlebars template files without the usage of jquery

1,869 lines (1,472 loc) 830 kB
// Version: v1.0.0-rc.4-23-gbfd3023 // Last commit: bfd3023 (2013-06-01 13:41:52 -0400) (function() { /*global __fail__*/ /** Ember Debug @module ember @submodule ember-debug */ /** @class Ember */ if ('undefined' === typeof Ember) { Ember = {}; if ('undefined' !== typeof window) { window.Em = window.Ember = Em = Ember; } } Ember.ENV = 'undefined' === typeof ENV ? {} : ENV; if (!('MANDATORY_SETTER' in Ember.ENV)) { Ember.ENV.MANDATORY_SETTER = true; // default to true for debug dist } /** Define an assertion that will throw an exception if the condition is not met. Ember build tools will remove any calls to `Ember.assert()` when doing a production build. Example: ```javascript // Test for truthiness Ember.assert('Must pass a valid object', obj); // Fail unconditionally Ember.assert('This code path should never be run') ``` @method assert @param {String} desc A description of the assertion. This will become the text of the Error thrown if the assertion fails. @param {Boolean} test Must be truthy for the assertion to pass. If falsy, an exception will be thrown. */ Ember.assert = function(desc, test) { if (!test) throw new Error("assertion failed: "+desc); }; /** Display a warning with the provided message. Ember build tools will remove any calls to `Ember.warn()` when doing a production build. @method warn @param {String} message A warning to display. @param {Boolean} test An optional boolean. If falsy, the warning will be displayed. */ Ember.warn = function(message, test) { if (!test) { Ember.Logger.warn("WARNING: "+message); if ('trace' in Ember.Logger) Ember.Logger.trace(); } }; /** Display a debug notice. Ember build tools will remove any calls to `Ember.debug()` when doing a production build. ```javascript Ember.debug("I'm a debug notice!"); ``` @method debug @param {String} message A debug message to display. */ Ember.debug = function(message) { Ember.Logger.debug("DEBUG: "+message); }; /** Display a deprecation warning with the provided message and a stack trace (Chrome and Firefox only). Ember build tools will remove any calls to `Ember.deprecate()` when doing a production build. @method deprecate @param {String} message A description of the deprecation. @param {Boolean} test An optional boolean. If falsy, the deprecation will be displayed. */ Ember.deprecate = function(message, test) { if (Ember && Ember.TESTING_DEPRECATION) { return; } if (arguments.length === 1) { test = false; } if (test) { return; } if (Ember && Ember.ENV.RAISE_ON_DEPRECATION) { throw new Error(message); } var error; // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome try { __fail__.fail(); } catch (e) { error = e; } if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) { var stack, stackStr = ''; if (error['arguments']) { // Chrome stack = error.stack.replace(/^\s+at\s+/gm, ''). replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2'). replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n'); stack.shift(); } else { // Firefox stack = error.stack.replace(/(?:\n@:0)?\s+$/m, ''). replace(/^\(/gm, '{anonymous}(').split('\n'); } stackStr = "\n " + stack.slice(2).join("\n "); message = message + stackStr; } Ember.Logger.warn("DEPRECATION: "+message); }; /** Display a deprecation warning with the provided message and a stack trace (Chrome and Firefox only) when the wrapped method is called. Ember build tools will not remove calls to `Ember.deprecateFunc()`, though no warnings will be shown in production. @method deprecateFunc @param {String} message A description of the deprecation. @param {Function} func The function to be deprecated. @return {Function} a new function that wrapped the original function with a deprecation warning */ Ember.deprecateFunc = function(message, func) { return function() { Ember.deprecate(message); return func.apply(this, arguments); }; }; })(); // Version: v1.0.0-rc.4-23-gbfd3023 // Last commit: bfd3023 (2013-06-01 13:41:52 -0400) (function() { var define, requireModule; (function() { var registry = {}, seen = {}; define = function(name, deps, callback) { registry[name] = { deps: deps, callback: callback }; }; requireModule = function(name) { if (seen[name]) { return seen[name]; } seen[name] = {}; var mod, deps, callback, reified, exports; mod = registry[name]; if (!mod) { throw new Error("Module '" + name + "' not found."); } deps = mod.deps; callback = mod.callback; reified = []; exports; for (var i=0, l=deps.length; i<l; i++) { if (deps[i] === 'exports') { reified.push(exports = {}); } else { reified.push(requireModule(deps[i])); } } var value = callback.apply(this, reified); return seen[name] = exports || value; }; })(); (function() { /*globals Em:true ENV */ /** @module ember @submodule ember-metal */ /** All Ember methods and functions are defined inside of this namespace. You generally should not add new properties to this namespace as it may be overwritten by future versions of Ember. You can also use the shorthand `Em` instead of `Ember`. Ember-Runtime is a framework that provides core functions for Ember including cross-platform functions, support for property observing and objects. Its focus is on small size and performance. You can use this in place of or along-side other cross-platform libraries such as jQuery. The core Runtime framework is based on the jQuery API with a number of performance optimizations. @class Ember @static @version 1.0.0-rc.5 */ if ('undefined' === typeof Ember) { // Create core object. Make it act like an instance of Ember.Namespace so that // objects assigned to it are given a sane string representation. Ember = {}; } // Default imports, exports and lookup to the global object; var imports = Ember.imports = Ember.imports || this; var exports = Ember.exports = Ember.exports || this; var lookup = Ember.lookup = Ember.lookup || this; // aliases needed to keep minifiers from removing the global context exports.Em = exports.Ember = Em = Ember; // Make sure these are set whether Ember was already defined or not Ember.isNamespace = true; Ember.toString = function() { return "Ember"; }; /** @property VERSION @type String @default '1.0.0-rc.5' @final */ Ember.VERSION = '1.0.0-rc.5'; /** Standard environmental variables. You can define these in a global `ENV` variable before loading Ember to control various configuration settings. @property ENV @type Hash */ Ember.ENV = Ember.ENV || ('undefined' === typeof ENV ? {} : ENV); Ember.config = Ember.config || {}; // .......................................................... // BOOTSTRAP // /** Determines whether Ember should enhances some built-in object prototypes to provide a more friendly API. If enabled, a few methods will be added to `Function`, `String`, and `Array`. `Object.prototype` will not be enhanced, which is the one that causes most trouble for people. In general we recommend leaving this option set to true since it rarely conflicts with other code. If you need to turn it off however, you can define an `ENV.EXTEND_PROTOTYPES` config to disable it. @property EXTEND_PROTOTYPES @type Boolean @default true */ Ember.EXTEND_PROTOTYPES = Ember.ENV.EXTEND_PROTOTYPES; if (typeof Ember.EXTEND_PROTOTYPES === 'undefined') { Ember.EXTEND_PROTOTYPES = true; } /** Determines whether Ember logs a full stack trace during deprecation warnings @property LOG_STACKTRACE_ON_DEPRECATION @type Boolean @default true */ Ember.LOG_STACKTRACE_ON_DEPRECATION = (Ember.ENV.LOG_STACKTRACE_ON_DEPRECATION !== false); /** Determines whether Ember should add ECMAScript 5 shims to older browsers. @property SHIM_ES5 @type Boolean @default Ember.EXTEND_PROTOTYPES */ Ember.SHIM_ES5 = (Ember.ENV.SHIM_ES5 === false) ? false : Ember.EXTEND_PROTOTYPES; /** Determines whether Ember logs info about version of used libraries @property LOG_VERSION @type Boolean @default true */ Ember.LOG_VERSION = (Ember.ENV.LOG_VERSION === false) ? false : true; /** Empty function. Useful for some operations. @method K @private @return {Object} */ Ember.K = function() { return this; }; // Stub out the methods defined by the ember-debug package in case it's not loaded if ('undefined' === typeof Ember.assert) { Ember.assert = Ember.K; } if ('undefined' === typeof Ember.warn) { Ember.warn = Ember.K; } if ('undefined' === typeof Ember.debug) { Ember.debug = Ember.K; } if ('undefined' === typeof Ember.deprecate) { Ember.deprecate = Ember.K; } if ('undefined' === typeof Ember.deprecateFunc) { Ember.deprecateFunc = function(_, func) { return func; }; } /** Previously we used `Ember.$.uuid`, however `$.uuid` has been removed from jQuery master. We'll just bootstrap our own uuid now. @property uuid @type Number @private */ Ember.uuid = 0; // .......................................................... // LOGGER // function consoleMethod(name) { if (imports.console && imports.console[name]) { // Older IE doesn't support apply, but Chrome needs it if (imports.console[name].apply) { return function() { imports.console[name].apply(imports.console, arguments); }; } else { return function() { var message = Array.prototype.join.call(arguments, ', '); imports.console[name](message); }; } } } /** Inside Ember-Metal, simply uses the methods from `imports.console`. Override this to provide more robust logging functionality. @class Logger @namespace Ember */ Ember.Logger = { log: consoleMethod('log') || Ember.K, warn: consoleMethod('warn') || Ember.K, error: consoleMethod('error') || Ember.K, info: consoleMethod('info') || Ember.K, debug: consoleMethod('debug') || consoleMethod('info') || Ember.K }; // .......................................................... // ERROR HANDLING // /** 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. @event onerror @for Ember @param {Exception} error the error object */ Ember.onerror = null; /** @private Wrap code block in a try/catch if `Ember.onerror` is set. @method handleErrors @for Ember @param {Function} func @param [context] */ Ember.handleErrors = function(func, context) { // Unfortunately in some browsers we lose the backtrace if we rethrow the existing error, // so in the event that we don't have an `onerror` handler we don't wrap in a try/catch if ('function' === typeof Ember.onerror) { try { return func.call(context || this); } catch (error) { Ember.onerror(error); } } else { return func.call(context || this); } }; Ember.merge = function(original, updates) { for (var prop in updates) { if (!updates.hasOwnProperty(prop)) { continue; } original[prop] = updates[prop]; } return original; }; /** 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} */ Ember.isNone = function(obj) { return obj === null || obj === undefined; }; Ember.none = Ember.deprecateFunc("Ember.none is deprecated. Please use Ember.isNone instead.", Ember.isNone); /** Verifies that a value is `null` or an empty string, empty array, or empty function. Constrains the rules on `Ember.isNone` by returning false for empty string and empty arrays. ```javascript Ember.isEmpty(); // true Ember.isEmpty(null); // true Ember.isEmpty(undefined); // true Ember.isEmpty(''); // true Ember.isEmpty([]); // true Ember.isEmpty('Adam Hawkins'); // false Ember.isEmpty([0,1,2]); // false ``` @method isEmpty @for Ember @param {Object} obj Value to test @return {Boolean} */ Ember.isEmpty = function(obj) { return Ember.isNone(obj) || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0); }; Ember.empty = Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.", Ember.isEmpty) ; })(); (function() { /*globals Node */ /** @module ember-metal */ /** Platform specific methods and feature detectors needed by the framework. @class platform @namespace Ember @static */ var platform = Ember.platform = {}; /** Identical to `Object.create()`. Implements if not available natively. @method create @for Ember */ Ember.create = Object.create; // IE8 has Object.create but it couldn't treat property descripters. if (Ember.create) { if (Ember.create({a: 1}, {a: {value: 2}}).a !== 2) { Ember.create = null; } } // STUB_OBJECT_CREATE allows us to override other libraries that stub // Object.create different than we would prefer if (!Ember.create || Ember.ENV.STUB_OBJECT_CREATE) { var K = function() {}; Ember.create = function(obj, props) { K.prototype = obj; obj = new K(); if (props) { K.prototype = obj; for (var prop in props) { K.prototype[prop] = props[prop].value; } obj = new K(); } K.prototype = null; return obj; }; Ember.create.isSimulated = true; } var defineProperty = Object.defineProperty; var canRedefineProperties, canDefinePropertyOnDOM; // Catch IE8 where Object.defineProperty exists but only works on DOM elements if (defineProperty) { try { defineProperty({}, 'a',{get:function(){}}); } catch (e) { defineProperty = null; } } if (defineProperty) { // Detects a bug in Android <3.2 where you cannot redefine a property using // Object.defineProperty once accessors have already been set. canRedefineProperties = (function() { var obj = {}; defineProperty(obj, 'a', { configurable: true, enumerable: true, get: function() { }, set: function() { } }); defineProperty(obj, 'a', { configurable: true, enumerable: true, writable: true, value: true }); return obj.a === true; })(); // This is for Safari 5.0, which supports Object.defineProperty, but not // on DOM nodes. canDefinePropertyOnDOM = (function(){ try { defineProperty(document.createElement('div'), 'definePropertyOnDOM', {}); return true; } catch(e) { } return false; })(); if (!canRedefineProperties) { defineProperty = null; } else if (!canDefinePropertyOnDOM) { defineProperty = function(obj, keyName, desc){ var isNode; if (typeof Node === "object") { isNode = obj instanceof Node; } else { isNode = typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string"; } if (isNode) { // TODO: Should we have a warning here? return (obj[keyName] = desc.value); } else { return Object.defineProperty(obj, keyName, desc); } }; } } /** @class platform @namespace Ember */ /** Identical to `Object.defineProperty()`. Implements as much functionality as possible if not available natively. @method defineProperty @param {Object} obj The object to modify @param {String} keyName property name to modify @param {Object} desc descriptor hash @return {void} */ platform.defineProperty = defineProperty; /** Set to true if the platform supports native getters and setters. @property hasPropertyAccessors @final */ platform.hasPropertyAccessors = true; if (!platform.defineProperty) { platform.hasPropertyAccessors = false; platform.defineProperty = function(obj, keyName, desc) { if (!desc.get) { obj[keyName] = desc.value; } }; platform.defineProperty.isSimulated = true; } if (Ember.ENV.MANDATORY_SETTER && !platform.hasPropertyAccessors) { Ember.ENV.MANDATORY_SETTER = false; } })(); (function() { /*jshint newcap:false*/ /** @module ember-metal */ // NOTE: There is a bug in jshint that doesn't recognize `Object()` without `new` // as being ok unless both `newcap:false` and not `use strict`. // https://github.com/jshint/jshint/issues/392 // Testing this is not ideal, but we want to use native functions // if available, but not to use versions created by libraries like Prototype var isNativeFunc = function(func) { // This should probably work in all browsers likely to have ES5 array methods return func && Function.prototype.toString.call(func).indexOf('[native code]') > -1; }; // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/map var arrayMap = isNativeFunc(Array.prototype.map) ? Array.prototype.map : function(fun /*, thisp */) { //"use strict"; if (this === void 0 || this === null) { throw new TypeError(); } var t = Object(this); var len = t.length >>> 0; if (typeof fun !== "function") { throw new TypeError(); } var res = new Array(len); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in t) { res[i] = fun.call(thisp, t[i], i, t); } } return res; }; // From: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/foreach var arrayForEach = isNativeFunc(Array.prototype.forEach) ? Array.prototype.forEach : function(fun /*, thisp */) { //"use strict"; if (this === void 0 || this === null) { throw new TypeError(); } var t = Object(this); var len = t.length >>> 0; if (typeof fun !== "function") { throw new TypeError(); } var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in t) { fun.call(thisp, t[i], i, t); } } }; var arrayIndexOf = isNativeFunc(Array.prototype.indexOf) ? Array.prototype.indexOf : function (obj, fromIndex) { if (fromIndex === null || fromIndex === undefined) { fromIndex = 0; } else if (fromIndex < 0) { fromIndex = Math.max(0, this.length + fromIndex); } for (var i = fromIndex, j = this.length; i < j; i++) { if (this[i] === obj) { return i; } } return -1; }; Ember.ArrayPolyfills = { map: arrayMap, forEach: arrayForEach, indexOf: arrayIndexOf }; if (Ember.SHIM_ES5) { if (!Array.prototype.map) { Array.prototype.map = arrayMap; } if (!Array.prototype.forEach) { Array.prototype.forEach = arrayForEach; } if (!Array.prototype.indexOf) { Array.prototype.indexOf = arrayIndexOf; } } })(); (function() { /** @module ember-metal */ var o_defineProperty = Ember.platform.defineProperty, o_create = Ember.create, // Used for guid generation... GUID_KEY = '__ember'+ (+ new Date()), uuid = 0, numberCache = [], stringCache = {}; var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER; /** @private 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. @property GUID_KEY @for Ember @type String @final */ Ember.GUID_KEY = GUID_KEY; var GUID_DESC = { writable: false, configurable: false, enumerable: false, value: null }; /** @private 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. @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 */ Ember.generateGuid = function generateGuid(obj, prefix) { if (!prefix) prefix = 'ember'; var ret = (prefix + (uuid++)); if (obj) { GUID_DESC.value = ret; o_defineProperty(obj, GUID_KEY, GUID_DESC); } return ret ; }; /** @private 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. @method guidFor @for Ember @param {Object} obj any object, string, number, Element, or primitive @return {String} the unique guid for this instance. */ Ember.guidFor = function guidFor(obj) { // special cases where we don't want to add a key to object if (obj === undefined) return "(undefined)"; if (obj === null) return "(null)"; var ret; var type = typeof obj; // Don't allow prototype changes to String etc. to change the guidFor switch(type) { case 'number': ret = numberCache[obj]; if (!ret) ret = numberCache[obj] = 'nu'+obj; return ret; case 'string': ret = stringCache[obj]; if (!ret) ret = stringCache[obj] = 'st'+(uuid++); return ret; case 'boolean': return obj ? '(true)' : '(false)'; default: if (obj[GUID_KEY]) return obj[GUID_KEY]; if (obj === Object) return '(Object)'; if (obj === Array) return '(Array)'; ret = 'ember'+(uuid++); GUID_DESC.value = ret; o_defineProperty(obj, GUID_KEY, GUID_DESC); return ret; } }; // .......................................................... // META // var META_DESC = { writable: true, configurable: false, enumerable: false, value: null }; var META_KEY = Ember.GUID_KEY+'_meta'; /** The key used to store meta information on object for property observing. @property META_KEY @for Ember @private @final @type String */ Ember.META_KEY = META_KEY; // Placeholder for non-writable metas. var EMPTY_META = { descs: {}, watching: {} }; if (MANDATORY_SETTER) { EMPTY_META.values = {}; } Ember.EMPTY_META = EMPTY_META; if (Object.freeze) Object.freeze(EMPTY_META); var isDefinePropertySimulated = Ember.platform.defineProperty.isSimulated; function Meta(obj) { this.descs = {}; this.watching = {}; this.cache = {}; this.source = obj; } if (isDefinePropertySimulated) { // on platforms that don't support enumerable false // make meta fail jQuery.isPlainObject() to hide from // jQuery.extend() by having a property that fails // hasOwnProperty check. Meta.prototype.__preventPlainObject__ = true; // Without non-enumerable properties, meta objects will be output in JSON // unless explicitly suppressed Meta.prototype.toJSON = function () { }; } /** 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 */ Ember.meta = function meta(obj, writable) { var ret = obj[META_KEY]; if (writable===false) return ret || EMPTY_META; if (!ret) { if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC); ret = new Meta(obj); if (MANDATORY_SETTER) { ret.values = {}; } obj[META_KEY] = ret; // make sure we don't accidentally try to create constructor like desc ret.descs.constructor = null; } else if (ret.source !== obj) { if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC); ret = o_create(ret); ret.descs = o_create(ret.descs); ret.watching = o_create(ret.watching); ret.cache = {}; ret.source = obj; if (MANDATORY_SETTER) { ret.values = o_create(ret.values); } obj[META_KEY] = ret; } return ret; }; Ember.getMeta = function getMeta(obj, property) { var meta = Ember.meta(obj, false); return meta[property]; }; Ember.setMeta = function setMeta(obj, property, value) { var meta = Ember.meta(obj, true); meta[property] = value; return value; }; /** @deprecated @private In order to store defaults for a class, a prototype may need to create a default meta object, which will be inherited by any objects instantiated from the class's constructor. However, the properties of that meta object are only shallow-cloned, so if a property is a hash (like the event system's `listeners` hash), it will by default be shared across all instances of that class. This method allows extensions to deeply clone a series of nested hashes or other complex objects. For instance, the event system might pass `['listeners', 'foo:change', 'ember157']` to `prepareMetaPath`, which will walk down the keys provided. For each key, if the key does not exist, it is created. If it already exists and it was inherited from its constructor, the constructor's key is cloned. You can also pass false for `writable`, which will simply return undefined if `prepareMetaPath` discovers any part of the path that shared or undefined. @method metaPath @for Ember @param {Object} obj The object whose meta we are examining @param {Array} path An array of keys to walk down @param {Boolean} writable whether or not to create a new meta (or meta property) if one does not already exist or if it's shared with its constructor */ Ember.metaPath = function metaPath(obj, path, writable) { Ember.deprecate("Ember.metaPath is deprecated and will be removed from future releases."); var meta = Ember.meta(obj, writable), keyName, value; for (var i=0, l=path.length; i<l; i++) { keyName = path[i]; value = meta[keyName]; if (!value) { if (!writable) { return undefined; } value = meta[keyName] = { __ember_source__: obj }; } else if (value.__ember_source__ !== obj) { if (!writable) { return undefined; } value = meta[keyName] = o_create(value); value.__ember_source__ = obj; } meta = value; } return value; }; /** @private 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. @method wrap @for Ember @param {Function} func The function to call @param {Function} superFunc The super function. @return {Function} wrapped function. */ Ember.wrap = function(func, superFunc) { function K() {} function superWrapper() { var ret, sup = this._super; this._super = superFunc || K; ret = func.apply(this, arguments); this._super = sup; return ret; } superWrapper.wrappedFunction = func; superWrapper.__ember_observes__ = func.__ember_observes__; superWrapper.__ember_observesBefore__ = func.__ember_observesBefore__; return superWrapper; }; /** Returns true if the passed object is an array or Array-like. Ember Array Protocol: - the object has an objectAt property - the object is a native Array - the object is an Object, and has a length property Unlike `Ember.typeOf` this method returns true even if the passed object is not formally array but appears to be array-like (i.e. implements `Ember.Array`) ```javascript Ember.isArray(); // false Ember.isArray([]); // true Ember.isArray( Ember.ArrayProxy.create({ content: [] }) ); // true ``` @method isArray @for Ember @param {Object} obj The object to test @return {Boolean} true if the passed object is an array or Array-like */ Ember.isArray = function(obj) { if (!obj || obj.setInterval) { return false; } if (Array.isArray && Array.isArray(obj)) { return true; } if (Ember.Array && Ember.Array.detect(obj)) { return true; } if ((obj.length !== undefined) && 'object'===typeof obj) { return true; } return false; }; /** Forces the passed object to be part of an array. If the object is already an array or array-like, returns the object. Otherwise adds the object to an array. If obj is `null` or `undefined`, returns an empty array. ```javascript Ember.makeArray(); // [] Ember.makeArray(null); // [] Ember.makeArray(undefined); // [] Ember.makeArray('lindsay'); // ['lindsay'] Ember.makeArray([1,2,42]); // [1,2,42] var controller = Ember.ArrayProxy.create({ content: [] }); Ember.makeArray(controller) === controller; // true ``` @method makeArray @for Ember @param {Object} obj the object @return {Array} */ Ember.makeArray = function(obj) { if (obj === null || obj === undefined) { return []; } return Ember.isArray(obj) ? obj : [obj]; }; function canInvoke(obj, methodName) { return !!(obj && typeof obj[methodName] === 'function'); } /** Checks to see if the `methodName` exists on the `obj`. @method canInvoke @for Ember @param {Object} obj The object to check for the method @param {String} methodName The method name to check for */ Ember.canInvoke = canInvoke; /** Checks to see if the `methodName` exists on the `obj`, and if it does, invokes it with the arguments passed. @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 */ Ember.tryInvoke = function(obj, methodName, args) { if (canInvoke(obj, methodName)) { return obj[methodName].apply(obj, args || []); } }; // https://github.com/emberjs/ember.js/pull/1617 var needsFinallyFix = (function() { var count = 0; try{ try { } finally { count++; throw new Error('needsFinallyFixTest'); } } catch (e) {} return count !== 1; })(); /** Provides try { } finally { } functionality, while working around Safari's double finally bug. @method tryFinally @for Ember @param {Function} tryable The function to run the try callback @param {Function} finalizer The function to run the finally callback @param [binding] @return {*} The return value is the that of the finalizer, unless that valueis undefined, in which case it is the return value of the tryable */ if (needsFinallyFix) { Ember.tryFinally = function(tryable, finalizer, binding) { var result, finalResult, finalError; binding = binding || this; try { result = tryable.call(binding); } finally { try { finalResult = finalizer.call(binding); } catch (e){ finalError = e; } } if (finalError) { throw finalError; } return (finalResult === undefined) ? result : finalResult; }; } else { Ember.tryFinally = function(tryable, finalizer, binding) { var result, finalResult; binding = binding || this; try { result = tryable.call(binding); } finally { finalResult = finalizer.call(binding); } return (finalResult === undefined) ? result : finalResult; }; } /** Provides try { } catch finally { } functionality, while working around Safari's double finally bug. @method tryCatchFinally @for Ember @param {Function} tryable The function to run the try callback @param {Function} catchable The function to run the catchable callback @param {Function} finalizer The function to run the finally callback @param [binding] @return {*} The return value is the that of the finalizer, unless that value is undefined, in which case it is the return value of the tryable. */ if (needsFinallyFix) { Ember.tryCatchFinally = function(tryable, catchable, finalizer, binding) { var result, finalResult, finalError; binding = binding || this; try { result = tryable.call(binding); } catch(error) { result = catchable.call(binding, error); } finally { try { finalResult = finalizer.call(binding); } catch (e){ finalError = e; } } if (finalError) { throw finalError; } return (finalResult === undefined) ? result : finalResult; }; } else { Ember.tryCatchFinally = function(tryable, catchable, finalizer, binding) { var result, finalResult; binding = binding || this; try { result = tryable.call(binding); } catch(error) { result = catchable.call(binding, error); } finally { finalResult = finalizer.call(binding); } return (finalResult === undefined) ? result : finalResult; }; } // ........................................ // TYPING & ARRAY MESSAGING // var TYPE_MAP = {}; var t = "Boolean Number String Function Array Date RegExp Object".split(" "); Ember.ArrayPolyfills.forEach.call(t, function(name) { TYPE_MAP[ "[object " + name + "]" ] = name.toLowerCase(); }); var toString = Object.prototype.toString; /** Returns a consistent type for the passed item. Use this instead of the built-in `typeof` to get the type of an item. It will return the same result across all browsers and includes a bit more detail. Here is what will be returned: | Return Value | Meaning | |---------------|------------------------------------------------------| | 'string' | String primitive | | 'number' | Number primitive | | 'boolean' | Boolean primitive | | 'null' | Null value | | 'undefined' | Undefined value | | 'function' | A function | | 'array' | An instance of Array | | '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(101); // 'number' Ember.typeOf(true); // 'boolean' Ember.typeOf(Ember.makeArray); // 'function' Ember.typeOf([1,2,90]); // 'array' 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 */ Ember.typeOf = function(item) { var ret; ret = (item === null || item === undefined) ? String(item) : TYPE_MAP[toString.call(item)] || 'object'; if (ret === 'function') { if (Ember.Object && Ember.Object.detect(item)) ret = 'class'; } else if (ret === 'object') { if (item instanceof Error) ret = 'error'; else if (Ember.Object && item instanceof Ember.Object) ret = 'instance'; else ret = 'object'; } return ret; }; })(); (function() { // Ember.tryCatchFinally /** The purpose of the Ember Instrumentation module is to provide efficient, general-purpose instrumentation for Ember. Subscribe to a listener by using `Ember.subscribe`: ```javascript Ember.subscribe("render", { before: function(name, timestamp, payload) { }, after: function(name, timestamp, payload) { } }); ``` If you return a value from the `before` callback, that same value will be passed as a fourth parameter to the `after` callback. Instrument a block of code by using `Ember.instrument`: ```javascript Ember.instrument("render.handlebars", payload, function() { // rendering logic }, binding); ``` Event names passed to `Ember.instrument` are namespaced by periods, from more general to more specific. Subscribers can listen for events by whatever level of granularity they are interested in. In the above example, the event is `render.handlebars`, and the subscriber listened for all events beginning with `render`. It would receive callbacks for events named `render`, `render.handlebars`, `render.container`, or even `render.handlebars.layout`. @class Instrumentation @namespace Ember @static */ Ember.Instrumentation = {}; var subscribers = [], cache = {}; var populateListeners = function(name) { var listeners = [], subscriber; for (var i=0, l=subscribers.length; i<l; i++) { subscriber = subscribers[i]; if (subscriber.regex.test(name)) { listeners.push(subscriber.object); } } cache[name] = listeners; return listeners; }; var time = (function() { var perf = 'undefined' !== typeof window ? window.performance || {} : {}; var fn = perf.now || perf.mozNow || perf.webkitNow || perf.msNow || perf.oNow; // fn.bind will be available in all the browsers that support the advanced window.performance... ;-) return fn ? fn.bind(perf) : function() { return +new Date(); }; })(); Ember.Instrumentation.instrument = function(name, payload, callback, binding) { var listeners = cache[name], timeName, ret; if (Ember.STRUCTURED_PROFILE) { timeName = name + ": " + payload.object; console.time(timeName); } if (!listeners) { listeners = populateListeners(name); } if (listeners.length === 0) { ret = callback.call(binding); if (Ember.STRUCTURED_PROFILE) { console.timeEnd(timeName); } return ret; } var beforeValues = [], listener, i, l; function tryable(){ for (i=0, l=listeners.length; i<l; i++) { listener = listeners[i]; beforeValues[i] = listener.before(name, time(), payload); } return callback.call(binding); } function catchable(e){ payload = payload || {}; payload.exception = e; } function finalizer() { for (i=0, l=listeners.length; i<l; i++) { listener = listeners[i]; listener.after(name, time(), payload, beforeValues[i]); } if (Ember.STRUCTURED_PROFILE) { console.timeEnd(timeName); } } return Ember.tryCatchFinally(tryable, catchable, finalizer); }; Ember.Instrumentation.subscribe = function(pattern, object) { var paths = pattern.split("."), path, regex = []; for (var i=0, l=paths.length; i<l; i++) { path = paths[i]; if (path === "*") { regex.push("[^\\.]*"); } else { regex.push(path); } } regex = regex.join("\\."); regex = regex + "(\\..*)?"; var subscriber = { pattern: pattern, regex: new RegExp("^" + regex + "$"), object: object }; subscribers.push(subscriber); cache = {}; return subscriber; }; Ember.Instrumentation.unsubscribe = function(subscriber) { var index; for (var i=0, l=subscribers.length; i<l; i++) { if (subscribers[i] === subscriber) { index = i; } } subscribers.splice(index, 1); cache = {}; }; Ember.Instrumentation.reset = function() { subscribers = []; cache = {}; }; Ember.instrument = Ember.Instrumentation.instrument; Ember.subscribe = Ember.Instrumentation.subscribe; })(); (function() { var map, forEach, indexOf, concat; concat = Array.prototype.concat; map = Array.prototype.map || Ember.ArrayPolyfills.map; forEach = Array.prototype.forEach || Ember.ArrayPolyfills.forEach; indexOf = Array.prototype.indexOf || Ember.ArrayPolyfills.indexOf; var utils = Ember.EnumerableUtils = { map: function(obj, callback, thisArg) { return obj.map ? obj.map.call(obj, callback, thisArg) : map.call(obj, callback, thisArg); }, forEach: function(obj, callback, thisArg) { return obj.forEach ? obj.forEach.call(obj, callback, thisArg) : forEach.call(obj, callback, thisArg); }, indexOf: function(obj, element, index) { return obj.indexOf ? obj.indexOf.call(obj, element, index) : indexOf.call(obj, element, index); }, indexesOf: function(obj, elements) { return elements === undefined ? [] : utils.map(elements, function(item) { return utils.indexOf(obj, item); }); }, addObject: function(array, item) { var index = utils.indexOf(array, item); if (index === -1) { array.push(item); } }, removeObject: function(array, item) { var index = utils.indexOf(array, item); if (index !== -1) { array.splice(index, 1); } }, replace: function(array, idx, amt, objects) { if (array.replace) { return array.replace(idx, amt, objects); } else { var args = concat.apply([idx, amt], objects); return array.splice.apply(array, args); } }, intersection: function(array1, array2) { var intersection = []; utils.forEach(array1, function(element) { if (utils.indexOf(array2, element) >= 0) { intersection.push(element); } }); return intersection; } }; })(); (function() { /** @module ember-metal */ var META_KEY = Ember.META_KEY, get; var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER; var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/; var HAS_THIS = /^this[\.\*]/; var FIRST_KEY = /^([^\.\*]+)/; // .......................................................... // GET AND SET // // If we are on a platform that supports accessors we can use those. // Otherwise simulate accessors by looking up the property directly on the // object. /** Gets the value of a property on an object. If the property is computed, the function will be invoked. If the property is not defined but the object implements the `unknownProperty` method then that will be invoked. If you plan to run on IE8 and older browsers then you should use this method anytime you want to retrieve a property on an object that you don't know for sure is private. (Properties beginning with an underscore '_' are considered private.) On all newer browsers, you only need to use this method to retrieve properties if the property might not be defined on the object and you want to respect the `unknownProperty` handler. Otherwise you can ignore this method. Note that if the object itself is `undefined`, this method will throw an error. @method get @for Ember @param {Object} obj The object to retrieve from. @param {String} keyName The property key to retrieve @return {Object} the property value or `null`. */ get = function get(obj, keyName) { // Helpers that operate with 'this' within an #each if (keyName === '') { return obj; } if (!keyName && 'string'===typeof obj) { keyName = obj; obj = null; } Ember.assert("Cannot call get with '"+ keyName +"' on an undefined object.", obj !== undefined); if (obj === null || keyName.indexOf('.') !== -1) { return getPath(obj, keyName); } var meta = obj[META_KEY], desc = meta && meta.descs[keyName], ret; if (desc) { return desc.get(obj, keyName); } else { if (MANDATORY_SETTER && meta && meta.watching[keyName] > 0) { ret = meta.values[keyName]; } else { ret = obj[keyName]; } if (ret === undefined && 'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) { return obj.unknownProperty(keyName); } return ret; } }; // Currently used only by Ember Data tests if (Ember.config.overrideAccessors) { Ember.get = get; Ember.config.overrideAccessors(); get = Ember.get; } function firstKey(path) { return path.match(FIRST_KEY)[0]; } // assumes path is already normalized function normalizeTuple(target, path) { var hasThis = HAS_THIS.test(path), isGlobal = !hasThis && IS_GLOBAL_PATH.test(path), key; if (!target || isGlobal) target = Ember.lookup; if (hasThis) path = path.slice(5); if (target === Ember.lookup) { key = firstKey(path); target = get(target, key); path = path.slice(key.length+1); } // must return some kind of path to be valid else other things will break. if (!path || path.length===0) throw new Error('Invalid Path'); return [ target, path ]; } var getPath = Ember._getPath = function(root, path) { var hasThis, parts, tuple, idx, len; // If there is no root and path is a key name, return that // property from the global object. // E.g. get('Ember') -> Ember if (root === null && path.indexOf('.') === -1) { return get(Ember.lookup, path); } // detect complicated paths and normalize them hasThis = HAS_THIS.test(path); if (!root || hasThis) { tuple = normalizeTuple(root, path); root = tuple[0]; path = tuple[1]; tuple.length = 0; } parts = path.split("."); len = parts.length; for (idx = 0; root != null && idx < len; idx++) { root = get(root, parts[idx], true); if (root && root.isDestroyed) { return undefined; } } return root; }; /** @private Normalizes a target/path pair to reflect that actual target/path that should be observed, etc. This takes into account passing in global property paths (i.e. a path beginning with a captial letter not defined on the target) and * separators. @method normalizeTuple @for Ember @param {Object} target The current target. May be `null`. @param {String} path A path on the target or a global property path. @return {Array} a temporary array with the normalized target/path pair. */ Ember.normalizeTuple = function(target, path) { return normalizeTuple(target, path); }; Ember.getWithDefault = function(root, key, defaultValue) { var value = get(root, key); if (value === undefined) { return defaultValue; } return value; }; Ember.get = get; Ember.getPath = Ember.deprecateFunc('getPath is deprecated since get now supports paths', Ember.get); })(); (function() { /** @module ember-metal */ var o_create = Ember.create, metaFor = Ember.meta, META_KEY = Ember.META_KEY, /* listener flags */ ONCE = 1, SUSPENDED = 2; /* The event system uses a series of nested hashes to store listeners on an object. When a listener is registered, or when an event arrives, these hashes are consulted to determine which target and action pair to invoke. The hashes are stored in the object's meta hash, and look like this: // Object's meta hash { listeners: { // variable name: `listenerSet` "foo:changed": [ // variable name: `actions` [target, method, flags] ] } } */ function indexOf(array, target, method) { var index = -1; for (var i = 0, l = array.length; i < l; i++) { if (target === array[i][0] && method === array[i][1]) { index = i; break; } } return index; } function actionsFor(obj, eventName) { var meta = metaFor(obj, true), actions; if (!meta.listeners) { meta.listeners = {}; } if (!meta.hasOwnProperty('listeners')) { // setup inherited copy of the listeners object meta.listeners = o_create(meta.listeners); } actions = meta.listeners[eventName]; // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype if (actions && !meta.listeners.hasOwnProperty(eventName)) { actions = meta.listeners[eventName] = meta.listeners[eventName].slice(); } else if (!actions) { actions = meta.listeners[eventName] = []; } return actions; } function actionsUnion(obj, eventName, otherActions) { var meta = obj[META_KEY], actions = meta && meta.listeners && meta.listeners[eventName]; if (!actions) { return; } for (var i = actions.length - 1; i >= 0; i--) { var target = actions[i][0], method = actions[i][1], flags = actions[i][2], actionIndex = indexOf(otherActions, target, method); if (actionIndex === -1) { otherActions.push([target, method, flags]); } } } function actionsDiff(obj, eventName, otherActions) { var meta = obj[META_KEY], actions = meta && meta.listeners && meta.listeners[eventName], diffActions = []; if (!actions) { return; } for (var i = actions.length - 1; i >= 0; i--) { var target = actions[i][0], method = actions[i][1], flags = actions[i][2], actionIndex = indexOf(otherActions, target, method); if (actionIndex !== -1) { continue; } otherActions.push([target, method, flags]); diffActions.push([target, method, flags]); } return diffActions; } /** Add an event listener @method addListener @for Ember @param obj @param {String} eventName @param {Object|Function} targetOrMethod A target obj