dist/ember.js in ember-source-1.6.0.beta.4 vs dist/ember.js in ember-source-1.6.0.beta.5

- 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.6.0-beta.4 + * @version 1.6.0-beta.5 */ (function() { var define, requireModule, require, requirejs, Ember; @@ -1872,10 +1872,11 @@ todoList.get('done'); // false todoList.get('todos').clear(); todoList.get('done'); // true ``` + @since 1.6.0 @method computed.empty @for Ember @param {String} dependentKey @return {Ember.ComputedProperty} computed property which negate the original value for property @@ -2363,11 +2364,11 @@ */ computed.alias = function(dependentKey) { return computed(dependentKey, function(key, value) { if (arguments.length > 1) { set(this, dependentKey, value); - return value; + return get(this, dependentKey); } else { return get(this, dependentKey); } }); }; @@ -2516,11 +2517,11 @@ The core Runtime framework is based on the jQuery API with a number of performance optimizations. @class Ember @static - @version 1.6.0-beta.4 + @version 1.6.0-beta.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. @@ -2543,14 +2544,14 @@ /** @property VERSION @type String - @default '1.6.0-beta.4' + @default '1.6.0-beta.5' @static */ - Ember.VERSION = '1.6.0-beta.4'; + Ember.VERSION = '1.6.0-beta.5'; /** Standard environmental variables. You can define these in a global `EmberENV` variable before loading Ember to control various configuration settings. @@ -2631,11 +2632,11 @@ // .......................................................... // BOOTSTRAP // /** - Determines whether Ember should enhances some built-in object prototypes to + Determines whether Ember should enhance some built-in object prototypes to provide a more friendly API. If enabled, a few methods will be added to `Function`, `String`, and `Array`. `Object.prototype` will not be enhanced, which is the one that causes most trouble for people. In general we recommend leaving this option set to true since it rarely @@ -3407,28 +3408,29 @@ __exports__.listenersFor = listenersFor; __exports__.listenersDiff = listenersDiff; __exports__.listenersUnion = listenersUnion; }); define("ember-metal/expand_properties", - ["ember-metal/enumerable_utils","exports"], - function(__dependency1__, __exports__) { + ["ember-metal/error","ember-metal/enumerable_utils","exports"], + function(__dependency1__, __dependency2__, __exports__) { "use strict"; - var EnumerableUtils = __dependency1__["default"]; + var EmberError = __dependency1__["default"]; + var EnumerableUtils = __dependency2__["default"]; /** @module ember-metal */ var forEach = EnumerableUtils.forEach, - BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/; + BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/; /** Expands `pattern`, invoking `callback` for each expansion. The only pattern supported is brace-expansion, anything else will be passed once to `callback` directly. Brace expansion can only appear at the end of a - pattern, for example as the last item in a chain. + pattern, for an example see the last call below. Example ```js function echo(arg){ console.log(arg); } @@ -3445,16 +3447,21 @@ expansion, and is passed the expansion. */ function expandProperties(pattern, callback) { var match, prefix, list; + if (pattern.indexOf(' ') > -1) { + throw new EmberError('Brace expanded properties cannot contain spaces, ' + + 'e.g. `user.{firstName, lastName}` should be `user.{firstName,lastName}`'); + } + if (match = BRACE_EXPANSION.exec(pattern)) { prefix = match[1]; list = match[2]; forEach(list.split(','), function (suffix) { - callback(prefix + suffix); + callback(prefix + suffix); }); } else { callback(pattern); } }; @@ -7113,38 +7120,41 @@ return apply(backburner, backburner.debounce, arguments); }; /** Ensure that the target method is never called more frequently than - the specified spacing period. + the specified spacing period. The target method is called immediately. ```javascript var myFunc = function() { console.log(this.name + ' ran.'); }; var myContext = {name: 'throttle'}; run.throttle(myContext, myFunc, 150); // myFunc is invoked with context myContext + // console logs 'throttle ran.' // 50ms passes run.throttle(myContext, myFunc, 150); // 50ms passes run.throttle(myContext, myFunc, 150); // 150ms passes run.throttle(myContext, myFunc, 150); // myFunc is invoked with context myContext - // console logs 'throttle ran.' twice, 250ms apart. + // console logs 'throttle ran.' ``` @method throttle @param {Object} [target] target of method to invoke @param {Function|String} method The method to invoke. May be a function or a string. If you pass a string then it will be looked up on the passed target. @param {Object} [args*] Optional arguments to pass to the timeout. @param {Number} spacing Number of milliseconds to space out requests. + @param {Boolean} immediate Trigger the function on the leading instead + of the trailing edge of the wait interval. Defaults to true. @return {Array} Timer information for use in cancelling, see `run.cancel`. */ run.throttle = function() { return apply(backburner, backburner.throttle, arguments); }; @@ -7591,11 +7601,11 @@ @param {Object} obj The object to test @return {Boolean} true if the passed object is an array or Array-like */ // ES6TODO: Move up to runtime? This is only use in ember-metal by concatenatedProperties function isArray(obj) { - var modulePath; + var modulePath, type; if (typeof EmberArray === "undefined") { modulePath = 'ember-runtime/mixins/array'; if (requirejs._eak_seen[modulePath]) { EmberArray = requireModule(modulePath)['default']; @@ -7603,11 +7613,14 @@ } if (!obj || obj.setInterval) { return false; } if (Array.isArray && Array.isArray(obj)) { return true; } if (EmberArray && EmberArray.detect(obj)) { return true; } - if ((obj.length !== undefined) && 'object'=== typeOf(obj)) { return true; } + + type = typeOf(obj); + if ('array' === type) { return true; } + if ((obj.length !== undefined) && 'object' === type) { return true; } return false; }; /** Forces the passed object to be part of an array. If the object is already @@ -8008,22 +8021,24 @@ __exports__.tryFinally = tryFinally; __exports__.wrap = wrap; __exports__.applyStr = applyStr; __exports__.apply = apply; }); -define("backburner", - ["backburner/deferred_action_queues","exports"], - function(__dependency1__, __exports__) { +define("backburner", + ["backburner/utils","backburner/deferred_action_queues","exports"], + function(__dependency1__, __dependency2__, __exports__) { "use strict"; - var DeferredActionQueues = __dependency1__.DeferredActionQueues; + var Utils = __dependency1__["default"]; + var DeferredActionQueues = __dependency2__.DeferredActionQueues; var slice = [].slice, pop = [].pop, - throttlers = [], - debouncees = [], + each = Utils.each, + isString = Utils.isString, + isFunction = Utils.isFunction, + isNumber = Utils.isNumber, timers = [], - autorun, laterTimer, laterTimerExpiresAt, global = this, NUMBER = /\d+/; // In IE 6-8, try/finally doesn't work without a catch. // Unfortunately, this is impossible to test for since wrapping it in a parent try/catch doesn't trigger the bug. @@ -8033,20 +8048,22 @@ catch(e) { } // jshint ignore:line return !!e; })(); function isCoercableNumber(number) { - return typeof number === 'number' || NUMBER.test(number); + return isNumber(number) || NUMBER.test(number); } function Backburner(queueNames, options) { this.queueNames = queueNames; this.options = options || {}; if (!this.options.defaultQueue) { this.options.defaultQueue = queueNames[0]; } this.instanceStack = []; + this._debouncees = []; + this._throttlers = []; } Backburner.prototype = { queueNames: null, options: null, @@ -8096,25 +8113,23 @@ } } }, run: function(target, method /*, args */) { - var options = this.options, - ret, length = arguments.length; + var onError = getOnError(this.options); this.begin(); if (!method) { method = target; target = null; } - if (typeof method === 'string') { + if (isString(method)) { method = target[method]; } - var onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]); var args = slice.call(arguments, 2); // guard against Safari 6's double-finally bug var didFinally = false; @@ -8145,11 +8160,11 @@ if (!method) { method = target; target = null; } - if (typeof method === 'string') { + if (isString(method)) { method = target[method]; } var stack = this.DEBUG ? new Error() : undefined, args = arguments.length > 3 ? slice.call(arguments, 3) : undefined; @@ -8161,38 +8176,36 @@ if (!method) { method = target; target = null; } - if (typeof method === 'string') { + if (isString(method)) { method = target[method]; } var stack = this.DEBUG ? new Error() : undefined, args = arguments.length > 3 ? slice.call(arguments, 3) : undefined; if (!this.currentInstance) { createAutorun(this); } return this.currentInstance.schedule(queueName, target, method, args, true, stack); }, setTimeout: function() { - var args = slice.call(arguments); - var length = args.length; - var method, wait, target; - var self = this; - var methodOrTarget, methodOrWait, methodOrArgs; - var options = this.options; + var args = slice.call(arguments), + length = args.length, + method, wait, target, + methodOrTarget, methodOrWait, methodOrArgs; if (length === 0) { return; } else if (length === 1) { method = args.shift(); wait = 0; } else if (length === 2) { methodOrTarget = args[0]; methodOrWait = args[1]; - if (typeof methodOrWait === 'function' || typeof methodOrTarget[methodOrWait] === 'function') { + if (isFunction(methodOrWait) || isFunction(methodOrTarget[methodOrWait])) { target = args.shift(); method = args.shift(); wait = 0; } else if (isCoercableNumber(methodOrWait)) { method = args.shift(); @@ -8211,27 +8224,27 @@ } methodOrTarget = args[0]; methodOrArgs = args[1]; - if (typeof methodOrArgs === 'function' || (typeof methodOrArgs === 'string' && - methodOrTarget !== null && - methodOrArgs in methodOrTarget)) { + if (isFunction(methodOrArgs) || (isString(methodOrArgs) && + methodOrTarget !== null && + methodOrArgs in methodOrTarget)) { target = args.shift(); method = args.shift(); } else { method = args.shift(); } } var executeAt = (+new Date()) + parseInt(wait, 10); - if (typeof method === 'string') { + if (isString(method)) { method = target[method]; } - var onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]); + var onError = getOnError(this.options); function fn() { if (onError) { try { method.apply(target, args); @@ -8246,11 +8259,11 @@ // find position to insert var i = searchTimer(executeAt, timers); timers.splice(i, 0, executeAt, fn); - updateLaterTimer(self, executeAt, wait); + updateLaterTimer(this, executeAt, wait); return fn; }, throttle: function(target, method /* , args, wait, [immediate] */) { @@ -8260,37 +8273,39 @@ wait, throttler, index, timer; - if (typeof immediate === "number" || typeof immediate === "string") { + if (isNumber(immediate) || isString(immediate)) { wait = immediate; immediate = true; } else { wait = pop.call(args); } wait = parseInt(wait, 10); - index = findThrottler(target, method); - if (index > -1) { return throttlers[index]; } // throttled + index = findThrottler(target, method, this._throttlers); + if (index > -1) { return this._throttlers[index]; } // throttled timer = global.setTimeout(function() { if (!immediate) { self.run.apply(self, args); } - var index = findThrottler(target, method); - if (index > -1) { throttlers.splice(index, 1); } + var index = findThrottler(target, method, self._throttlers); + if (index > -1) { + self._throttlers.splice(index, 1); + } }, wait); if (immediate) { self.run.apply(self, args); } throttler = [target, method, timer]; - throttlers.push(throttler); + this._throttlers.push(throttler); return throttler; }, debounce: function(target, method /* , args, wait, [immediate] */) { @@ -8300,75 +8315,73 @@ wait, index, debouncee, timer; - if (typeof immediate === "number" || typeof immediate === "string") { + if (isNumber(immediate) || isString(immediate)) { wait = immediate; immediate = false; } else { wait = pop.call(args); } wait = parseInt(wait, 10); // Remove debouncee - index = findDebouncee(target, method); + index = findDebouncee(target, method, this._debouncees); if (index > -1) { - debouncee = debouncees[index]; - debouncees.splice(index, 1); + debouncee = this._debouncees[index]; + this._debouncees.splice(index, 1); clearTimeout(debouncee[2]); } timer = global.setTimeout(function() { if (!immediate) { self.run.apply(self, args); } - var index = findDebouncee(target, method); + var index = findDebouncee(target, method, self._debouncees); if (index > -1) { - debouncees.splice(index, 1); + self._debouncees.splice(index, 1); } }, wait); if (immediate && index === -1) { self.run.apply(self, args); } debouncee = [target, method, timer]; - debouncees.push(debouncee); + self._debouncees.push(debouncee); return debouncee; }, cancelTimers: function() { - var i, len; + var clearItems = function(item) { + clearTimeout(item[2]); + }; - for (i = 0, len = throttlers.length; i < len; i++) { - clearTimeout(throttlers[i][2]); - } - throttlers = []; + each(this._throttlers, clearItems); + this._throttlers = []; - for (i = 0, len = debouncees.length; i < len; i++) { - clearTimeout(debouncees[i][2]); - } - debouncees = []; + each(this._debouncees, clearItems); + this._debouncees = []; - if (laterTimer) { - clearTimeout(laterTimer); - laterTimer = null; + if (this._laterTimer) { + clearTimeout(this._laterTimer); + this._laterTimer = null; } timers = []; - if (autorun) { - clearTimeout(autorun); - autorun = null; + if (this._autorun) { + clearTimeout(this._autorun); + this._autorun = null; } }, hasTimers: function() { - return !!timers.length || !!debouncees.length || !!throttlers.length || autorun; + return !!timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun; }, cancel: function(timer) { var timerType = typeof timer; @@ -8380,12 +8393,12 @@ timers.splice(i, 2); // remove the two elements return true; } } } else if (Object.prototype.toString.call(timer) === "[object Array]"){ // we're cancelling a throttle or debounce - return this._cancelItem(findThrottler, throttlers, timer) || - this._cancelItem(findDebouncee, debouncees, timer); + return this._cancelItem(findThrottler, this._throttlers, timer) || + this._cancelItem(findDebouncee, this._debouncees, timer); } else { return; // timer was null or not a timer } }, @@ -8393,11 +8406,11 @@ var item, index; if (timer.length < 3) { return false; } - index = findMethod(timer[0], timer[1]); + index = findMethod(timer[0], timer[1], array); if(index > -1) { item = array[index]; @@ -8416,48 +8429,47 @@ Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce; Backburner.prototype.later = Backburner.prototype.setTimeout; if (needsIETryCatchFix) { var originalRun = Backburner.prototype.run; - Backburner.prototype.run = function() { - try { - originalRun.apply(this, arguments); - } catch (e) { - throw e; - } - }; + Backburner.prototype.run = wrapInTryCatch(originalRun); var originalEnd = Backburner.prototype.end; - Backburner.prototype.end = function() { + Backburner.prototype.end = wrapInTryCatch(originalEnd); + } + + function wrapInTryCatch(func) { + return function () { try { - originalEnd.apply(this, arguments); + return func.apply(this, arguments); } catch (e) { throw e; } }; } + function getOnError(options) { + return options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]); + } + function createAutorun(backburner) { backburner.begin(); - autorun = global.setTimeout(function() { - autorun = null; + backburner._autorun = global.setTimeout(function() { + backburner._autorun = null; backburner.end(); }); } function updateLaterTimer(self, executeAt, wait) { - if (!laterTimer || executeAt < laterTimerExpiresAt) { - if (laterTimer) { - clearTimeout(laterTimer); - } - laterTimer = global.setTimeout(function() { - laterTimer = null; - laterTimerExpiresAt = null; + if (!self._laterTimer || executeAt < self._laterTimerExpiresAt) { + self._laterTimer = global.setTimeout(function() { + self._laterTimer = null; + self._laterTimerExpiresAt = null; executeTimers(self); }, wait); - laterTimerExpiresAt = executeAt; + self._laterTimerExpiresAt = executeAt; } } function executeTimers(self) { var now = +new Date(), @@ -8476,32 +8488,25 @@ if (timers.length) { updateLaterTimer(self, timers[0], timers[0] - now); } } - function findDebouncee(target, method) { - var debouncee, - index = -1; + function findDebouncee(target, method, debouncees) { + return findItem(target, method, debouncees); + } - for (var i = 0, l = debouncees.length; i < l; i++) { - debouncee = debouncees[i]; - if (debouncee[0] === target && debouncee[1] === method) { - index = i; - break; - } - } - - return index; + function findThrottler(target, method, throttlers) { + return findItem(target, method, throttlers); } - function findThrottler(target, method) { - var throttler, + function findItem(target, method, collection) { + var item, index = -1; - for (var i = 0, l = throttlers.length; i < l; i++) { - throttler = throttlers[i]; - if (throttler[0] === target && throttler[1] === method) { + for (var i = 0, l = collection.length; i < l; i++) { + item = collection[i]; + if (item[0] === target && item[1] === method) { index = i; break; } } @@ -8532,27 +8537,29 @@ return (time >= timers[start]) ? start + 2 : start; } __exports__.Backburner = Backburner; }); -define("backburner/deferred_action_queues", - ["backburner/queue","exports"], - function(__dependency1__, __exports__) { +define("backburner/deferred_action_queues", + ["backburner/utils","backburner/queue","exports"], + function(__dependency1__, __dependency2__, __exports__) { "use strict"; - var Queue = __dependency1__.Queue; + var Utils = __dependency1__["default"]; + var Queue = __dependency2__.Queue; + var each = Utils.each, + isString = Utils.isString; + function DeferredActionQueues(queueNames, options) { var queues = this.queues = {}; this.queueNames = queueNames = queueNames || []; this.options = options; - var queueName; - for (var i = 0, l = queueNames.length; i < l; i++) { - queueName = queueNames[i]; - queues[queueName] = new Queue(this, queueName, this.options); - } + each(queueNames, function(queueName) { + queues[queueName] = new Queue(this, queueName, options); + }); } DeferredActionQueues.prototype = { queueNames: null, queues: null, @@ -8619,11 +8626,11 @@ target = queueItems[queueIndex]; method = queueItems[queueIndex+1]; args = queueItems[queueIndex+2]; stack = queueItems[queueIndex+3]; // Debugging assistance - if (typeof method === 'string') { method = target[method]; } + if (isString(method)) { method = target[method]; } // method could have been nullified / canceled during flush if (method) { invoke(target, method, args, onError); } @@ -8656,11 +8663,11 @@ return -1; } __exports__.DeferredActionQueues = DeferredActionQueues; }); -define("backburner/queue", +define("backburner/queue", ["exports"], function(__exports__) { "use strict"; function Queue(daq, name, options) { this.daq = daq; @@ -8695,11 +8702,11 @@ queue[i+3] = stack; // replace stack return {queue: this, target: target, method: method}; } } - this._queue.push(target, method, args, stack); + queue.push(target, method, args, stack); return {queue: this, target: target, method: method}; }, // TODO: remove me, only being used for Ember.run.sync flush: function() { @@ -8785,10 +8792,35 @@ } }; __exports__.Queue = Queue; }); +define("backburner/utils", + ["exports"], + function(__exports__) { + "use strict"; + __exports__["default"] = { + each: function(collection, callback) { + for (var i = 0; i < collection.length; i++) { + callback(collection[i]); + } + }, + + isString: function(suspect) { + return typeof suspect === 'string'; + }, + + isFunction: function(suspect) { + return typeof suspect === 'function'; + }, + + isNumber: function(suspect) { + return typeof suspect === 'number'; + } + }; + }); + define("ember-metal/watch_key", ["ember-metal/core","ember-metal/utils","ember-metal/platform","exports"], function(__dependency1__, __dependency2__, __dependency3__, __exports__) { "use strict"; var Ember = __dependency1__["default"]; @@ -14324,11 +14356,11 @@ }, init: function() { this._super(); - this.set('_subControllers', Ember.A()); + this.set('_subControllers', [ ]); }, content: computed(function () { return Ember.A(); }), @@ -14374,17 +14406,27 @@ _subControllers: null, _resetSubControllers: function() { var subControllers = get(this, '_subControllers'); - if (subControllers) { - forEach(subControllers, function(subController) { - if (subController) { subController.destroy(); } - }); + var controller; + + if (subControllers.length) { + for (var i = 0, length = subControllers.length; length > i; i++) { + controller = subControllers[i]; + if (controller) { + controller.destroy(); + } + } + + subControllers.length = 0; } + }, - this.set('_subControllers', Ember.A()); + willDestroy: function() { + this._resetSubControllers(); + this._super(); } }); __exports__["default"] = ArrayController; }); @@ -17840,11 +17882,13 @@ @param {Ember.Enumerable} objects the objects to remove @return {Object} receiver */ removeObjects: function(objects) { beginPropertyChanges(this); - forEach(objects, function(obj) { this.removeObject(obj); }, this); + for (var i = objects.length - 1; i >= 0; i--) { + this.removeObject(objects[i]); + } endPropertyChanges(this); return this; } }); @@ -23000,11 +23044,11 @@ will be updated. @private @property elementClasses @type Array - @default [] + @default null */ elementClasses: null, /** Array of class names which will be applied in the class attribute. @@ -23012,11 +23056,11 @@ You can use `setClasses()` to set this property directly. If you use `addClass()`, it will be maintained for you. @property classes @type Array - @default [] + @default null */ classes: null, /** The id in of the element, to be applied in the id attribute. @@ -23570,32 +23614,33 @@ __exports__.setInnerHTML = setInnerHTML; __exports__.isSimpleClick = isSimpleClick; }); define("ember-views/views/collection_view", - ["ember-metal/core","ember-metal/platform","ember-metal/merge","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-views/views/container_view","ember-views/views/view","ember-metal/mixin","ember-runtime/mixins/array","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __exports__) { + ["ember-metal/core","ember-metal/platform","ember-metal/binding","ember-metal/merge","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-views/views/container_view","ember-views/views/view","ember-metal/mixin","ember-runtime/mixins/array","exports"], + function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) { "use strict"; /** @module ember @submodule ember-views */ var Ember = __dependency1__["default"]; // Ember.assert var create = __dependency2__.create; - var merge = __dependency3__["default"]; - var get = __dependency4__.get; - var set = __dependency5__.set; - var fmt = __dependency6__.fmt; - var ContainerView = __dependency7__["default"]; - var CoreView = __dependency8__.CoreView; - var View = __dependency8__.View; - var observer = __dependency9__.observer; - var beforeObserver = __dependency9__.beforeObserver; - var EmberArray = __dependency10__["default"]; + var isGlobalPath = __dependency3__.isGlobalPath; + var merge = __dependency4__["default"]; + var get = __dependency5__.get; + var set = __dependency6__.set; + var fmt = __dependency7__.fmt; + var ContainerView = __dependency8__["default"]; + var CoreView = __dependency9__.CoreView; + var View = __dependency9__.View; + var observer = __dependency10__.observer; + var beforeObserver = __dependency10__.beforeObserver; + var EmberArray = __dependency11__["default"]; /** `Ember.CollectionView` is an `Ember.View` descendent responsible for managing a collection (an array or array-like object) by maintaining a child view object and associated DOM representation for each item in the array and ensuring @@ -23919,11 +23964,11 @@ len = content ? get(content, 'length') : 0; if (len) { itemViewClass = get(this, 'itemViewClass'); - if ('string' === typeof itemViewClass) { + if ('string' === typeof itemViewClass && isGlobalPath(itemViewClass)) { itemViewClass = get(itemViewClass) || itemViewClass; } Ember.assert(fmt("itemViewClass must be a subclass of Ember.View, not %@", [itemViewClass]), @@ -23942,11 +23987,11 @@ } else { emptyView = get(this, 'emptyView'); if (!emptyView) { return; } - if ('string' === typeof emptyView) { + if ('string' === typeof emptyView && isGlobalPath(emptyView)) { emptyView = get(emptyView) || emptyView; } emptyView = this.createChildView(emptyView); addedViews.push(emptyView); @@ -24118,10 +24163,17 @@ @class Component @namespace Ember @extends Ember.View */ var Component = View.extend(TargetActionSupport, ComponentTemplateDeprecation, { + instrumentName: 'component', + instrumentDisplay: computed(function() { + if (this._debugContainerKey) { + return '{{' + this._debugContainerKey.split(':')[1] + '}}'; + } + }), + init: function() { this._super(); set(this, 'context', this); set(this, 'controller', this); }, @@ -24543,11 +24595,11 @@ }, replace: function(idx, removedCount, addedViews) { var addedCount = addedViews ? get(addedViews, 'length') : 0; var self = this; - Ember.assert("You can't add a child to a container that is already a child of another view", A(addedViews).every(function(item) { return !get(item, '_parentView') || get(item, '_parentView') === self; })); + Ember.assert("You can't add a child to a container - the child is already a child of another view", A(addedViews).every(function(item) { return !get(item, '_parentView') || get(item, '_parentView') === self; })); this.arrayContentWillChange(idx, removedCount, addedCount); this.childViewsWillChange(this._childViews, idx, removedCount); if (addedCount === 0) { @@ -25354,10 +25406,12 @@ instrumentName: 'core_view', instrumentDetails: function(hash) { hash.object = this.toString(); + hash.containerKey = this._debugContainerKey; + hash.view = this; }, /** Invoked by the view system when this view needs to produce an HTML representation. This method will create a new render buffer, if needed, @@ -26156,10 +26210,22 @@ @default null */ layoutName: null, /** + Used to identify this view during debugging + + @property instrumentDisplay + @type String + */ + instrumentDisplay: computed(function() { + if (this.helperName) { + return '{{' + this.helperName + '}}'; + } + }), + + /** The template used to render the view. This should be a function that accepts an optional context parameter and returns a string of HTML that will be inserted into the DOM relative to its parent view. In general, you should set the `templateName` property instead of setting @@ -28739,12 +28805,12 @@ ## Extension Internally, `{{input type="text"}}` creates an instance of `Ember.TextField`, passing arguments from the helper to `Ember.TextField`'s `create` method. You can extend the - capablilties of text inputs in your applications by reopening this class. For example, - if you are building a Bootstrap 3 project where `data-*` attributes are used, you + 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({ @@ -28977,19 +29043,19 @@ ## 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 deploying to browsers where the `required` - attribute is used, you can globally add support for the `required` attribute + 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: ['required'] + attributeBindings: ['data-error'] }); ``` Keep in mind when writing `Ember.TextArea` subclasses that `Ember.TextArea` itself extends `Ember.Component`, meaning that it does NOT inherit @@ -29049,10 +29115,12 @@ @class Checkbox @namespace Ember @extends Ember.View */ var Checkbox = View.extend({ + instrumentDisplay: '{{input type="checkbox"}}', + classNames: ['ember-checkbox'], tagName: 'input', attributeBindings: ['type', 'checked', 'indeterminate', 'disabled', 'tabindex', 'name', @@ -29109,10 +29177,12 @@ forEach = EnumerableUtils.forEach, replace = EnumerableUtils.replace, precompileTemplate = EmberHandlebars.compile; var SelectOption = View.extend({ + instrumentDisplay: 'Ember.SelectOption', + tagName: 'option', attributeBindings: ['value', 'selected'], defaultTemplate: function(context, options) { options = { data: options.data, hash: {} }; @@ -29158,10 +29228,12 @@ }).property(valuePath)); }) }); var SelectOptgroup = CollectionView.extend({ + instrumentDisplay: 'Ember.SelectOptgroup', + tagName: 'optgroup', attributeBindings: ['label'], selectionBinding: 'parentView.selection', multipleBinding: 'parentView.multiple', @@ -29188,11 +29260,11 @@ the inner text of each `<option>` element inside the rendered `<select>`. Example: ```javascript - App.ApplicationController = Ember.Controller.extend({ + App.ApplicationController = Ember.ObjectController.extend({ names: ["Yehuda", "Tom"] }); ``` ```handlebars @@ -29210,11 +29282,11 @@ You can control which `<option>` is selected through the `Ember.Select`'s `value` property: ```javascript - App.ApplicationController = Ember.Controller.extend({ + App.ApplicationController = Ember.ObjectController.extend({ selectedName: 'Tom', names: ["Yehuda", "Tom"] }); ``` @@ -29250,11 +29322,11 @@ the desired property for the `value` attribute. The `optionLabelPath` specifies the path on each object to the desired property for the element's text. Both paths must reference each object itself as `content`: ```javascript - App.ApplicationController = Ember.Controller.extend({ + App.ApplicationController = Ember.ObjectController.extend({ programmers: [ {firstName: "Yehuda", id: 1}, {firstName: "Tom", id: 2} ] }); @@ -29278,11 +29350,11 @@ The `value` attribute of the selected `<option>` within an `Ember.Select` can be bound to a property on another object: ```javascript - App.ApplicationController = Ember.Controller.extend({ + App.ApplicationController = Ember.ObjectController.extend({ programmers: [ {firstName: "Yehuda", id: 1}, {firstName: "Tom", id: 2} ], currentProgrammer: { @@ -29317,15 +29389,19 @@ `<option>` is changed, the property path provided to `selection` will be updated to match the content object of the rendered `<option>` element: ```javascript - App.ApplicationController = Ember.Controller.extend({ - selectedPerson: null, + + var yehuda = {firstName: "Yehuda", id: 1, bff4eva: 'tom'} + var tom = {firstName: "Tom", id: 2, bff4eva: 'yehuda'}; + + App.ApplicationController = Ember.ObjectController.extend({ + selectedPerson: tom, programmers: [ - {firstName: "Yehuda", id: 1}, - {firstName: "Tom", id: 2} + yehuda, + tom ] }); ``` ```handlebars @@ -29354,11 +29430,11 @@ A `null` value for the `Ember.Select`'s `value` or `selection` property results in there being no `<option>` with a `selected` attribute: ```javascript - App.ApplicationController = Ember.Controller.extend({ + App.ApplicationController = Ember.ObjectController.extend({ selectedProgrammer: null, programmers: [ "Yehuda", "Tom" ] @@ -29386,11 +29462,11 @@ first item as though it were selected. You can supply a string value for the `Ember.Select` to display when there is no selection with the `prompt` option: ```javascript - App.ApplicationController = Ember.Controller.extend({ + App.ApplicationController = Ember.ObjectController.extend({ selectedProgrammer: null, programmers: [ "Yehuda", "Tom" ] @@ -29418,10 +29494,12 @@ @class Select @namespace Ember @extends Ember.View */ var Select = View.extend({ + instrumentDisplay: 'Ember.Select', + tagName: 'select', classNames: ['ember-select'], defaultTemplate: Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; @@ -29794,10 +29872,12 @@ @namespace Ember @extends Ember.Component @uses Ember.TextSupport */ var TextArea = Component.extend(TextSupport, { + instrumentDisplay: '{{textarea}}', + classNames: ['ember-text-area'], tagName: "textarea", attributeBindings: ['rows', 'cols', 'name', 'selectionEnd', 'selectionStart', 'wrap'], rows: null, @@ -29852,10 +29932,11 @@ @namespace Ember @extends Ember.Component @uses Ember.TextSupport */ var TextField = Component.extend(TextSupport, { + instrumentDisplay: '{{input type="text"}}', classNames: ['ember-text-field'], tagName: "input", attributeBindings: ['type', 'value', 'size', 'pattern', 'name', 'min', 'max', 'accept', 'autocomplete', 'autosave', 'formaction', @@ -30672,11 +30753,11 @@ __exports__.evaluateUnboundHelper = evaluateUnboundHelper; __exports__.helperMissingHelper = helperMissingHelper; __exports__.blockHelperMissingHelper = blockHelperMissingHelper; }); define("ember-handlebars/helpers/binding", - ["ember-metal/core","ember-handlebars-compiler","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-metal/platform","ember-metal/is_none","ember-metal/enumerable_utils","ember-metal/array","ember-views/views/view","ember-metal/run_loop","ember-handlebars/views/handlebars_bound_view","ember-metal/observer","ember-metal/binding","ember-metal/utils","ember-views/system/jquery","ember-handlebars/ext","ember-runtime/keys","exports"], + ["ember-metal/core","ember-handlebars-compiler","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/string","ember-metal/utils","ember-metal/platform","ember-metal/is_none","ember-metal/enumerable_utils","ember-metal/array","ember-views/views/view","ember-metal/run_loop","ember-handlebars/views/handlebars_bound_view","ember-metal/observer","ember-metal/binding","ember-views/system/jquery","ember-handlebars/ext","ember-runtime/keys","exports"], function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __exports__) { "use strict"; /** @module ember @submodule ember-handlebars @@ -30691,35 +30772,86 @@ var SafeString = EmberHandlebars.SafeString; var get = __dependency3__.get; var set = __dependency4__.set; var fmt = __dependency5__.fmt; - var o_create = __dependency6__.create; - var isNone = __dependency7__["default"]; - var EnumerableUtils = __dependency8__["default"]; - var forEach = __dependency9__.forEach; - var View = __dependency10__.View; - var run = __dependency11__["default"]; - var _HandlebarsBoundView = __dependency12__._HandlebarsBoundView; - var SimpleHandlebarsView = __dependency12__.SimpleHandlebarsView; - var removeObserver = __dependency13__.removeObserver; - var isGlobalPath = __dependency14__.isGlobalPath; - var emberBind = __dependency14__.bind; - var guidFor = __dependency15__.guidFor; - var typeOf = __dependency15__.typeOf; + var apply = __dependency6__.apply; + var o_create = __dependency7__.create; + var isNone = __dependency8__["default"]; + var EnumerableUtils = __dependency9__["default"]; + var forEach = __dependency10__.forEach; + var View = __dependency11__.View; + var run = __dependency12__["default"]; + var _HandlebarsBoundView = __dependency13__._HandlebarsBoundView; + var SimpleHandlebarsView = __dependency13__.SimpleHandlebarsView; + var removeObserver = __dependency14__.removeObserver; + var isGlobalPath = __dependency15__.isGlobalPath; + var emberBind = __dependency15__.bind; + var guidFor = __dependency6__.guidFor; + var typeOf = __dependency6__.typeOf; var jQuery = __dependency16__["default"]; - var isArray = __dependency15__.isArray; + var isArray = __dependency6__.isArray; var normalizePath = __dependency17__.normalizePath; var handlebarsGet = __dependency17__.handlebarsGet; var getEscaped = __dependency17__.getEscaped; var handlebarsGetEscaped = __dependency17__.getEscaped; var keys = __dependency18__["default"]; function exists(value) { return !isNone(value); } + var WithView = _HandlebarsBoundView.extend({ + init: function() { + var controller; + + apply(this, this._super, arguments); + + var keywords = this.templateData.keywords; + var keywordName = this.templateHash.keywordName; + var keywordPath = this.templateHash.keywordPath; + var controllerName = this.templateHash.controller; + var preserveContext = this.preserveContext; + + if (controllerName) { + var previousContext = this.previousContext; + controller = this.container.lookupFactory('controller:'+controllerName).create({ + parentController: previousContext, + target: previousContext + }); + + this._generatedController = controller; + + if (!preserveContext) { + this.set('controller', controller); + + this.valueNormalizerFunc = function(result) { + controller.set('model', result); + return controller; + }; + } else { + var controllerPath = jQuery.expando + guidFor(controller); + keywords[controllerPath] = controller; + emberBind(keywords, controllerPath + '.model', keywordPath); + keywordPath = controllerPath; + } + } + + if (preserveContext) { + emberBind(keywords, keywordName, keywordPath); + } + + }, + willDestroy: function() { + this._super(); + + if (this._generatedController) { + this._generatedController.destroy(); + } + } + }); + // Binds a property into the DOM. This will create a hook in DOM that the // KVO system will look for and update if the property changes. function bind(property, options, preserveContext, shouldDisplay, valueNormalizer, childProperties) { var data = options.data, fn = options.fn, @@ -30752,34 +30884,35 @@ template = inverse; } template(context, { data: options.data }); } else { - // Create the view that will wrap the output of this template/property - // and add it to the nearest view's childViews array. - // See the documentation of Ember._HandlebarsBoundView for more. - var bindView = view.createChildView(Ember._HandlebarsBoundView, { + var viewClass = _HandlebarsBoundView; + var viewOptions = { preserveContext: preserveContext, shouldDisplayFunc: shouldDisplay, valueNormalizerFunc: valueNormalizer, displayTemplate: fn, inverseTemplate: inverse, path: property, pathRoot: currentContext, previousContext: currentContext, isEscaped: !options.hash.unescaped, - templateData: options.data - }); + templateData: options.data, + templateHash: options.hash, + helperName: options.helperName + }; - if (options.hash.controller) { - bindView.set('_contextController', this.container.lookupFactory('controller:'+options.hash.controller).create({ - container: currentContext.container, - parentController: currentContext, - target: currentContext - })); + if (options.isWithHelper) { + viewClass = WithView; } + // Create the view that will wrap the output of this template/property + // and add it to the nearest view's childViews array. + // See the documentation of Ember._HandlebarsBoundView for more. + var bindView = view.createChildView(viewClass, viewOptions); + view.appendChild(bindView); observer = function() { run.scheduleOnce('render', bindView, 'rerenderIfNeeded'); }; @@ -30956,10 +31089,12 @@ if (!options.fn) { return simpleBind(context, property, options); } + options.helperName = 'bind'; + return bind.call(context, property, options, false, exists); } /** Use the `boundIf` helper to create a conditional that re-evaluates @@ -30979,10 +31114,12 @@ @return {String} HTML string */ function boundIfHelper(property, fn) { var context = (fn.contexts && fn.contexts.length) ? fn.contexts[0] : this; + fn.helperName = fn.helperName || 'boundIf'; + return bind.call(context, property, fn, true, shouldDisplayIfHelperContent, shouldDisplayIfHelperContent, ['isTruthy', 'length']); } /** @@ -31097,18 +31234,24 @@ @param {Function} context @param {Hash} options @return {String} HTML string */ function withHelper(context, options) { + var bindContext, preserveContext, controller, helperName = 'with'; + if (arguments.length === 4) { var keywordName, path, rootPath, normalized, contextPath; Ember.assert("If you pass more than one argument to the with helper, it must be in the form #with foo as bar", arguments[1] === "as"); options = arguments[3]; keywordName = arguments[2]; path = arguments[0]; + if (path) { + helperName += ' ' + path + ' as ' + keywordName; + } + Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop); var localizedOptions = o_create(options); localizedOptions.data = o_create(options.data); localizedOptions.data.keywords = o_create(options.data.keywords || {}); @@ -31126,21 +31269,31 @@ localizedOptions.data.keywords[contextKey] = rootPath; // if the path is '' ("this"), just bind directly to the current context contextPath = path ? contextKey + '.' + path : contextKey; } - emberBind(localizedOptions.data.keywords, keywordName, contextPath); + localizedOptions.hash.keywordName = keywordName; + localizedOptions.hash.keywordPath = contextPath; - return bind.call(this, path, localizedOptions, true, exists); + bindContext = this; + context = path; + options = localizedOptions; + preserveContext = true; } else { Ember.assert("You must pass exactly one argument to the with helper", arguments.length === 2); Ember.assert("You must pass a block to the with helper", options.fn && options.fn !== Handlebars.VM.noop); - return helpers.bind.call(options.contexts[0], context, options); + + helperName += ' ' + context; + bindContext = options.contexts[0]; + preserveContext = false; } - } + options.helperName = helperName; + options.isWithHelper = true; + return bind.call(bindContext, context, options, preserveContext, exists); + } /** See [boundIf](/api/classes/Ember.Handlebars.helpers.html#method_boundIf) and [unboundIf](/api/classes/Ember.Handlebars.helpers.html#method_unboundIf) @method if @@ -31150,10 +31303,13 @@ @return {String} HTML string */ function ifHelper(context, options) { Ember.assert("You must pass exactly one argument to the if helper", arguments.length === 2); Ember.assert("You must pass a block to the if helper", options.fn && options.fn !== Handlebars.VM.noop); + + options.helperName = options.helperName || ('if ' + context); + if (options.data.isUnbound) { return helpers.unboundIf.call(options.contexts[0], context, options); } else { return helpers.boundIf.call(options.contexts[0], context, options); } @@ -31168,15 +31324,21 @@ */ function unlessHelper(context, options) { Ember.assert("You must pass exactly one argument to the unless helper", arguments.length === 2); Ember.assert("You must pass a block to the unless helper", options.fn && options.fn !== Handlebars.VM.noop); - var fn = options.fn, inverse = options.inverse; + var fn = options.fn, inverse = options.inverse, helperName = 'unless'; + if (context) { + helperName += ' ' + context; + } + options.fn = inverse; options.inverse = fn; + options.helperName = options.helperName || helperName; + if (options.data.isUnbound) { return helpers.unboundIf.call(options.contexts[0], context, options); } else { return helpers.boundIf.call(options.contexts[0], context, options); } @@ -31789,10 +31951,12 @@ } var viewOptions = ViewHelper.propertiesFromHTMLOptions({ data: data, hash: itemHash }, this); hash.itemViewClass = itemViewClass.extend(viewOptions); + options.helperName = options.helperName || 'collection'; + return helpers.view.call(this, collectionClass, options); } __exports__["default"] = collectionHelper; }); @@ -31901,12 +32065,12 @@ __exports__.logHelper = logHelper; __exports__.debuggerHelper = debuggerHelper; }); define("ember-handlebars/helpers/each", - ["ember-metal/core","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-metal/property_set","ember-handlebars/views/metamorph_view","ember-views/views/collection_view","ember-metal/binding","ember-runtime/controllers/controller","ember-runtime/controllers/array_controller","ember-runtime/mixins/array","ember-runtime/copy","ember-metal/run_loop","ember-metal/observer","ember-metal/events","ember-handlebars/ext","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) { + ["ember-metal/core","ember-handlebars-compiler","ember-runtime/system/string","ember-metal/property_get","ember-metal/property_set","ember-handlebars/views/metamorph_view","ember-views/views/collection_view","ember-metal/binding","ember-runtime/controllers/controller","ember-runtime/controllers/array_controller","ember-runtime/mixins/array","ember-runtime/copy","ember-metal/run_loop","ember-metal/observer","ember-metal/events","ember-handlebars/ext","ember-metal/computed","exports"], + function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __exports__) { "use strict"; /** @module ember @submodule ember-handlebars @@ -31934,14 +32098,17 @@ var addObserver = __dependency14__.addObserver; var removeObserver = __dependency14__.removeObserver; var addBeforeObserver = __dependency14__.addBeforeObserver; var removeBeforeObserver = __dependency14__.removeBeforeObserver; var on = __dependency15__.on; + var handlebarsGet = __dependency16__.handlebarsGet; + var computed = __dependency17__.computed; var handlebarsGet = __dependency16__.handlebarsGet; var EachView = CollectionView.extend(_Metamorph, { + init: function() { var itemController = get(this, 'itemController'); var binding; if (itemController) { @@ -32330,35 +32497,43 @@ @param [options.itemViewClass] {String} a path to a view class used for each item @param [options.itemController] {String} name of a controller to be created for each item @param [options.groupedRows] {boolean} enable normal item-by-item rendering when inside a `#group` helper */ function eachHelper(path, options) { - var ctx; + var ctx, helperName = 'each'; if (arguments.length === 4) { Ember.assert("If you pass more than one argument to the each helper, it must be in the form #each foo in bar", arguments[1] === "in"); var keywordName = arguments[0]; + options = arguments[3]; path = arguments[2]; + + helperName += ' ' + keywordName + ' in ' + path; + if (path === '') { path = "this"; } options.hash.keyword = keywordName; - } - if (arguments.length === 1) { + } else if (arguments.length === 1) { options = path; path = 'this'; + } else { + helperName += ' ' + path; } options.hash.dataSourceBinding = path; // Set up emptyView as a metamorph with no tag //options.hash.emptyViewClass = Ember._MetamorphView; // can't rely on this default behavior when use strict ctx = this || window; + + options.helperName = options.helperName || helperName; + if (options.data.insideGroup && !options.hash.groupedRows && !options.hash.itemViewClass) { new GroupedEach(ctx, path, options).render(); } else { // ES6TODO: figure out how to do this without global lookup. return helpers.collection.call(ctx, 'Ember.Handlebars.EachView', options); @@ -32482,10 +32657,12 @@ function partialHelper(name, options) { var context = (options.contexts && options.contexts.length) ? options.contexts[0] : this; + options.helperName = options.helperName || 'partial'; + if (options.types[0] === "ID") { // Helper was passed a property path; we need to // create a binding that will re-render whenever // this property changes. options.fn = function(context, fnOptions) { @@ -32602,10 +32779,13 @@ @for Ember.Handlebars.helpers @param {String} templateName the template to render */ function templateHelper(name, options) { Ember.deprecate("The `template` helper has been deprecated in favor of the `partial` helper. Please use `partial` instead, which will work the same way."); + + options.helperName = options.helperName || 'template'; + return helpers.partial.apply(this, arguments); } __exports__["default"] = templateHelper; }); @@ -32873,10 +33053,15 @@ // no specified controller. See View#_context for more information. if (!newViewProto.controller && !newViewProto.controllerBinding && !viewOptions.controller && !viewOptions.controllerBinding) { viewOptions._context = thisContext; } + // for instrumentation + if (options.helperName) { + viewOptions.helperName = options.helperName; + } + currentView.appendChild(newView, viewOptions); } }); /** @@ -33052,10 +33237,12 @@ if (path && path.data && path.data.isRenderData) { options = path; path = "Ember.View"; } + options.helperName = options.helperName || 'view'; + return ViewHelper.helper(this, path, options); } __exports__.ViewHelper = ViewHelper; __exports__.viewHelper = viewHelper; @@ -33466,12 +33653,12 @@ } __exports__["default"] = htmlSafe; }); define("ember-handlebars/views/handlebars_bound_view", - ["ember-handlebars-compiler","ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/merge","ember-metal/run_loop","ember-views/views/view","ember-views/views/states","ember-handlebars/views/metamorph_view","ember-handlebars/ext","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __exports__) { + ["ember-handlebars-compiler","ember-metal/core","ember-metal/error","ember-metal/property_get","ember-metal/property_set","ember-metal/merge","ember-metal/run_loop","ember-metal/computed","ember-views/views/view","ember-views/views/states","ember-handlebars/views/metamorph_view","ember-handlebars/ext","exports"], + function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __exports__) { "use strict"; /*globals Handlebars */ /*jshint newcap:false*/ @@ -33493,17 +33680,18 @@ var EmberError = __dependency3__["default"]; var get = __dependency4__.get; var set = __dependency5__.set; var merge = __dependency6__["default"]; var run = __dependency7__["default"]; - var View = __dependency8__.View; - var cloneStates = __dependency9__.cloneStates; - var states = __dependency9__.states; + var computed = __dependency8__.computed; + var View = __dependency9__.View; + var cloneStates = __dependency10__.cloneStates; + var states = __dependency10__.states; var viewStates = states; - var _MetamorphView = __dependency10__._MetamorphView; - var handlebarsGet = __dependency11__.handlebarsGet; + var _MetamorphView = __dependency11__._MetamorphView; + var handlebarsGet = __dependency12__.handlebarsGet; function SimpleHandlebarsView(path, pathRoot, isEscaped, templateData) { this.path = path; this.pathRoot = pathRoot; this.isEscaped = isEscaped; @@ -33634,12 +33822,12 @@ @namespace Ember @extends Ember._MetamorphView @private */ var _HandlebarsBoundView = _MetamorphView.extend({ - instrumentName: 'boundHandlebars', states: states, + instrumentName: 'boundHandlebars', /** The function used to determine if the `displayTemplate` or `inverseTemplate` should be rendered. This should be a function that takes a value and returns a Boolean. @@ -33767,12 +33955,10 @@ var shouldDisplay = get(this, 'shouldDisplayFunc'), preserveContext = get(this, 'preserveContext'), context = get(this, 'previousContext'); - var _contextController = get(this, '_contextController'); - var inverseTemplate = get(this, 'inverseTemplate'), displayTemplate = get(this, 'displayTemplate'); var result = this.normalizedValue(); this._lastNormalizedValue = result; @@ -33788,14 +33974,10 @@ set(this, '_context', context); } else { // Otherwise, determine if this is a block bind or not. // If so, pass the specified object to the template if (displayTemplate) { - if (_contextController) { - set(_contextController, 'content', result); - result = _contextController; - } set(this, '_context', result); } else { // This is not a bind block, just push the result of the // expression to the render context and return. if (result === null || result === undefined) { @@ -35559,10 +35741,12 @@ context: this, options: options, params: params }; + options.helperName = options.helperName || 'link-to'; + return viewHelper.call(this, LinkView, options); }; @@ -35707,10 +35891,12 @@ viewClass = viewName ? container.lookupFactory(viewFullName) : options.hash.viewClass || OutletView; options.data.view.set('outletSource', outletSource); options.hash.currentViewBinding = '_view.outletSource._outlets.' + property; + options.helperName = options.helperName || 'outlet'; + return viewHelper.call(this, viewClass, options); }; __exports__.outletHelper = outletHelper; __exports__.OutletView = OutletView; @@ -35890,10 +36076,12 @@ if (router && !context) { router._connectActiveView(name, view); } + options.helperName = options.helperName || ('render "' + name + '"'); + viewHelper.call(this, view, options); }; __exports__["default"] = renderHelper; }); @@ -36199,30 +36387,33 @@ @private This property is used by router:main to know whether to cancel the routing setup process, which is needed while we redirect the browser. + @since 1.5.1 @property cancelRouterSetup @default false */ cancelRouterSetup: false, /** @private Will be pre-pended to path upon state change. + @since 1.5.1 @property rootURL @default '/' */ rootURL: '/', /** @private Attached for mocking in tests + @since 1.5.1 @property _window @default window */ _window: window, @@ -36239,40 +36430,44 @@ /** @private Attached for mocking in tests + @since 1.5.1 @property _history @default window.history */ _history: window.history, /** @private Attached for mocking in tests + @since 1.5.1 @property _HistoryLocation @default Ember.HistoryLocation */ _HistoryLocation: HistoryLocation, /** @private Attached for mocking in tests + @since 1.5.1 @property _HashLocation @default Ember.HashLocation */ _HashLocation: HashLocation, /** @private Attached for mocking in tests + @since 1.5.1 @property _NoneLocation @default Ember.NoneLocation */ _NoneLocation: NoneLocation, @@ -36351,10 +36546,11 @@ _replacePath: function (path) { this._location.replace(this._getOrigin() + path); }, /** + @since 1.5.1 @private @method _getRootURL */ _getRootURL: function () { return this.rootURL; @@ -36380,19 +36576,21 @@ /** @private Returns normalized location.hash as an alias to Ember.Location._getHash + @since 1.5.1 @method _getHash */ _getHash: EmberLocation._getHash, /** @private Returns location.search + @since 1.5.1 @method _getQuery */ _getQuery: function () { return this._location.search; }, @@ -36577,10 +36775,11 @@ /** @private Returns normalized location.hash + @since 1.5.1 @method getHash */ getHash: EmberLocation._getHash, /** @@ -37402,131 +37601,10 @@ @since 1.4.0 */ controllerName: null, /** - The collection of functions, keyed by name, available on this route 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 `Route#send` - or `Controller#send`. - - The `actions` hash will inherit action handlers from - the `actions` hash defined on extended Route 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 route's action handler, the value of the `this` context - is the Route object: - - ```js - App.SongRoute = Ember.Route.extend({ - actions: { - myAction: function() { - this.controllerFor("song"); - this.transitionTo("other.route"); - ... - } - } - }); - ``` - - It is also possible to call `this._super()` from within an - action handler if it overrides a handler defined on a parent - class or mixin: - - Take for example the following routes: - - ```js - App.DebugRoute = Ember.Mixin.create({ - actions: { - debugRouteInformation: function() { - console.debug("trololo"); - } - } - }); - - App.AnnoyingDebugRoute = Ember.Route.extend(App.DebugRoute, { - actions: { - debugRouteInformation: function() { - // also call the debugRouteInformation of mixed in App.DebugRoute - this._super(); - - // show additional annoyance - window.alert(...); - } - } - }); - ``` - - ## Bubbling - - By default, an action will stop bubbling once a handler defined - on the `actions` hash handles it. To continue bubbling the action, - you must return `true` from the handler: - - ```js - App.Router.map(function() { - this.resource("album", function() { - this.route("song"); - }); - }); - - App.AlbumRoute = Ember.Route.extend({ - actions: { - startPlaying: function() { - } - } - }); - - App.AlbumSongRoute = Ember.Route.extend({ - actions: { - startPlaying: function() { - // ... - - if (actionShouldAlsoBeTriggeredOnParentRoute) { - return true; - } - } - } - }); - ``` - - ## Built-in actions - - There are a few built-in actions pertaining to transitions that you - can use to customize transition behavior: `willTransition` and - `error`. - - ### `willTransition` - 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. @@ -37553,12 +37631,68 @@ 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()`. - ### `error` + @event willTransition + @param {Transition} transition + */ + /** + The `didTransition` action is fired after a transition has + successfully been completed. This occurs after the normal model + hooks (`beforeModel`, `model`, `afterModel`, `setupController`) + have resolved. The `didTransition` action has no arguments, + however, it can be useful for tracking page views or resetting + state on the controller. + + ```js + App.LoginRoute = Ember.Route.extend({ + actions: { + didTransition: function() { + this.controller.get('errors.base').clear(); + return true; // Bubble the didTransition event + } + } + }); + ``` + + @event didTransition + @since 1.2.0 + */ + + /** + The `loading` action is fired on the route when a route's `model` + hook returns a promise that is not already resolved. The current + `Transition` object is the first parameter and the route that + triggered the loading event is the second parameter. + + ```js + App.ApplicationRoute = Ember.Route.extend({ + actions: { + loading: function(transition, route) { + var view = Ember.View.create({ + classNames: ['app-loading'] + }) + .append(); + + this.router.one('didTransition', function () { + view.destroy(); + }); + return true; // Bubble the loading event + } + } + }); + ``` + + @event loading + @param {Transition} transition + @param {Ember.Route} route The route that triggered the loading event + @since 1.2.0 + */ + + /** When attempting to transition into a route, any of the hooks may return a promise that rejects, at which point an `error` action will be fired on the partially-entered routes, allowing for per-route error handling logic, or shared error handling logic defined on a parent route. @@ -37603,15 +37737,42 @@ this.controllerFor('banner').displayError(error.message); } } }); ``` + @event error + @param {Error} error + @param {Transition} transition + */ - @property actions - @type Hash - @default null + /** + The controller associated with this route. + + Example + + ```javascript + App.FormRoute = Ember.Route.extend({ + actions: { + willTransition: function(transition) { + if (this.controller.get('userHasEnteredData') && + !confirm("Are you sure you want to abandon progress?")) { + transition.abort(); + } else { + // Bubble the `willTransition` action so that + // parent routes can decide whether or not to abort. + return true; + } + } + } + }); + ``` + + @property controller + @type Ember.Controller + @since 1.6.0 */ + _actions: { queryParamsDidChange: function(changed, totalPresent, removed) { }, @@ -38009,11 +38170,11 @@ resolved. ```js App.PostsRoute = Ember.Route.extend({ afterModel: function(posts, transition) { - if (posts.length === 1) { - this.transitionTo('post.show', posts[0]); + if (posts.get('length') === 1) { + this.transitionTo('post.show', posts.get('firstObject')); } } }); ```