dist/ember.js in ember-source-1.4.0.beta.1 vs dist/ember.js in ember-source-1.4.0.beta.2
- old
+ new
@@ -3,11 +3,11 @@
* @copyright Copyright 2011-2014 Tilde Inc. and contributors
* Portions Copyright 2006-2011 Strobe Inc.
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
* @license Licensed under MIT license
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
- * @version 1.4.0-beta.1
+ * @version 1.4.0-beta.2
*/
(function() {
/*global __fail__*/
@@ -196,11 +196,11 @@
* @copyright Copyright 2011-2014 Tilde Inc. and contributors
* Portions Copyright 2006-2011 Strobe Inc.
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
* @license Licensed under MIT license
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
- * @version 1.4.0-beta.1
+ * @version 1.4.0-beta.2
*/
(function() {
var define, requireModule, require, requirejs;
@@ -279,11 +279,11 @@
The core Runtime framework is based on the jQuery API with a number of
performance optimizations.
@class Ember
@static
- @version 1.4.0-beta.1+canary.64fee6ed
+ @version 1.4.0-beta.2
*/
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.
@@ -306,14 +306,14 @@
/**
@property VERSION
@type String
- @default '1.4.0-beta.1+canary.64fee6ed'
+ @default '1.4.0-beta.2'
@static
*/
-Ember.VERSION = '1.4.0-beta.1+canary.64fee6ed';
+Ember.VERSION = '1.4.0-beta.2';
/**
Standard environmental variables. You can define these in a global `EmberENV`
variable before loading Ember to control various configuration settings.
@@ -1024,11 +1024,11 @@
// ..........................................................
// META
//
-var META_DESC = {
+var META_DESC = Ember.META_DESC = {
writable: true,
configurable: false,
enumerable: false,
value: null
};
@@ -1828,38 +1828,127 @@
forEach = Array.prototype.forEach || Ember.ArrayPolyfills.forEach;
indexOf = Array.prototype.indexOf || Ember.ArrayPolyfills.indexOf;
filter = Array.prototype.filter || Ember.ArrayPolyfills.filter;
splice = Array.prototype.splice;
+/**
+ * Defines some convenience methods for working with Enumerables.
+ * `Ember.EnumerableUtils` uses `Ember.ArrayPolyfills` when necessary.
+ *
+ * @class EnumerableUtils
+ * @namespace Ember
+ * @static
+ * */
var utils = Ember.EnumerableUtils = {
+ /**
+ * Calls the map function on the passed object with a specified callback. This
+ * uses `Ember.ArrayPolyfill`'s-map method when necessary.
+ *
+ * @method map
+ * @param {Object} obj The object that should be mapped
+ * @param {Function} callback The callback to execute
+ * @param {Object} thisArg Value to use as this when executing *callback*
+ *
+ * @return {Array} An array of mapped values.
+ */
map: function(obj, callback, thisArg) {
return obj.map ? obj.map.call(obj, callback, thisArg) : map.call(obj, callback, thisArg);
},
+ /**
+ * Calls the forEach function on the passed object with a specified callback. This
+ * uses `Ember.ArrayPolyfill`'s-forEach method when necessary.
+ *
+ * @method forEach
+ * @param {Object} obj The object to call forEach on
+ * @param {Function} callback The callback to execute
+ * @param {Object} thisArg Value to use as this when executing *callback*
+ *
+ */
forEach: function(obj, callback, thisArg) {
return obj.forEach ? obj.forEach.call(obj, callback, thisArg) : forEach.call(obj, callback, thisArg);
},
+ /**
+ * Calls the filter function on the passed object with a specified callback. This
+ * uses `Ember.ArrayPolyfill`'s-filter method when necessary.
+ *
+ * @method filter
+ * @param {Object} obj The object to call filter on
+ * @param {Function} callback The callback to execute
+ * @param {Object} thisArg Value to use as this when executing *callback*
+ *
+ * @return {Array} An array containing the filtered values
+ */
filter: function(obj, callback, thisArg) {
return obj.filter ? obj.filter.call(obj, callback, thisArg) : filter.call(obj, callback, thisArg);
},
+ /**
+ * Calls the indexOf function on the passed object with a specified callback. This
+ * uses `Ember.ArrayPolyfill`'s-indexOf method when necessary.
+ *
+ * @method indexOf
+ * @param {Object} obj The object to call indexOn on
+ * @param {Function} callback The callback to execute
+ * @param {Object} index The index to start searching from
+ *
+ */
indexOf: function(obj, element, index) {
return obj.indexOf ? obj.indexOf.call(obj, element, index) : indexOf.call(obj, element, index);
},
+ /**
+ * Returns an array of indexes of the first occurrences of the passed elements
+ * on the passed object.
+ *
+ * ```javascript
+ * var array = [1, 2, 3, 4, 5];
+ * Ember.EnumerableUtils.indexesOf(array, [2, 5]); // [1, 4]
+ *
+ * var fubar = "Fubarr";
+ * Ember.EnumerableUtils.indexesOf(fubar, ['b', 'r']); // [2, 4]
+ * ```
+ *
+ * @method indexesOf
+ * @param {Object} obj The object to check for element indexes
+ * @param {Array} elements The elements to search for on *obj*
+ *
+ * @return {Array} An array of indexes.
+ *
+ */
indexesOf: function(obj, elements) {
return elements === undefined ? [] : utils.map(elements, function(item) {
return utils.indexOf(obj, item);
});
},
+ /**
+ * Adds an object to an array. If the array already includes the object this
+ * method has no effect.
+ *
+ * @method addObject
+ * @param {Array} array The array the passed item should be added to
+ * @param {Object} item The item to add to the passed array
+ *
+ * @return 'undefined'
+ */
addObject: function(array, item) {
var index = utils.indexOf(array, item);
if (index === -1) { array.push(item); }
},
+ /**
+ * Removes an object from an array. If the array does not contain the passed
+ * object this method has no effect.
+ *
+ * @method removeObject
+ * @param {Array} array The array to remove the item from.
+ * @param {Object} item The item to remove from the passed array.
+ *
+ * @return 'undefined'
+ */
removeObject: function(array, item) {
var index = utils.indexOf(array, item);
if (index !== -1) { array.splice(index, 1); }
},
@@ -1881,18 +1970,66 @@
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
+ * @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 remove 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 changed array.
+ */
replace: function(array, idx, amt, objects) {
if (array.replace) {
return array.replace(idx, amt, objects);
} else {
return utils._replace(array, idx, amt, objects);
}
},
+ /**
+ * Calculates the intersection of two arrays. This method returns a new array
+ * filled with the records that the two passed arrays share with each other.
+ * If there is no intersection, an empty array will be returned.
+ *
+ * ```javascript
+ * var array1 = [1, 2, 3, 4, 5];
+ * var array2 = [1, 3, 5, 6, 7];
+ *
+ * Ember.EnumerableUtils.intersection(array1, array2); // [1, 3, 5]
+ *
+ * var array1 = [1, 2, 3];
+ * var array2 = [4, 5, 6];
+ *
+ * Ember.EnumerableUtils.intersection(array1, array2); // []
+ * ```
+ *
+ * @method intersection
+ * @param {Array} array1 The first array
+ * @param {Array} array2 The second array
+ *
+ * @return {Array} The intersection of the two passed arrays.
+ */
intersection: function(array1, array2) {
var intersection = [];
utils.forEach(array1, function(element) {
if (utils.indexOf(array2, element) >= 0) {
@@ -2541,11 +2678,11 @@
})();
(function() {
-var metaFor = Ember.meta,
+var META_KEY = Ember.META_KEY,
guidFor = Ember.guidFor,
tryFinally = Ember.tryFinally,
sendEvent = Ember.sendEvent,
listenersUnion = Ember.listenersUnion,
listenersDiff = Ember.listenersDiff,
@@ -2572,14 +2709,14 @@
@param {Object} obj The object with the property that will change
@param {String} keyName The property key (or path) that will change.
@return {void}
*/
function propertyWillChange(obj, keyName) {
- var m = metaFor(obj, false),
- watching = m.watching[keyName] > 0 || keyName === 'length',
- proto = m.proto,
- desc = m.descs[keyName];
+ var m = obj[META_KEY],
+ watching = (m && m.watching[keyName] > 0) || keyName === 'length',
+ proto = m && m.proto,
+ desc = m && m.descs[keyName];
if (!watching) { return; }
if (proto === obj) { return; }
if (desc && desc.willChange) { desc.willChange(obj, keyName); }
dependentKeysWillChange(obj, keyName, m);
@@ -2602,14 +2739,14 @@
@param {Object} obj The object with the property that will change
@param {String} keyName The property key (or path) that will change.
@return {void}
*/
function propertyDidChange(obj, keyName) {
- var m = metaFor(obj, false),
- watching = m.watching[keyName] > 0 || keyName === 'length',
- proto = m.proto,
- desc = m.descs[keyName];
+ var m = obj[META_KEY],
+ watching = (m && m.watching[keyName] > 0) || keyName === 'length',
+ proto = m && m.proto,
+ desc = m && m.descs[keyName];
if (proto === obj) { return; }
// shouldn't this mean that we're watching this key?
if (desc && desc.didChange) { desc.didChange(obj, keyName); }
@@ -2678,11 +2815,11 @@
propertyWillChange(events[i], events[i+1]);
}
}
function chainsDidChange(obj, keyName, m, suppressEvents) {
- if (!(m.hasOwnProperty('chainWatchers') &&
+ if (!(m && m.hasOwnProperty('chainWatchers') &&
m.chainWatchers[keyName])) {
return;
}
var nodes = m.chainWatchers[keyName],
@@ -3703,15 +3840,15 @@
var metaFor = Ember.meta, // utils.js
typeOf = Ember.typeOf, // utils.js
MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER,
o_defineProperty = Ember.platform.defineProperty;
-Ember.watchKey = function(obj, keyName) {
+Ember.watchKey = function(obj, keyName, meta) {
// can't watch length on Array - it is special...
if (keyName === 'length' && typeOf(obj) === 'array') { return; }
- var m = metaFor(obj), watching = m.watching;
+ var m = meta || metaFor(obj), watching = m.watching;
// activate watching first time
if (!watching[keyName]) {
watching[keyName] = 1;
@@ -3732,12 +3869,12 @@
watching[keyName] = (watching[keyName] || 0) + 1;
}
};
-Ember.unwatchKey = function(obj, keyName) {
- var m = metaFor(obj), watching = m.watching;
+Ember.unwatchKey = function(obj, keyName, meta) {
+ var m = meta || metaFor(obj), watching = m.watching;
if (watching[keyName] === 1) {
watching[keyName] = 0;
if ('function' === typeof obj.didUnwatchProperty) {
@@ -3776,11 +3913,12 @@
normalizeTuple = Ember.normalizeTuple, // property_get.js
forEach = Ember.ArrayPolyfills.forEach, // array.js
warn = Ember.warn,
watchKey = Ember.watchKey,
unwatchKey = Ember.unwatchKey,
- FIRST_KEY = /^([^\.\*]+)/;
+ FIRST_KEY = /^([^\.\*]+)/,
+ META_KEY = Ember.META_KEY;
function firstKey(path) {
return path.match(FIRST_KEY)[0];
}
@@ -3810,28 +3948,28 @@
nodes = m.chainWatchers = {};
}
if (!nodes[keyName]) { nodes[keyName] = []; }
nodes[keyName].push(node);
- watchKey(obj, keyName);
+ watchKey(obj, keyName, m);
}
var removeChainWatcher = Ember.removeChainWatcher = function(obj, keyName, node) {
if (!obj || 'object' !== typeof obj) { return; } // nothing to do
- var m = metaFor(obj, false);
- if (!m.hasOwnProperty('chainWatchers')) { return; } // nothing to do
+ var m = obj[META_KEY];
+ if (m && !m.hasOwnProperty('chainWatchers')) { return; } // nothing to do
- var nodes = m.chainWatchers;
+ var nodes = m && m.chainWatchers;
- if (nodes[keyName]) {
+ if (nodes && nodes[keyName]) {
nodes = nodes[keyName];
for (var i = 0, l = nodes.length; i < l; i++) {
if (nodes[i] === node) { nodes.splice(i, 1); }
}
}
- unwatchKey(obj, keyName);
+ 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.
@@ -3867,18 +4005,18 @@
var ChainNodePrototype = ChainNode.prototype;
function lazyGet(obj, key) {
if (!obj) return undefined;
- var meta = metaFor(obj, false);
+ var meta = obj[META_KEY];
// check if object meant only to be a prototype
- if (meta.proto === obj) return undefined;
+ if (meta && meta.proto === obj) return undefined;
if (key === "@each") return get(obj, key);
// if a CP only return cached value
- var desc = meta.descs[key];
+ var desc = meta && meta.descs[key];
if (desc && desc._cacheable) {
if (key in meta.cache) {
return meta.cache[key];
} else {
return undefined;
@@ -4086,16 +4224,18 @@
// and finally tell parent about my path changing...
if (this._parent) { this._parent.chainDidChange(this, this._key, 1, events); }
};
Ember.finishChains = function(obj) {
- var m = metaFor(obj, false), chains = m.chains;
+ // We only create meta if we really have to
+ var m = obj[META_KEY], chains = m && m.chains;
if (chains) {
if (chains.value() !== obj) {
- m.chains = chains = chains.copy(obj);
+ metaFor(obj).chains = chains = chains.copy(obj);
+ } else {
+ chains.didChange(null);
}
- chains.didChange(null);
}
};
})();
@@ -4159,40 +4299,40 @@
ChainNode = Ember._ChainNode; // chains.js
// 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) {
- var m = metaFor(obj), ret = m.chains;
+function chainsFor(obj, meta) {
+ var m = meta || metaFor(obj), ret = m.chains;
if (!ret) {
ret = m.chains = new ChainNode(null, null, obj);
} else if (ret.value() !== obj) {
ret = m.chains = ret.copy(obj);
}
return ret;
}
-Ember.watchPath = function(obj, keyPath) {
+Ember.watchPath = function(obj, keyPath, meta) {
// can't watch length on Array - it is special...
if (keyPath === 'length' && typeOf(obj) === 'array') { return; }
- var m = metaFor(obj), watching = m.watching;
+ var m = meta || metaFor(obj), watching = m.watching;
if (!watching[keyPath]) { // activate watching first time
watching[keyPath] = 1;
- chainsFor(obj).add(keyPath);
+ chainsFor(obj, m).add(keyPath);
} else {
watching[keyPath] = (watching[keyPath] || 0) + 1;
}
};
-Ember.unwatchPath = function(obj, keyPath) {
- var m = metaFor(obj), watching = m.watching;
+Ember.unwatchPath = function(obj, keyPath, meta) {
+ var m = meta || metaFor(obj), watching = m.watching;
if (watching[keyPath] === 1) {
watching[keyPath] = 0;
- chainsFor(obj).remove(keyPath);
+ chainsFor(obj, m).remove(keyPath);
} else if (watching[keyPath] > 1) {
watching[keyPath]--;
}
};
})();
@@ -4232,36 +4372,36 @@
@method watch
@for Ember
@param obj
@param {String} keyName
*/
-Ember.watch = function(obj, _keyPath) {
+Ember.watch = function(obj, _keyPath, m) {
// can't watch length on Array - it is special...
if (_keyPath === 'length' && typeOf(obj) === 'array') { return; }
if (isKeyName(_keyPath)) {
- watchKey(obj, _keyPath);
+ watchKey(obj, _keyPath, m);
} else {
- watchPath(obj, _keyPath);
+ watchPath(obj, _keyPath, m);
}
};
Ember.isWatching = function isWatching(obj, key) {
var meta = obj[META_KEY];
return (meta && meta.watching[key]) > 0;
};
Ember.watch.flushPending = Ember.flushPendingChains;
-Ember.unwatch = function(obj, _keyPath) {
+Ember.unwatch = function(obj, _keyPath, m) {
// can't watch length on Array - it is special...
if (_keyPath === 'length' && typeOf(obj) === 'array') { return; }
if (isKeyName(_keyPath)) {
- unwatchKey(obj, _keyPath);
+ unwatchKey(obj, _keyPath, m);
} else {
- unwatchPath(obj, _keyPath);
+ unwatchPath(obj, _keyPath, m);
}
};
/**
Call on an object when you first beget it from another object. This will
@@ -4272,11 +4412,11 @@
@method rewatch
@for Ember
@param obj
*/
Ember.rewatch = function(obj) {
- var m = metaFor(obj, false), chains = m.chains;
+ var m = obj[META_KEY], chains = m && m.chains;
// make sure the object has its own guid.
if (GUID_KEY in obj && !obj.hasOwnProperty(GUID_KEY)) {
generateGuid(obj);
}
@@ -4405,11 +4545,11 @@
// Lookup keys meta for depKey
keys = keysForDep(depsMeta, depKey);
// Increment the number of times depKey depends on keyName.
keys[keyName] = (keys[keyName] || 0) + 1;
// Watch the depKey
- watch(obj, depKey);
+ watch(obj, depKey, meta);
}
}
function removeDependentKeys(desc, obj, keyName, meta) {
// the descriptor has a list of dependent keys, so
@@ -4424,11 +4564,11 @@
// Lookup keys meta for depKey
keys = keysForDep(depsMeta, depKey);
// Increment the number of times depKey depends on keyName.
keys[keyName] = (keys[keyName] || 0) - 1;
// Watch the depKey
- unwatch(obj, depKey);
+ unwatch(obj, depKey, meta);
}
}
// ..........................................................
// COMPUTED PROPERTY
@@ -4632,11 +4772,11 @@
ComputedPropertyPrototype.property = function() {
var args;
var addArg = function (property) {
- args.push(property);
+ args.push(property);
};
args = [];
for (var i = 0, l = arguments.length; i < l; i++) {
expandProperties(arguments[i], addArg);
@@ -4885,11 +5025,12 @@
@param {String} key the name of the property whose cached value you want
to return
@return {Object} the cached value
*/
Ember.cacheFor = function cacheFor(obj, key) {
- var cache = metaFor(obj, false).cache;
+ var meta = obj[META_KEY],
+ cache = meta && meta.cache;
if (cache && key in cache) {
return cache[key];
}
};
@@ -7461,18 +7602,20 @@
a_indexOf = Ember.ArrayPolyfills.indexOf,
a_forEach = Ember.ArrayPolyfills.forEach,
a_slice = [].slice,
o_create = Ember.create,
defineProperty = Ember.defineProperty,
- guidFor = Ember.guidFor;
+ guidFor = Ember.guidFor,
+ metaFor = Ember.meta,
+ META_KEY = Ember.META_KEY;
var expandProperties = Ember.expandProperties;
function mixinsMeta(obj) {
- var m = Ember.meta(obj, true), ret = m.mixins;
+ var m = metaFor(obj, true), ret = m.mixins;
if (!ret) {
ret = m.mixins = {};
} else if (!m.hasOwnProperty('mixins')) {
ret = m.mixins = o_create(ret);
}
@@ -7653,11 +7796,11 @@
props = mixinProperties(m, mixin);
if (props === CONTINUE) { continue; }
if (props) {
- meta = Ember.meta(base);
+ meta = metaFor(base);
if (base.willMergeMixin) { base.willMergeMixin(props); }
concats = concatenatedMixinProperties('concatenatedProperties', props, values, base);
mergings = concatenatedMixinProperties('mergedProperties', props, values, base);
for (key in props) {
@@ -7711,11 +7854,11 @@
m.bindings = {};
}
}
function finishPartial(obj, m) {
- connectBindings(obj, m || Ember.meta(obj));
+ connectBindings(obj, m || metaFor(obj));
return obj;
}
function followAlias(obj, desc, m, descs, values) {
var altKey = desc.methodName, value;
@@ -7758,11 +7901,11 @@
updateObserversAndListeners(obj, key, observerOrListener, '__ember_listens__', 'addListener');
}
}
function applyMixin(obj, mixins, partial) {
- var descs = {}, values = {}, m = Ember.meta(obj),
+ var descs = {}, values = {}, m = metaFor(obj),
key, value, desc, keys = [];
// Go through all mixins and hashes passed in, and:
//
// * Handle concatenated properties
@@ -7970,11 +8113,12 @@
@return {Boolean}
*/
MixinPrototype.detect = function(obj) {
if (!obj) { return false; }
if (obj instanceof Mixin) { return _detect(obj, this, {}); }
- var mixins = Ember.meta(obj, false).mixins;
+ var m = obj[META_KEY],
+ mixins = m && m.mixins;
if (mixins) {
return !!mixins[guidFor(this)];
}
return false;
};
@@ -8009,11 +8153,12 @@
};
// returns the mixins currently applied to the specified object
// TODO: Make Ember.mixin
Mixin.mixins = function(obj) {
- var mixins = Ember.meta(obj, false).mixins, ret = [];
+ var m = obj[META_KEY],
+ mixins = m && m.mixins, ret = [];
if (!mixins) { return ret; }
for (var key in mixins) {
var mixin = mixins[key];
@@ -9889,11 +10034,11 @@
// error.message === "2"
});
```
@method all
- @for RSVP.Promise
+ @for Ember.RSVP.Promise
@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.
@@ -12617,10 +12762,11 @@
o_defineProperty = Ember.platform.defineProperty,
GUID_KEY = Ember.GUID_KEY,
guidFor = Ember.guidFor,
generateGuid = Ember.generateGuid,
meta = Ember.meta,
+ META_KEY = Ember.META_KEY,
rewatch = Ember.rewatch,
finishChains = Ember.finishChains,
sendEvent = Ember.sendEvent,
destroy = Ember.destroy,
schedule = Ember.run.schedule,
@@ -13310,11 +13456,12 @@
@method metaForProperty
@param key {String} property name
*/
metaForProperty: function(key) {
- var desc = meta(this.proto(), false).descs[key];
+ var meta = this.proto()[META_KEY],
+ desc = meta && meta.descs[key];
Ember.assert("metaForProperty() could not find a computed property with key '"+key+"'.", !!desc && desc instanceof Ember.ComputedProperty);
return desc._meta || {};
},
@@ -20458,11 +20605,11 @@
},
deprecatedSend: function(actionName) {
var args = [].slice.call(arguments, 1);
Ember.assert('' + this + " has the action " + actionName + " but it is not a function", typeof this[actionName] === 'function');
- Ember.deprecate('Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object (' + actionName + ' on ' + this + ')', false);
+ Ember.deprecate('Action handlers implemented directly on controllers are deprecated in favor of action handlers on an `actions` object ( action: `' + actionName + '` on ' + this + ')', false);
this[actionName].apply(this, args);
return;
}
});
@@ -22237,11 +22384,11 @@
},
deprecatedSend: function(actionName) {
var args = [].slice.call(arguments, 1);
Ember.assert('' + this + " has the action " + actionName + " but it is not a function", typeof this[actionName] === 'function');
- Ember.deprecate('Action handlers implemented directly on views are deprecated in favor of action handlers on an `actions` object (' + actionName + ' on ' + this + ')', false);
+ Ember.deprecate('Action handlers implemented directly on views are deprecated in favor of action handlers on an `actions` object ( action: `' + actionName + '` on ' + this + ')', false);
this[actionName].apply(this, args);
return;
},
has: function(name) {
@@ -24529,19 +24676,16 @@
if (name !== 'value' && (type === 'string' || (type === 'number' && !isNaN(value)))) {
if (value !== elem.attr(name)) {
elem.attr(name, value);
}
} else if (name === 'value' || type === 'boolean') {
- // We can't set properties to undefined or null
- if (Ember.isNone(value)) { value = ''; }
-
- if (!value) {
+ if (Ember.isNone(value) || value === false) {
+ // `null`, `undefined` or `false` should remove attribute
elem.removeAttr(name);
- }
-
- if (value !== elem.prop(name)) {
- // value and booleans should always be properties
+ elem.prop(name, '');
+ } else if (value !== elem.prop(name)) {
+ // value should always be properties
elem.prop(name, value);
}
} else if (!value) {
elem.removeAttr(name);
}
@@ -25922,13 +26066,12 @@
this._super();
set(this, 'context', this);
set(this, 'controller', this);
},
- defaultLayout: function(options){
- options.data = {view: options._context};
- Ember.Handlebars.helpers['yield'].apply(this, [options]);
+ defaultLayout: function(context, options){
+ Ember.Handlebars.helpers['yield'].call(context, options);
},
/**
A components template property is set by passing a block
during its invocation. It is executed within the parent context.
@@ -28061,10 +28204,24 @@
function exists(value) {
return !Ember.isNone(value);
}
+function sanitizedHandlebarsGet(currentContext, property, options) {
+ var result = handlebarsGet(currentContext, property, options);
+ if (result === null || result === undefined) {
+ result = "";
+ } else if (!(result instanceof Handlebars.SafeString)) {
+ result = String(result);
+ }
+ if (!options.hash.unescaped){
+ result = Handlebars.Utils.escapeExpression(result);
+ }
+
+ return result;
+}
+
// Binds a property into the DOM. This will create a hook in DOM that the
// KVO system will look for and update if the property changes.
function bind(property, options, preserveContext, shouldDisplay, valueNormalizer, childProperties) {
var data = options.data,
fn = options.fn,
@@ -28162,13 +28319,13 @@
if (data.insideGroup) {
observer = function() {
Ember.run.once(view, 'rerender');
};
- var result = handlebarsGet(currentContext, property, options);
- if (result === null || result === undefined) { result = ""; }
- data.buffer.push(result);
+ output = sanitizedHandlebarsGet(currentContext, property, options);
+
+ data.buffer.push(output);
} else {
var bindView = new Ember._SimpleHandlebarsView(
property, currentContext, !options.hash.unescaped, options.data
);
@@ -28188,12 +28345,13 @@
view.registerObserver(normalized.root, normalized.path, observer);
}
} else {
// The object is not observable, so just render it out and
// be done with it.
- output = handlebarsGet(currentContext, property, options);
- data.buffer.push((output === null || typeof output === 'undefined') ? '' : output);
+ output = sanitizedHandlebarsGet(currentContext, property, options);
+
+ data.buffer.push(output);
}
}
function shouldDisplayIfHelperContent(result) {
var truthy = result && get(result, 'isTruthy');
@@ -32276,11 +32434,12 @@
return queryParams;
},
recognize: function(path) {
var states = [ this.rootState ],
- pathLen, i, l, queryStart, queryParams = {};
+ 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);
@@ -32292,10 +32451,11 @@
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; }
@@ -32311,10 +32471,15 @@
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);
}
}
};
@@ -32561,12 +32726,15 @@
function ResolvedHandlerInfo(props) {
HandlerInfo.call(this, props);
}
ResolvedHandlerInfo.prototype = oCreate(HandlerInfo.prototype);
- ResolvedHandlerInfo.prototype.resolve = function() {
+ ResolvedHandlerInfo.prototype.resolve = function(async, shouldContinue, payload) {
// A ResolvedHandlerInfo just resolved with itself.
+ if (payload && payload.resolvedModels) {
+ payload.resolvedModels[this.name] = this.context;
+ }
return resolve(this);
};
// These are generated by URL transitions and
// named transitions for non-dynamic route segments.
@@ -33726,23 +33894,10 @@
var handlerInfo = currentState.handlerInfos[payload.resolveIndex];
return handlerInfo.resolve(async, innerShouldContinue, payload)
.then(proceed);
}
- },
-
- getResolvedHandlerInfos: function() {
- var resolvedHandlerInfos = [];
- var handlerInfos = this.handlerInfos;
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- var handlerInfo = handlerInfos[i];
- if (!(handlerInfo instanceof ResolvedHandlerInfo)) {
- break;
- }
- resolvedHandlerInfos.push(handlerInfo);
- }
- return resolvedHandlerInfos;
}
};
__exports__.TransitionState = TransitionState;
});
@@ -36357,11 +36512,11 @@
options = options || {};
options.parentView = options.parentView ? options.parentView.replace(/\//g, '.') : parentTemplate(this);
options.outlet = options.outlet || 'main';
var parentView = this.router._lookupActiveView(options.parentView);
- parentView.disconnectOutlet(options.outlet);
+ if (parentView) { parentView.disconnectOutlet(options.outlet); }
},
willDestroy: function() {
this.teardownViews();
},
@@ -38386,9 +38541,10 @@
@private
@method _finishDisconnections
*/
_finishDisconnections: function() {
+ if (this.isDestroyed) return; // _outlets will be gone anyway
var outlets = get(this, '_outlets');
var pendingDisconnections = this._pendingDisconnections;
this._pendingDisconnections = null;
for (var outletName in pendingDisconnections) {