dist/ember.prod.js in ember-source-2.6.1 vs dist/ember.prod.js in ember-source-2.6.2

- old
+ new

@@ -4,11 +4,11 @@ * @copyright Copyright 2011-2016 Tilde Inc. and contributors * Portions Copyright 2006-2011 Strobe Inc. * Portions Copyright 2008-2011 Apple Inc. All rights reserved. * @license Licensed under MIT license * See https://raw.github.com/emberjs/ember.js/master/LICENSE - * @version 2.6.1 + * @version 2.6.2 */ var enifed, requireModule, require, Ember; var mainContext = this; @@ -111,393 +111,10 @@ enifed = Ember.__loader.define; require = requireModule = Ember.__loader.require; } })(); -enifed("backburner/binary-search", ["exports"], function (exports) { - "use strict"; - - exports.default = binarySearch; - - function binarySearch(time, timers) { - var start = 0; - var end = timers.length - 2; - var middle, l; - - while (start < end) { - // since timers is an array of pairs 'l' will always - // be an integer - l = (end - start) / 2; - - // compensate for the index in case even number - // of pairs inside timers - middle = start + l - l % 2; - - if (time >= timers[middle]) { - start = middle + 2; - } else { - end = middle; - } - } - - return time >= timers[start] ? start + 2 : start; - } -}); -enifed('backburner/deferred-action-queues', ['exports', 'backburner/utils', 'backburner/queue'], function (exports, _backburnerUtils, _backburnerQueue) { - 'use strict'; - - exports.default = DeferredActionQueues; - - function DeferredActionQueues(queueNames, options) { - var queues = this.queues = {}; - this.queueNames = queueNames = queueNames || []; - - this.options = options; - - _backburnerUtils.each(queueNames, function (queueName) { - queues[queueName] = new _backburnerQueue.default(queueName, options[queueName], options); - }); - } - - function noSuchQueue(name) { - throw new Error('You attempted to schedule an action in a queue (' + name + ') that doesn\'t exist'); - } - - function noSuchMethod(name) { - throw new Error('You attempted to schedule an action in a queue (' + name + ') for a method that doesn\'t exist'); - } - - DeferredActionQueues.prototype = { - schedule: function (name, target, method, args, onceFlag, stack) { - var queues = this.queues; - var queue = queues[name]; - - if (!queue) { - noSuchQueue(name); - } - - if (!method) { - noSuchMethod(name); - } - - if (onceFlag) { - return queue.pushUnique(target, method, args, stack); - } else { - return queue.push(target, method, args, stack); - } - }, - - flush: function () { - var queues = this.queues; - var queueNames = this.queueNames; - var queueName, queue; - var queueNameIndex = 0; - var numberOfQueues = queueNames.length; - - while (queueNameIndex < numberOfQueues) { - queueName = queueNames[queueNameIndex]; - queue = queues[queueName]; - - var numberOfQueueItems = queue._queue.length; - - if (numberOfQueueItems === 0) { - queueNameIndex++; - } else { - queue.flush(false /* async */); - queueNameIndex = 0; - } - } - } - }; -}); -enifed('backburner/platform', ['exports'], function (exports) { - 'use strict'; - - var GlobalContext; - - /* global self */ - if (typeof self === 'object') { - GlobalContext = self; - - /* global global */ - } else if (typeof global === 'object') { - GlobalContext = global; - - /* global window */ - } else if (typeof window === 'object') { - GlobalContext = window; - } else { - throw new Error('no global: `self`, `global` nor `window` was found'); - } - - exports.default = GlobalContext; -}); -enifed('backburner/queue', ['exports', 'backburner/utils'], function (exports, _backburnerUtils) { - 'use strict'; - - exports.default = Queue; - - function Queue(name, options, globalOptions) { - this.name = name; - this.globalOptions = globalOptions || {}; - this.options = options; - this._queue = []; - this.targetQueues = {}; - this._queueBeingFlushed = undefined; - } - - Queue.prototype = { - push: function (target, method, args, stack) { - var queue = this._queue; - queue.push(target, method, args, stack); - - return { - queue: this, - target: target, - method: method - }; - }, - - pushUniqueWithoutGuid: function (target, method, args, stack) { - var queue = this._queue; - - for (var i = 0, l = queue.length; i < l; i += 4) { - var currentTarget = queue[i]; - var currentMethod = queue[i + 1]; - - if (currentTarget === target && currentMethod === method) { - queue[i + 2] = args; // replace args - queue[i + 3] = stack; // replace stack - return; - } - } - - queue.push(target, method, args, stack); - }, - - targetQueue: function (targetQueue, target, method, args, stack) { - var queue = this._queue; - - for (var i = 0, l = targetQueue.length; i < l; i += 2) { - var currentMethod = targetQueue[i]; - var currentIndex = targetQueue[i + 1]; - - if (currentMethod === method) { - queue[currentIndex + 2] = args; // replace args - queue[currentIndex + 3] = stack; // replace stack - return; - } - } - - targetQueue.push(method, queue.push(target, method, args, stack) - 4); - }, - - pushUniqueWithGuid: function (guid, target, method, args, stack) { - var hasLocalQueue = this.targetQueues[guid]; - - if (hasLocalQueue) { - this.targetQueue(hasLocalQueue, target, method, args, stack); - } else { - this.targetQueues[guid] = [method, this._queue.push(target, method, args, stack) - 4]; - } - - return { - queue: this, - target: target, - method: method - }; - }, - - pushUnique: function (target, method, args, stack) { - var KEY = this.globalOptions.GUID_KEY; - - if (target && KEY) { - var guid = target[KEY]; - if (guid) { - return this.pushUniqueWithGuid(guid, target, method, args, stack); - } - } - - this.pushUniqueWithoutGuid(target, method, args, stack); - - return { - queue: this, - target: target, - method: method - }; - }, - - invoke: function (target, method, args, _, _errorRecordedForStack) { - if (args && args.length > 0) { - method.apply(target, args); - } else { - method.call(target); - } - }, - - invokeWithOnError: function (target, method, args, onError, errorRecordedForStack) { - try { - if (args && args.length > 0) { - method.apply(target, args); - } else { - method.call(target); - } - } catch (error) { - onError(error, errorRecordedForStack); - } - }, - - flush: function (sync) { - var queue = this._queue; - var length = queue.length; - - if (length === 0) { - return; - } - - var globalOptions = this.globalOptions; - var options = this.options; - var before = options && options.before; - var after = options && options.after; - var onError = globalOptions.onError || globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod]; - var target, method, args, errorRecordedForStack; - var invoke = onError ? this.invokeWithOnError : this.invoke; - - this.targetQueues = Object.create(null); - var queueItems = this._queueBeingFlushed = this._queue.slice(); - this._queue = []; - - if (before) { - before(); - } - - for (var i = 0; i < length; i += 4) { - target = queueItems[i]; - method = queueItems[i + 1]; - args = queueItems[i + 2]; - errorRecordedForStack = queueItems[i + 3]; // Debugging assistance - - if (_backburnerUtils.isString(method)) { - method = target[method]; - } - - // method could have been nullified / canceled during flush - if (method) { - // - // ** Attention intrepid developer ** - // - // To find out the stack of this task when it was scheduled onto - // the run loop, add the following to your app.js: - // - // Ember.run.backburner.DEBUG = true; // NOTE: This slows your app, don't leave it on in production. - // - // Once that is in place, when you are at a breakpoint and navigate - // here in the stack explorer, you can look at `errorRecordedForStack.stack`, - // which will be the captured stack when this job was scheduled. - // - invoke(target, method, args, onError, errorRecordedForStack); - } - } - - if (after) { - after(); - } - - this._queueBeingFlushed = undefined; - - if (sync !== false && this._queue.length > 0) { - // check if new items have been added - this.flush(true); - } - }, - - cancel: function (actionToCancel) { - var queue = this._queue, - currentTarget, - currentMethod, - i, - l; - var target = actionToCancel.target; - var method = actionToCancel.method; - var GUID_KEY = this.globalOptions.GUID_KEY; - - if (GUID_KEY && this.targetQueues && target) { - var targetQueue = this.targetQueues[target[GUID_KEY]]; - - if (targetQueue) { - for (i = 0, l = targetQueue.length; i < l; i++) { - if (targetQueue[i] === method) { - targetQueue.splice(i, 1); - } - } - } - } - - for (i = 0, l = queue.length; i < l; i += 4) { - currentTarget = queue[i]; - currentMethod = queue[i + 1]; - - if (currentTarget === target && currentMethod === method) { - queue.splice(i, 4); - return true; - } - } - - // if not found in current queue - // could be in the queue that is being flushed - queue = this._queueBeingFlushed; - - if (!queue) { - return; - } - - for (i = 0, l = queue.length; i < l; i += 4) { - currentTarget = queue[i]; - currentMethod = queue[i + 1]; - - if (currentTarget === target && currentMethod === method) { - // don't mess with array during flush - // just nullify the method - queue[i + 1] = null; - return true; - } - } - } - }; -}); -enifed('backburner/utils', ['exports'], function (exports) { - 'use strict'; - - exports.each = each; - exports.isString = isString; - exports.isFunction = isFunction; - exports.isNumber = isNumber; - exports.isCoercableNumber = isCoercableNumber; - var NUMBER = /\d+/; - - function each(collection, callback) { - for (var i = 0; i < collection.length; i++) { - callback(collection[i]); - } - } - - function isString(suspect) { - return typeof suspect === 'string'; - } - - function isFunction(suspect) { - return typeof suspect === 'function'; - } - - function isNumber(suspect) { - return typeof suspect === 'number'; - } - - function isCoercableNumber(number) { - return isNumber(number) || NUMBER.test(number); - } -}); enifed('backburner', ['exports', 'backburner/utils', 'backburner/platform', 'backburner/binary-search', 'backburner/deferred-action-queues'], function (exports, _backburnerUtils, _backburnerPlatform, _backburnerBinarySearch, _backburnerDeferredActionQueues) { 'use strict'; exports.default = Backburner; @@ -1152,10 +769,393 @@ function clearItems(item) { this._platform.clearTimeout(item[2]); } }); +enifed("backburner/binary-search", ["exports"], function (exports) { + "use strict"; + + exports.default = binarySearch; + + function binarySearch(time, timers) { + var start = 0; + var end = timers.length - 2; + var middle, l; + + while (start < end) { + // since timers is an array of pairs 'l' will always + // be an integer + l = (end - start) / 2; + + // compensate for the index in case even number + // of pairs inside timers + middle = start + l - l % 2; + + if (time >= timers[middle]) { + start = middle + 2; + } else { + end = middle; + } + } + + return time >= timers[start] ? start + 2 : start; + } +}); +enifed('backburner/deferred-action-queues', ['exports', 'backburner/utils', 'backburner/queue'], function (exports, _backburnerUtils, _backburnerQueue) { + 'use strict'; + + exports.default = DeferredActionQueues; + + function DeferredActionQueues(queueNames, options) { + var queues = this.queues = {}; + this.queueNames = queueNames = queueNames || []; + + this.options = options; + + _backburnerUtils.each(queueNames, function (queueName) { + queues[queueName] = new _backburnerQueue.default(queueName, options[queueName], options); + }); + } + + function noSuchQueue(name) { + throw new Error('You attempted to schedule an action in a queue (' + name + ') that doesn\'t exist'); + } + + function noSuchMethod(name) { + throw new Error('You attempted to schedule an action in a queue (' + name + ') for a method that doesn\'t exist'); + } + + DeferredActionQueues.prototype = { + schedule: function (name, target, method, args, onceFlag, stack) { + var queues = this.queues; + var queue = queues[name]; + + if (!queue) { + noSuchQueue(name); + } + + if (!method) { + noSuchMethod(name); + } + + if (onceFlag) { + return queue.pushUnique(target, method, args, stack); + } else { + return queue.push(target, method, args, stack); + } + }, + + flush: function () { + var queues = this.queues; + var queueNames = this.queueNames; + var queueName, queue; + var queueNameIndex = 0; + var numberOfQueues = queueNames.length; + + while (queueNameIndex < numberOfQueues) { + queueName = queueNames[queueNameIndex]; + queue = queues[queueName]; + + var numberOfQueueItems = queue._queue.length; + + if (numberOfQueueItems === 0) { + queueNameIndex++; + } else { + queue.flush(false /* async */); + queueNameIndex = 0; + } + } + } + }; +}); +enifed('backburner/platform', ['exports'], function (exports) { + 'use strict'; + + var GlobalContext; + + /* global self */ + if (typeof self === 'object') { + GlobalContext = self; + + /* global global */ + } else if (typeof global === 'object') { + GlobalContext = global; + + /* global window */ + } else if (typeof window === 'object') { + GlobalContext = window; + } else { + throw new Error('no global: `self`, `global` nor `window` was found'); + } + + exports.default = GlobalContext; +}); +enifed('backburner/queue', ['exports', 'backburner/utils'], function (exports, _backburnerUtils) { + 'use strict'; + + exports.default = Queue; + + function Queue(name, options, globalOptions) { + this.name = name; + this.globalOptions = globalOptions || {}; + this.options = options; + this._queue = []; + this.targetQueues = {}; + this._queueBeingFlushed = undefined; + } + + Queue.prototype = { + push: function (target, method, args, stack) { + var queue = this._queue; + queue.push(target, method, args, stack); + + return { + queue: this, + target: target, + method: method + }; + }, + + pushUniqueWithoutGuid: function (target, method, args, stack) { + var queue = this._queue; + + for (var i = 0, l = queue.length; i < l; i += 4) { + var currentTarget = queue[i]; + var currentMethod = queue[i + 1]; + + if (currentTarget === target && currentMethod === method) { + queue[i + 2] = args; // replace args + queue[i + 3] = stack; // replace stack + return; + } + } + + queue.push(target, method, args, stack); + }, + + targetQueue: function (targetQueue, target, method, args, stack) { + var queue = this._queue; + + for (var i = 0, l = targetQueue.length; i < l; i += 2) { + var currentMethod = targetQueue[i]; + var currentIndex = targetQueue[i + 1]; + + if (currentMethod === method) { + queue[currentIndex + 2] = args; // replace args + queue[currentIndex + 3] = stack; // replace stack + return; + } + } + + targetQueue.push(method, queue.push(target, method, args, stack) - 4); + }, + + pushUniqueWithGuid: function (guid, target, method, args, stack) { + var hasLocalQueue = this.targetQueues[guid]; + + if (hasLocalQueue) { + this.targetQueue(hasLocalQueue, target, method, args, stack); + } else { + this.targetQueues[guid] = [method, this._queue.push(target, method, args, stack) - 4]; + } + + return { + queue: this, + target: target, + method: method + }; + }, + + pushUnique: function (target, method, args, stack) { + var KEY = this.globalOptions.GUID_KEY; + + if (target && KEY) { + var guid = target[KEY]; + if (guid) { + return this.pushUniqueWithGuid(guid, target, method, args, stack); + } + } + + this.pushUniqueWithoutGuid(target, method, args, stack); + + return { + queue: this, + target: target, + method: method + }; + }, + + invoke: function (target, method, args, _, _errorRecordedForStack) { + if (args && args.length > 0) { + method.apply(target, args); + } else { + method.call(target); + } + }, + + invokeWithOnError: function (target, method, args, onError, errorRecordedForStack) { + try { + if (args && args.length > 0) { + method.apply(target, args); + } else { + method.call(target); + } + } catch (error) { + onError(error, errorRecordedForStack); + } + }, + + flush: function (sync) { + var queue = this._queue; + var length = queue.length; + + if (length === 0) { + return; + } + + var globalOptions = this.globalOptions; + var options = this.options; + var before = options && options.before; + var after = options && options.after; + var onError = globalOptions.onError || globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod]; + var target, method, args, errorRecordedForStack; + var invoke = onError ? this.invokeWithOnError : this.invoke; + + this.targetQueues = Object.create(null); + var queueItems = this._queueBeingFlushed = this._queue.slice(); + this._queue = []; + + if (before) { + before(); + } + + for (var i = 0; i < length; i += 4) { + target = queueItems[i]; + method = queueItems[i + 1]; + args = queueItems[i + 2]; + errorRecordedForStack = queueItems[i + 3]; // Debugging assistance + + if (_backburnerUtils.isString(method)) { + method = target[method]; + } + + // method could have been nullified / canceled during flush + if (method) { + // + // ** Attention intrepid developer ** + // + // To find out the stack of this task when it was scheduled onto + // the run loop, add the following to your app.js: + // + // Ember.run.backburner.DEBUG = true; // NOTE: This slows your app, don't leave it on in production. + // + // Once that is in place, when you are at a breakpoint and navigate + // here in the stack explorer, you can look at `errorRecordedForStack.stack`, + // which will be the captured stack when this job was scheduled. + // + invoke(target, method, args, onError, errorRecordedForStack); + } + } + + if (after) { + after(); + } + + this._queueBeingFlushed = undefined; + + if (sync !== false && this._queue.length > 0) { + // check if new items have been added + this.flush(true); + } + }, + + cancel: function (actionToCancel) { + var queue = this._queue, + currentTarget, + currentMethod, + i, + l; + var target = actionToCancel.target; + var method = actionToCancel.method; + var GUID_KEY = this.globalOptions.GUID_KEY; + + if (GUID_KEY && this.targetQueues && target) { + var targetQueue = this.targetQueues[target[GUID_KEY]]; + + if (targetQueue) { + for (i = 0, l = targetQueue.length; i < l; i++) { + if (targetQueue[i] === method) { + targetQueue.splice(i, 1); + } + } + } + } + + for (i = 0, l = queue.length; i < l; i += 4) { + currentTarget = queue[i]; + currentMethod = queue[i + 1]; + + if (currentTarget === target && currentMethod === method) { + queue.splice(i, 4); + return true; + } + } + + // if not found in current queue + // could be in the queue that is being flushed + queue = this._queueBeingFlushed; + + if (!queue) { + return; + } + + for (i = 0, l = queue.length; i < l; i += 4) { + currentTarget = queue[i]; + currentMethod = queue[i + 1]; + + if (currentTarget === target && currentMethod === method) { + // don't mess with array during flush + // just nullify the method + queue[i + 1] = null; + return true; + } + } + } + }; +}); +enifed('backburner/utils', ['exports'], function (exports) { + 'use strict'; + + exports.each = each; + exports.isString = isString; + exports.isFunction = isFunction; + exports.isNumber = isNumber; + exports.isCoercableNumber = isCoercableNumber; + var NUMBER = /\d+/; + + function each(collection, callback) { + for (var i = 0; i < collection.length; i++) { + callback(collection[i]); + } + } + + function isString(suspect) { + return typeof suspect === 'string'; + } + + function isFunction(suspect) { + return typeof suspect === 'function'; + } + + function isNumber(suspect) { + return typeof suspect === 'number'; + } + + function isCoercableNumber(number) { + return isNumber(number) || NUMBER.test(number); + } +}); enifed('container/container', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-metal/dictionary', 'ember-metal/features', 'container/owner', 'ember-runtime/mixins/container_proxy', 'ember-metal/symbol'], function (exports, _emberMetalCore, _emberMetalDebug, _emberMetalDictionary, _emberMetalFeatures, _containerOwner, _emberRuntimeMixinsContainer_proxy, _emberMetalSymbol) { 'use strict'; var CONTAINER_OVERRIDE = _emberMetalSymbol.default('CONTAINER_OVERRIDE'); @@ -2463,28 +2463,10 @@ return privateNames[fullName] = _emberMetalUtils.intern(type + ':' + rawName + '-' + privateSuffix); } exports.default = Registry; }); -enifed('dag-map/platform', ['exports'], function (exports) { - 'use strict'; - - var platform; - - /* global self */ - if (typeof self === 'object') { - platform = self; - - /* global global */ - } else if (typeof global === 'object') { - platform = global; - } else { - throw new Error('no global: `self` or `global` found'); - } - - exports.default = platform; -}); enifed('dag-map', ['exports', 'vertex', 'visit'], function (exports, _vertex, _visit) { 'use strict'; exports.default = DAG; @@ -2638,468 +2620,27 @@ module.exports = _dagMap.default; } else if (typeof _dagMapPlatform.default !== 'undefined') { _dagMapPlatform.default['DAG'] = _dagMap.default; } }); -enifed('dom-helper/build-html-dom', ['exports'], function (exports) { - /* global XMLSerializer:false */ +enifed('dag-map/platform', ['exports'], function (exports) { 'use strict'; - var svgHTMLIntegrationPoints = { foreignObject: 1, desc: 1, title: 1 }; - exports.svgHTMLIntegrationPoints = svgHTMLIntegrationPoints; - var svgNamespace = 'http://www.w3.org/2000/svg'; + var platform; - exports.svgNamespace = svgNamespace; - var doc = typeof document === 'undefined' ? false : document; + /* global self */ + if (typeof self === 'object') { + platform = self; - // Safari does not like using innerHTML on SVG HTML integration - // points (desc/title/foreignObject). - var needsIntegrationPointFix = doc && (function (document) { - if (document.createElementNS === undefined) { - return; - } - // In FF title will not accept innerHTML. - var testEl = document.createElementNS(svgNamespace, 'title'); - testEl.innerHTML = "<div></div>"; - return testEl.childNodes.length === 0 || testEl.childNodes[0].nodeType !== 1; - })(doc); - - // Internet Explorer prior to 9 does not allow setting innerHTML if the first element - // is a "zero-scope" element. This problem can be worked around by making - // the first node an invisible text node. We, like Modernizr, use &shy; - var needsShy = doc && (function (document) { - var testEl = document.createElement('div'); - testEl.innerHTML = "<div></div>"; - testEl.firstChild.innerHTML = "<script><\/script>"; - return testEl.firstChild.innerHTML === ''; - })(doc); - - // IE 8 (and likely earlier) likes to move whitespace preceeding - // a script tag to appear after it. This means that we can - // accidentally remove whitespace when updating a morph. - var movesWhitespace = doc && (function (document) { - var testEl = document.createElement('div'); - testEl.innerHTML = "Test: <script type='text/x-placeholder'><\/script>Value"; - return testEl.childNodes[0].nodeValue === 'Test:' && testEl.childNodes[2].nodeValue === ' Value'; - })(doc); - - var tagNamesRequiringInnerHTMLFix = doc && (function (document) { - var tagNamesRequiringInnerHTMLFix; - // IE 9 and earlier don't allow us to set innerHTML on col, colgroup, frameset, - // html, style, table, tbody, tfoot, thead, title, tr. Detect this and add - // them to an initial list of corrected tags. - // - // Here we are only dealing with the ones which can have child nodes. - // - var tableNeedsInnerHTMLFix; - var tableInnerHTMLTestElement = document.createElement('table'); - try { - tableInnerHTMLTestElement.innerHTML = '<tbody></tbody>'; - } catch (e) {} finally { - tableNeedsInnerHTMLFix = tableInnerHTMLTestElement.childNodes.length === 0; - } - if (tableNeedsInnerHTMLFix) { - tagNamesRequiringInnerHTMLFix = { - colgroup: ['table'], - table: [], - tbody: ['table'], - tfoot: ['table'], - thead: ['table'], - tr: ['table', 'tbody'] - }; - } - - // IE 8 doesn't allow setting innerHTML on a select tag. Detect this and - // add it to the list of corrected tags. - // - var selectInnerHTMLTestElement = document.createElement('select'); - selectInnerHTMLTestElement.innerHTML = '<option></option>'; - if (!selectInnerHTMLTestElement.childNodes[0]) { - tagNamesRequiringInnerHTMLFix = tagNamesRequiringInnerHTMLFix || {}; - tagNamesRequiringInnerHTMLFix.select = []; - } - return tagNamesRequiringInnerHTMLFix; - })(doc); - - function scriptSafeInnerHTML(element, html) { - // without a leading text node, IE will drop a leading script tag. - html = '&shy;' + html; - - element.innerHTML = html; - - var nodes = element.childNodes; - - // Look for &shy; to remove it. - var shyElement = nodes[0]; - while (shyElement.nodeType === 1 && !shyElement.nodeName) { - shyElement = shyElement.firstChild; - } - // At this point it's the actual unicode character. - if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") { - var newValue = shyElement.nodeValue.slice(1); - if (newValue.length) { - shyElement.nodeValue = shyElement.nodeValue.slice(1); - } else { - shyElement.parentNode.removeChild(shyElement); - } - } - - return nodes; - } - - function buildDOMWithFix(html, contextualElement) { - var tagName = contextualElement.tagName; - - // Firefox versions < 11 do not have support for element.outerHTML. - var outerHTML = contextualElement.outerHTML || new XMLSerializer().serializeToString(contextualElement); - if (!outerHTML) { - throw "Can't set innerHTML on " + tagName + " in this browser"; - } - - html = fixSelect(html, contextualElement); - - var wrappingTags = tagNamesRequiringInnerHTMLFix[tagName.toLowerCase()]; - - var startTag = outerHTML.match(new RegExp("<" + tagName + "([^>]*)>", 'i'))[0]; - var endTag = '</' + tagName + '>'; - - var wrappedHTML = [startTag, html, endTag]; - - var i = wrappingTags.length; - var wrappedDepth = 1 + i; - while (i--) { - wrappedHTML.unshift('<' + wrappingTags[i] + '>'); - wrappedHTML.push('</' + wrappingTags[i] + '>'); - } - - var wrapper = document.createElement('div'); - scriptSafeInnerHTML(wrapper, wrappedHTML.join('')); - var element = wrapper; - while (wrappedDepth--) { - element = element.firstChild; - while (element && element.nodeType !== 1) { - element = element.nextSibling; - } - } - while (element && element.tagName !== tagName) { - element = element.nextSibling; - } - return element ? element.childNodes : []; - } - - var buildDOM; - if (needsShy) { - buildDOM = function buildDOM(html, contextualElement, dom) { - html = fixSelect(html, contextualElement); - - contextualElement = dom.cloneNode(contextualElement, false); - scriptSafeInnerHTML(contextualElement, html); - return contextualElement.childNodes; - }; - } else { - buildDOM = function buildDOM(html, contextualElement, dom) { - html = fixSelect(html, contextualElement); - - contextualElement = dom.cloneNode(contextualElement, false); - contextualElement.innerHTML = html; - return contextualElement.childNodes; - }; - } - - function fixSelect(html, contextualElement) { - if (contextualElement.tagName === 'SELECT') { - html = "<option></option>" + html; - } - - return html; - } - - var buildIESafeDOM; - if (tagNamesRequiringInnerHTMLFix || movesWhitespace) { - buildIESafeDOM = function buildIESafeDOM(html, contextualElement, dom) { - // Make a list of the leading text on script nodes. Include - // script tags without any whitespace for easier processing later. - var spacesBefore = []; - var spacesAfter = []; - if (typeof html === 'string') { - html = html.replace(/(\s*)(<script)/g, function (match, spaces, tag) { - spacesBefore.push(spaces); - return tag; - }); - - html = html.replace(/(<\/script>)(\s*)/g, function (match, tag, spaces) { - spacesAfter.push(spaces); - return tag; - }); - } - - // Fetch nodes - var nodes; - if (tagNamesRequiringInnerHTMLFix[contextualElement.tagName.toLowerCase()]) { - // buildDOMWithFix uses string wrappers for problematic innerHTML. - nodes = buildDOMWithFix(html, contextualElement); - } else { - nodes = buildDOM(html, contextualElement, dom); - } - - // Build a list of script tags, the nodes themselves will be - // mutated as we add test nodes. - var i, j, node, nodeScriptNodes; - var scriptNodes = []; - for (i = 0; i < nodes.length; i++) { - node = nodes[i]; - if (node.nodeType !== 1) { - continue; - } - if (node.tagName === 'SCRIPT') { - scriptNodes.push(node); - } else { - nodeScriptNodes = node.getElementsByTagName('script'); - for (j = 0; j < nodeScriptNodes.length; j++) { - scriptNodes.push(nodeScriptNodes[j]); - } - } - } - - // Walk the script tags and put back their leading text nodes. - var scriptNode, textNode, spaceBefore, spaceAfter; - for (i = 0; i < scriptNodes.length; i++) { - scriptNode = scriptNodes[i]; - spaceBefore = spacesBefore[i]; - if (spaceBefore && spaceBefore.length > 0) { - textNode = dom.document.createTextNode(spaceBefore); - scriptNode.parentNode.insertBefore(textNode, scriptNode); - } - - spaceAfter = spacesAfter[i]; - if (spaceAfter && spaceAfter.length > 0) { - textNode = dom.document.createTextNode(spaceAfter); - scriptNode.parentNode.insertBefore(textNode, scriptNode.nextSibling); - } - } - - return nodes; - }; - } else { - buildIESafeDOM = buildDOM; - } - - var buildHTMLDOM; - if (needsIntegrationPointFix) { - exports.buildHTMLDOM = buildHTMLDOM = function buildHTMLDOM(html, contextualElement, dom) { - if (svgHTMLIntegrationPoints[contextualElement.tagName]) { - return buildIESafeDOM(html, document.createElement('div'), dom); - } else { - return buildIESafeDOM(html, contextualElement, dom); - } - }; - } else { - exports.buildHTMLDOM = buildHTMLDOM = buildIESafeDOM; - } - - exports.buildHTMLDOM = buildHTMLDOM; -}); -enifed('dom-helper/classes', ['exports'], function (exports) { - 'use strict'; - - var doc = typeof document === 'undefined' ? false : document; - - // PhantomJS has a broken classList. See https://github.com/ariya/phantomjs/issues/12782 - var canClassList = doc && (function () { - var d = document.createElement('div'); - if (!d.classList) { - return false; - } - d.classList.add('boo'); - d.classList.add('boo', 'baz'); - return d.className === 'boo baz'; - })(); - - function buildClassList(element) { - var classString = element.getAttribute('class') || ''; - return classString !== '' && classString !== ' ' ? classString.split(' ') : []; - } - - function intersect(containingArray, valuesArray) { - var containingIndex = 0; - var containingLength = containingArray.length; - var valuesIndex = 0; - var valuesLength = valuesArray.length; - - var intersection = new Array(valuesLength); - - // TODO: rewrite this loop in an optimal manner - for (; containingIndex < containingLength; containingIndex++) { - valuesIndex = 0; - for (; valuesIndex < valuesLength; valuesIndex++) { - if (valuesArray[valuesIndex] === containingArray[containingIndex]) { - intersection[valuesIndex] = containingIndex; - break; - } - } - } - - return intersection; - } - - function addClassesViaAttribute(element, classNames) { - var existingClasses = buildClassList(element); - - var indexes = intersect(existingClasses, classNames); - var didChange = false; - - for (var i = 0, l = classNames.length; i < l; i++) { - if (indexes[i] === undefined) { - didChange = true; - existingClasses.push(classNames[i]); - } - } - - if (didChange) { - element.setAttribute('class', existingClasses.length > 0 ? existingClasses.join(' ') : ''); - } - } - - function removeClassesViaAttribute(element, classNames) { - var existingClasses = buildClassList(element); - - var indexes = intersect(classNames, existingClasses); - var didChange = false; - var newClasses = []; - - for (var i = 0, l = existingClasses.length; i < l; i++) { - if (indexes[i] === undefined) { - newClasses.push(existingClasses[i]); - } else { - didChange = true; - } - } - - if (didChange) { - element.setAttribute('class', newClasses.length > 0 ? newClasses.join(' ') : ''); - } - } - - var addClasses, removeClasses; - if (canClassList) { - exports.addClasses = addClasses = function addClasses(element, classNames) { - if (element.classList) { - if (classNames.length === 1) { - element.classList.add(classNames[0]); - } else if (classNames.length === 2) { - element.classList.add(classNames[0], classNames[1]); - } else { - element.classList.add.apply(element.classList, classNames); - } - } else { - addClassesViaAttribute(element, classNames); - } - }; - exports.removeClasses = removeClasses = function removeClasses(element, classNames) { - if (element.classList) { - if (classNames.length === 1) { - element.classList.remove(classNames[0]); - } else if (classNames.length === 2) { - element.classList.remove(classNames[0], classNames[1]); - } else { - element.classList.remove.apply(element.classList, classNames); - } - } else { - removeClassesViaAttribute(element, classNames); - } - }; - } else { - exports.addClasses = addClasses = addClassesViaAttribute; - exports.removeClasses = removeClasses = removeClassesViaAttribute; - } - - exports.addClasses = addClasses; - exports.removeClasses = removeClasses; -}); -enifed('dom-helper/prop', ['exports'], function (exports) { - 'use strict'; - - exports.isAttrRemovalValue = isAttrRemovalValue; - exports.normalizeProperty = normalizeProperty; - - function isAttrRemovalValue(value) { - return value === null || value === undefined; - } - - /* - * - * @method normalizeProperty - * @param element {HTMLElement} - * @param slotName {String} - * @returns {Object} { name, type } - */ - - function normalizeProperty(element, slotName) { - var type, normalized; - - if (slotName in element) { - normalized = slotName; - type = 'prop'; + /* global global */ + } else if (typeof global === 'object') { + platform = global; } else { - var lower = slotName.toLowerCase(); - if (lower in element) { - type = 'prop'; - normalized = lower; - } else { - type = 'attr'; - normalized = slotName; - } + throw new Error('no global: `self` or `global` found'); } - if (type === 'prop' && (normalized.toLowerCase() === 'style' || preferAttr(element.tagName, normalized))) { - type = 'attr'; - } - - return { normalized: normalized, type: type }; - } - - // properties that MUST be set as attributes, due to: - // * browser bug - // * strange spec outlier - var ATTR_OVERRIDES = { - - // phantomjs < 2.0 lets you set it as a prop but won't reflect it - // back to the attribute. button.getAttribute('type') === null - BUTTON: { type: true, form: true }, - - INPUT: { - // TODO: remove when IE8 is droped - // Some versions of IE (IE8) throw an exception when setting - // `input.list = 'somestring'`: - // https://github.com/emberjs/ember.js/issues/10908 - // https://github.com/emberjs/ember.js/issues/11364 - list: true, - // Some version of IE (like IE9) actually throw an exception - // if you set input.type = 'something-unknown' - type: true, - form: true, - // Chrome 46.0.2464.0: 'autocorrect' in document.createElement('input') === false - // Safari 8.0.7: 'autocorrect' in document.createElement('input') === false - // Mobile Safari (iOS 8.4 simulator): 'autocorrect' in document.createElement('input') === true - autocorrect: true - }, - - // element.form is actually a legitimate readOnly property, that is to be - // mutated, but must be mutated by setAttribute... - SELECT: { form: true }, - OPTION: { form: true }, - TEXTAREA: { form: true }, - LABEL: { form: true }, - FIELDSET: { form: true }, - LEGEND: { form: true }, - OBJECT: { form: true } - }; - - function preferAttr(tagName, propName) { - var tag = ATTR_OVERRIDES[tagName.toUpperCase()]; - return tag && tag[propName.toLowerCase()] || false; - } + exports.default = platform; }); enifed("dom-helper", ["exports", "htmlbars-runtime/morph", "morph-attr", "dom-helper/build-html-dom", "dom-helper/classes", "dom-helper/prop"], function (exports, _htmlbarsRuntimeMorph, _morphAttr, _domHelperBuildHtmlDom, _domHelperClasses, _domHelperProp) { /*globals module, URL*/ "use strict"; @@ -3705,31 +3246,469 @@ return protocol === null ? ':' : protocol; } exports.default = DOMHelper; }); -enifed('ember/index', ['exports', 'ember-metal', 'ember-runtime', 'ember-views', 'ember-routing', 'ember-application', 'ember-extension-support', 'ember-htmlbars', 'ember-routing-htmlbars', 'ember-routing-views', 'require', 'ember-runtime/system/lazy_load'], function (exports, _emberMetal, _emberRuntime, _emberViews, _emberRouting, _emberApplication, _emberExtensionSupport, _emberHtmlbars, _emberRoutingHtmlbars, _emberRoutingViews, _require, _emberRuntimeSystemLazy_load) { - // require the main entry points for each of these packages - // this is so that the global exports occur properly +enifed('dom-helper/build-html-dom', ['exports'], function (exports) { + /* global XMLSerializer:false */ 'use strict'; - if (_require.has('ember-template-compiler')) { - _require.default('ember-template-compiler'); + var svgHTMLIntegrationPoints = { foreignObject: 1, desc: 1, title: 1 }; + exports.svgHTMLIntegrationPoints = svgHTMLIntegrationPoints; + var svgNamespace = 'http://www.w3.org/2000/svg'; + + exports.svgNamespace = svgNamespace; + var doc = typeof document === 'undefined' ? false : document; + + // Safari does not like using innerHTML on SVG HTML integration + // points (desc/title/foreignObject). + var needsIntegrationPointFix = doc && (function (document) { + if (document.createElementNS === undefined) { + return; + } + // In FF title will not accept innerHTML. + var testEl = document.createElementNS(svgNamespace, 'title'); + testEl.innerHTML = "<div></div>"; + return testEl.childNodes.length === 0 || testEl.childNodes[0].nodeType !== 1; + })(doc); + + // Internet Explorer prior to 9 does not allow setting innerHTML if the first element + // is a "zero-scope" element. This problem can be worked around by making + // the first node an invisible text node. We, like Modernizr, use &shy; + var needsShy = doc && (function (document) { + var testEl = document.createElement('div'); + testEl.innerHTML = "<div></div>"; + testEl.firstChild.innerHTML = "<script><\/script>"; + return testEl.firstChild.innerHTML === ''; + })(doc); + + // IE 8 (and likely earlier) likes to move whitespace preceeding + // a script tag to appear after it. This means that we can + // accidentally remove whitespace when updating a morph. + var movesWhitespace = doc && (function (document) { + var testEl = document.createElement('div'); + testEl.innerHTML = "Test: <script type='text/x-placeholder'><\/script>Value"; + return testEl.childNodes[0].nodeValue === 'Test:' && testEl.childNodes[2].nodeValue === ' Value'; + })(doc); + + var tagNamesRequiringInnerHTMLFix = doc && (function (document) { + var tagNamesRequiringInnerHTMLFix; + // IE 9 and earlier don't allow us to set innerHTML on col, colgroup, frameset, + // html, style, table, tbody, tfoot, thead, title, tr. Detect this and add + // them to an initial list of corrected tags. + // + // Here we are only dealing with the ones which can have child nodes. + // + var tableNeedsInnerHTMLFix; + var tableInnerHTMLTestElement = document.createElement('table'); + try { + tableInnerHTMLTestElement.innerHTML = '<tbody></tbody>'; + } catch (e) {} finally { + tableNeedsInnerHTMLFix = tableInnerHTMLTestElement.childNodes.length === 0; + } + if (tableNeedsInnerHTMLFix) { + tagNamesRequiringInnerHTMLFix = { + colgroup: ['table'], + table: [], + tbody: ['table'], + tfoot: ['table'], + thead: ['table'], + tr: ['table', 'tbody'] + }; + } + + // IE 8 doesn't allow setting innerHTML on a select tag. Detect this and + // add it to the list of corrected tags. + // + var selectInnerHTMLTestElement = document.createElement('select'); + selectInnerHTMLTestElement.innerHTML = '<option></option>'; + if (!selectInnerHTMLTestElement.childNodes[0]) { + tagNamesRequiringInnerHTMLFix = tagNamesRequiringInnerHTMLFix || {}; + tagNamesRequiringInnerHTMLFix.select = []; + } + return tagNamesRequiringInnerHTMLFix; + })(doc); + + function scriptSafeInnerHTML(element, html) { + // without a leading text node, IE will drop a leading script tag. + html = '&shy;' + html; + + element.innerHTML = html; + + var nodes = element.childNodes; + + // Look for &shy; to remove it. + var shyElement = nodes[0]; + while (shyElement.nodeType === 1 && !shyElement.nodeName) { + shyElement = shyElement.firstChild; + } + // At this point it's the actual unicode character. + if (shyElement.nodeType === 3 && shyElement.nodeValue.charAt(0) === "\u00AD") { + var newValue = shyElement.nodeValue.slice(1); + if (newValue.length) { + shyElement.nodeValue = shyElement.nodeValue.slice(1); + } else { + shyElement.parentNode.removeChild(shyElement); + } + } + + return nodes; } - // do this to ensure that Ember.Test is defined properly on the global - // if it is present. - if (_require.has('ember-testing')) { - _require.default('ember-testing'); + function buildDOMWithFix(html, contextualElement) { + var tagName = contextualElement.tagName; + + // Firefox versions < 11 do not have support for element.outerHTML. + var outerHTML = contextualElement.outerHTML || new XMLSerializer().serializeToString(contextualElement); + if (!outerHTML) { + throw "Can't set innerHTML on " + tagName + " in this browser"; + } + + html = fixSelect(html, contextualElement); + + var wrappingTags = tagNamesRequiringInnerHTMLFix[tagName.toLowerCase()]; + + var startTag = outerHTML.match(new RegExp("<" + tagName + "([^>]*)>", 'i'))[0]; + var endTag = '</' + tagName + '>'; + + var wrappedHTML = [startTag, html, endTag]; + + var i = wrappingTags.length; + var wrappedDepth = 1 + i; + while (i--) { + wrappedHTML.unshift('<' + wrappingTags[i] + '>'); + wrappedHTML.push('</' + wrappingTags[i] + '>'); + } + + var wrapper = document.createElement('div'); + scriptSafeInnerHTML(wrapper, wrappedHTML.join('')); + var element = wrapper; + while (wrappedDepth--) { + element = element.firstChild; + while (element && element.nodeType !== 1) { + element = element.nextSibling; + } + } + while (element && element.tagName !== tagName) { + element = element.nextSibling; + } + return element ? element.childNodes : []; } - _emberRuntimeSystemLazy_load.runLoadHooks('Ember'); + var buildDOM; + if (needsShy) { + buildDOM = function buildDOM(html, contextualElement, dom) { + html = fixSelect(html, contextualElement); - /** - @module ember - */ + contextualElement = dom.cloneNode(contextualElement, false); + scriptSafeInnerHTML(contextualElement, html); + return contextualElement.childNodes; + }; + } else { + buildDOM = function buildDOM(html, contextualElement, dom) { + html = fixSelect(html, contextualElement); + + contextualElement = dom.cloneNode(contextualElement, false); + contextualElement.innerHTML = html; + return contextualElement.childNodes; + }; + } + + function fixSelect(html, contextualElement) { + if (contextualElement.tagName === 'SELECT') { + html = "<option></option>" + html; + } + + return html; + } + + var buildIESafeDOM; + if (tagNamesRequiringInnerHTMLFix || movesWhitespace) { + buildIESafeDOM = function buildIESafeDOM(html, contextualElement, dom) { + // Make a list of the leading text on script nodes. Include + // script tags without any whitespace for easier processing later. + var spacesBefore = []; + var spacesAfter = []; + if (typeof html === 'string') { + html = html.replace(/(\s*)(<script)/g, function (match, spaces, tag) { + spacesBefore.push(spaces); + return tag; + }); + + html = html.replace(/(<\/script>)(\s*)/g, function (match, tag, spaces) { + spacesAfter.push(spaces); + return tag; + }); + } + + // Fetch nodes + var nodes; + if (tagNamesRequiringInnerHTMLFix[contextualElement.tagName.toLowerCase()]) { + // buildDOMWithFix uses string wrappers for problematic innerHTML. + nodes = buildDOMWithFix(html, contextualElement); + } else { + nodes = buildDOM(html, contextualElement, dom); + } + + // Build a list of script tags, the nodes themselves will be + // mutated as we add test nodes. + var i, j, node, nodeScriptNodes; + var scriptNodes = []; + for (i = 0; i < nodes.length; i++) { + node = nodes[i]; + if (node.nodeType !== 1) { + continue; + } + if (node.tagName === 'SCRIPT') { + scriptNodes.push(node); + } else { + nodeScriptNodes = node.getElementsByTagName('script'); + for (j = 0; j < nodeScriptNodes.length; j++) { + scriptNodes.push(nodeScriptNodes[j]); + } + } + } + + // Walk the script tags and put back their leading text nodes. + var scriptNode, textNode, spaceBefore, spaceAfter; + for (i = 0; i < scriptNodes.length; i++) { + scriptNode = scriptNodes[i]; + spaceBefore = spacesBefore[i]; + if (spaceBefore && spaceBefore.length > 0) { + textNode = dom.document.createTextNode(spaceBefore); + scriptNode.parentNode.insertBefore(textNode, scriptNode); + } + + spaceAfter = spacesAfter[i]; + if (spaceAfter && spaceAfter.length > 0) { + textNode = dom.document.createTextNode(spaceAfter); + scriptNode.parentNode.insertBefore(textNode, scriptNode.nextSibling); + } + } + + return nodes; + }; + } else { + buildIESafeDOM = buildDOM; + } + + var buildHTMLDOM; + if (needsIntegrationPointFix) { + exports.buildHTMLDOM = buildHTMLDOM = function buildHTMLDOM(html, contextualElement, dom) { + if (svgHTMLIntegrationPoints[contextualElement.tagName]) { + return buildIESafeDOM(html, document.createElement('div'), dom); + } else { + return buildIESafeDOM(html, contextualElement, dom); + } + }; + } else { + exports.buildHTMLDOM = buildHTMLDOM = buildIESafeDOM; + } + + exports.buildHTMLDOM = buildHTMLDOM; }); +enifed('dom-helper/classes', ['exports'], function (exports) { + 'use strict'; + + var doc = typeof document === 'undefined' ? false : document; + + // PhantomJS has a broken classList. See https://github.com/ariya/phantomjs/issues/12782 + var canClassList = doc && (function () { + var d = document.createElement('div'); + if (!d.classList) { + return false; + } + d.classList.add('boo'); + d.classList.add('boo', 'baz'); + return d.className === 'boo baz'; + })(); + + function buildClassList(element) { + var classString = element.getAttribute('class') || ''; + return classString !== '' && classString !== ' ' ? classString.split(' ') : []; + } + + function intersect(containingArray, valuesArray) { + var containingIndex = 0; + var containingLength = containingArray.length; + var valuesIndex = 0; + var valuesLength = valuesArray.length; + + var intersection = new Array(valuesLength); + + // TODO: rewrite this loop in an optimal manner + for (; containingIndex < containingLength; containingIndex++) { + valuesIndex = 0; + for (; valuesIndex < valuesLength; valuesIndex++) { + if (valuesArray[valuesIndex] === containingArray[containingIndex]) { + intersection[valuesIndex] = containingIndex; + break; + } + } + } + + return intersection; + } + + function addClassesViaAttribute(element, classNames) { + var existingClasses = buildClassList(element); + + var indexes = intersect(existingClasses, classNames); + var didChange = false; + + for (var i = 0, l = classNames.length; i < l; i++) { + if (indexes[i] === undefined) { + didChange = true; + existingClasses.push(classNames[i]); + } + } + + if (didChange) { + element.setAttribute('class', existingClasses.length > 0 ? existingClasses.join(' ') : ''); + } + } + + function removeClassesViaAttribute(element, classNames) { + var existingClasses = buildClassList(element); + + var indexes = intersect(classNames, existingClasses); + var didChange = false; + var newClasses = []; + + for (var i = 0, l = existingClasses.length; i < l; i++) { + if (indexes[i] === undefined) { + newClasses.push(existingClasses[i]); + } else { + didChange = true; + } + } + + if (didChange) { + element.setAttribute('class', newClasses.length > 0 ? newClasses.join(' ') : ''); + } + } + + var addClasses, removeClasses; + if (canClassList) { + exports.addClasses = addClasses = function addClasses(element, classNames) { + if (element.classList) { + if (classNames.length === 1) { + element.classList.add(classNames[0]); + } else if (classNames.length === 2) { + element.classList.add(classNames[0], classNames[1]); + } else { + element.classList.add.apply(element.classList, classNames); + } + } else { + addClassesViaAttribute(element, classNames); + } + }; + exports.removeClasses = removeClasses = function removeClasses(element, classNames) { + if (element.classList) { + if (classNames.length === 1) { + element.classList.remove(classNames[0]); + } else if (classNames.length === 2) { + element.classList.remove(classNames[0], classNames[1]); + } else { + element.classList.remove.apply(element.classList, classNames); + } + } else { + removeClassesViaAttribute(element, classNames); + } + }; + } else { + exports.addClasses = addClasses = addClassesViaAttribute; + exports.removeClasses = removeClasses = removeClassesViaAttribute; + } + + exports.addClasses = addClasses; + exports.removeClasses = removeClasses; +}); +enifed('dom-helper/prop', ['exports'], function (exports) { + 'use strict'; + + exports.isAttrRemovalValue = isAttrRemovalValue; + exports.normalizeProperty = normalizeProperty; + + function isAttrRemovalValue(value) { + return value === null || value === undefined; + } + + /* + * + * @method normalizeProperty + * @param element {HTMLElement} + * @param slotName {String} + * @returns {Object} { name, type } + */ + + function normalizeProperty(element, slotName) { + var type, normalized; + + if (slotName in element) { + normalized = slotName; + type = 'prop'; + } else { + var lower = slotName.toLowerCase(); + if (lower in element) { + type = 'prop'; + normalized = lower; + } else { + type = 'attr'; + normalized = slotName; + } + } + + if (type === 'prop' && (normalized.toLowerCase() === 'style' || preferAttr(element.tagName, normalized))) { + type = 'attr'; + } + + return { normalized: normalized, type: type }; + } + + // properties that MUST be set as attributes, due to: + // * browser bug + // * strange spec outlier + var ATTR_OVERRIDES = { + + // phantomjs < 2.0 lets you set it as a prop but won't reflect it + // back to the attribute. button.getAttribute('type') === null + BUTTON: { type: true, form: true }, + + INPUT: { + // TODO: remove when IE8 is droped + // Some versions of IE (IE8) throw an exception when setting + // `input.list = 'somestring'`: + // https://github.com/emberjs/ember.js/issues/10908 + // https://github.com/emberjs/ember.js/issues/11364 + list: true, + // Some version of IE (like IE9) actually throw an exception + // if you set input.type = 'something-unknown' + type: true, + form: true, + // Chrome 46.0.2464.0: 'autocorrect' in document.createElement('input') === false + // Safari 8.0.7: 'autocorrect' in document.createElement('input') === false + // Mobile Safari (iOS 8.4 simulator): 'autocorrect' in document.createElement('input') === true + autocorrect: true + }, + + // element.form is actually a legitimate readOnly property, that is to be + // mutated, but must be mutated by setAttribute... + SELECT: { form: true }, + OPTION: { form: true }, + TEXTAREA: { form: true }, + LABEL: { form: true }, + FIELDSET: { form: true }, + LEGEND: { form: true }, + OBJECT: { form: true } + }; + + function preferAttr(tagName, propName) { + var tag = ATTR_OVERRIDES[tagName.toUpperCase()]; + return tag && tag[propName.toLowerCase()] || false; + } +}); enifed('ember-application/index', ['exports', 'ember-metal/core', 'ember-metal/features', 'ember-runtime/system/lazy_load', 'ember-application/system/resolver', 'ember-application/system/application', 'ember-application/system/application-instance', 'ember-application/system/engine', 'ember-application/system/engine-instance'], function (exports, _emberMetalCore, _emberMetalFeatures, _emberRuntimeSystemLazy_load, _emberApplicationSystemResolver, _emberApplicationSystemApplication, _emberApplicationSystemApplicationInstance, _emberApplicationSystemEngine, _emberApplicationSystemEngineInstance) { 'use strict'; _emberMetalCore.default.Application = _emberApplicationSystemApplication.default; _emberMetalCore.default.Resolver = _emberApplicationSystemResolver.Resolver; @@ -7035,10 +7014,45 @@ }; } exports.default = Helper; }); +enifed('ember-htmlbars/helpers', ['exports', 'ember-metal/empty_object'], function (exports, _emberMetalEmpty_object) { + /** + @module ember + @submodule ember-htmlbars + */ + + /** + @private + @property helpers + */ + 'use strict'; + + exports.registerHelper = registerHelper; + + var helpers = new _emberMetalEmpty_object.default(); + + /** + @module ember + @submodule ember-htmlbars + */ + + /** + @private + @method _registerHelper + @for Ember.HTMLBars + @param {String} name + @param {Object|Function} helperFunc The helper function to add. + */ + + function registerHelper(name, helperFunc) { + helpers[name] = helperFunc; + } + + exports.default = helpers; +}); enifed('ember-htmlbars/helpers/-html-safe', ['exports', 'htmlbars-util/safe-string'], function (exports, _htmlbarsUtilSafeString) { 'use strict'; exports.default = htmlSafeHelper; @@ -7583,45 +7597,10 @@ } else if (options.inverse && options.inverse.yield) { options.inverse.yield([]); } } }); -enifed('ember-htmlbars/helpers', ['exports', 'ember-metal/empty_object'], function (exports, _emberMetalEmpty_object) { - /** - @module ember - @submodule ember-htmlbars - */ - - /** - @private - @property helpers - */ - 'use strict'; - - exports.registerHelper = registerHelper; - - var helpers = new _emberMetalEmpty_object.default(); - - /** - @module ember - @submodule ember-htmlbars - */ - - /** - @private - @method _registerHelper - @for Ember.HTMLBars - @param {String} name - @param {Object|Function} helperFunc The helper function to add. - */ - - function registerHelper(name, helperFunc) { - helpers[name] = helperFunc; - } - - exports.default = helpers; -}); enifed('ember-htmlbars/hooks/bind-block', ['exports'], function (exports) { 'use strict'; exports.default = bindBlock; @@ -8828,10 +8807,45 @@ // Importing adds template bootstrapping // initializer to enable embedded templates. // Importing ember-htmlbars/compat updates the // Ember.Handlebars global if htmlbars is enabled. +enifed('ember-htmlbars/keywords', ['exports', 'htmlbars-runtime'], function (exports, _htmlbarsRuntime) { + /** + @module ember + @submodule ember-htmlbars + */ + + 'use strict'; + + exports.registerKeyword = registerKeyword; + + /** + @private + @property helpers + */ + var keywords = Object.create(_htmlbarsRuntime.hooks.keywords); + + /** + @module ember + @submodule ember-htmlbars + */ + + /** + @private + @method _registerHelper + @for Ember.HTMLBars + @param {String} name + @param {Object|Function} keyword The keyword to add. + */ + + function registerKeyword(name, keyword) { + keywords[name] = keyword; + } + + exports.default = keywords; +}); enifed('ember-htmlbars/keywords/closure-component', ['exports', 'ember-metal/debug', 'ember-metal/is_none', 'ember-metal/symbol', 'ember-metal/streams/stream', 'ember-metal/empty_object', 'ember-metal/streams/utils', 'ember-htmlbars/hooks/subexpr', 'ember-metal/assign', 'ember-htmlbars/utils/extract-positional-params', 'ember-htmlbars/utils/lookup-component'], function (exports, _emberMetalDebug, _emberMetalIs_none, _emberMetalSymbol, _emberMetalStreamsStream, _emberMetalEmpty_object, _emberMetalStreamsUtils, _emberHtmlbarsHooksSubexpr, _emberMetalAssign, _emberHtmlbarsUtilsExtractPositionalParams, _emberHtmlbarsUtilsLookupComponent) { /** @module ember @submodule ember-templates */ @@ -9693,11 +9707,11 @@ @submodule ember-templates */ 'use strict'; - _emberHtmlbarsTemplatesTopLevelView.default.meta.revision = 'Ember@2.6.1'; + _emberHtmlbarsTemplatesTopLevelView.default.meta.revision = 'Ember@2.6.2'; /** The `{{outlet}}` helper lets you specify where a child route will render in your template. An important use of the `{{outlet}}` helper is in your application's `application.hbs` file: @@ -10555,45 +10569,10 @@ } return true; } }); -enifed('ember-htmlbars/keywords', ['exports', 'htmlbars-runtime'], function (exports, _htmlbarsRuntime) { - /** - @module ember - @submodule ember-htmlbars - */ - - 'use strict'; - - exports.registerKeyword = registerKeyword; - - /** - @private - @property helpers - */ - var keywords = Object.create(_htmlbarsRuntime.hooks.keywords); - - /** - @module ember - @submodule ember-htmlbars - */ - - /** - @private - @method _registerHelper - @for Ember.HTMLBars - @param {String} name - @param {Object|Function} keyword The keyword to add. - */ - - function registerKeyword(name, keyword) { - keywords[name] = keyword; - } - - exports.default = keywords; -}); enifed('ember-htmlbars/morphs/attr-morph', ['exports', 'ember-metal/debug', 'dom-helper', 'ember-metal/is_none'], function (exports, _emberMetalDebug, _domHelper, _emberMetalIs_none) { 'use strict'; var HTMLBarsAttrMorph = _domHelper.default.prototype.AttrMorphClass; @@ -12260,10 +12239,334 @@ } scope[key] = stream; } } }); +enifed('ember-metal-views/htmlbars-renderer', ['exports', 'ember-metal/run_loop', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/assign', 'ember-metal/set_properties', 'ember-views/system/build-component-template', 'ember-metal/environment', 'htmlbars-runtime'], function (exports, _emberMetalRun_loop, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalAssign, _emberMetalSet_properties, _emberViewsSystemBuildComponentTemplate, _emberMetalEnvironment, _htmlbarsRuntime) { + 'use strict'; + + exports.Renderer = Renderer; + exports.MorphSet = MorphSet; + + function Renderer(domHelper) { + var _ref = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var destinedForDOM = _ref.destinedForDOM; + + this._dom = domHelper; + + // This flag indicates whether the resulting rendered element will be + // inserted into the DOM. This should be set to `false` if the rendered + // element is going to be serialized to HTML without being inserted into + // the DOM (e.g., in FastBoot mode). By default, this flag is the same + // as whether we are running in an environment with DOM, but may be + // overridden. + this._destinedForDOM = destinedForDOM === undefined ? _emberMetalEnvironment.default.hasDOM : destinedForDOM; + } + + Renderer.prototype.prerenderTopLevelView = function Renderer_prerenderTopLevelView(view, renderNode) { + if (view._state === 'inDOM') { + throw new Error('You cannot insert a View that has already been rendered'); + } + view.ownerView = renderNode.emberView = view; + view._renderNode = renderNode; + + var layout = _emberMetalProperty_get.get(view, 'layout'); + var template = _emberMetalProperty_get.get(view, 'template'); + + var componentInfo = { component: view, layout: layout }; + + var block = _emberViewsSystemBuildComponentTemplate.default(componentInfo, {}, { + self: view, + templates: template ? { default: template.raw } : undefined + }).block; + + view.renderBlock(block, renderNode); + view.lastResult = renderNode.lastResult; + this.clearRenderedViews(view.env); + }; + + Renderer.prototype.renderTopLevelView = function Renderer_renderTopLevelView(view, renderNode) { + // Check to see if insertion has been canceled. + if (view._willInsert) { + view._willInsert = false; + this.prerenderTopLevelView(view, renderNode); + this.dispatchLifecycleHooks(view.env); + } + }; + + Renderer.prototype.revalidateTopLevelView = function Renderer_revalidateTopLevelView(view) { + // This guard prevents revalidation on an already-destroyed view. + if (view._renderNode.lastResult) { + view._renderNode.lastResult.revalidate(view.env); + // supports createElement, which operates without moving the view into + // the inDOM state. + if (view._state === 'inDOM') { + this.dispatchLifecycleHooks(view.env); + } + this.clearRenderedViews(view.env); + } + }; + + Renderer.prototype.dispatchLifecycleHooks = function Renderer_dispatchLifecycleHooks(env) { + var ownerView = env.view; + + var lifecycleHooks = env.lifecycleHooks; + var i, hook; + + for (i = 0; i < lifecycleHooks.length; i++) { + hook = lifecycleHooks[i]; + ownerView._dispatching = hook.type; + + switch (hook.type) { + case 'didInsertElement': + this.didInsertElement(hook.view);break; + case 'didUpdate': + this.didUpdate(hook.view);break; + } + + this.didRender(hook.view); + } + + ownerView._dispatching = null; + env.lifecycleHooks.length = 0; + }; + + Renderer.prototype.ensureViewNotRendering = function Renderer_ensureViewNotRendering(view) { + var env = view.ownerView.env; + if (env && env.renderedViews.indexOf(view.elementId) !== -1) { + throw new Error('Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.'); + } + }; + + function MorphSet() { + this.morphs = []; + } + + MorphSet.prototype.add = function (morph) { + this.morphs.push(morph); + morph.seen = true; + }; + + MorphSet.prototype.has = function (morph) { + return morph.seen; + }; + + MorphSet.prototype.clear = function () { + var morphs = this.morphs; + for (var i = 0, l = morphs.length; i < l; i++) { + morphs[i].seen = false; + } + + this.morphs = []; + }; + + Renderer.prototype.clearRenderedViews = function Renderer_clearRenderedViews(env) { + env.renderedNodes.clear(); + env.renderedViews.length = 0; + }; + + // This entry point is called from top-level `view.appendTo`. + Renderer.prototype.appendTo = function Renderer_appendTo(view, target) { + var morph = this._dom.appendMorph(target); + morph.ownerNode = morph; + view._willInsert = true; + _emberMetalRun_loop.default.schedule('render', this, this.renderTopLevelView, view, morph); + }; + + Renderer.prototype.replaceIn = function Renderer_replaceIn(view, target) { + var morph = this._dom.replaceContentWithMorph(target); + morph.ownerNode = morph; + view._willInsert = true; + _emberMetalRun_loop.default.scheduleOnce('render', this, this.renderTopLevelView, view, morph); + }; + + Renderer.prototype.createElement = function Renderer_createElement(view) { + var morph = this._dom.createFragmentMorph(); + morph.ownerNode = morph; + this.prerenderTopLevelView(view, morph); + }; + + Renderer.prototype.didCreateElement = function (view, element) { + if (element) { + view.element = element; + } + + if (view._transitionTo) { + view._transitionTo('hasElement'); + } + }; // hasElement + + Renderer.prototype.willInsertElement = function (view) { + if (view.trigger) { + view.trigger('willInsertElement'); + } + }; // Will place into DOM. + + Renderer.prototype.setAttrs = function (view, attrs) { + _emberMetalProperty_set.set(view, 'attrs', attrs); + }; // Set attrs the first time. + + Renderer.prototype.componentInitAttrs = function (component, attrs) { + component.trigger('didInitAttrs', { attrs: attrs }); + component.trigger('didReceiveAttrs', { newAttrs: attrs }); + }; // Set attrs the first time. + + Renderer.prototype.didInsertElement = function (view) { + if (view._transitionTo) { + view._transitionTo('inDOM'); + } + + if (view.trigger) { + view.trigger('didInsertElement'); + } + }; // inDOM // Placed into DOM. + + Renderer.prototype.didUpdate = function (view) { + if (view.trigger) { + view.trigger('didUpdate'); + } + }; + + Renderer.prototype.didRender = function (view) { + if (view.trigger) { + view.trigger('didRender'); + } + }; + + Renderer.prototype.updateAttrs = function (view, attrs) { + this.setAttrs(view, attrs); + }; // Setting new attrs. + + Renderer.prototype.componentUpdateAttrs = function (component, newAttrs) { + var oldAttrs = null; + + if (component.attrs) { + oldAttrs = _emberMetalAssign.default({}, component.attrs); + _emberMetalSet_properties.default(component.attrs, newAttrs); + } else { + _emberMetalProperty_set.set(component, 'attrs', newAttrs); + } + + component.trigger('didUpdateAttrs', { oldAttrs: oldAttrs, newAttrs: newAttrs }); + component.trigger('didReceiveAttrs', { oldAttrs: oldAttrs, newAttrs: newAttrs }); + }; + + Renderer.prototype.willUpdate = function (view, attrs) { + if (view._willUpdate) { + view._willUpdate(attrs); + } + }; + + Renderer.prototype.componentWillUpdate = function (component) { + component.trigger('willUpdate'); + }; + + Renderer.prototype.willRender = function (view) { + if (view._willRender) { + view._willRender(); + } + }; + + Renderer.prototype.componentWillRender = function (component) { + component.trigger('willRender'); + }; + + Renderer.prototype.rerender = function (view) { + var renderNode = view._renderNode; + + renderNode.isDirty = true; + _htmlbarsRuntime.internal.visitChildren(renderNode.childNodes, function (node) { + if (node.getState().manager) { + node.shouldReceiveAttrs = true; + } + node.isDirty = true; + }); + + renderNode.ownerNode.emberView.scheduleRevalidate(renderNode, view.toString(), 'rerendering'); + }; + + Renderer.prototype.remove = function (view, shouldDestroy) { + this.willDestroyElement(view); + + view._willRemoveElement = true; + _emberMetalRun_loop.default.schedule('render', this, this.renderElementRemoval, view); + }; + + Renderer.prototype.renderElementRemoval = function Renderer_renderElementRemoval(view) { + // Use the _willRemoveElement flag to avoid mulitple removal attempts in + // case many have been scheduled. This should be more performant than using + // `scheduleOnce`. + if (view._willRemoveElement) { + view._willRemoveElement = false; + + if (view._renderNode && view.element && view.element.parentNode) { + view._renderNode.clear(); + } + this.didDestroyElement(view); + } + }; + + Renderer.prototype.willRemoveElement = function () /*view*/{}; + + Renderer.prototype.willDestroyElement = function (view) { + if (view._willDestroyElement) { + view._willDestroyElement(); + } + if (view.trigger) { + view.trigger('willDestroyElement'); + view.trigger('willClearRender'); + } + + if (view._transitionTo) { + view._transitionTo('destroying'); + } + }; + + Renderer.prototype.didDestroyElement = function (view) { + view.element = null; + + // Views that are being destroyed should never go back to the preRender state. + // However if we're just destroying an element on a view (as is the case when + // using View#remove) then the view should go to a preRender state so that + // it can be rendered again later. + if (view._state !== 'destroying' && view._transitionTo) { + view._transitionTo('preRender'); + } + + if (view.trigger) { + view.trigger('didDestroyElement'); + } + }; // Element destroyed so view.destroy shouldn't try to remove it removedFromDOM + + var InertRenderer = { + create: function (_ref2) { + var dom = _ref2.dom; + + return new Renderer(dom, { destinedForDOM: false }); + } + }; + + exports.InertRenderer = InertRenderer; + var InteractiveRenderer = { + create: function (_ref3) { + var dom = _ref3.dom; + + return new Renderer(dom, { destinedForDOM: true }); + } + }; + exports.InteractiveRenderer = InteractiveRenderer; +}); +enifed('ember-metal-views/index', ['exports', 'ember-metal-views/htmlbars-renderer'], function (exports, _emberMetalViewsHtmlbarsRenderer) { + 'use strict'; + + function _interopExportWildcard(obj, defaults) { var newObj = defaults({}, obj); delete newObj['default']; return newObj; } + + function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; } + + _defaults(exports, _interopExportWildcard(_emberMetalViewsHtmlbarsRenderer, _defaults)); +}); enifed('ember-metal/alias', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/error', 'ember-metal/properties', 'ember-metal/computed', 'ember-metal/utils', 'ember-metal/meta', 'ember-metal/dependent_keys'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalError, _emberMetalProperties, _emberMetalComputed, _emberMetalUtils, _emberMetalMeta, _emberMetalDependent_keys) { 'use strict'; exports.default = alias; exports.AliasedProperty = AliasedProperty; @@ -14530,11 +14833,11 @@ cross-platform libraries such as jQuery. For more details, see [Ember-Runtime](http://emberjs.com/api/modules/ember-runtime.html). @class Ember @static - @version 2.6.1 + @version 2.6.2 @public */ if ('undefined' === typeof Ember) { // Create core object. Make it act like an instance of Ember.Namespace so that @@ -14572,15 +14875,15 @@ /** The semantic version. @property VERSION @type String - @default '2.6.1' + @default '2.6.2' @static @public */ - Ember.VERSION = '2.6.1'; + Ember.VERSION = '2.6.2'; /** The hash of environment variables used to control various configuration settings. To specify your own or override default settings, add the desired properties to a global hash named `EmberENV` (or `ENV` for @@ -15061,12 +15364,10 @@ @public */ function addListener(obj, eventName, target, method, once) { - if (eventName === 'didInitAttrs' && obj.isComponent) {} - if (!method && 'function' === typeof target) { method = target; target = null; } @@ -22012,333 +22313,1720 @@ } else { return false; } }; }); -enifed('ember-metal-views/htmlbars-renderer', ['exports', 'ember-metal/run_loop', 'ember-metal/property_get', 'ember-metal/property_set', 'ember-metal/assign', 'ember-metal/set_properties', 'ember-views/system/build-component-template', 'ember-metal/environment', 'htmlbars-runtime'], function (exports, _emberMetalRun_loop, _emberMetalProperty_get, _emberMetalProperty_set, _emberMetalAssign, _emberMetalSet_properties, _emberViewsSystemBuildComponentTemplate, _emberMetalEnvironment, _htmlbarsRuntime) { +enifed('ember-routing-htmlbars/helpers/query-params', ['exports', 'ember-metal/debug', 'ember-routing/system/query_params'], function (exports, _emberMetalDebug, _emberRoutingSystemQuery_params) { + /** + @module ember + @submodule ember-routing-htmlbars + */ + 'use strict'; - exports.Renderer = Renderer; - exports.MorphSet = MorphSet; + exports.queryParamsHelper = queryParamsHelper; - function Renderer(domHelper) { - var _ref = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + /** + This is a helper to be used in conjunction with the link-to helper. + It will supply url query parameters to the target route. + + Example + + ```handlebars + {{#link-to 'posts' (query-params direction="asc")}}Sort{{/link-to}} + ``` + + @method query-params + @for Ember.Templates.helpers + @param {Object} hash takes a hash of query parameters + @return {Object} A `QueryParams` object for `{{link-to}}` + @public + */ - var destinedForDOM = _ref.destinedForDOM; + function queryParamsHelper(params, hash) { - this._dom = domHelper; - - // This flag indicates whether the resulting rendered element will be - // inserted into the DOM. This should be set to `false` if the rendered - // element is going to be serialized to HTML without being inserted into - // the DOM (e.g., in FastBoot mode). By default, this flag is the same - // as whether we are running in an environment with DOM, but may be - // overridden. - this._destinedForDOM = destinedForDOM === undefined ? _emberMetalEnvironment.default.hasDOM : destinedForDOM; + return _emberRoutingSystemQuery_params.default.create({ + values: hash + }); } +}); +enifed('ember-routing-htmlbars/index', ['exports', 'ember-metal/core', 'ember-htmlbars/helpers', 'ember-htmlbars/keywords', 'ember-routing-htmlbars/helpers/query-params', 'ember-routing-htmlbars/keywords/action', 'ember-routing-htmlbars/keywords/element-action', 'ember-routing-htmlbars/keywords/render'], function (exports, _emberMetalCore, _emberHtmlbarsHelpers, _emberHtmlbarsKeywords, _emberRoutingHtmlbarsHelpersQueryParams, _emberRoutingHtmlbarsKeywordsAction, _emberRoutingHtmlbarsKeywordsElementAction, _emberRoutingHtmlbarsKeywordsRender) { + /** + @module ember + @submodule ember-routing-htmlbars + */ - Renderer.prototype.prerenderTopLevelView = function Renderer_prerenderTopLevelView(view, renderNode) { - if (view._state === 'inDOM') { - throw new Error('You cannot insert a View that has already been rendered'); - } - view.ownerView = renderNode.emberView = view; - view._renderNode = renderNode; + 'use strict'; - var layout = _emberMetalProperty_get.get(view, 'layout'); - var template = _emberMetalProperty_get.get(view, 'template'); + _emberHtmlbarsHelpers.registerHelper('query-params', _emberRoutingHtmlbarsHelpersQueryParams.queryParamsHelper); - var componentInfo = { component: view, layout: layout }; + _emberHtmlbarsKeywords.registerKeyword('action', _emberRoutingHtmlbarsKeywordsAction.default); + _emberHtmlbarsKeywords.registerKeyword('@element_action', _emberRoutingHtmlbarsKeywordsElementAction.default); + _emberHtmlbarsKeywords.registerKeyword('render', _emberRoutingHtmlbarsKeywordsRender.default); - var block = _emberViewsSystemBuildComponentTemplate.default(componentInfo, {}, { - self: view, - templates: template ? { default: template.raw } : undefined - }).block; + exports.default = _emberMetalCore.default; +}); +enifed('ember-routing-htmlbars/keywords/action', ['exports', 'htmlbars-runtime/hooks', 'ember-routing-htmlbars/keywords/closure-action'], function (exports, _htmlbarsRuntimeHooks, _emberRoutingHtmlbarsKeywordsClosureAction) { + /** + @module ember + @submodule ember-templates + */ - view.renderBlock(block, renderNode); - view.lastResult = renderNode.lastResult; - this.clearRenderedViews(view.env); - }; + 'use strict'; - Renderer.prototype.renderTopLevelView = function Renderer_renderTopLevelView(view, renderNode) { - // Check to see if insertion has been canceled. - if (view._willInsert) { - view._willInsert = false; - this.prerenderTopLevelView(view, renderNode); - this.dispatchLifecycleHooks(view.env); + /** + The `{{action}}` helper provides a way to pass triggers for behavior (usually + just a function) between components, and into components from controllers. + + ### Passing functions with the action helper + + There are three contexts an action helper can be used in. The first two + contexts to discuss are attribute context, and Handlebars value context. + + ```handlebars + {{! An example of attribute context }} + <div onclick={{action "save"}}></div> + {{! Examples of Handlebars value context }} + {{input on-input=(action "save")}} + {{yield (action "refreshData") andAnotherParam}} + ``` + + In these contexts, + the helper is called a "closure action" helper. Its behavior is simple: + If passed a function name, read that function off the `actions` property + of the current context. Once that function is read (or if a function was + passed), create a closure over that function and any arguments. + + The resulting value of an action helper used this way is simply a function. + For example, in the attribute context: + + ```handlebars + {{! An example of attribute context }} + <div onclick={{action "save"}}></div> + ``` + + The resulting template render logic would be: + + ```js + var div = document.createElement('div'); + var actionFunction = (function(context){ + return function() { + return context.actions.save.apply(context, arguments); + }; + })(context); + div.onclick = actionFunction; + ``` + + Thus when the div is clicked, the action on that context is called. + Because the `actionFunction` is just a function, closure actions can be + passed between components and still execute in the correct context. + + Here is an example action handler on a component: + + ```js + export default Ember.Component.extend({ + actions: { + save() { + this.get('model').save(); + } + } + }); + ``` + + Actions are always looked up on the `actions` property of the current context. + This avoids collisions in the naming of common actions, such as `destroy`. + + Two options can be passed to the `action` helper when it is used in this way. + + * `target=someProperty` will look to `someProperty` instead of the current + context for the `actions` hash. This can be useful when targetting a + service for actions. + * `value="target.value"` will read the path `target.value` off the first + argument to the action when it is called and rewrite the first argument + to be that value. This is useful when attaching actions to event listeners. + + ### Invoking an action + + Closure actions curry both their scope and any arguments. When invoked, any + additional arguments are added to the already curried list. + + Actions should be invoked using the [sendAction](/api/classes/Ember.Component.html#method_sendAction) + method. The first argument to `sendAction` is the action to be called, and + additional arguments are passed to the action function. This has interesting + properties combined with currying of arguments. For example: + + ```js + export default Ember.Component.extend({ + actions: { + // Usage {{input on-input=(action (action 'setName' model) value="target.value")}} + setName(model, name) { + model.set('name', name); + } + } + }); + ``` + + The first argument (`model`) was curried over, and the run-time argument (`event`) + becomes a second argument. Action calls can be nested this way because each simply + returns a function. Any function can be passed to the `{{action}}` helper, including + other actions. + + Actions invoked with `sendAction` have the same currying behavior as demonstrated + with `on-input` above. For example: + + ```js + export default Ember.Component.extend({ + actions: { + setName(model, name) { + model.set('name', name); + } + } + }); + ``` + + ```handlebars + {{my-input submit=(action 'setName' model)}} + ``` + + ```js + // app/components/my-component.js + export default Ember.Component.extend({ + click() { + // Note that model is not passed, it was curried in the template + this.sendAction('submit', 'bob'); + } + }); + ``` + + ### Attaching actions to DOM elements + + The third context of the `{{action}}` helper can be called "element space". + For example: + + ```handlebars + {{! An example of element space }} + <div {{action "save"}}></div> + ``` + + Used this way, the `{{action}}` helper provides a useful shortcut for + registering an HTML element in a template for a single DOM event and + forwarding that interaction to the template's context (controller or component). + + If the context of a template is a controller, actions used this way will + bubble to routes when the controller does not implement the specified action. + Once an action hits a route, it will bubble through the route hierarchy. + + ### Event Propagation + + `{{action}}` helpers called in element space can control event bubbling. Note + that the closure style actions cannot. + + Events triggered through the action helper will automatically have + `.preventDefault()` called on them. You do not need to do so in your event + handlers. If you need to allow event propagation (to handle file inputs for + example) you can supply the `preventDefault=false` option to the `{{action}}` helper: + + ```handlebars + <div {{action "sayHello" preventDefault=false}}> + <input type="file" /> + <input type="checkbox" /> + </div> + ``` + + To disable bubbling, pass `bubbles=false` to the helper: + + ```handlebars + <button {{action 'edit' post bubbles=false}}>Edit</button> + ``` + + To disable bubbling with closure style actions you must create your own + wrapper helper that makes use of `event.stopPropagation()`: + + ```handlebars + <div onclick={{disable-bubbling (action "sayHello")}}>Hello</div> + ``` + + ```js + // app/helpers/disable-bubbling.js + import Ember from 'ember'; + + export function disableBubbling([action]) { + return function(event) { + event.stopPropagation(); + + return action(event); + }; } - }; + + export default Ember.Helper.helper(disableBubbling); + ``` + + If you need the default handler to trigger you should either register your + own event handler, or use event methods on your view class. See + ["Responding to Browser Events"](/api/classes/Ember.View.html#toc_responding-to-browser-events) + in the documentation for Ember.View for more information. + + ### Specifying DOM event type + + `{{action}}` helpers called in element space can specify an event type. + + By default the `{{action}}` helper registers for DOM `click` events. You can + supply an `on` option to the helper to specify a different DOM event name: + + ```handlebars + <div {{action "anActionName" on="doubleClick"}}> + click me + </div> + ``` + + See ["Event Names"](/api/classes/Ember.View.html#toc_event-names) for a list of + acceptable DOM event names. + + ### Specifying whitelisted modifier keys + + `{{action}}` helpers called in element space can specify modifier keys. + + By default the `{{action}}` helper will ignore click events with pressed modifier + keys. You can supply an `allowedKeys` option to specify which keys should not be ignored. + + ```handlebars + <div {{action "anActionName" allowedKeys="alt"}}> + click me + </div> + ``` + + This way the action will fire when clicking with the alt key pressed down. + + Alternatively, supply "any" to the `allowedKeys` option to accept any combination of modifier keys. + + ```handlebars + <div {{action "anActionName" allowedKeys="any"}}> + click me with any key pressed + </div> + ``` + + ### Specifying a Target + + A `target` option can be provided to the helper to change + which object will receive the method call. This option must be a path + to an object, accessible in the current context: + + ```handlebars + {{! app/templates/application.hbs }} + <div {{action "anActionName" target=someService}}> + click me + </div> + ``` + + ```javascript + // app/controllers/application.js + export default Ember.Controller.extend({ + someService: Ember.inject.service() + }); + ``` + + @method action + @for Ember.Templates.helpers + @public + */ - Renderer.prototype.revalidateTopLevelView = function Renderer_revalidateTopLevelView(view) { - // This guard prevents revalidation on an already-destroyed view. - if (view._renderNode.lastResult) { - view._renderNode.lastResult.revalidate(view.env); - // supports createElement, which operates without moving the view into - // the inDOM state. - if (view._state === 'inDOM') { - this.dispatchLifecycleHooks(view.env); - } - this.clearRenderedViews(view.env); + exports.default = function (morph, env, scope, params, hash, template, inverse, visitor) { + if (morph) { + _htmlbarsRuntimeHooks.keyword('@element_action', morph, env, scope, params, hash, template, inverse, visitor); + return true; } + + return _emberRoutingHtmlbarsKeywordsClosureAction.default(morph, env, scope, params, hash, template, inverse, visitor); }; +}); +enifed('ember-routing-htmlbars/keywords/closure-action', ['exports', 'ember-metal/streams/stream', 'ember-metal/streams/utils', 'ember-metal/symbol', 'ember-metal/property_get', 'ember-htmlbars/hooks/subexpr', 'ember-metal/error', 'ember-metal/run_loop', 'ember-metal/instrumentation', 'ember-metal/is_none'], function (exports, _emberMetalStreamsStream, _emberMetalStreamsUtils, _emberMetalSymbol, _emberMetalProperty_get, _emberHtmlbarsHooksSubexpr, _emberMetalError, _emberMetalRun_loop, _emberMetalInstrumentation, _emberMetalIs_none) { + 'use strict'; - Renderer.prototype.dispatchLifecycleHooks = function Renderer_dispatchLifecycleHooks(env) { - var ownerView = env.view; + exports.default = closureAction; + var INVOKE = _emberMetalSymbol.default('INVOKE'); + exports.INVOKE = INVOKE; + var ACTION = _emberMetalSymbol.default('ACTION'); - var lifecycleHooks = env.lifecycleHooks; - var i, hook; + exports.ACTION = ACTION; - for (i = 0; i < lifecycleHooks.length; i++) { - hook = lifecycleHooks[i]; - ownerView._dispatching = hook.type; + function closureAction(morph, env, scope, params, hash, template, inverse, visitor) { + var s = new _emberMetalStreamsStream.Stream(function () { + var rawAction = params[0]; + var actionArguments = _emberMetalStreamsUtils.readArray(params.slice(1, params.length)); - switch (hook.type) { - case 'didInsertElement': - this.didInsertElement(hook.view);break; - case 'didUpdate': - this.didUpdate(hook.view);break; + var target = undefined, + action = undefined, + valuePath = undefined; + + if (_emberMetalIs_none.default(rawAction)) { + var label = _emberHtmlbarsHooksSubexpr.labelForSubexpr(params, hash, 'action'); + throw new _emberMetalError.default('Action passed is null or undefined in ' + label + ' from ' + _emberMetalStreamsUtils.read(scope.getSelf()) + '.'); + } else if (rawAction[INVOKE]) { + // on-change={{action (mut name)}} + target = rawAction; + action = rawAction[INVOKE]; + } else { + // on-change={{action setName}} + // element-space actions look to "controller" then target. Here we only + // look to "target". + target = _emberMetalStreamsUtils.read(scope.getSelf()); + action = _emberMetalStreamsUtils.read(rawAction); + var actionType = typeof action; + + if (actionType === 'string') { + var actionName = action; + action = null; + // on-change={{action 'setName'}} + if (hash.target) { + // on-change={{action 'setName' target=alternativeComponent}} + target = _emberMetalStreamsUtils.read(hash.target); + } + if (target.actions) { + action = target.actions[actionName]; + } + + if (!action) { + throw new _emberMetalError.default('An action named \'' + actionName + '\' was not found in ' + target + '.'); + } + } else if (action && typeof action[INVOKE] === 'function') { + target = action; + action = action[INVOKE]; + } else if (actionType !== 'function') { + throw new _emberMetalError.default('An action could not be made for `' + rawAction.label + '` in ' + target + '. Please confirm that you are using either a quoted action name (i.e. `(action \'' + rawAction.label + '\')`) or a function available in ' + target + '.'); + } } - this.didRender(hook.view); - } + if (hash.value) { + // <button on-keypress={{action (mut name) value="which"}} + // on-keypress is not even an Ember feature yet + valuePath = _emberMetalStreamsUtils.read(hash.value); + } - ownerView._dispatching = null; - env.lifecycleHooks.length = 0; - }; + return createClosureAction(this, target, action, valuePath, actionArguments); + }, function () { + return _emberHtmlbarsHooksSubexpr.labelForSubexpr(params, hash, 'action'); + }); - Renderer.prototype.ensureViewNotRendering = function Renderer_ensureViewNotRendering(view) { - var env = view.ownerView.env; - if (env && env.renderedViews.indexOf(view.elementId) !== -1) { - throw new Error('Something you did caused a view to re-render after it rendered but before it was inserted into the DOM.'); + params.forEach(s.addDependency, s); + Object.keys(hash).forEach(function (item) { + return s.addDependency(item); + }); + + return s; + } + + function createClosureAction(stream, target, action, valuePath, actionArguments) { + var closureAction; + + if (actionArguments.length > 0) { + closureAction = function () { + var args = actionArguments; + + for (var _len = arguments.length, passedArguments = Array(_len), _key = 0; _key < _len; _key++) { + passedArguments[_key] = arguments[_key]; + } + + if (passedArguments.length > 0) { + args = actionArguments.concat(passedArguments); + } + if (valuePath && args.length > 0) { + args[0] = _emberMetalProperty_get.get(args[0], valuePath); + } + + var payload = { target: target, args: args, label: _emberMetalStreamsUtils.labelFor(stream) }; + return _emberMetalInstrumentation.flaggedInstrument('interaction.ember-action', payload, function () { + return _emberMetalRun_loop.default.join.apply(_emberMetalRun_loop.default, [target, action].concat(args)); + }); + }; + } else { + closureAction = function () { + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + + if (valuePath && args.length > 0) { + args[0] = _emberMetalProperty_get.get(args[0], valuePath); + } + + var payload = { target: target, args: args, label: _emberMetalStreamsUtils.labelFor(stream) }; + return _emberMetalInstrumentation.flaggedInstrument('interaction.ember-action', payload, function () { + return _emberMetalRun_loop.default.join.apply(_emberMetalRun_loop.default, [target, action].concat(args)); + }); + }; } - }; - function MorphSet() { - this.morphs = []; + closureAction[ACTION] = true; + + return closureAction; } +}); +enifed('ember-routing-htmlbars/keywords/element-action', ['exports', 'ember-metal/debug', 'ember-metal/utils', 'ember-metal/streams/utils', 'ember-metal/run_loop', 'ember-views/streams/utils', 'ember-views/system/utils', 'ember-views/system/action_manager'], function (exports, _emberMetalDebug, _emberMetalUtils, _emberMetalStreamsUtils, _emberMetalRun_loop, _emberViewsStreamsUtils, _emberViewsSystemUtils, _emberViewsSystemAction_manager) { + 'use strict'; - MorphSet.prototype.add = function (morph) { - this.morphs.push(morph); - morph.seen = true; - }; + exports.default = { + setupState: function (state, env, scope, params, hash) { + var getStream = env.hooks.get; + var read = env.hooks.getValue; - MorphSet.prototype.has = function (morph) { - return morph.seen; + var actionName = read(params[0]); + + var actionArgs = []; + for (var i = 1, l = params.length; i < l; i++) { + actionArgs.push(_emberViewsStreamsUtils.readUnwrappedModel(params[i])); + } + + var target; + if (hash.target) { + if (typeof hash.target === 'string') { + target = read(getStream(env, scope, hash.target)); + } else { + target = read(hash.target); + } + } else { + target = read(scope.getLocal('controller')) || read(scope.getSelf()); + } + + return { actionName: actionName, actionArgs: actionArgs, target: target }; + }, + + isStable: function (state, env, scope, params, hash) { + return true; + }, + + render: function (node, env, scope, params, hash, template, inverse, visitor) { + var actionId = env.dom.getAttribute(node.element, 'data-ember-action') || _emberMetalUtils.uuid(); + + ActionHelper.registerAction({ + actionId: actionId, + node: node, + eventName: hash.on || 'click', + bubbles: hash.bubbles, + preventDefault: hash.preventDefault, + withKeyCode: hash.withKeyCode, + allowedKeys: hash.allowedKeys + }); + + node.cleanup = function () { + ActionHelper.unregisterAction(actionId); + }; + + env.dom.setAttribute(node.element, 'data-ember-action', actionId); + } }; + var ActionHelper = {}; - MorphSet.prototype.clear = function () { - var morphs = this.morphs; - for (var i = 0, l = morphs.length; i < l; i++) { - morphs[i].seen = false; + exports.ActionHelper = ActionHelper; + // registeredActions is re-exported for compatibility with older plugins + // that were using this undocumented API. + ActionHelper.registeredActions = _emberViewsSystemAction_manager.default.registeredActions; + + ActionHelper.registerAction = function (_ref) { + var actionId = _ref.actionId; + var node = _ref.node; + var eventName = _ref.eventName; + var preventDefault = _ref.preventDefault; + var bubbles = _ref.bubbles; + var allowedKeys = _ref.allowedKeys; + + var actions = _emberViewsSystemAction_manager.default.registeredActions[actionId]; + + if (!actions) { + actions = _emberViewsSystemAction_manager.default.registeredActions[actionId] = []; } - this.morphs = []; - }; + actions.push({ + eventName: eventName, + handler: function (event) { + if (!isAllowedEvent(event, _emberMetalStreamsUtils.read(allowedKeys))) { + return true; + } - Renderer.prototype.clearRenderedViews = function Renderer_clearRenderedViews(env) { - env.renderedNodes.clear(); - env.renderedViews.length = 0; - }; + if (_emberMetalStreamsUtils.read(preventDefault) !== false) { + event.preventDefault(); + } - // This entry point is called from top-level `view.appendTo`. - Renderer.prototype.appendTo = function Renderer_appendTo(view, target) { - var morph = this._dom.appendMorph(target); - morph.ownerNode = morph; - view._willInsert = true; - _emberMetalRun_loop.default.schedule('render', this, this.renderTopLevelView, view, morph); - }; + if (_emberMetalStreamsUtils.read(bubbles) === false) { + event.stopPropagation(); + } - Renderer.prototype.replaceIn = function Renderer_replaceIn(view, target) { - var morph = this._dom.replaceContentWithMorph(target); - morph.ownerNode = morph; - view._willInsert = true; - _emberMetalRun_loop.default.scheduleOnce('render', this, this.renderTopLevelView, view, morph); + var _node$getState = node.getState(); + + var target = _node$getState.target; + var actionName = _node$getState.actionName; + var actionArgs = _node$getState.actionArgs; + + _emberMetalRun_loop.default(function runRegisteredAction() { + if (typeof actionName === 'function') { + actionName.apply(target, actionArgs); + return; + } + if (target.send) { + target.send.apply(target, [actionName].concat(actionArgs)); + } else { + + target[actionName].apply(target, actionArgs); + } + }); + } + }); + + return actionId; }; - Renderer.prototype.createElement = function Renderer_createElement(view) { - var morph = this._dom.createFragmentMorph(); - morph.ownerNode = morph; - this.prerenderTopLevelView(view, morph); + ActionHelper.unregisterAction = function (actionId) { + delete _emberViewsSystemAction_manager.default.registeredActions[actionId]; }; - Renderer.prototype.didCreateElement = function (view, element) { - if (element) { - view.element = element; + var MODIFIERS = ['alt', 'shift', 'meta', 'ctrl']; + var POINTER_EVENT_TYPE_REGEX = /^click|mouse|touch/; + + function isAllowedEvent(event, allowedKeys) { + if (typeof allowedKeys === 'undefined') { + if (POINTER_EVENT_TYPE_REGEX.test(event.type)) { + return _emberViewsSystemUtils.isSimpleClick(event); + } else { + allowedKeys = ''; + } } - if (view._transitionTo) { - view._transitionTo('hasElement'); + if (allowedKeys.indexOf('any') >= 0) { + return true; } - }; // hasElement - Renderer.prototype.willInsertElement = function (view) { - if (view.trigger) { - view.trigger('willInsertElement'); + for (var i = 0, l = MODIFIERS.length; i < l; i++) { + if (event[MODIFIERS[i] + 'Key'] && allowedKeys.indexOf(MODIFIERS[i]) === -1) { + return false; + } } - }; // Will place into DOM. - Renderer.prototype.setAttrs = function (view, attrs) { - _emberMetalProperty_set.set(view, 'attrs', attrs); - }; // Set attrs the first time. + return true; + } +}); +enifed('ember-routing-htmlbars/keywords/render', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/empty_object', 'ember-metal/error', 'ember-metal/streams/utils', 'ember-runtime/system/string', 'ember-routing/system/generate_controller', 'ember-htmlbars/node-managers/view-node-manager'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalEmpty_object, _emberMetalError, _emberMetalStreamsUtils, _emberRuntimeSystemString, _emberRoutingSystemGenerate_controller, _emberHtmlbarsNodeManagersViewNodeManager) { + /** + @module ember + @submodule ember-templates + */ - Renderer.prototype.componentInitAttrs = function (component, attrs) { - component.trigger('didInitAttrs', { attrs: attrs }); - component.trigger('didReceiveAttrs', { newAttrs: attrs }); - }; // Set attrs the first time. + 'use strict'; - Renderer.prototype.didInsertElement = function (view) { - if (view._transitionTo) { - view._transitionTo('inDOM'); - } + /** + Calling ``{{render}}`` from within a template will insert another + template that matches the provided name. The inserted template will + access its properties on its own controller (rather than the controller + of the parent template). + If a view class with the same name exists, the view class also will be used. + Note: A given controller may only be used *once* in your app in this manner. + A singleton instance of the controller will be created for you. + Example: + + ```javascript + App.NavigationController = Ember.Controller.extend({ + who: "world" + }); + ``` + + ```handlebars + <!-- navigation.hbs --> + Hello, {{who}}. + ``` + + ```handlebars + <!-- application.hbs --> + <h1>My great app</h1> + {{render "navigation"}} + ``` + + ```html + <h1>My great app</h1> + <div class='ember-view'> + Hello, world. + </div> + ``` + + Optionally you may provide a second argument: a property path + that will be bound to the `model` property of the controller. + If a `model` property path is specified, then a new instance of the + controller will be created and `{{render}}` can be used multiple times + with the same name. + + For example if you had this `author` template. + + ```handlebars + <div class="author"> + Written by {{firstName}} {{lastName}}. + Total Posts: {{postCount}} + </div> + ``` + + You could render it inside the `post` template using the `render` helper. + + ```handlebars + <div class="post"> + <h1>{{title}}</h1> + <div>{{body}}</div> + {{render "author" author}} + </div> + ``` + + @method render + @for Ember.Templates.helpers + @param {String} name + @param {Object?} context + @param {Hash} options + @return {String} HTML string + @public + */ + exports.default = { + willRender: function (renderNode, env) { + if (env.view.ownerView._outlets) { + // We make sure we will get dirtied when outlet state changes. + env.view.ownerView._outlets.push(renderNode); + } + }, - if (view.trigger) { - view.trigger('didInsertElement'); - } - }; // inDOM // Placed into DOM. + setupState: function (prevState, env, scope, params, hash) { + var name = params[0]; - Renderer.prototype.didUpdate = function (view) { - if (view.trigger) { - view.trigger('didUpdate'); - } - }; + return { + parentView: env.view, + manager: prevState.manager, + controller: prevState.controller, + childOutletState: childOutletState(name, env) + }; + }, - Renderer.prototype.didRender = function (view) { - if (view.trigger) { - view.trigger('didRender'); - } - }; + childEnv: function (state, env) { + return env.childWithOutletState(state.childOutletState); + }, - Renderer.prototype.updateAttrs = function (view, attrs) { - this.setAttrs(view, attrs); - }; // Setting new attrs. + isStable: function (lastState, nextState) { + return isStable(lastState.childOutletState, nextState.childOutletState); + }, - Renderer.prototype.componentUpdateAttrs = function (component, newAttrs) { - var oldAttrs = null; + isEmpty: function (state) { + return false; + }, - if (component.attrs) { - oldAttrs = _emberMetalAssign.default({}, component.attrs); - _emberMetalSet_properties.default(component.attrs, newAttrs); - } else { - _emberMetalProperty_set.set(component, 'attrs', newAttrs); - } + render: function (node, env, scope, params, hash, template, inverse, visitor) { + var state = node.getState(); + var name = params[0]; + var context = params[1]; - component.trigger('didUpdateAttrs', { oldAttrs: oldAttrs, newAttrs: newAttrs }); - component.trigger('didReceiveAttrs', { oldAttrs: oldAttrs, newAttrs: newAttrs }); - }; + var owner = env.owner; - Renderer.prototype.willUpdate = function (view, attrs) { - if (view._willUpdate) { - view._willUpdate(attrs); - } - }; + // The render keyword presumes it can work without a router. This is really + // only to satisfy the test: + // + // {{view}} should not override class bindings defined on a child view" + // + var router = owner.lookup('router:main'); - Renderer.prototype.componentWillUpdate = function (component) { - component.trigger('willUpdate'); - }; + if (params.length === 1) {} else if (params.length !== 2) { + throw new _emberMetalError.default('You must pass a templateName to render'); + } - Renderer.prototype.willRender = function (view) { - if (view._willRender) { - view._willRender(); - } - }; + var templateName = 'template:' + name; - Renderer.prototype.componentWillRender = function (component) { - component.trigger('willRender'); - }; + var view = owner.lookup('view:' + name); + if (!view) { + view = owner.lookup('view:default'); + } + var viewHasTemplateSpecified = view && !!_emberMetalProperty_get.get(view, 'template'); + if (!template && !viewHasTemplateSpecified) { + template = owner.lookup(templateName); + } - Renderer.prototype.rerender = function (view) { - var renderNode = view._renderNode; + if (view) { + view.ownerView = env.view.ownerView; + } - renderNode.isDirty = true; - _htmlbarsRuntime.internal.visitChildren(renderNode.childNodes, function (node) { - if (node.getState().manager) { - node.shouldReceiveAttrs = true; + // provide controller override + var controllerName; + var controllerFullName; + + if (hash.controller) { + controllerName = hash.controller; + controllerFullName = 'controller:' + controllerName; + delete hash.controller; + } else { + controllerName = name; + controllerFullName = 'controller:' + controllerName; } - node.isDirty = true; - }); - renderNode.ownerNode.emberView.scheduleRevalidate(renderNode, view.toString(), 'rerendering'); - }; + var target = router; + var controller; - Renderer.prototype.remove = function (view, shouldDestroy) { - this.willDestroyElement(view); + // choose name + if (params.length > 1) { + var factory = owner._lookupFactory(controllerFullName) || _emberRoutingSystemGenerate_controller.generateControllerFactory(owner, controllerName); - view._willRemoveElement = true; - _emberMetalRun_loop.default.schedule('render', this, this.renderElementRemoval, view); - }; + controller = factory.create({ + model: _emberMetalStreamsUtils.read(context), + target: target + }); - Renderer.prototype.renderElementRemoval = function Renderer_renderElementRemoval(view) { - // Use the _willRemoveElement flag to avoid mulitple removal attempts in - // case many have been scheduled. This should be more performant than using - // `scheduleOnce`. - if (view._willRemoveElement) { - view._willRemoveElement = false; + node.addDestruction(controller); + } else { + controller = owner.lookup(controllerFullName) || _emberRoutingSystemGenerate_controller.default(owner, controllerName); - if (view._renderNode && view.element && view.element.parentNode) { - view._renderNode.clear(); + controller.setProperties({ + target: target + }); } - this.didDestroyElement(view); - } - }; - Renderer.prototype.willRemoveElement = function () /*view*/{}; + if (view) { + view.set('controller', controller); + } + state.controller = controller; - Renderer.prototype.willDestroyElement = function (view) { - if (view._willDestroyElement) { - view._willDestroyElement(); - } - if (view.trigger) { - view.trigger('willDestroyElement'); - view.trigger('willClearRender'); - } + hash.viewName = _emberRuntimeSystemString.camelize(name); - if (view._transitionTo) { - view._transitionTo('destroying'); + if (template && template.raw) { + template = template.raw; + } + + var options = { + layout: null, + self: controller + }; + + if (view) { + options.component = view; + } + + var nodeManager = _emberHtmlbarsNodeManagersViewNodeManager.default.create(node, env, hash, options, state.parentView, null, null, template); + state.manager = nodeManager; + + if (router && params.length === 1) { + router._connectActiveComponentNode(name, nodeManager); + } + + nodeManager.render(env, hash, visitor); + }, + + rerender: function (node, env, scope, params, hash, template, inverse, visitor) { + if (params.length > 1) { + var model = _emberMetalStreamsUtils.read(params[1]); + node.getState().controller.set('model', model); + } } }; - Renderer.prototype.didDestroyElement = function (view) { - view.element = null; + function childOutletState(name, env) { + var topLevel = env.view.ownerView; + if (!topLevel || !topLevel.outletState) { + return; + } - // Views that are being destroyed should never go back to the preRender state. - // However if we're just destroying an element on a view (as is the case when - // using View#remove) then the view should go to a preRender state so that - // it can be rendered again later. - if (view._state !== 'destroying' && view._transitionTo) { - view._transitionTo('preRender'); + var outletState = topLevel.outletState; + if (!outletState.main) { + return; } - if (view.trigger) { - view.trigger('didDestroyElement'); + var selectedOutletState = outletState.main.outlets['__ember_orphans__']; + if (!selectedOutletState) { + return; } - }; // Element destroyed so view.destroy shouldn't try to remove it removedFromDOM + var matched = selectedOutletState.outlets[name]; + if (matched) { + var childState = new _emberMetalEmpty_object.default(); + childState[matched.render.outlet] = matched; + matched.wasUsed = true; + return childState; + } + } - var InertRenderer = { - create: function (_ref2) { - var dom = _ref2.dom; + function isStable(a, b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + for (var outletName in a) { + if (!isStableOutlet(a[outletName], b[outletName])) { + return false; + } + } + return true; + } - return new Renderer(dom, { destinedForDOM: false }); + function isStableOutlet(a, b) { + if (!a && !b) { + return true; } - }; + if (!a || !b) { + return false; + } + a = a.render; + b = b.render; + for (var key in a) { + if (a.hasOwnProperty(key)) { + // name is only here for logging & debugging. If two different + // names result in otherwise identical states, they're still + // identical. + if (a[key] !== b[key] && key !== 'name') { + return false; + } + } + } + return true; + } +}); - exports.InertRenderer = InertRenderer; - var InteractiveRenderer = { - create: function (_ref3) { - var dom = _ref3.dom; +// use the singleton controller +enifed('ember-routing-views/components/link-to', ['exports', 'ember-metal/features', 'ember-metal/logger', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/computed', 'ember-metal/computed_macros', 'ember-views/system/utils', 'ember-views/components/component', 'ember-runtime/inject', 'ember-runtime/system/service', 'ember-runtime/mixins/controller', 'ember-htmlbars/node-managers/component-node-manager', 'ember-htmlbars/templates/link-to', 'require'], function (exports, _emberMetalFeatures, _emberMetalLogger, _emberMetalDebug, _emberMetalProperty_get, _emberMetalComputed, _emberMetalComputed_macros, _emberViewsSystemUtils, _emberViewsComponentsComponent, _emberRuntimeInject, _emberRuntimeSystemService, _emberRuntimeMixinsController, _emberHtmlbarsNodeManagersComponentNodeManager, _emberHtmlbarsTemplatesLinkTo, _require) { + /** + @module ember + @submodule ember-templates + */ - return new Renderer(dom, { destinedForDOM: true }); + /** + The `{{link-to}}` component renders a link to the supplied + `routeName` passing an optionally supplied model to the + route as its `model` context of the route. The block + for `{{link-to}}` becomes the innerHTML of the rendered + element: + + ```handlebars + {{#link-to 'photoGallery'}} + Great Hamster Photos + {{/link-to}} + ``` + + You can also use an inline form of `{{link-to}}` component by + passing the link text as the first argument + to the component: + + ```handlebars + {{link-to 'Great Hamster Photos' 'photoGallery'}} + ``` + + Both will result in: + + ```html + <a href="/hamster-photos"> + Great Hamster Photos + </a> + ``` + + ### Supplying a tagName + By default `{{link-to}}` renders an `<a>` element. This can + be overridden for a single use of `{{link-to}}` by supplying + a `tagName` option: + + ```handlebars + {{#link-to 'photoGallery' tagName="li"}} + Great Hamster Photos + {{/link-to}} + ``` + + ```html + <li> + Great Hamster Photos + </li> + ``` + + To override this option for your entire application, see + "Overriding Application-wide Defaults". + + ### Disabling the `link-to` component + By default `{{link-to}}` is enabled. + any passed value to the `disabled` component property will disable + the `link-to` component. + + static use: the `disabled` option: + + ```handlebars + {{#link-to 'photoGallery' disabled=true}} + Great Hamster Photos + {{/link-to}} + ``` + + dynamic use: the `disabledWhen` option: + + ```handlebars + {{#link-to 'photoGallery' disabledWhen=controller.someProperty}} + Great Hamster Photos + {{/link-to}} + ``` + + any passed value to `disabled` will disable it except `undefined`. + to ensure that only `true` disable the `link-to` component you can + override the global behaviour of `Ember.LinkComponent`. + + ```javascript + Ember.LinkComponent.reopen({ + disabled: Ember.computed(function(key, value) { + if (value !== undefined) { + this.set('_isDisabled', value === true); + } + return value === true ? get(this, 'disabledClass') : false; + }) + }); + ``` + + see "Overriding Application-wide Defaults" for more. + + ### Handling `href` + `{{link-to}}` will use your application's Router to + fill the element's `href` property with a url that + matches the path to the supplied `routeName` for your + router's configured `Location` scheme, which defaults + to Ember.HashLocation. + + ### Handling current route + `{{link-to}}` will apply a CSS class name of 'active' + when the application's current route matches + the supplied routeName. For example, if the application's + current route is 'photoGallery.recent' the following + use of `{{link-to}}`: + + ```handlebars + {{#link-to 'photoGallery.recent'}} + Great Hamster Photos + {{/link-to}} + ``` + + will result in + + ```html + <a href="/hamster-photos/this-week" class="active"> + Great Hamster Photos + </a> + ``` + + The CSS class name used for active classes can be customized + for a single use of `{{link-to}}` by passing an `activeClass` + option: + + ```handlebars + {{#link-to 'photoGallery.recent' activeClass="current-url"}} + Great Hamster Photos + {{/link-to}} + ``` + + ```html + <a href="/hamster-photos/this-week" class="current-url"> + Great Hamster Photos + </a> + ``` + + To override this option for your entire application, see + "Overriding Application-wide Defaults". + + ### Keeping a link active for other routes + + If you need a link to be 'active' even when it doesn't match + the current route, you can use the `current-when` argument. + + ```handlebars + {{#link-to 'photoGallery' current-when='photos'}} + Photo Gallery + {{/link-to}} + ``` + + This may be helpful for keeping links active for: + + * non-nested routes that are logically related + * some secondary menu approaches + * 'top navigation' with 'sub navigation' scenarios + + A link will be active if `current-when` is `true` or the current + route is the route this link would transition to. + + To match multiple routes 'space-separate' the routes: + + ```handlebars + {{#link-to 'gallery' current-when='photos drawings paintings'}} + Art Gallery + {{/link-to}} + ``` + + ### Supplying a model + An optional model argument can be used for routes whose + paths contain dynamic segments. This argument will become + the model context of the linked route: + + ```javascript + Router.map(function() { + this.route("photoGallery", {path: "hamster-photos/:photo_id"}); + }); + ``` + + ```handlebars + {{#link-to 'photoGallery' aPhoto}} + {{aPhoto.title}} + {{/link-to}} + ``` + + ```html + <a href="/hamster-photos/42"> + Tomster + </a> + ``` + + ### Supplying multiple models + For deep-linking to route paths that contain multiple + dynamic segments, multiple model arguments can be used. + As the router transitions through the route path, each + supplied model argument will become the context for the + route with the dynamic segments: + + ```javascript + Router.map(function() { + this.route("photoGallery", { path: "hamster-photos/:photo_id" }, function() { + this.route("comment", {path: "comments/:comment_id"}); + }); + }); + ``` + This argument will become the model context of the linked route: + + ```handlebars + {{#link-to 'photoGallery.comment' aPhoto comment}} + {{comment.body}} + {{/link-to}} + ``` + + ```html + <a href="/hamster-photos/42/comments/718"> + A+++ would snuggle again. + </a> + ``` + + ### Supplying an explicit dynamic segment value + If you don't have a model object available to pass to `{{link-to}}`, + an optional string or integer argument can be passed for routes whose + paths contain dynamic segments. This argument will become the value + of the dynamic segment: + + ```javascript + Router.map(function() { + this.route("photoGallery", { path: "hamster-photos/:photo_id" }); + }); + ``` + + ```handlebars + {{#link-to 'photoGallery' aPhotoId}} + {{aPhoto.title}} + {{/link-to}} + ``` + + ```html + <a href="/hamster-photos/42"> + Tomster + </a> + ``` + + When transitioning into the linked route, the `model` hook will + be triggered with parameters including this passed identifier. + + ### Allowing Default Action + + By default the `{{link-to}}` component prevents the default browser action + by calling `preventDefault()` as this sort of action bubbling is normally + handled internally and we do not want to take the browser to a new URL (for + example). + + If you need to override this behavior specify `preventDefault=false` in + your template: + + ```handlebars + {{#link-to 'photoGallery' aPhotoId preventDefault=false}} + {{aPhotoId.title}} + {{/link-to}} + ``` + + ### Overriding attributes + You can override any given property of the `Ember.LinkComponent` + that is generated by the `{{link-to}}` component by passing + key/value pairs, like so: + + ```handlebars + {{#link-to aPhoto tagName='li' title='Following this link will change your life' classNames='pic sweet'}} + Uh-mazing! + {{/link-to}} + ``` + + See [Ember.LinkComponent](/api/classes/Ember.LinkComponent.html) for a + complete list of overrideable properties. Be sure to also + check out inherited properties of `LinkComponent`. + + ### Overriding Application-wide Defaults + ``{{link-to}}`` creates an instance of `Ember.LinkComponent` + for rendering. To override options for your entire + application, reopen `Ember.LinkComponent` and supply the + desired values: + + ``` javascript + Ember.LinkComponent.reopen({ + activeClass: "is-active", + tagName: 'li' + }) + ``` + + It is also possible to override the default event in + this manner: + + ``` javascript + Ember.LinkComponent.reopen({ + eventName: 'customEventName' + }); + ``` + + @method link-to + @for Ember.Templates.helpers + @param {String} routeName + @param {Object} [context]* + @param [options] {Object} Handlebars key/value pairs of options, you can override any property of Ember.LinkComponent + @return {String} HTML string + @see {Ember.LinkComponent} + @public + */ + + /** + @module ember + @submodule ember-routing-views + */ + + 'use strict'; + + var layout = _emberHtmlbarsTemplatesLinkTo.default; + + /** + `Ember.LinkComponent` renders an element whose `click` event triggers a + transition of the application's instance of `Ember.Router` to + a supplied route by name. + + `Ember.LinkComponent` components are invoked with {{#link-to}}. Properties + of this class can be overridden with `reopen` to customize application-wide + behavior. + + @class LinkComponent + @namespace Ember + @extends Ember.Component + @see {Ember.Templates.helpers.link-to} + @private + **/ + var LinkComponent = _emberViewsComponentsComponent.default.extend({ + layout: layout, + + tagName: 'a', + + /** + @deprecated Use current-when instead. + @property currentWhen + @private + */ + currentWhen: _emberMetalComputed_macros.deprecatingAlias('current-when', { id: 'ember-routing-view.deprecated-current-when', until: '3.0.0' }), + + /** + Used to determine when this `LinkComponent` is active. + @property currentWhen + @public + */ + 'current-when': null, + + /** + Sets the `title` attribute of the `LinkComponent`'s HTML element. + @property title + @default null + @public + **/ + title: null, + + /** + Sets the `rel` attribute of the `LinkComponent`'s HTML element. + @property rel + @default null + @public + **/ + rel: null, + + /** + Sets the `tabindex` attribute of the `LinkComponent`'s HTML element. + @property tabindex + @default null + @public + **/ + tabindex: null, + + /** + Sets the `target` attribute of the `LinkComponent`'s HTML element. + @since 1.8.0 + @property target + @default null + @public + **/ + target: null, + + /** + The CSS class to apply to `LinkComponent`'s element when its `active` + property is `true`. + @property activeClass + @type String + @default active + @private + **/ + activeClass: 'active', + + /** + The CSS class to apply to `LinkComponent`'s element when its `loading` + property is `true`. + @property loadingClass + @type String + @default loading + @private + **/ + loadingClass: 'loading', + + /** + The CSS class to apply to a `LinkComponent`'s element when its `disabled` + property is `true`. + @property disabledClass + @type String + @default disabled + @private + **/ + disabledClass: 'disabled', + _isDisabled: false, + + /** + Determines whether the `LinkComponent` will trigger routing via + the `replaceWith` routing strategy. + @property replace + @type Boolean + @default false + @public + **/ + replace: false, + + /** + By default the `{{link-to}}` component will bind to the `href` and + `title` attributes. It's discouraged that you override these defaults, + however you can push onto the array if needed. + @property attributeBindings + @type Array | String + @default ['title', 'rel', 'tabindex', 'target'] + @public + */ + attributeBindings: ['href', 'title', 'rel', 'tabindex', 'target'], + + /** + By default the `{{link-to}}` component will bind to the `active`, `loading`, + and `disabled` classes. It is discouraged to override these directly. + @property classNameBindings + @type Array + @default ['active', 'loading', 'disabled', 'ember-transitioning-in', 'ember-transitioning-out'] + @public + */ + classNameBindings: ['active', 'loading', 'disabled', 'transitioningIn', 'transitioningOut'], + + /** + By default the `{{link-to}}` component responds to the `click` event. You + can override this globally by setting this property to your custom + event name. + This is particularly useful on mobile when one wants to avoid the 300ms + click delay using some sort of custom `tap` event. + @property eventName + @type String + @default click + @private + */ + eventName: 'click', + + // this is doc'ed here so it shows up in the events + // section of the API documentation, which is where + // people will likely go looking for it. + /** + Triggers the `LinkComponent`'s routing behavior. If + `eventName` is changed to a value other than `click` + the routing behavior will trigger on that custom event + instead. + @event click + @private + */ + + /** + An overridable method called when `LinkComponent` objects are instantiated. + Example: + ```javascript + App.MyLinkComponent = Ember.LinkComponent.extend({ + init: function() { + this._super(...arguments); + Ember.Logger.log('Event is ' + this.get('eventName')); + } + }); + ``` + NOTE: If you do override `init` for a framework class like `Ember.View`, + be sure to call `this._super(...arguments)` in your + `init` declaration! If you don't, Ember may not have an opportunity to + do important setup work, and you'll see strange behavior in your + application. + @method init + @private + */ + init: function () { + this._super.apply(this, arguments); + + // Map desired event name to invoke function + var eventName = _emberMetalProperty_get.get(this, 'eventName'); + this.on(eventName, this, this._invoke); + }, + + _routing: _emberRuntimeInject.default.service('-routing'), + + /** + Accessed as a classname binding to apply the `LinkComponent`'s `disabledClass` + CSS `class` to the element when the link is disabled. + When `true` interactions with the element will not trigger route changes. + @property disabled + @private + */ + disabled: _emberMetalComputed.computed({ + get: function (key, value) { + return false; + }, + set: function (key, value) { + if (value !== undefined) { + this.set('_isDisabled', value); + } + + return value ? _emberMetalProperty_get.get(this, 'disabledClass') : false; + } + }), + + _computeActive: function (routerState) { + if (_emberMetalProperty_get.get(this, 'loading')) { + return false; + } + + var routing = _emberMetalProperty_get.get(this, '_routing'); + var models = _emberMetalProperty_get.get(this, 'models'); + var resolvedQueryParams = _emberMetalProperty_get.get(this, 'resolvedQueryParams'); + + var currentWhen = _emberMetalProperty_get.get(this, 'current-when'); + var isCurrentWhenSpecified = !!currentWhen; + currentWhen = currentWhen || _emberMetalProperty_get.get(this, 'qualifiedRouteName'); + currentWhen = currentWhen.split(' '); + + for (var i = 0, len = currentWhen.length; i < len; i++) { + if (routing.isActiveForRoute(models, resolvedQueryParams, currentWhen[i], routerState, isCurrentWhenSpecified)) { + return _emberMetalProperty_get.get(this, 'activeClass'); + } + } + + return false; + }, + + /** + Accessed as a classname binding to apply the `LinkComponent`'s `activeClass` + CSS `class` to the element when the link is active. + A `LinkComponent` is considered active when its `currentWhen` property is `true` + or the application's current route is the route the `LinkComponent` would trigger + transitions into. + The `currentWhen` property can match against multiple routes by separating + route names using the ` ` (space) character. + @property active + @private + */ + active: _emberMetalComputed.computed('attrs.params', '_routing.currentState', function computeLinkToComponentActive() { + var currentState = _emberMetalProperty_get.get(this, '_routing.currentState'); + if (!currentState) { + return false; + } + + return this._computeActive(currentState); + }), + + willBeActive: _emberMetalComputed.computed('_routing.targetState', function computeLinkToComponentWillBeActive() { + var routing = _emberMetalProperty_get.get(this, '_routing'); + var targetState = _emberMetalProperty_get.get(routing, 'targetState'); + if (_emberMetalProperty_get.get(routing, 'currentState') === targetState) { + return; + } + + return !!this._computeActive(targetState); + }), + + transitioningIn: _emberMetalComputed.computed('active', 'willBeActive', function computeLinkToComponentTransitioningIn() { + var willBeActive = _emberMetalProperty_get.get(this, 'willBeActive'); + if (typeof willBeActive === 'undefined') { + return false; + } + + return !_emberMetalProperty_get.get(this, 'active') && willBeActive && 'ember-transitioning-in'; + }), + + transitioningOut: _emberMetalComputed.computed('active', 'willBeActive', function computeLinkToComponentTransitioningOut() { + var willBeActive = _emberMetalProperty_get.get(this, 'willBeActive'); + if (typeof willBeActive === 'undefined') { + return false; + } + + return _emberMetalProperty_get.get(this, 'active') && !willBeActive && 'ember-transitioning-out'; + }), + + /** + Event handler that invokes the link, activating the associated route. + @private + @method _invoke + @param {Event} event + @private + */ + _invoke: function (event) { + if (!_emberViewsSystemUtils.isSimpleClick(event)) { + return true; + } + + var preventDefault = _emberMetalProperty_get.get(this, 'preventDefault'); + var targetAttribute = _emberMetalProperty_get.get(this, 'target'); + + if (preventDefault !== false) { + if (!targetAttribute || targetAttribute === '_self') { + event.preventDefault(); + } + } + + if (_emberMetalProperty_get.get(this, 'bubbles') === false) { + event.stopPropagation(); + } + + if (_emberMetalProperty_get.get(this, '_isDisabled')) { + return false; + } + + if (_emberMetalProperty_get.get(this, 'loading')) { + _emberMetalLogger.default.warn('This link-to is in an inactive loading state because at least one of its parameters presently has a null/undefined value, or the provided route name is invalid.'); + return false; + } + + if (targetAttribute && targetAttribute !== '_self') { + return false; + } + + var routing = _emberMetalProperty_get.get(this, '_routing'); + var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName'); + var models = _emberMetalProperty_get.get(this, 'models'); + var queryParamValues = _emberMetalProperty_get.get(this, 'queryParams.values'); + var shouldReplace = _emberMetalProperty_get.get(this, 'replace'); + + routing.transitionTo(qualifiedRouteName, models, queryParamValues, shouldReplace); + }, + + queryParams: null, + + qualifiedRouteName: _emberMetalComputed.computed('targetRouteName', '_routing.currentState', function computeLinkToComponentQualifiedRouteName() { + var params = _emberMetalProperty_get.get(this, 'params').slice(); + var lastParam = params[params.length - 1]; + if (lastParam && lastParam.isQueryParams) { + params.pop(); + } + var onlyQueryParamsSupplied = this[_emberHtmlbarsNodeManagersComponentNodeManager.HAS_BLOCK] ? params.length === 0 : params.length === 1; + if (onlyQueryParamsSupplied) { + return _emberMetalProperty_get.get(this, '_routing.currentRouteName'); + } + return _emberMetalProperty_get.get(this, 'targetRouteName'); + }), + + resolvedQueryParams: _emberMetalComputed.computed('queryParams', function computeLinkToComponentResolvedQueryParams() { + var resolvedQueryParams = {}; + var queryParams = _emberMetalProperty_get.get(this, 'queryParams'); + + if (!queryParams) { + return resolvedQueryParams; + } + + var values = queryParams.values; + for (var key in values) { + if (!values.hasOwnProperty(key)) { + continue; + } + resolvedQueryParams[key] = values[key]; + } + + return resolvedQueryParams; + }), + + /** + Sets the element's `href` attribute to the url for + the `LinkComponent`'s targeted route. + If the `LinkComponent`'s `tagName` is changed to a value other + than `a`, this property will be ignored. + @property href + @private + */ + href: _emberMetalComputed.computed('models', 'qualifiedRouteName', function computeLinkToComponentHref() { + if (_emberMetalProperty_get.get(this, 'tagName') !== 'a') { + return; + } + + var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName'); + var models = _emberMetalProperty_get.get(this, 'models'); + + if (_emberMetalProperty_get.get(this, 'loading')) { + return _emberMetalProperty_get.get(this, 'loadingHref'); + } + + var routing = _emberMetalProperty_get.get(this, '_routing'); + var queryParams = _emberMetalProperty_get.get(this, 'queryParams.values'); + return routing.generateURL(qualifiedRouteName, models, queryParams); + }), + + loading: _emberMetalComputed.computed('_modelsAreLoaded', 'qualifiedRouteName', function computeLinkToComponentLoading() { + var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName'); + var modelsAreLoaded = _emberMetalProperty_get.get(this, '_modelsAreLoaded'); + + if (!modelsAreLoaded || qualifiedRouteName == null) { + return _emberMetalProperty_get.get(this, 'loadingClass'); + } + }), + + _modelsAreLoaded: _emberMetalComputed.computed('models', function computeLinkToComponentModelsAreLoaded() { + var models = _emberMetalProperty_get.get(this, 'models'); + for (var i = 0, l = models.length; i < l; i++) { + if (models[i] == null) { + return false; + } + } + + return true; + }), + + _getModels: function (params) { + var modelCount = params.length - 1; + var models = new Array(modelCount); + + for (var i = 0; i < modelCount; i++) { + var value = params[i + 1]; + + while (_emberRuntimeMixinsController.default.detect(value)) { + value = value.get('model'); + } + + models[i] = value; + } + + return models; + }, + + /** + The default href value to use while a link-to is loading. + Only applies when tagName is 'a' + @property loadingHref + @type String + @default # + @private + */ + loadingHref: '#', + + willRender: function () { + var queryParams = undefined; + + // Do not mutate params in place + var params = _emberMetalProperty_get.get(this, 'params').slice(); + + var disabledWhen = _emberMetalProperty_get.get(this, 'disabledWhen'); + if (disabledWhen !== undefined) { + this.set('disabled', disabledWhen); + } + + // Process the positional arguments, in order. + // 1. Inline link title comes first, if present. + if (!this[_emberHtmlbarsNodeManagersComponentNodeManager.HAS_BLOCK]) { + this.set('linkTitle', params.shift()); + } + + // 2. `targetRouteName` is now always at index 0. + this.set('targetRouteName', params[0]); + + // 3. The last argument (if still remaining) is the `queryParams` object. + var lastParam = params[params.length - 1]; + + if (lastParam && lastParam.isQueryParams) { + queryParams = params.pop(); + } else { + queryParams = {}; + } + this.set('queryParams', queryParams); + + // 4. Any remaining indices (excepting `targetRouteName` at 0) are `models`. + if (params.length > 1) { + this.set('models', this._getModels(params)); + } else { + this.set('models', []); + } } + }); + + LinkComponent.toString = function () { + return 'LinkComponent'; }; - exports.InteractiveRenderer = InteractiveRenderer; + + LinkComponent.reopenClass({ + positionalParams: 'params' + }); + + exports.default = LinkComponent; }); -enifed('ember-metal-views/index', ['exports', 'ember-metal-views/htmlbars-renderer'], function (exports, _emberMetalViewsHtmlbarsRenderer) { +// creates inject.service +enifed('ember-routing-views/index', ['exports', 'ember-metal/core', 'ember-routing-views/components/link-to', 'ember-routing-views/views/outlet'], function (exports, _emberMetalCore, _emberRoutingViewsComponentsLinkTo, _emberRoutingViewsViewsOutlet) { + /** + @module ember + @submodule ember-routing-views + */ + 'use strict'; - function _interopExportWildcard(obj, defaults) { var newObj = defaults({}, obj); delete newObj['default']; return newObj; } + _emberMetalCore.default.LinkComponent = _emberRoutingViewsComponentsLinkTo.default; + _emberMetalCore.default.OutletView = _emberRoutingViewsViewsOutlet.OutletView; - function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; } + exports.default = _emberMetalCore.default; +}); +enifed('ember-routing-views/views/outlet', ['exports', 'ember-views/views/view', 'ember-htmlbars/templates/top-level-view'], function (exports, _emberViewsViewsView, _emberHtmlbarsTemplatesTopLevelView) { + /** + @module ember + @submodule ember-routing-views + */ - _defaults(exports, _interopExportWildcard(_emberMetalViewsHtmlbarsRenderer, _defaults)); + 'use strict'; + + var CoreOutletView = _emberViewsViewsView.default.extend({ + defaultTemplate: _emberHtmlbarsTemplatesTopLevelView.default, + + init: function () { + this._super(); + this._outlets = []; + }, + + setOutletState: function (state) { + this.outletState = { main: state }; + + if (this.env) { + this.env.outletState = this.outletState; + } + + if (this.lastResult) { + this.dirtyOutlets(); + this._outlets = []; + + this.scheduleRevalidate(null, null); + } + }, + + dirtyOutlets: function () { + // Dirty any render nodes that correspond to outlets + for (var i = 0; i < this._outlets.length; i++) { + this._outlets[i].isDirty = true; + } + } + }); + + exports.CoreOutletView = CoreOutletView; + var OutletView = CoreOutletView.extend({ tagName: '' }); + exports.OutletView = OutletView; }); enifed('ember-routing/ext/controller', ['exports', 'ember-metal/property_get', 'ember-runtime/mixins/controller'], function (exports, _emberMetalProperty_get, _emberRuntimeMixinsController) { 'use strict'; /** @@ -23199,11 +24887,11 @@ // remove trailing slashes if they exists rootURL = rootURL.replace(/\/$/, ''); baseURL = baseURL.replace(/\/$/, ''); // remove baseURL and rootURL from start of path - var url = path.replace(new RegExp('^' + baseURL), '').replace(new RegExp('^' + rootURL), ''); + var url = path.replace(new RegExp('^' + baseURL + '(?=/|$)'), '').replace(new RegExp('^' + rootURL + '(?=/|$)'), ''); var search = location.search || ''; url += search; url += this.getHash(); @@ -23405,11 +25093,11 @@ // remove trailing slashes if they exists rootURL = rootURL.replace(/\/$/, ''); // remove rootURL from url - return path.replace(new RegExp('^' + rootURL), ''); + return path.replace(new RegExp('^' + rootURL + '(?=/|$)'), ''); }, /** Set the path and remembers what was set. Using this method to change the path will not invoke the `updateURL` callback. @@ -27396,1721 +29084,10 @@ accum[key] = tmp; } } }); -enifed('ember-routing-htmlbars/helpers/query-params', ['exports', 'ember-metal/debug', 'ember-routing/system/query_params'], function (exports, _emberMetalDebug, _emberRoutingSystemQuery_params) { - /** - @module ember - @submodule ember-routing-htmlbars - */ - - 'use strict'; - - exports.queryParamsHelper = queryParamsHelper; - - /** - This is a helper to be used in conjunction with the link-to helper. - It will supply url query parameters to the target route. - - Example - - ```handlebars - {{#link-to 'posts' (query-params direction="asc")}}Sort{{/link-to}} - ``` - - @method query-params - @for Ember.Templates.helpers - @param {Object} hash takes a hash of query parameters - @return {Object} A `QueryParams` object for `{{link-to}}` - @public - */ - - function queryParamsHelper(params, hash) { - - return _emberRoutingSystemQuery_params.default.create({ - values: hash - }); - } -}); -enifed('ember-routing-htmlbars/index', ['exports', 'ember-metal/core', 'ember-htmlbars/helpers', 'ember-htmlbars/keywords', 'ember-routing-htmlbars/helpers/query-params', 'ember-routing-htmlbars/keywords/action', 'ember-routing-htmlbars/keywords/element-action', 'ember-routing-htmlbars/keywords/render'], function (exports, _emberMetalCore, _emberHtmlbarsHelpers, _emberHtmlbarsKeywords, _emberRoutingHtmlbarsHelpersQueryParams, _emberRoutingHtmlbarsKeywordsAction, _emberRoutingHtmlbarsKeywordsElementAction, _emberRoutingHtmlbarsKeywordsRender) { - /** - @module ember - @submodule ember-routing-htmlbars - */ - - 'use strict'; - - _emberHtmlbarsHelpers.registerHelper('query-params', _emberRoutingHtmlbarsHelpersQueryParams.queryParamsHelper); - - _emberHtmlbarsKeywords.registerKeyword('action', _emberRoutingHtmlbarsKeywordsAction.default); - _emberHtmlbarsKeywords.registerKeyword('@element_action', _emberRoutingHtmlbarsKeywordsElementAction.default); - _emberHtmlbarsKeywords.registerKeyword('render', _emberRoutingHtmlbarsKeywordsRender.default); - - exports.default = _emberMetalCore.default; -}); -enifed('ember-routing-htmlbars/keywords/action', ['exports', 'htmlbars-runtime/hooks', 'ember-routing-htmlbars/keywords/closure-action'], function (exports, _htmlbarsRuntimeHooks, _emberRoutingHtmlbarsKeywordsClosureAction) { - /** - @module ember - @submodule ember-templates - */ - - 'use strict'; - - /** - The `{{action}}` helper provides a way to pass triggers for behavior (usually - just a function) between components, and into components from controllers. - - ### Passing functions with the action helper - - There are three contexts an action helper can be used in. The first two - contexts to discuss are attribute context, and Handlebars value context. - - ```handlebars - {{! An example of attribute context }} - <div onclick={{action "save"}}></div> - {{! Examples of Handlebars value context }} - {{input on-input=(action "save")}} - {{yield (action "refreshData") andAnotherParam}} - ``` - - In these contexts, - the helper is called a "closure action" helper. Its behavior is simple: - If passed a function name, read that function off the `actions` property - of the current context. Once that function is read (or if a function was - passed), create a closure over that function and any arguments. - - The resulting value of an action helper used this way is simply a function. - For example, in the attribute context: - - ```handlebars - {{! An example of attribute context }} - <div onclick={{action "save"}}></div> - ``` - - The resulting template render logic would be: - - ```js - var div = document.createElement('div'); - var actionFunction = (function(context){ - return function() { - return context.actions.save.apply(context, arguments); - }; - })(context); - div.onclick = actionFunction; - ``` - - Thus when the div is clicked, the action on that context is called. - Because the `actionFunction` is just a function, closure actions can be - passed between components and still execute in the correct context. - - Here is an example action handler on a component: - - ```js - export default Ember.Component.extend({ - actions: { - save() { - this.get('model').save(); - } - } - }); - ``` - - Actions are always looked up on the `actions` property of the current context. - This avoids collisions in the naming of common actions, such as `destroy`. - - Two options can be passed to the `action` helper when it is used in this way. - - * `target=someProperty` will look to `someProperty` instead of the current - context for the `actions` hash. This can be useful when targetting a - service for actions. - * `value="target.value"` will read the path `target.value` off the first - argument to the action when it is called and rewrite the first argument - to be that value. This is useful when attaching actions to event listeners. - - ### Invoking an action - - Closure actions curry both their scope and any arguments. When invoked, any - additional arguments are added to the already curried list. - - Actions should be invoked using the [sendAction](/api/classes/Ember.Component.html#method_sendAction) - method. The first argument to `sendAction` is the action to be called, and - additional arguments are passed to the action function. This has interesting - properties combined with currying of arguments. For example: - - ```js - export default Ember.Component.extend({ - actions: { - // Usage {{input on-input=(action (action 'setName' model) value="target.value")}} - setName(model, name) { - model.set('name', name); - } - } - }); - ``` - - The first argument (`model`) was curried over, and the run-time argument (`event`) - becomes a second argument. Action calls can be nested this way because each simply - returns a function. Any function can be passed to the `{{action}}` helper, including - other actions. - - Actions invoked with `sendAction` have the same currying behavior as demonstrated - with `on-input` above. For example: - - ```js - export default Ember.Component.extend({ - actions: { - setName(model, name) { - model.set('name', name); - } - } - }); - ``` - - ```handlebars - {{my-input submit=(action 'setName' model)}} - ``` - - ```js - // app/components/my-component.js - export default Ember.Component.extend({ - click() { - // Note that model is not passed, it was curried in the template - this.sendAction('submit', 'bob'); - } - }); - ``` - - ### Attaching actions to DOM elements - - The third context of the `{{action}}` helper can be called "element space". - For example: - - ```handlebars - {{! An example of element space }} - <div {{action "save"}}></div> - ``` - - Used this way, the `{{action}}` helper provides a useful shortcut for - registering an HTML element in a template for a single DOM event and - forwarding that interaction to the template's context (controller or component). - - If the context of a template is a controller, actions used this way will - bubble to routes when the controller does not implement the specified action. - Once an action hits a route, it will bubble through the route hierarchy. - - ### Event Propagation - - `{{action}}` helpers called in element space can control event bubbling. Note - that the closure style actions cannot. - - Events triggered through the action helper will automatically have - `.preventDefault()` called on them. You do not need to do so in your event - handlers. If you need to allow event propagation (to handle file inputs for - example) you can supply the `preventDefault=false` option to the `{{action}}` helper: - - ```handlebars - <div {{action "sayHello" preventDefault=false}}> - <input type="file" /> - <input type="checkbox" /> - </div> - ``` - - To disable bubbling, pass `bubbles=false` to the helper: - - ```handlebars - <button {{action 'edit' post bubbles=false}}>Edit</button> - ``` - - To disable bubbling with closure style actions you must create your own - wrapper helper that makes use of `event.stopPropagation()`: - - ```handlebars - <div onclick={{disable-bubbling (action "sayHello")}}>Hello</div> - ``` - - ```js - // app/helpers/disable-bubbling.js - import Ember from 'ember'; - - export function disableBubbling([action]) { - return function(event) { - event.stopPropagation(); - - return action(event); - }; - } - - export default Ember.Helper.helper(disableBubbling); - ``` - - If you need the default handler to trigger you should either register your - own event handler, or use event methods on your view class. See - ["Responding to Browser Events"](/api/classes/Ember.View.html#toc_responding-to-browser-events) - in the documentation for Ember.View for more information. - - ### Specifying DOM event type - - `{{action}}` helpers called in element space can specify an event type. - - By default the `{{action}}` helper registers for DOM `click` events. You can - supply an `on` option to the helper to specify a different DOM event name: - - ```handlebars - <div {{action "anActionName" on="doubleClick"}}> - click me - </div> - ``` - - See ["Event Names"](/api/classes/Ember.View.html#toc_event-names) for a list of - acceptable DOM event names. - - ### Specifying whitelisted modifier keys - - `{{action}}` helpers called in element space can specify modifier keys. - - By default the `{{action}}` helper will ignore click events with pressed modifier - keys. You can supply an `allowedKeys` option to specify which keys should not be ignored. - - ```handlebars - <div {{action "anActionName" allowedKeys="alt"}}> - click me - </div> - ``` - - This way the action will fire when clicking with the alt key pressed down. - - Alternatively, supply "any" to the `allowedKeys` option to accept any combination of modifier keys. - - ```handlebars - <div {{action "anActionName" allowedKeys="any"}}> - click me with any key pressed - </div> - ``` - - ### Specifying a Target - - A `target` option can be provided to the helper to change - which object will receive the method call. This option must be a path - to an object, accessible in the current context: - - ```handlebars - {{! app/templates/application.hbs }} - <div {{action "anActionName" target=someService}}> - click me - </div> - ``` - - ```javascript - // app/controllers/application.js - export default Ember.Controller.extend({ - someService: Ember.inject.service() - }); - ``` - - @method action - @for Ember.Templates.helpers - @public - */ - - exports.default = function (morph, env, scope, params, hash, template, inverse, visitor) { - if (morph) { - _htmlbarsRuntimeHooks.keyword('@element_action', morph, env, scope, params, hash, template, inverse, visitor); - return true; - } - - return _emberRoutingHtmlbarsKeywordsClosureAction.default(morph, env, scope, params, hash, template, inverse, visitor); - }; -}); -enifed('ember-routing-htmlbars/keywords/closure-action', ['exports', 'ember-metal/streams/stream', 'ember-metal/streams/utils', 'ember-metal/symbol', 'ember-metal/property_get', 'ember-htmlbars/hooks/subexpr', 'ember-metal/error', 'ember-metal/run_loop', 'ember-metal/instrumentation', 'ember-metal/is_none'], function (exports, _emberMetalStreamsStream, _emberMetalStreamsUtils, _emberMetalSymbol, _emberMetalProperty_get, _emberHtmlbarsHooksSubexpr, _emberMetalError, _emberMetalRun_loop, _emberMetalInstrumentation, _emberMetalIs_none) { - 'use strict'; - - exports.default = closureAction; - var INVOKE = _emberMetalSymbol.default('INVOKE'); - exports.INVOKE = INVOKE; - var ACTION = _emberMetalSymbol.default('ACTION'); - - exports.ACTION = ACTION; - - function closureAction(morph, env, scope, params, hash, template, inverse, visitor) { - var s = new _emberMetalStreamsStream.Stream(function () { - var rawAction = params[0]; - var actionArguments = _emberMetalStreamsUtils.readArray(params.slice(1, params.length)); - - var target = undefined, - action = undefined, - valuePath = undefined; - - if (_emberMetalIs_none.default(rawAction)) { - var label = _emberHtmlbarsHooksSubexpr.labelForSubexpr(params, hash, 'action'); - throw new _emberMetalError.default('Action passed is null or undefined in ' + label + ' from ' + _emberMetalStreamsUtils.read(scope.getSelf()) + '.'); - } else if (rawAction[INVOKE]) { - // on-change={{action (mut name)}} - target = rawAction; - action = rawAction[INVOKE]; - } else { - // on-change={{action setName}} - // element-space actions look to "controller" then target. Here we only - // look to "target". - target = _emberMetalStreamsUtils.read(scope.getSelf()); - action = _emberMetalStreamsUtils.read(rawAction); - var actionType = typeof action; - - if (actionType === 'string') { - var actionName = action; - action = null; - // on-change={{action 'setName'}} - if (hash.target) { - // on-change={{action 'setName' target=alternativeComponent}} - target = _emberMetalStreamsUtils.read(hash.target); - } - if (target.actions) { - action = target.actions[actionName]; - } - - if (!action) { - throw new _emberMetalError.default('An action named \'' + actionName + '\' was not found in ' + target + '.'); - } - } else if (action && typeof action[INVOKE] === 'function') { - target = action; - action = action[INVOKE]; - } else if (actionType !== 'function') { - throw new _emberMetalError.default('An action could not be made for `' + rawAction.label + '` in ' + target + '. Please confirm that you are using either a quoted action name (i.e. `(action \'' + rawAction.label + '\')`) or a function available in ' + target + '.'); - } - } - - if (hash.value) { - // <button on-keypress={{action (mut name) value="which"}} - // on-keypress is not even an Ember feature yet - valuePath = _emberMetalStreamsUtils.read(hash.value); - } - - return createClosureAction(this, target, action, valuePath, actionArguments); - }, function () { - return _emberHtmlbarsHooksSubexpr.labelForSubexpr(params, hash, 'action'); - }); - - params.forEach(s.addDependency, s); - Object.keys(hash).forEach(function (item) { - return s.addDependency(item); - }); - - return s; - } - - function createClosureAction(stream, target, action, valuePath, actionArguments) { - var closureAction; - - if (actionArguments.length > 0) { - closureAction = function () { - var args = actionArguments; - - for (var _len = arguments.length, passedArguments = Array(_len), _key = 0; _key < _len; _key++) { - passedArguments[_key] = arguments[_key]; - } - - if (passedArguments.length > 0) { - args = actionArguments.concat(passedArguments); - } - if (valuePath && args.length > 0) { - args[0] = _emberMetalProperty_get.get(args[0], valuePath); - } - - var payload = { target: target, args: args, label: _emberMetalStreamsUtils.labelFor(stream) }; - return _emberMetalInstrumentation.flaggedInstrument('interaction.ember-action', payload, function () { - return _emberMetalRun_loop.default.join.apply(_emberMetalRun_loop.default, [target, action].concat(args)); - }); - }; - } else { - closureAction = function () { - for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - if (valuePath && args.length > 0) { - args[0] = _emberMetalProperty_get.get(args[0], valuePath); - } - - var payload = { target: target, args: args, label: _emberMetalStreamsUtils.labelFor(stream) }; - return _emberMetalInstrumentation.flaggedInstrument('interaction.ember-action', payload, function () { - return _emberMetalRun_loop.default.join.apply(_emberMetalRun_loop.default, [target, action].concat(args)); - }); - }; - } - - closureAction[ACTION] = true; - - return closureAction; - } -}); -enifed('ember-routing-htmlbars/keywords/element-action', ['exports', 'ember-metal/debug', 'ember-metal/utils', 'ember-metal/streams/utils', 'ember-metal/run_loop', 'ember-views/streams/utils', 'ember-views/system/utils', 'ember-views/system/action_manager'], function (exports, _emberMetalDebug, _emberMetalUtils, _emberMetalStreamsUtils, _emberMetalRun_loop, _emberViewsStreamsUtils, _emberViewsSystemUtils, _emberViewsSystemAction_manager) { - 'use strict'; - - exports.default = { - setupState: function (state, env, scope, params, hash) { - var getStream = env.hooks.get; - var read = env.hooks.getValue; - - var actionName = read(params[0]); - - var actionArgs = []; - for (var i = 1, l = params.length; i < l; i++) { - actionArgs.push(_emberViewsStreamsUtils.readUnwrappedModel(params[i])); - } - - var target; - if (hash.target) { - if (typeof hash.target === 'string') { - target = read(getStream(env, scope, hash.target)); - } else { - target = read(hash.target); - } - } else { - target = read(scope.getLocal('controller')) || read(scope.getSelf()); - } - - return { actionName: actionName, actionArgs: actionArgs, target: target }; - }, - - isStable: function (state, env, scope, params, hash) { - return true; - }, - - render: function (node, env, scope, params, hash, template, inverse, visitor) { - var actionId = env.dom.getAttribute(node.element, 'data-ember-action') || _emberMetalUtils.uuid(); - - ActionHelper.registerAction({ - actionId: actionId, - node: node, - eventName: hash.on || 'click', - bubbles: hash.bubbles, - preventDefault: hash.preventDefault, - withKeyCode: hash.withKeyCode, - allowedKeys: hash.allowedKeys - }); - - node.cleanup = function () { - ActionHelper.unregisterAction(actionId); - }; - - env.dom.setAttribute(node.element, 'data-ember-action', actionId); - } - }; - var ActionHelper = {}; - - exports.ActionHelper = ActionHelper; - // registeredActions is re-exported for compatibility with older plugins - // that were using this undocumented API. - ActionHelper.registeredActions = _emberViewsSystemAction_manager.default.registeredActions; - - ActionHelper.registerAction = function (_ref) { - var actionId = _ref.actionId; - var node = _ref.node; - var eventName = _ref.eventName; - var preventDefault = _ref.preventDefault; - var bubbles = _ref.bubbles; - var allowedKeys = _ref.allowedKeys; - - var actions = _emberViewsSystemAction_manager.default.registeredActions[actionId]; - - if (!actions) { - actions = _emberViewsSystemAction_manager.default.registeredActions[actionId] = []; - } - - actions.push({ - eventName: eventName, - handler: function (event) { - if (!isAllowedEvent(event, _emberMetalStreamsUtils.read(allowedKeys))) { - return true; - } - - if (_emberMetalStreamsUtils.read(preventDefault) !== false) { - event.preventDefault(); - } - - if (_emberMetalStreamsUtils.read(bubbles) === false) { - event.stopPropagation(); - } - - var _node$getState = node.getState(); - - var target = _node$getState.target; - var actionName = _node$getState.actionName; - var actionArgs = _node$getState.actionArgs; - - _emberMetalRun_loop.default(function runRegisteredAction() { - if (typeof actionName === 'function') { - actionName.apply(target, actionArgs); - return; - } - if (target.send) { - target.send.apply(target, [actionName].concat(actionArgs)); - } else { - - target[actionName].apply(target, actionArgs); - } - }); - } - }); - - return actionId; - }; - - ActionHelper.unregisterAction = function (actionId) { - delete _emberViewsSystemAction_manager.default.registeredActions[actionId]; - }; - - var MODIFIERS = ['alt', 'shift', 'meta', 'ctrl']; - var POINTER_EVENT_TYPE_REGEX = /^click|mouse|touch/; - - function isAllowedEvent(event, allowedKeys) { - if (typeof allowedKeys === 'undefined') { - if (POINTER_EVENT_TYPE_REGEX.test(event.type)) { - return _emberViewsSystemUtils.isSimpleClick(event); - } else { - allowedKeys = ''; - } - } - - if (allowedKeys.indexOf('any') >= 0) { - return true; - } - - for (var i = 0, l = MODIFIERS.length; i < l; i++) { - if (event[MODIFIERS[i] + 'Key'] && allowedKeys.indexOf(MODIFIERS[i]) === -1) { - return false; - } - } - - return true; - } -}); -enifed('ember-routing-htmlbars/keywords/render', ['exports', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/empty_object', 'ember-metal/error', 'ember-metal/streams/utils', 'ember-runtime/system/string', 'ember-routing/system/generate_controller', 'ember-htmlbars/node-managers/view-node-manager'], function (exports, _emberMetalDebug, _emberMetalProperty_get, _emberMetalEmpty_object, _emberMetalError, _emberMetalStreamsUtils, _emberRuntimeSystemString, _emberRoutingSystemGenerate_controller, _emberHtmlbarsNodeManagersViewNodeManager) { - /** - @module ember - @submodule ember-templates - */ - - 'use strict'; - - /** - Calling ``{{render}}`` from within a template will insert another - template that matches the provided name. The inserted template will - access its properties on its own controller (rather than the controller - of the parent template). - If a view class with the same name exists, the view class also will be used. - Note: A given controller may only be used *once* in your app in this manner. - A singleton instance of the controller will be created for you. - Example: - - ```javascript - App.NavigationController = Ember.Controller.extend({ - who: "world" - }); - ``` - - ```handlebars - <!-- navigation.hbs --> - Hello, {{who}}. - ``` - - ```handlebars - <!-- application.hbs --> - <h1>My great app</h1> - {{render "navigation"}} - ``` - - ```html - <h1>My great app</h1> - <div class='ember-view'> - Hello, world. - </div> - ``` - - Optionally you may provide a second argument: a property path - that will be bound to the `model` property of the controller. - If a `model` property path is specified, then a new instance of the - controller will be created and `{{render}}` can be used multiple times - with the same name. - - For example if you had this `author` template. - - ```handlebars - <div class="author"> - Written by {{firstName}} {{lastName}}. - Total Posts: {{postCount}} - </div> - ``` - - You could render it inside the `post` template using the `render` helper. - - ```handlebars - <div class="post"> - <h1>{{title}}</h1> - <div>{{body}}</div> - {{render "author" author}} - </div> - ``` - - @method render - @for Ember.Templates.helpers - @param {String} name - @param {Object?} context - @param {Hash} options - @return {String} HTML string - @public - */ - exports.default = { - willRender: function (renderNode, env) { - if (env.view.ownerView._outlets) { - // We make sure we will get dirtied when outlet state changes. - env.view.ownerView._outlets.push(renderNode); - } - }, - - setupState: function (prevState, env, scope, params, hash) { - var name = params[0]; - - return { - parentView: env.view, - manager: prevState.manager, - controller: prevState.controller, - childOutletState: childOutletState(name, env) - }; - }, - - childEnv: function (state, env) { - return env.childWithOutletState(state.childOutletState); - }, - - isStable: function (lastState, nextState) { - return isStable(lastState.childOutletState, nextState.childOutletState); - }, - - isEmpty: function (state) { - return false; - }, - - render: function (node, env, scope, params, hash, template, inverse, visitor) { - var state = node.getState(); - var name = params[0]; - var context = params[1]; - - var owner = env.owner; - - // The render keyword presumes it can work without a router. This is really - // only to satisfy the test: - // - // {{view}} should not override class bindings defined on a child view" - // - var router = owner.lookup('router:main'); - - if (params.length === 1) {} else if (params.length !== 2) { - throw new _emberMetalError.default('You must pass a templateName to render'); - } - - var templateName = 'template:' + name; - - var view = owner.lookup('view:' + name); - if (!view) { - view = owner.lookup('view:default'); - } - var viewHasTemplateSpecified = view && !!_emberMetalProperty_get.get(view, 'template'); - if (!template && !viewHasTemplateSpecified) { - template = owner.lookup(templateName); - } - - if (view) { - view.ownerView = env.view.ownerView; - } - - // provide controller override - var controllerName; - var controllerFullName; - - if (hash.controller) { - controllerName = hash.controller; - controllerFullName = 'controller:' + controllerName; - delete hash.controller; - } else { - controllerName = name; - controllerFullName = 'controller:' + controllerName; - } - - var target = router; - var controller; - - // choose name - if (params.length > 1) { - var factory = owner._lookupFactory(controllerFullName) || _emberRoutingSystemGenerate_controller.generateControllerFactory(owner, controllerName); - - controller = factory.create({ - model: _emberMetalStreamsUtils.read(context), - target: target - }); - - node.addDestruction(controller); - } else { - controller = owner.lookup(controllerFullName) || _emberRoutingSystemGenerate_controller.default(owner, controllerName); - - controller.setProperties({ - target: target - }); - } - - if (view) { - view.set('controller', controller); - } - state.controller = controller; - - hash.viewName = _emberRuntimeSystemString.camelize(name); - - if (template && template.raw) { - template = template.raw; - } - - var options = { - layout: null, - self: controller - }; - - if (view) { - options.component = view; - } - - var nodeManager = _emberHtmlbarsNodeManagersViewNodeManager.default.create(node, env, hash, options, state.parentView, null, null, template); - state.manager = nodeManager; - - if (router && params.length === 1) { - router._connectActiveComponentNode(name, nodeManager); - } - - nodeManager.render(env, hash, visitor); - }, - - rerender: function (node, env, scope, params, hash, template, inverse, visitor) { - if (params.length > 1) { - var model = _emberMetalStreamsUtils.read(params[1]); - node.getState().controller.set('model', model); - } - } - }; - - function childOutletState(name, env) { - var topLevel = env.view.ownerView; - if (!topLevel || !topLevel.outletState) { - return; - } - - var outletState = topLevel.outletState; - if (!outletState.main) { - return; - } - - var selectedOutletState = outletState.main.outlets['__ember_orphans__']; - if (!selectedOutletState) { - return; - } - var matched = selectedOutletState.outlets[name]; - if (matched) { - var childState = new _emberMetalEmpty_object.default(); - childState[matched.render.outlet] = matched; - matched.wasUsed = true; - return childState; - } - } - - function isStable(a, b) { - if (!a && !b) { - return true; - } - if (!a || !b) { - return false; - } - for (var outletName in a) { - if (!isStableOutlet(a[outletName], b[outletName])) { - return false; - } - } - return true; - } - - function isStableOutlet(a, b) { - if (!a && !b) { - return true; - } - if (!a || !b) { - return false; - } - a = a.render; - b = b.render; - for (var key in a) { - if (a.hasOwnProperty(key)) { - // name is only here for logging & debugging. If two different - // names result in otherwise identical states, they're still - // identical. - if (a[key] !== b[key] && key !== 'name') { - return false; - } - } - } - return true; - } -}); - -// use the singleton controller -enifed('ember-routing-views/components/link-to', ['exports', 'ember-metal/features', 'ember-metal/logger', 'ember-metal/debug', 'ember-metal/property_get', 'ember-metal/computed', 'ember-metal/computed_macros', 'ember-views/system/utils', 'ember-views/components/component', 'ember-runtime/inject', 'ember-runtime/system/service', 'ember-runtime/mixins/controller', 'ember-htmlbars/node-managers/component-node-manager', 'ember-htmlbars/templates/link-to', 'require'], function (exports, _emberMetalFeatures, _emberMetalLogger, _emberMetalDebug, _emberMetalProperty_get, _emberMetalComputed, _emberMetalComputed_macros, _emberViewsSystemUtils, _emberViewsComponentsComponent, _emberRuntimeInject, _emberRuntimeSystemService, _emberRuntimeMixinsController, _emberHtmlbarsNodeManagersComponentNodeManager, _emberHtmlbarsTemplatesLinkTo, _require) { - /** - @module ember - @submodule ember-templates - */ - - /** - The `{{link-to}}` component renders a link to the supplied - `routeName` passing an optionally supplied model to the - route as its `model` context of the route. The block - for `{{link-to}}` becomes the innerHTML of the rendered - element: - - ```handlebars - {{#link-to 'photoGallery'}} - Great Hamster Photos - {{/link-to}} - ``` - - You can also use an inline form of `{{link-to}}` component by - passing the link text as the first argument - to the component: - - ```handlebars - {{link-to 'Great Hamster Photos' 'photoGallery'}} - ``` - - Both will result in: - - ```html - <a href="/hamster-photos"> - Great Hamster Photos - </a> - ``` - - ### Supplying a tagName - By default `{{link-to}}` renders an `<a>` element. This can - be overridden for a single use of `{{link-to}}` by supplying - a `tagName` option: - - ```handlebars - {{#link-to 'photoGallery' tagName="li"}} - Great Hamster Photos - {{/link-to}} - ``` - - ```html - <li> - Great Hamster Photos - </li> - ``` - - To override this option for your entire application, see - "Overriding Application-wide Defaults". - - ### Disabling the `link-to` component - By default `{{link-to}}` is enabled. - any passed value to the `disabled` component property will disable - the `link-to` component. - - static use: the `disabled` option: - - ```handlebars - {{#link-to 'photoGallery' disabled=true}} - Great Hamster Photos - {{/link-to}} - ``` - - dynamic use: the `disabledWhen` option: - - ```handlebars - {{#link-to 'photoGallery' disabledWhen=controller.someProperty}} - Great Hamster Photos - {{/link-to}} - ``` - - any passed value to `disabled` will disable it except `undefined`. - to ensure that only `true` disable the `link-to` component you can - override the global behaviour of `Ember.LinkComponent`. - - ```javascript - Ember.LinkComponent.reopen({ - disabled: Ember.computed(function(key, value) { - if (value !== undefined) { - this.set('_isDisabled', value === true); - } - return value === true ? get(this, 'disabledClass') : false; - }) - }); - ``` - - see "Overriding Application-wide Defaults" for more. - - ### Handling `href` - `{{link-to}}` will use your application's Router to - fill the element's `href` property with a url that - matches the path to the supplied `routeName` for your - router's configured `Location` scheme, which defaults - to Ember.HashLocation. - - ### Handling current route - `{{link-to}}` will apply a CSS class name of 'active' - when the application's current route matches - the supplied routeName. For example, if the application's - current route is 'photoGallery.recent' the following - use of `{{link-to}}`: - - ```handlebars - {{#link-to 'photoGallery.recent'}} - Great Hamster Photos - {{/link-to}} - ``` - - will result in - - ```html - <a href="/hamster-photos/this-week" class="active"> - Great Hamster Photos - </a> - ``` - - The CSS class name used for active classes can be customized - for a single use of `{{link-to}}` by passing an `activeClass` - option: - - ```handlebars - {{#link-to 'photoGallery.recent' activeClass="current-url"}} - Great Hamster Photos - {{/link-to}} - ``` - - ```html - <a href="/hamster-photos/this-week" class="current-url"> - Great Hamster Photos - </a> - ``` - - To override this option for your entire application, see - "Overriding Application-wide Defaults". - - ### Keeping a link active for other routes - - If you need a link to be 'active' even when it doesn't match - the current route, you can use the `current-when` argument. - - ```handlebars - {{#link-to 'photoGallery' current-when='photos'}} - Photo Gallery - {{/link-to}} - ``` - - This may be helpful for keeping links active for: - - * non-nested routes that are logically related - * some secondary menu approaches - * 'top navigation' with 'sub navigation' scenarios - - A link will be active if `current-when` is `true` or the current - route is the route this link would transition to. - - To match multiple routes 'space-separate' the routes: - - ```handlebars - {{#link-to 'gallery' current-when='photos drawings paintings'}} - Art Gallery - {{/link-to}} - ``` - - ### Supplying a model - An optional model argument can be used for routes whose - paths contain dynamic segments. This argument will become - the model context of the linked route: - - ```javascript - Router.map(function() { - this.route("photoGallery", {path: "hamster-photos/:photo_id"}); - }); - ``` - - ```handlebars - {{#link-to 'photoGallery' aPhoto}} - {{aPhoto.title}} - {{/link-to}} - ``` - - ```html - <a href="/hamster-photos/42"> - Tomster - </a> - ``` - - ### Supplying multiple models - For deep-linking to route paths that contain multiple - dynamic segments, multiple model arguments can be used. - As the router transitions through the route path, each - supplied model argument will become the context for the - route with the dynamic segments: - - ```javascript - Router.map(function() { - this.route("photoGallery", { path: "hamster-photos/:photo_id" }, function() { - this.route("comment", {path: "comments/:comment_id"}); - }); - }); - ``` - This argument will become the model context of the linked route: - - ```handlebars - {{#link-to 'photoGallery.comment' aPhoto comment}} - {{comment.body}} - {{/link-to}} - ``` - - ```html - <a href="/hamster-photos/42/comments/718"> - A+++ would snuggle again. - </a> - ``` - - ### Supplying an explicit dynamic segment value - If you don't have a model object available to pass to `{{link-to}}`, - an optional string or integer argument can be passed for routes whose - paths contain dynamic segments. This argument will become the value - of the dynamic segment: - - ```javascript - Router.map(function() { - this.route("photoGallery", { path: "hamster-photos/:photo_id" }); - }); - ``` - - ```handlebars - {{#link-to 'photoGallery' aPhotoId}} - {{aPhoto.title}} - {{/link-to}} - ``` - - ```html - <a href="/hamster-photos/42"> - Tomster - </a> - ``` - - When transitioning into the linked route, the `model` hook will - be triggered with parameters including this passed identifier. - - ### Allowing Default Action - - By default the `{{link-to}}` component prevents the default browser action - by calling `preventDefault()` as this sort of action bubbling is normally - handled internally and we do not want to take the browser to a new URL (for - example). - - If you need to override this behavior specify `preventDefault=false` in - your template: - - ```handlebars - {{#link-to 'photoGallery' aPhotoId preventDefault=false}} - {{aPhotoId.title}} - {{/link-to}} - ``` - - ### Overriding attributes - You can override any given property of the `Ember.LinkComponent` - that is generated by the `{{link-to}}` component by passing - key/value pairs, like so: - - ```handlebars - {{#link-to aPhoto tagName='li' title='Following this link will change your life' classNames='pic sweet'}} - Uh-mazing! - {{/link-to}} - ``` - - See [Ember.LinkComponent](/api/classes/Ember.LinkComponent.html) for a - complete list of overrideable properties. Be sure to also - check out inherited properties of `LinkComponent`. - - ### Overriding Application-wide Defaults - ``{{link-to}}`` creates an instance of `Ember.LinkComponent` - for rendering. To override options for your entire - application, reopen `Ember.LinkComponent` and supply the - desired values: - - ``` javascript - Ember.LinkComponent.reopen({ - activeClass: "is-active", - tagName: 'li' - }) - ``` - - It is also possible to override the default event in - this manner: - - ``` javascript - Ember.LinkComponent.reopen({ - eventName: 'customEventName' - }); - ``` - - @method link-to - @for Ember.Templates.helpers - @param {String} routeName - @param {Object} [context]* - @param [options] {Object} Handlebars key/value pairs of options, you can override any property of Ember.LinkComponent - @return {String} HTML string - @see {Ember.LinkComponent} - @public - */ - - /** - @module ember - @submodule ember-routing-views - */ - - 'use strict'; - - var layout = _emberHtmlbarsTemplatesLinkTo.default; - - /** - `Ember.LinkComponent` renders an element whose `click` event triggers a - transition of the application's instance of `Ember.Router` to - a supplied route by name. - - `Ember.LinkComponent` components are invoked with {{#link-to}}. Properties - of this class can be overridden with `reopen` to customize application-wide - behavior. - - @class LinkComponent - @namespace Ember - @extends Ember.Component - @see {Ember.Templates.helpers.link-to} - @private - **/ - var LinkComponent = _emberViewsComponentsComponent.default.extend({ - layout: layout, - - tagName: 'a', - - /** - @deprecated Use current-when instead. - @property currentWhen - @private - */ - currentWhen: _emberMetalComputed_macros.deprecatingAlias('current-when', { id: 'ember-routing-view.deprecated-current-when', until: '3.0.0' }), - - /** - Used to determine when this `LinkComponent` is active. - @property currentWhen - @public - */ - 'current-when': null, - - /** - Sets the `title` attribute of the `LinkComponent`'s HTML element. - @property title - @default null - @public - **/ - title: null, - - /** - Sets the `rel` attribute of the `LinkComponent`'s HTML element. - @property rel - @default null - @public - **/ - rel: null, - - /** - Sets the `tabindex` attribute of the `LinkComponent`'s HTML element. - @property tabindex - @default null - @public - **/ - tabindex: null, - - /** - Sets the `target` attribute of the `LinkComponent`'s HTML element. - @since 1.8.0 - @property target - @default null - @public - **/ - target: null, - - /** - The CSS class to apply to `LinkComponent`'s element when its `active` - property is `true`. - @property activeClass - @type String - @default active - @private - **/ - activeClass: 'active', - - /** - The CSS class to apply to `LinkComponent`'s element when its `loading` - property is `true`. - @property loadingClass - @type String - @default loading - @private - **/ - loadingClass: 'loading', - - /** - The CSS class to apply to a `LinkComponent`'s element when its `disabled` - property is `true`. - @property disabledClass - @type String - @default disabled - @private - **/ - disabledClass: 'disabled', - _isDisabled: false, - - /** - Determines whether the `LinkComponent` will trigger routing via - the `replaceWith` routing strategy. - @property replace - @type Boolean - @default false - @public - **/ - replace: false, - - /** - By default the `{{link-to}}` component will bind to the `href` and - `title` attributes. It's discouraged that you override these defaults, - however you can push onto the array if needed. - @property attributeBindings - @type Array | String - @default ['title', 'rel', 'tabindex', 'target'] - @public - */ - attributeBindings: ['href', 'title', 'rel', 'tabindex', 'target'], - - /** - By default the `{{link-to}}` component will bind to the `active`, `loading`, - and `disabled` classes. It is discouraged to override these directly. - @property classNameBindings - @type Array - @default ['active', 'loading', 'disabled', 'ember-transitioning-in', 'ember-transitioning-out'] - @public - */ - classNameBindings: ['active', 'loading', 'disabled', 'transitioningIn', 'transitioningOut'], - - /** - By default the `{{link-to}}` component responds to the `click` event. You - can override this globally by setting this property to your custom - event name. - This is particularly useful on mobile when one wants to avoid the 300ms - click delay using some sort of custom `tap` event. - @property eventName - @type String - @default click - @private - */ - eventName: 'click', - - // this is doc'ed here so it shows up in the events - // section of the API documentation, which is where - // people will likely go looking for it. - /** - Triggers the `LinkComponent`'s routing behavior. If - `eventName` is changed to a value other than `click` - the routing behavior will trigger on that custom event - instead. - @event click - @private - */ - - /** - An overridable method called when `LinkComponent` objects are instantiated. - Example: - ```javascript - App.MyLinkComponent = Ember.LinkComponent.extend({ - init: function() { - this._super(...arguments); - Ember.Logger.log('Event is ' + this.get('eventName')); - } - }); - ``` - NOTE: If you do override `init` for a framework class like `Ember.View`, - be sure to call `this._super(...arguments)` in your - `init` declaration! If you don't, Ember may not have an opportunity to - do important setup work, and you'll see strange behavior in your - application. - @method init - @private - */ - init: function () { - this._super.apply(this, arguments); - - // Map desired event name to invoke function - var eventName = _emberMetalProperty_get.get(this, 'eventName'); - this.on(eventName, this, this._invoke); - }, - - _routing: _emberRuntimeInject.default.service('-routing'), - - /** - Accessed as a classname binding to apply the `LinkComponent`'s `disabledClass` - CSS `class` to the element when the link is disabled. - When `true` interactions with the element will not trigger route changes. - @property disabled - @private - */ - disabled: _emberMetalComputed.computed({ - get: function (key, value) { - return false; - }, - set: function (key, value) { - if (value !== undefined) { - this.set('_isDisabled', value); - } - - return value ? _emberMetalProperty_get.get(this, 'disabledClass') : false; - } - }), - - _computeActive: function (routerState) { - if (_emberMetalProperty_get.get(this, 'loading')) { - return false; - } - - var routing = _emberMetalProperty_get.get(this, '_routing'); - var models = _emberMetalProperty_get.get(this, 'models'); - var resolvedQueryParams = _emberMetalProperty_get.get(this, 'resolvedQueryParams'); - - var currentWhen = _emberMetalProperty_get.get(this, 'current-when'); - var isCurrentWhenSpecified = !!currentWhen; - currentWhen = currentWhen || _emberMetalProperty_get.get(this, 'qualifiedRouteName'); - currentWhen = currentWhen.split(' '); - - for (var i = 0, len = currentWhen.length; i < len; i++) { - if (routing.isActiveForRoute(models, resolvedQueryParams, currentWhen[i], routerState, isCurrentWhenSpecified)) { - return _emberMetalProperty_get.get(this, 'activeClass'); - } - } - - return false; - }, - - /** - Accessed as a classname binding to apply the `LinkComponent`'s `activeClass` - CSS `class` to the element when the link is active. - A `LinkComponent` is considered active when its `currentWhen` property is `true` - or the application's current route is the route the `LinkComponent` would trigger - transitions into. - The `currentWhen` property can match against multiple routes by separating - route names using the ` ` (space) character. - @property active - @private - */ - active: _emberMetalComputed.computed('attrs.params', '_routing.currentState', function computeLinkToComponentActive() { - var currentState = _emberMetalProperty_get.get(this, '_routing.currentState'); - if (!currentState) { - return false; - } - - return this._computeActive(currentState); - }), - - willBeActive: _emberMetalComputed.computed('_routing.targetState', function computeLinkToComponentWillBeActive() { - var routing = _emberMetalProperty_get.get(this, '_routing'); - var targetState = _emberMetalProperty_get.get(routing, 'targetState'); - if (_emberMetalProperty_get.get(routing, 'currentState') === targetState) { - return; - } - - return !!this._computeActive(targetState); - }), - - transitioningIn: _emberMetalComputed.computed('active', 'willBeActive', function computeLinkToComponentTransitioningIn() { - var willBeActive = _emberMetalProperty_get.get(this, 'willBeActive'); - if (typeof willBeActive === 'undefined') { - return false; - } - - return !_emberMetalProperty_get.get(this, 'active') && willBeActive && 'ember-transitioning-in'; - }), - - transitioningOut: _emberMetalComputed.computed('active', 'willBeActive', function computeLinkToComponentTransitioningOut() { - var willBeActive = _emberMetalProperty_get.get(this, 'willBeActive'); - if (typeof willBeActive === 'undefined') { - return false; - } - - return _emberMetalProperty_get.get(this, 'active') && !willBeActive && 'ember-transitioning-out'; - }), - - /** - Event handler that invokes the link, activating the associated route. - @private - @method _invoke - @param {Event} event - @private - */ - _invoke: function (event) { - if (!_emberViewsSystemUtils.isSimpleClick(event)) { - return true; - } - - var preventDefault = _emberMetalProperty_get.get(this, 'preventDefault'); - var targetAttribute = _emberMetalProperty_get.get(this, 'target'); - - if (preventDefault !== false) { - if (!targetAttribute || targetAttribute === '_self') { - event.preventDefault(); - } - } - - if (_emberMetalProperty_get.get(this, 'bubbles') === false) { - event.stopPropagation(); - } - - if (_emberMetalProperty_get.get(this, '_isDisabled')) { - return false; - } - - if (_emberMetalProperty_get.get(this, 'loading')) { - _emberMetalLogger.default.warn('This link-to is in an inactive loading state because at least one of its parameters presently has a null/undefined value, or the provided route name is invalid.'); - return false; - } - - if (targetAttribute && targetAttribute !== '_self') { - return false; - } - - var routing = _emberMetalProperty_get.get(this, '_routing'); - var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName'); - var models = _emberMetalProperty_get.get(this, 'models'); - var queryParamValues = _emberMetalProperty_get.get(this, 'queryParams.values'); - var shouldReplace = _emberMetalProperty_get.get(this, 'replace'); - - routing.transitionTo(qualifiedRouteName, models, queryParamValues, shouldReplace); - }, - - queryParams: null, - - qualifiedRouteName: _emberMetalComputed.computed('targetRouteName', '_routing.currentState', function computeLinkToComponentQualifiedRouteName() { - var params = _emberMetalProperty_get.get(this, 'params').slice(); - var lastParam = params[params.length - 1]; - if (lastParam && lastParam.isQueryParams) { - params.pop(); - } - var onlyQueryParamsSupplied = this[_emberHtmlbarsNodeManagersComponentNodeManager.HAS_BLOCK] ? params.length === 0 : params.length === 1; - if (onlyQueryParamsSupplied) { - return _emberMetalProperty_get.get(this, '_routing.currentRouteName'); - } - return _emberMetalProperty_get.get(this, 'targetRouteName'); - }), - - resolvedQueryParams: _emberMetalComputed.computed('queryParams', function computeLinkToComponentResolvedQueryParams() { - var resolvedQueryParams = {}; - var queryParams = _emberMetalProperty_get.get(this, 'queryParams'); - - if (!queryParams) { - return resolvedQueryParams; - } - - var values = queryParams.values; - for (var key in values) { - if (!values.hasOwnProperty(key)) { - continue; - } - resolvedQueryParams[key] = values[key]; - } - - return resolvedQueryParams; - }), - - /** - Sets the element's `href` attribute to the url for - the `LinkComponent`'s targeted route. - If the `LinkComponent`'s `tagName` is changed to a value other - than `a`, this property will be ignored. - @property href - @private - */ - href: _emberMetalComputed.computed('models', 'qualifiedRouteName', function computeLinkToComponentHref() { - if (_emberMetalProperty_get.get(this, 'tagName') !== 'a') { - return; - } - - var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName'); - var models = _emberMetalProperty_get.get(this, 'models'); - - if (_emberMetalProperty_get.get(this, 'loading')) { - return _emberMetalProperty_get.get(this, 'loadingHref'); - } - - var routing = _emberMetalProperty_get.get(this, '_routing'); - var queryParams = _emberMetalProperty_get.get(this, 'queryParams.values'); - return routing.generateURL(qualifiedRouteName, models, queryParams); - }), - - loading: _emberMetalComputed.computed('_modelsAreLoaded', 'qualifiedRouteName', function computeLinkToComponentLoading() { - var qualifiedRouteName = _emberMetalProperty_get.get(this, 'qualifiedRouteName'); - var modelsAreLoaded = _emberMetalProperty_get.get(this, '_modelsAreLoaded'); - - if (!modelsAreLoaded || qualifiedRouteName == null) { - return _emberMetalProperty_get.get(this, 'loadingClass'); - } - }), - - _modelsAreLoaded: _emberMetalComputed.computed('models', function computeLinkToComponentModelsAreLoaded() { - var models = _emberMetalProperty_get.get(this, 'models'); - for (var i = 0, l = models.length; i < l; i++) { - if (models[i] == null) { - return false; - } - } - - return true; - }), - - _getModels: function (params) { - var modelCount = params.length - 1; - var models = new Array(modelCount); - - for (var i = 0; i < modelCount; i++) { - var value = params[i + 1]; - - while (_emberRuntimeMixinsController.default.detect(value)) { - value = value.get('model'); - } - - models[i] = value; - } - - return models; - }, - - /** - The default href value to use while a link-to is loading. - Only applies when tagName is 'a' - @property loadingHref - @type String - @default # - @private - */ - loadingHref: '#', - - willRender: function () { - var queryParams = undefined; - - // Do not mutate params in place - var params = _emberMetalProperty_get.get(this, 'params').slice(); - - var disabledWhen = _emberMetalProperty_get.get(this, 'disabledWhen'); - if (disabledWhen !== undefined) { - this.set('disabled', disabledWhen); - } - - // Process the positional arguments, in order. - // 1. Inline link title comes first, if present. - if (!this[_emberHtmlbarsNodeManagersComponentNodeManager.HAS_BLOCK]) { - this.set('linkTitle', params.shift()); - } - - // 2. `targetRouteName` is now always at index 0. - this.set('targetRouteName', params[0]); - - // 3. The last argument (if still remaining) is the `queryParams` object. - var lastParam = params[params.length - 1]; - - if (lastParam && lastParam.isQueryParams) { - queryParams = params.pop(); - } else { - queryParams = {}; - } - this.set('queryParams', queryParams); - - // 4. Any remaining indices (excepting `targetRouteName` at 0) are `models`. - if (params.length > 1) { - this.set('models', this._getModels(params)); - } else { - this.set('models', []); - } - } - }); - - LinkComponent.toString = function () { - return 'LinkComponent'; - }; - - LinkComponent.reopenClass({ - positionalParams: 'params' - }); - - exports.default = LinkComponent; -}); -// creates inject.service -enifed('ember-routing-views/index', ['exports', 'ember-metal/core', 'ember-routing-views/components/link-to', 'ember-routing-views/views/outlet'], function (exports, _emberMetalCore, _emberRoutingViewsComponentsLinkTo, _emberRoutingViewsViewsOutlet) { - /** - @module ember - @submodule ember-routing-views - */ - - 'use strict'; - - _emberMetalCore.default.LinkComponent = _emberRoutingViewsComponentsLinkTo.default; - _emberMetalCore.default.OutletView = _emberRoutingViewsViewsOutlet.OutletView; - - exports.default = _emberMetalCore.default; -}); -enifed('ember-routing-views/views/outlet', ['exports', 'ember-views/views/view', 'ember-htmlbars/templates/top-level-view'], function (exports, _emberViewsViewsView, _emberHtmlbarsTemplatesTopLevelView) { - /** - @module ember - @submodule ember-routing-views - */ - - 'use strict'; - - var CoreOutletView = _emberViewsViewsView.default.extend({ - defaultTemplate: _emberHtmlbarsTemplatesTopLevelView.default, - - init: function () { - this._super(); - this._outlets = []; - }, - - setOutletState: function (state) { - this.outletState = { main: state }; - - if (this.env) { - this.env.outletState = this.outletState; - } - - if (this.lastResult) { - this.dirtyOutlets(); - this._outlets = []; - - this.scheduleRevalidate(null, null); - } - }, - - dirtyOutlets: function () { - // Dirty any render nodes that correspond to outlets - for (var i = 0; i < this._outlets.length; i++) { - this._outlets[i].isDirty = true; - } - } - }); - - exports.CoreOutletView = CoreOutletView; - var OutletView = CoreOutletView.extend({ tagName: '' }); - exports.OutletView = OutletView; -}); enifed('ember-runtime/compare', ['exports', 'ember-runtime/utils', 'ember-runtime/mixins/comparable'], function (exports, _emberRuntimeUtils, _emberRuntimeMixinsComparable) { 'use strict'; exports.default = compare; @@ -36993,10 +36970,19 @@ } return ret; } }); +enifed('ember-template-compiler/compat', ['exports', 'ember-metal/core', 'ember-template-compiler/compat/precompile', 'ember-template-compiler/system/compile', 'ember-template-compiler/system/template'], function (exports, _emberMetalCore, _emberTemplateCompilerCompatPrecompile, _emberTemplateCompilerSystemCompile, _emberTemplateCompilerSystemTemplate) { + 'use strict'; + + var EmberHandlebars = _emberMetalCore.default.Handlebars = _emberMetalCore.default.Handlebars || {}; + + EmberHandlebars.precompile = _emberTemplateCompilerCompatPrecompile.default; + EmberHandlebars.compile = _emberTemplateCompilerSystemCompile.default; + EmberHandlebars.template = _emberTemplateCompilerSystemTemplate.default; +}); enifed('ember-template-compiler/compat/precompile', ['exports', 'require', 'ember-template-compiler/system/compile_options'], function (exports, _require, _emberTemplateCompilerSystemCompile_options) { /** @module ember @submodule ember-template-compiler */ @@ -37020,19 +37006,10 @@ var compileFunc = asObject ? compile : compileSpec; return compileFunc(string, _emberTemplateCompilerSystemCompile_options.default()); }; }); -enifed('ember-template-compiler/compat', ['exports', 'ember-metal/core', 'ember-template-compiler/compat/precompile', 'ember-template-compiler/system/compile', 'ember-template-compiler/system/template'], function (exports, _emberMetalCore, _emberTemplateCompilerCompatPrecompile, _emberTemplateCompilerSystemCompile, _emberTemplateCompilerSystemTemplate) { - 'use strict'; - - var EmberHandlebars = _emberMetalCore.default.Handlebars = _emberMetalCore.default.Handlebars || {}; - - EmberHandlebars.precompile = _emberTemplateCompilerCompatPrecompile.default; - EmberHandlebars.compile = _emberTemplateCompilerSystemCompile.default; - EmberHandlebars.template = _emberTemplateCompilerSystemTemplate.default; -}); enifed('ember-template-compiler/index', ['exports', 'ember-metal', 'ember-template-compiler/system/precompile', 'ember-template-compiler/system/compile', 'ember-template-compiler/system/template', 'ember-template-compiler/plugins', 'ember-template-compiler/plugins/transform-old-binding-syntax', 'ember-template-compiler/plugins/transform-old-class-binding-syntax', 'ember-template-compiler/plugins/transform-item-class', 'ember-template-compiler/plugins/transform-closure-component-attrs-into-mut', 'ember-template-compiler/plugins/transform-component-attrs-into-mut', 'ember-template-compiler/plugins/transform-component-curly-to-readonly', 'ember-template-compiler/plugins/transform-angle-bracket-components', 'ember-template-compiler/plugins/transform-input-on-to-onEvent', 'ember-template-compiler/plugins/transform-top-level-components', 'ember-template-compiler/plugins/deprecate-render-model', 'ember-template-compiler/plugins/prevent-render-block', 'ember-template-compiler/plugins/transform-inline-link-to', 'ember-template-compiler/plugins/assert-no-view-and-controller-paths', 'ember-template-compiler/plugins/assert-no-view-helper', 'ember-template-compiler/plugins/assert-no-each-in', 'ember-template-compiler/compat'], function (exports, _emberMetal, _emberTemplateCompilerSystemPrecompile, _emberTemplateCompilerSystemCompile, _emberTemplateCompilerSystemTemplate, _emberTemplateCompilerPlugins, _emberTemplateCompilerPluginsTransformOldBindingSyntax, _emberTemplateCompilerPluginsTransformOldClassBindingSyntax, _emberTemplateCompilerPluginsTransformItemClass, _emberTemplateCompilerPluginsTransformClosureComponentAttrsIntoMut, _emberTemplateCompilerPluginsTransformComponentAttrsIntoMut, _emberTemplateCompilerPluginsTransformComponentCurlyToReadonly, _emberTemplateCompilerPluginsTransformAngleBracketComponents, _emberTemplateCompilerPluginsTransformInputOnToOnEvent, _emberTemplateCompilerPluginsTransformTopLevelComponents, _emberTemplateCompilerPluginsDeprecateRenderModel, _emberTemplateCompilerPluginsPreventRenderBlock, _emberTemplateCompilerPluginsTransformInlineLinkTo, _emberTemplateCompilerPluginsAssertNoViewAndControllerPaths, _emberTemplateCompilerPluginsAssertNoViewHelper, _emberTemplateCompilerPluginsAssertNoEachIn, _emberTemplateCompilerCompat) { 'use strict'; _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformOldBindingSyntax.default); _emberTemplateCompilerPlugins.registerPlugin('ast', _emberTemplateCompilerPluginsTransformOldClassBindingSyntax.default); @@ -37059,10 +37036,44 @@ exports.template = _emberTemplateCompilerSystemTemplate.default; exports.registerPlugin = _emberTemplateCompilerPlugins.registerPlugin; }); // used for adding Ember.Handlebars.compile for backwards compat +enifed('ember-template-compiler/plugins', ['exports'], function (exports) { + /** + @module ember + @submodule ember-template-compiler + */ + + /** + @private + @property helpers + */ + 'use strict'; + + exports.registerPlugin = registerPlugin; + var plugins = { + ast: [] + }; + + /** + Adds an AST plugin to be used by Ember.HTMLBars.compile. + + @private + @method registerASTPlugin + */ + + function registerPlugin(type, Plugin) { + if (!plugins[type]) { + throw new Error('Attempting to register "' + Plugin + '" as "' + type + '" which is not a valid HTMLBars plugin type.'); + } + + plugins[type].push(Plugin); + } + + exports.default = plugins; +}); enifed('ember-template-compiler/plugins/assert-no-each-in', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalCore, _emberMetalDebug, _emberTemplateCompilerSystemCalculateLocationDisplay) { 'use strict'; function AssertNoEachIn() { var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; @@ -37983,44 +37994,10 @@ } } exports.default = TransformTopLevelComponents; }); -enifed('ember-template-compiler/plugins', ['exports'], function (exports) { - /** - @module ember - @submodule ember-template-compiler - */ - - /** - @private - @property helpers - */ - 'use strict'; - - exports.registerPlugin = registerPlugin; - var plugins = { - ast: [] - }; - - /** - Adds an AST plugin to be used by Ember.HTMLBars.compile. - - @private - @method registerASTPlugin - */ - - function registerPlugin(type, Plugin) { - if (!plugins[type]) { - throw new Error('Attempting to register "' + Plugin + '" as "' + type + '" which is not a valid HTMLBars plugin type.'); - } - - plugins[type].push(Plugin); - } - - exports.default = plugins; -}); enifed('ember-template-compiler/system/calculate-location-display', ['exports'], function (exports) { 'use strict'; exports.default = calculateLocationDisplay; @@ -38127,11 +38104,11 @@ options.plugins = plugins; options.buildMeta = function buildMeta(program) { return { fragmentReason: fragmentReason(program), - revision: 'Ember@2.6.1', + revision: 'Ember@2.6.2', loc: program.loc, moduleName: options.moduleName }; }; @@ -41855,10 +41832,43 @@ return _domHelper = _domHelper || _require.default('ember-htmlbars/system/dom-helper').default; } exports.default = CoreView; }); +enifed('ember-views/views/states', ['exports', 'ember-metal/assign', 'ember-views/views/states/default', 'ember-views/views/states/pre_render', 'ember-views/views/states/has_element', 'ember-views/views/states/in_dom', 'ember-views/views/states/destroying'], function (exports, _emberMetalAssign, _emberViewsViewsStatesDefault, _emberViewsViewsStatesPre_render, _emberViewsViewsStatesHas_element, _emberViewsViewsStatesIn_dom, _emberViewsViewsStatesDestroying) { + 'use strict'; + + exports.cloneStates = cloneStates; + + function cloneStates(from) { + var into = {}; + + into._default = {}; + into.preRender = Object.create(into._default); + into.destroying = Object.create(into._default); + into.hasElement = Object.create(into._default); + into.inDOM = Object.create(into.hasElement); + + for (var stateName in from) { + if (!from.hasOwnProperty(stateName)) { + continue; + } + _emberMetalAssign.default(into[stateName], from[stateName]); + } + + return into; + } + + var states = { + _default: _emberViewsViewsStatesDefault.default, + preRender: _emberViewsViewsStatesPre_render.default, + inDOM: _emberViewsViewsStatesIn_dom.default, + hasElement: _emberViewsViewsStatesHas_element.default, + destroying: _emberViewsViewsStatesDestroying.default + }; + exports.states = states; +}); enifed('ember-views/views/states/default', ['exports', 'ember-metal/error', 'ember-metal/property_get', 'ember-views/compat/attrs-proxy'], function (exports, _emberMetalError, _emberMetalProperty_get, _emberViewsCompatAttrsProxy) { 'use strict'; /** @module ember @@ -42038,43 +42048,10 @@ legacyPropertyDidChange: function (view, key) {} }); exports.default = preRender; }); -enifed('ember-views/views/states', ['exports', 'ember-metal/assign', 'ember-views/views/states/default', 'ember-views/views/states/pre_render', 'ember-views/views/states/has_element', 'ember-views/views/states/in_dom', 'ember-views/views/states/destroying'], function (exports, _emberMetalAssign, _emberViewsViewsStatesDefault, _emberViewsViewsStatesPre_render, _emberViewsViewsStatesHas_element, _emberViewsViewsStatesIn_dom, _emberViewsViewsStatesDestroying) { - 'use strict'; - - exports.cloneStates = cloneStates; - - function cloneStates(from) { - var into = {}; - - into._default = {}; - into.preRender = Object.create(into._default); - into.destroying = Object.create(into._default); - into.hasElement = Object.create(into._default); - into.inDOM = Object.create(into.hasElement); - - for (var stateName in from) { - if (!from.hasOwnProperty(stateName)) { - continue; - } - _emberMetalAssign.default(into[stateName], from[stateName]); - } - - return into; - } - - var states = { - _default: _emberViewsViewsStatesDefault.default, - preRender: _emberViewsViewsStatesPre_render.default, - inDOM: _emberViewsViewsStatesIn_dom.default, - hasElement: _emberViewsViewsStatesHas_element.default, - destroying: _emberViewsViewsStatesDestroying.default - }; - exports.states = states; -}); enifed('ember-views/views/text_area', ['exports', 'ember-views/components/component', 'ember-views/mixins/text_support'], function (exports, _emberViewsComponentsComponent, _emberViewsMixinsText_support) { /** @module ember @submodule ember-views */ @@ -42946,10 +42923,49 @@ exports.ViewStateSupport = _emberViewsMixinsView_state_support.default; exports.TemplateRenderingSupport = _emberViewsMixinsTemplate_rendering_support.default; exports.ClassNamesSupport = _emberViewsMixinsClass_names_support.default; }); // for the side effect of extending Ember.run.queues +enifed('ember/index', ['exports', 'ember-metal', 'ember-runtime', 'ember-views', 'ember-routing', 'ember-application', 'ember-extension-support', 'ember-htmlbars', 'ember-routing-htmlbars', 'ember-routing-views', 'require', 'ember-runtime/system/lazy_load'], function (exports, _emberMetal, _emberRuntime, _emberViews, _emberRouting, _emberApplication, _emberExtensionSupport, _emberHtmlbars, _emberRoutingHtmlbars, _emberRoutingViews, _require, _emberRuntimeSystemLazy_load) { + // require the main entry points for each of these packages + // this is so that the global exports occur properly + 'use strict'; + + if (_require.has('ember-template-compiler')) { + _require.default('ember-template-compiler'); + } + + // do this to ensure that Ember.Test is defined properly on the global + // if it is present. + if (_require.has('ember-testing')) { + _require.default('ember-testing'); + } + + _emberRuntimeSystemLazy_load.runLoadHooks('Ember'); + + /** + @module ember + */ +}); +enifed('htmlbars-runtime', ['exports', 'htmlbars-runtime/hooks', 'htmlbars-runtime/render', 'htmlbars-util/morph-utils', 'htmlbars-util/template-utils'], function (exports, _htmlbarsRuntimeHooks, _htmlbarsRuntimeRender, _htmlbarsUtilMorphUtils, _htmlbarsUtilTemplateUtils) { + 'use strict'; + + var internal = { + blockFor: _htmlbarsUtilTemplateUtils.blockFor, + manualElement: _htmlbarsRuntimeRender.manualElement, + hostBlock: _htmlbarsRuntimeHooks.hostBlock, + continueBlock: _htmlbarsRuntimeHooks.continueBlock, + hostYieldWithShadowTemplate: _htmlbarsRuntimeHooks.hostYieldWithShadowTemplate, + visitChildren: _htmlbarsUtilMorphUtils.visitChildren, + validateChildMorphs: _htmlbarsUtilMorphUtils.validateChildMorphs, + clearMorph: _htmlbarsUtilTemplateUtils.clearMorph + }; + + exports.hooks = _htmlbarsRuntimeHooks.default; + exports.render = _htmlbarsRuntimeRender.default; + exports.internal = internal; +}); enifed('htmlbars-runtime/expression-visitor', ['exports'], function (exports) { /** # Expression Nodes: These nodes are not directly responsible for any part of the DOM, but are @@ -44811,27 +44827,19 @@ } return fragment; } }); -enifed('htmlbars-runtime', ['exports', 'htmlbars-runtime/hooks', 'htmlbars-runtime/render', 'htmlbars-util/morph-utils', 'htmlbars-util/template-utils'], function (exports, _htmlbarsRuntimeHooks, _htmlbarsRuntimeRender, _htmlbarsUtilMorphUtils, _htmlbarsUtilTemplateUtils) { +enifed('htmlbars-util', ['exports', 'htmlbars-util/safe-string', 'htmlbars-util/handlebars/utils', 'htmlbars-util/namespaces', 'htmlbars-util/morph-utils'], function (exports, _htmlbarsUtilSafeString, _htmlbarsUtilHandlebarsUtils, _htmlbarsUtilNamespaces, _htmlbarsUtilMorphUtils) { 'use strict'; - var internal = { - blockFor: _htmlbarsUtilTemplateUtils.blockFor, - manualElement: _htmlbarsRuntimeRender.manualElement, - hostBlock: _htmlbarsRuntimeHooks.hostBlock, - continueBlock: _htmlbarsRuntimeHooks.continueBlock, - hostYieldWithShadowTemplate: _htmlbarsRuntimeHooks.hostYieldWithShadowTemplate, - visitChildren: _htmlbarsUtilMorphUtils.visitChildren, - validateChildMorphs: _htmlbarsUtilMorphUtils.validateChildMorphs, - clearMorph: _htmlbarsUtilTemplateUtils.clearMorph - }; - - exports.hooks = _htmlbarsRuntimeHooks.default; - exports.render = _htmlbarsRuntimeRender.default; - exports.internal = internal; + exports.SafeString = _htmlbarsUtilSafeString.default; + exports.escapeExpression = _htmlbarsUtilHandlebarsUtils.escapeExpression; + exports.getAttrNamespace = _htmlbarsUtilNamespaces.getAttrNamespace; + exports.validateChildMorphs = _htmlbarsUtilMorphUtils.validateChildMorphs; + exports.linkParams = _htmlbarsUtilMorphUtils.linkParams; + exports.dump = _htmlbarsUtilMorphUtils.dump; }); enifed('htmlbars-util/array-utils', ['exports'], function (exports) { 'use strict'; exports.forEach = forEach; @@ -45450,84 +45458,10 @@ voidMap[tagName] = true; }); exports.default = voidMap; }); -enifed('htmlbars-util', ['exports', 'htmlbars-util/safe-string', 'htmlbars-util/handlebars/utils', 'htmlbars-util/namespaces', 'htmlbars-util/morph-utils'], function (exports, _htmlbarsUtilSafeString, _htmlbarsUtilHandlebarsUtils, _htmlbarsUtilNamespaces, _htmlbarsUtilMorphUtils) { - 'use strict'; - - exports.SafeString = _htmlbarsUtilSafeString.default; - exports.escapeExpression = _htmlbarsUtilHandlebarsUtils.escapeExpression; - exports.getAttrNamespace = _htmlbarsUtilNamespaces.getAttrNamespace; - exports.validateChildMorphs = _htmlbarsUtilMorphUtils.validateChildMorphs; - exports.linkParams = _htmlbarsUtilMorphUtils.linkParams; - exports.dump = _htmlbarsUtilMorphUtils.dump; -}); -enifed('morph-attr/sanitize-attribute-value', ['exports'], function (exports) { - /* jshint scripturl:true */ - - 'use strict'; - - exports.sanitizeAttributeValue = sanitizeAttributeValue; - var badProtocols = { - 'javascript:': true, - 'vbscript:': true - }; - - var badTags = { - 'A': true, - 'BODY': true, - 'LINK': true, - 'IMG': true, - 'IFRAME': true, - 'BASE': true, - 'FORM': true - }; - - var badTagsForDataURI = { - 'EMBED': true - }; - - var badAttributes = { - 'href': true, - 'src': true, - 'background': true, - 'action': true - }; - - exports.badAttributes = badAttributes; - var badAttributesForDataURI = { - 'src': true - }; - - function sanitizeAttributeValue(dom, element, attribute, value) { - var tagName; - - if (!element) { - tagName = null; - } else { - tagName = element.tagName.toUpperCase(); - } - - if (value && value.toHTML) { - return value.toHTML(); - } - - if ((tagName === null || badTags[tagName]) && badAttributes[attribute]) { - var protocol = dom.protocolForURL(value); - if (badProtocols[protocol] === true) { - return 'unsafe:' + value; - } - } - - if (badTagsForDataURI[tagName] && badAttributesForDataURI[attribute]) { - return 'unsafe:' + value; - } - - return value; - } -}); enifed("morph-attr", ["exports", "morph-attr/sanitize-attribute-value", "dom-helper/prop", "dom-helper/build-html-dom", "htmlbars-util"], function (exports, _morphAttrSanitizeAttributeValue, _domHelperProp, _domHelperBuildHtmlDom, _htmlbarsUtil) { "use strict"; function getProperty() { return this.domHelper.getPropertyStrict(this.element, this.attrName); @@ -45702,148 +45636,73 @@ AttributeAttrMorph.prototype._get = getAttribute; exports.default = AttrMorph; exports.sanitizeAttributeValue = _morphAttrSanitizeAttributeValue.sanitizeAttributeValue; }); -enifed('morph-range/morph-list', ['exports', 'morph-range/utils'], function (exports, _morphRangeUtils) { +enifed('morph-attr/sanitize-attribute-value', ['exports'], function (exports) { + /* jshint scripturl:true */ + 'use strict'; - function MorphList() { - // morph graph - this.firstChildMorph = null; - this.lastChildMorph = null; + exports.sanitizeAttributeValue = sanitizeAttributeValue; + var badProtocols = { + 'javascript:': true, + 'vbscript:': true + }; - this.mountedMorph = null; - } + var badTags = { + 'A': true, + 'BODY': true, + 'LINK': true, + 'IMG': true, + 'IFRAME': true, + 'BASE': true, + 'FORM': true + }; - var prototype = MorphList.prototype; + var badTagsForDataURI = { + 'EMBED': true + }; - prototype.clear = function MorphList$clear() { - var current = this.firstChildMorph; - - while (current) { - var next = current.nextMorph; - current.previousMorph = null; - current.nextMorph = null; - current.parentMorphList = null; - current = next; - } - - this.firstChildMorph = this.lastChildMorph = null; + var badAttributes = { + 'href': true, + 'src': true, + 'background': true, + 'action': true }; - prototype.destroy = function MorphList$destroy() {}; - - prototype.appendMorph = function MorphList$appendMorph(morph) { - this.insertBeforeMorph(morph, null); + exports.badAttributes = badAttributes; + var badAttributesForDataURI = { + 'src': true }; - prototype.insertBeforeMorph = function MorphList$insertBeforeMorph(morph, referenceMorph) { - if (morph.parentMorphList !== null) { - morph.unlink(); - } - if (referenceMorph && referenceMorph.parentMorphList !== this) { - throw new Error('The morph before which the new morph is to be inserted is not a child of this morph.'); - } + function sanitizeAttributeValue(dom, element, attribute, value) { + var tagName; - var mountedMorph = this.mountedMorph; - - if (mountedMorph) { - - var parentNode = mountedMorph.firstNode.parentNode; - var referenceNode = referenceMorph ? referenceMorph.firstNode : mountedMorph.lastNode.nextSibling; - - _morphRangeUtils.insertBefore(parentNode, morph.firstNode, morph.lastNode, referenceNode); - - // was not in list mode replace current content - if (!this.firstChildMorph) { - _morphRangeUtils.clear(this.mountedMorph.firstNode.parentNode, this.mountedMorph.firstNode, this.mountedMorph.lastNode); - } - } - - morph.parentMorphList = this; - - var previousMorph = referenceMorph ? referenceMorph.previousMorph : this.lastChildMorph; - if (previousMorph) { - previousMorph.nextMorph = morph; - morph.previousMorph = previousMorph; + if (!element) { + tagName = null; } else { - this.firstChildMorph = morph; + tagName = element.tagName.toUpperCase(); } - if (referenceMorph) { - referenceMorph.previousMorph = morph; - morph.nextMorph = referenceMorph; - } else { - this.lastChildMorph = morph; + if (value && value.toHTML) { + return value.toHTML(); } - this.firstChildMorph._syncFirstNode(); - this.lastChildMorph._syncLastNode(); - }; - - prototype.removeChildMorph = function MorphList$removeChildMorph(morph) { - if (morph.parentMorphList !== this) { - throw new Error("Cannot remove a morph from a parent it is not inside of"); + if ((tagName === null || badTags[tagName]) && badAttributes[attribute]) { + var protocol = dom.protocolForURL(value); + if (badProtocols[protocol] === true) { + return 'unsafe:' + value; + } } - morph.destroy(); - }; - - exports.default = MorphList; -}); -enifed('morph-range/morph-list.umd', ['exports', 'morph-range/morph-list'], function (exports, _morphRangeMorphList) { - 'use strict'; - - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define([], factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - root.MorphList = factory(); + if (badTagsForDataURI[tagName] && badAttributesForDataURI[attribute]) { + return 'unsafe:' + value; } - })(undefined, function () { - return _morphRangeMorphList.default; - }); -}); -enifed("morph-range/utils", ["exports"], function (exports) { - // inclusive of both nodes - "use strict"; - exports.clear = clear; - exports.insertBefore = insertBefore; - - function clear(parentNode, firstNode, lastNode) { - if (!parentNode) { - return; - } - - var node = firstNode; - var nextNode; - do { - nextNode = node.nextSibling; - parentNode.removeChild(node); - if (node === lastNode) { - break; - } - node = nextNode; - } while (node); + return value; } - - function insertBefore(parentNode, firstNode, lastNode, refNode) { - var node = firstNode; - var nextNode; - do { - nextNode = node.nextSibling; - parentNode.insertBefore(node, refNode); - if (node === lastNode) { - break; - } - node = nextNode; - } while (node); - } }); enifed('morph-range', ['exports', 'morph-range/utils'], function (exports, _morphRangeUtils) { 'use strict'; // constructor just initializes the fields @@ -46120,117 +45979,148 @@ _morphRangeUtils.insertBefore(parentNode, this.firstNode, this.lastNode, null); }; exports.default = Morph; }); -enifed("route-recognizer/dsl", ["exports"], function (exports) { - "use strict"; +enifed('morph-range/morph-list', ['exports', 'morph-range/utils'], function (exports, _morphRangeUtils) { + 'use strict'; - function Target(path, matcher, delegate) { - this.path = path; - this.matcher = matcher; - this.delegate = delegate; + function MorphList() { + // morph graph + this.firstChildMorph = null; + this.lastChildMorph = null; + + this.mountedMorph = null; } - Target.prototype = { - to: function (target, callback) { - var delegate = this.delegate; + var prototype = MorphList.prototype; - if (delegate && delegate.willAddRoute) { - target = delegate.willAddRoute(this.matcher.target, target); - } + prototype.clear = function MorphList$clear() { + var current = this.firstChildMorph; - this.matcher.add(this.path, target); - - if (callback) { - if (callback.length === 0) { - throw new Error("You must have an argument in the function passed to `to`"); - } - this.matcher.addChild(this.path, target, callback, this.delegate); - } - return this; + while (current) { + var next = current.nextMorph; + current.previousMorph = null; + current.nextMorph = null; + current.parentMorphList = null; + current = next; } + + this.firstChildMorph = this.lastChildMorph = null; }; - function Matcher(target) { - this.routes = {}; - this.children = {}; - this.target = target; - } + prototype.destroy = function MorphList$destroy() {}; - Matcher.prototype = { - add: function (path, handler) { - this.routes[path] = handler; - }, + prototype.appendMorph = function MorphList$appendMorph(morph) { + this.insertBeforeMorph(morph, null); + }; - addChild: function (path, target, callback, delegate) { - var matcher = new Matcher(target); - this.children[path] = matcher; + prototype.insertBeforeMorph = function MorphList$insertBeforeMorph(morph, referenceMorph) { + if (morph.parentMorphList !== null) { + morph.unlink(); + } + if (referenceMorph && referenceMorph.parentMorphList !== this) { + throw new Error('The morph before which the new morph is to be inserted is not a child of this morph.'); + } - var match = generateMatch(path, matcher, delegate); + var mountedMorph = this.mountedMorph; - if (delegate && delegate.contextEntered) { - delegate.contextEntered(target, match); - } + if (mountedMorph) { - callback(match); - } - }; + var parentNode = mountedMorph.firstNode.parentNode; + var referenceNode = referenceMorph ? referenceMorph.firstNode : mountedMorph.lastNode.nextSibling; - function generateMatch(startingPath, matcher, delegate) { - return function (path, nestedCallback) { - var fullPath = startingPath + path; + _morphRangeUtils.insertBefore(parentNode, morph.firstNode, morph.lastNode, referenceNode); - if (nestedCallback) { - nestedCallback(generateMatch(fullPath, matcher, delegate)); - } else { - return new Target(startingPath + path, matcher, delegate); + // was not in list mode replace current content + if (!this.firstChildMorph) { + _morphRangeUtils.clear(this.mountedMorph.firstNode.parentNode, this.mountedMorph.firstNode, this.mountedMorph.lastNode); } - }; - } + } - function addRoute(routeArray, path, handler) { - var len = 0; - for (var i = 0, l = routeArray.length; i < l; i++) { - len += routeArray[i].path.length; + morph.parentMorphList = this; + + var previousMorph = referenceMorph ? referenceMorph.previousMorph : this.lastChildMorph; + if (previousMorph) { + previousMorph.nextMorph = morph; + morph.previousMorph = previousMorph; + } else { + this.firstChildMorph = morph; } - path = path.substr(len); - var route = { path: path, handler: handler }; - routeArray.push(route); - } + if (referenceMorph) { + referenceMorph.previousMorph = morph; + morph.nextMorph = referenceMorph; + } else { + this.lastChildMorph = morph; + } - function eachRoute(baseRoute, matcher, callback, binding) { - var routes = matcher.routes; + this.firstChildMorph._syncFirstNode(); + this.lastChildMorph._syncLastNode(); + }; - for (var path in routes) { - if (routes.hasOwnProperty(path)) { - var routeArray = baseRoute.slice(); - addRoute(routeArray, path, routes[path]); + prototype.removeChildMorph = function MorphList$removeChildMorph(morph) { + if (morph.parentMorphList !== this) { + throw new Error("Cannot remove a morph from a parent it is not inside of"); + } - if (matcher.children[path]) { - eachRoute(routeArray, matcher.children[path], callback, binding); - } else { - callback.call(binding, routeArray); - } - } + morph.destroy(); + }; + + exports.default = MorphList; +}); +enifed('morph-range/morph-list.umd', ['exports', 'morph-range/morph-list'], function (exports, _morphRangeMorphList) { + 'use strict'; + + (function (root, factory) { + if (typeof define === 'function' && define.amd) { + define([], factory); + } else if (typeof exports === 'object') { + module.exports = factory(); + } else { + root.MorphList = factory(); } - } + })(undefined, function () { + return _morphRangeMorphList.default; + }); +}); +enifed("morph-range/utils", ["exports"], function (exports) { + // inclusive of both nodes + "use strict"; - exports.default = function (callback, addRouteCallback) { - var matcher = new Matcher(); + exports.clear = clear; + exports.insertBefore = insertBefore; - callback(generateMatch("", matcher, this.delegate)); + function clear(parentNode, firstNode, lastNode) { + if (!parentNode) { + return; + } - eachRoute([], matcher, function (route) { - if (addRouteCallback) { - addRouteCallback(this, route); - } else { - this.add(route); + var node = firstNode; + var nextNode; + do { + nextNode = node.nextSibling; + parentNode.removeChild(node); + if (node === lastNode) { + break; } - }, this); - }; + node = nextNode; + } while (node); + } + + function insertBefore(parentNode, firstNode, lastNode, refNode) { + var node = firstNode; + var nextNode; + do { + nextNode = node.nextSibling; + parentNode.insertBefore(node, refNode); + if (node === lastNode) { + break; + } + node = nextNode; + } while (node); + } }); enifed('route-recognizer', ['exports', 'route-recognizer/dsl'], function (exports, _routeRecognizerDsl) { 'use strict'; var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']; @@ -46827,133 +46717,123 @@ RouteRecognizer.VERSION = '0.1.5'; exports.default = RouteRecognizer; }); -enifed('router/handler-info/factory', ['exports', 'router/handler-info/resolved-handler-info', 'router/handler-info/unresolved-handler-info-by-object', 'router/handler-info/unresolved-handler-info-by-param'], function (exports, _routerHandlerInfoResolvedHandlerInfo, _routerHandlerInfoUnresolvedHandlerInfoByObject, _routerHandlerInfoUnresolvedHandlerInfoByParam) { - 'use strict'; +enifed("route-recognizer/dsl", ["exports"], function (exports) { + "use strict"; - handlerInfoFactory.klasses = { - resolved: _routerHandlerInfoResolvedHandlerInfo.default, - param: _routerHandlerInfoUnresolvedHandlerInfoByParam.default, - object: _routerHandlerInfoUnresolvedHandlerInfoByObject.default - }; - - function handlerInfoFactory(name, props) { - var Ctor = handlerInfoFactory.klasses[name], - handlerInfo = new Ctor(props || {}); - handlerInfo.factory = handlerInfoFactory; - return handlerInfo; + function Target(path, matcher, delegate) { + this.path = path; + this.matcher = matcher; + this.delegate = delegate; } - exports.default = handlerInfoFactory; -}); -enifed('router/handler-info/resolved-handler-info', ['exports', 'router/handler-info', 'router/utils', 'rsvp/promise'], function (exports, _routerHandlerInfo, _routerUtils, _rsvpPromise) { - 'use strict'; + Target.prototype = { + to: function (target, callback) { + var delegate = this.delegate; - var ResolvedHandlerInfo = _routerUtils.subclass(_routerHandlerInfo.default, { - resolve: function (shouldContinue, payload) { - // A ResolvedHandlerInfo just resolved with itself. - if (payload && payload.resolvedModels) { - payload.resolvedModels[this.name] = this.context; + if (delegate && delegate.willAddRoute) { + target = delegate.willAddRoute(this.matcher.target, target); } - return _rsvpPromise.default.resolve(this, this.promiseLabel("Resolve")); - }, - getUnresolved: function () { - return this.factory('param', { - name: this.name, - handler: this.handler, - params: this.params - }); - }, + this.matcher.add(this.path, target); - isResolved: true - }); + if (callback) { + if (callback.length === 0) { + throw new Error("You must have an argument in the function passed to `to`"); + } + this.matcher.addChild(this.path, target, callback, this.delegate); + } + return this; + } + }; - exports.default = ResolvedHandlerInfo; -}); -enifed('router/handler-info/unresolved-handler-info-by-object', ['exports', 'router/handler-info', 'router/utils', 'rsvp/promise'], function (exports, _routerHandlerInfo, _routerUtils, _rsvpPromise) { - 'use strict'; + function Matcher(target) { + this.routes = {}; + this.children = {}; + this.target = target; + } - var UnresolvedHandlerInfoByObject = _routerUtils.subclass(_routerHandlerInfo.default, { - getModel: function (payload) { - this.log(payload, this.name + ": resolving provided model"); - return _rsvpPromise.default.resolve(this.context); + Matcher.prototype = { + add: function (path, handler) { + this.routes[path] = handler; }, - initialize: function (props) { - this.names = props.names || []; - this.context = props.context; - }, + addChild: function (path, target, callback, delegate) { + var matcher = new Matcher(target); + this.children[path] = matcher; - /** - @private - Serializes a handler using its custom `serialize` method or - by a default that looks up the expected property name from - the dynamic segment. - @param {Object} model the model to be serialized for this handler - */ - serialize: function (_model) { - var model = _model || this.context, - names = this.names, - handler = this.handler; + var match = generateMatch(path, matcher, delegate); - var object = {}; - if (_routerUtils.isParam(model)) { - object[names[0]] = model; - return object; + if (delegate && delegate.contextEntered) { + delegate.contextEntered(target, match); } - // Use custom serialize if it exists. - if (handler.serialize) { - return handler.serialize(model, names); - } + callback(match); + } + }; - if (names.length !== 1) { - return; - } + function generateMatch(startingPath, matcher, delegate) { + return function (path, nestedCallback) { + var fullPath = startingPath + path; - var name = names[0]; - - if (/_id$/.test(name)) { - object[name] = model.id; + if (nestedCallback) { + nestedCallback(generateMatch(fullPath, matcher, delegate)); } else { - object[name] = model; + return new Target(startingPath + path, matcher, delegate); } - return object; + }; + } + + function addRoute(routeArray, path, handler) { + var len = 0; + for (var i = 0, l = routeArray.length; i < l; i++) { + len += routeArray[i].path.length; } - }); - exports.default = UnresolvedHandlerInfoByObject; -}); -enifed('router/handler-info/unresolved-handler-info-by-param', ['exports', 'router/handler-info', 'router/utils'], function (exports, _routerHandlerInfo, _routerUtils) { - 'use strict'; + path = path.substr(len); + var route = { path: path, handler: handler }; + routeArray.push(route); + } - // Generated by URL transitions and non-dynamic route segments in named Transitions. - var UnresolvedHandlerInfoByParam = _routerUtils.subclass(_routerHandlerInfo.default, { - initialize: function (props) { - this.params = props.params || {}; - }, + function eachRoute(baseRoute, matcher, callback, binding) { + var routes = matcher.routes; - getModel: function (payload) { - var fullParams = this.params; - if (payload && payload.queryParams) { - fullParams = {}; - _routerUtils.merge(fullParams, this.params); - fullParams.queryParams = payload.queryParams; + for (var path in routes) { + if (routes.hasOwnProperty(path)) { + var routeArray = baseRoute.slice(); + addRoute(routeArray, path, routes[path]); + + if (matcher.children[path]) { + eachRoute(routeArray, matcher.children[path], callback, binding); + } else { + callback.call(binding, routeArray); + } } + } + } - var handler = this.handler; - var hookName = _routerUtils.resolveHook(handler, 'deserialize') || _routerUtils.resolveHook(handler, 'model'); + exports.default = function (callback, addRouteCallback) { + var matcher = new Matcher(); - return this.runSharedModelHook(payload, hookName, [fullParams]); - } - }); + callback(generateMatch("", matcher, this.delegate)); - exports.default = UnresolvedHandlerInfoByParam; + eachRoute([], matcher, function (route) { + if (addRouteCallback) { + addRouteCallback(this, route); + } else { + this.add(route); + } + }, this); + }; }); +enifed('router', ['exports', 'router/router'], function (exports, _routerRouter) { + 'use strict'; + + exports.default = _routerRouter.default; +}); enifed('router/handler-info', ['exports', 'router/utils', 'rsvp/promise'], function (exports, _routerUtils, _rsvpPromise) { 'use strict'; function HandlerInfo(_props) { var props = _props || {}; @@ -47110,10 +46990,133 @@ return true; } exports.default = HandlerInfo; }); +enifed('router/handler-info/factory', ['exports', 'router/handler-info/resolved-handler-info', 'router/handler-info/unresolved-handler-info-by-object', 'router/handler-info/unresolved-handler-info-by-param'], function (exports, _routerHandlerInfoResolvedHandlerInfo, _routerHandlerInfoUnresolvedHandlerInfoByObject, _routerHandlerInfoUnresolvedHandlerInfoByParam) { + 'use strict'; + + handlerInfoFactory.klasses = { + resolved: _routerHandlerInfoResolvedHandlerInfo.default, + param: _routerHandlerInfoUnresolvedHandlerInfoByParam.default, + object: _routerHandlerInfoUnresolvedHandlerInfoByObject.default + }; + + function handlerInfoFactory(name, props) { + var Ctor = handlerInfoFactory.klasses[name], + handlerInfo = new Ctor(props || {}); + handlerInfo.factory = handlerInfoFactory; + return handlerInfo; + } + + exports.default = handlerInfoFactory; +}); +enifed('router/handler-info/resolved-handler-info', ['exports', 'router/handler-info', 'router/utils', 'rsvp/promise'], function (exports, _routerHandlerInfo, _routerUtils, _rsvpPromise) { + 'use strict'; + + var ResolvedHandlerInfo = _routerUtils.subclass(_routerHandlerInfo.default, { + resolve: function (shouldContinue, payload) { + // A ResolvedHandlerInfo just resolved with itself. + if (payload && payload.resolvedModels) { + payload.resolvedModels[this.name] = this.context; + } + return _rsvpPromise.default.resolve(this, this.promiseLabel("Resolve")); + }, + + getUnresolved: function () { + return this.factory('param', { + name: this.name, + handler: this.handler, + params: this.params + }); + }, + + isResolved: true + }); + + exports.default = ResolvedHandlerInfo; +}); +enifed('router/handler-info/unresolved-handler-info-by-object', ['exports', 'router/handler-info', 'router/utils', 'rsvp/promise'], function (exports, _routerHandlerInfo, _routerUtils, _rsvpPromise) { + 'use strict'; + + var UnresolvedHandlerInfoByObject = _routerUtils.subclass(_routerHandlerInfo.default, { + getModel: function (payload) { + this.log(payload, this.name + ": resolving provided model"); + return _rsvpPromise.default.resolve(this.context); + }, + + initialize: function (props) { + this.names = props.names || []; + this.context = props.context; + }, + + /** + @private + Serializes a handler using its custom `serialize` method or + by a default that looks up the expected property name from + the dynamic segment. + @param {Object} model the model to be serialized for this handler + */ + serialize: function (_model) { + var model = _model || this.context, + names = this.names, + handler = this.handler; + + var object = {}; + if (_routerUtils.isParam(model)) { + object[names[0]] = model; + return object; + } + + // Use custom serialize if it exists. + if (handler.serialize) { + return handler.serialize(model, names); + } + + if (names.length !== 1) { + return; + } + + var name = names[0]; + + if (/_id$/.test(name)) { + object[name] = model.id; + } else { + object[name] = model; + } + return object; + } + }); + + exports.default = UnresolvedHandlerInfoByObject; +}); +enifed('router/handler-info/unresolved-handler-info-by-param', ['exports', 'router/handler-info', 'router/utils'], function (exports, _routerHandlerInfo, _routerUtils) { + 'use strict'; + + // Generated by URL transitions and non-dynamic route segments in named Transitions. + var UnresolvedHandlerInfoByParam = _routerUtils.subclass(_routerHandlerInfo.default, { + initialize: function (props) { + this.params = props.params || {}; + }, + + getModel: function (payload) { + var fullParams = this.params; + if (payload && payload.queryParams) { + fullParams = {}; + _routerUtils.merge(fullParams, this.params); + fullParams.queryParams = payload.queryParams; + } + + var handler = this.handler; + var hookName = _routerUtils.resolveHook(handler, 'deserialize') || _routerUtils.resolveHook(handler, 'model'); + + return this.runSharedModelHook(payload, hookName, [fullParams]); + } + }); + + exports.default = UnresolvedHandlerInfoByParam; +}); enifed('router/router', ['exports', 'route-recognizer', 'rsvp/promise', 'router/utils', 'router/transition-state', 'router/transition', 'router/transition-intent/named-transition-intent', 'router/transition-intent/url-transition-intent', 'router/handler-info'], function (exports, _routeRecognizer, _rsvpPromise, _routerUtils, _routerTransitionState, _routerTransition, _routerTransitionIntentNamedTransitionIntent, _routerTransitionIntentUrlTransitionIntent, _routerHandlerInfo) { 'use strict'; var pop = Array.prototype.pop; @@ -47915,10 +47918,27 @@ } } exports.default = Router; }); +enifed('router/transition-intent', ['exports', 'router/utils'], function (exports, _routerUtils) { + 'use strict'; + + function TransitionIntent(props) { + this.initialize(props); + + // TODO: wat + this.data = this.data || {}; + } + + TransitionIntent.prototype = { + initialize: null, + applyToState: null + }; + + exports.default = TransitionIntent; +}); enifed('router/transition-intent/named-transition-intent', ['exports', 'router/transition-intent', 'router/transition-state', 'router/handler-info/factory', 'router/utils'], function (exports, _routerTransitionIntent, _routerTransitionState, _routerHandlerInfoFactory, _routerUtils) { 'use strict'; exports.default = _routerUtils.subclass(_routerTransitionIntent.default, { name: null, @@ -48161,27 +48181,10 @@ return newState; } }); }); -enifed('router/transition-intent', ['exports', 'router/utils'], function (exports, _routerUtils) { - 'use strict'; - - function TransitionIntent(props) { - this.initialize(props); - - // TODO: wat - this.data = this.data || {}; - } - - TransitionIntent.prototype = { - initialize: null, - applyToState: null - }; - - exports.default = TransitionIntent; -}); enifed('router/transition-state', ['exports', 'router/handler-info', 'router/utils', 'rsvp/promise'], function (exports, _routerHandlerInfo, _routerUtils, _rsvpPromise) { 'use strict'; function TransitionState(other) { this.handlerInfos = []; @@ -48854,15 +48857,97 @@ exports.coerceQueryParamsToString = coerceQueryParamsToString; exports.callHook = callHook; exports.resolveHook = resolveHook; exports.applyHook = applyHook; }); -enifed('router', ['exports', 'router/router'], function (exports, _routerRouter) { +enifed('rsvp', ['exports', 'rsvp/promise', 'rsvp/events', 'rsvp/node', 'rsvp/all', 'rsvp/all-settled', 'rsvp/race', 'rsvp/hash', 'rsvp/hash-settled', 'rsvp/rethrow', 'rsvp/defer', 'rsvp/config', 'rsvp/map', 'rsvp/resolve', 'rsvp/reject', 'rsvp/filter', 'rsvp/asap'], function (exports, _rsvpPromise, _rsvpEvents, _rsvpNode, _rsvpAll, _rsvpAllSettled, _rsvpRace, _rsvpHash, _rsvpHashSettled, _rsvpRethrow, _rsvpDefer, _rsvpConfig, _rsvpMap, _rsvpResolve, _rsvpReject, _rsvpFilter, _rsvpAsap) { 'use strict'; - exports.default = _routerRouter.default; + // defaults + _rsvpConfig.config.async = _rsvpAsap.default; + _rsvpConfig.config.after = function (cb) { + setTimeout(cb, 0); + }; + var cast = _rsvpResolve.default; + function async(callback, arg) { + _rsvpConfig.config.async(callback, arg); + } + + function on() { + _rsvpConfig.config['on'].apply(_rsvpConfig.config, arguments); + } + + function off() { + _rsvpConfig.config['off'].apply(_rsvpConfig.config, arguments); + } + + // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` + if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { + var callbacks = window['__PROMISE_INSTRUMENTATION__']; + _rsvpConfig.configure('instrument', true); + for (var eventName in callbacks) { + if (callbacks.hasOwnProperty(eventName)) { + on(eventName, callbacks[eventName]); + } + } + } + + exports.cast = cast; + exports.Promise = _rsvpPromise.default; + exports.EventTarget = _rsvpEvents.default; + exports.all = _rsvpAll.default; + exports.allSettled = _rsvpAllSettled.default; + exports.race = _rsvpRace.default; + exports.hash = _rsvpHash.default; + exports.hashSettled = _rsvpHashSettled.default; + exports.rethrow = _rsvpRethrow.default; + exports.defer = _rsvpDefer.default; + exports.denodeify = _rsvpNode.default; + exports.configure = _rsvpConfig.configure; + exports.on = on; + exports.off = off; + exports.resolve = _rsvpResolve.default; + exports.reject = _rsvpReject.default; + exports.async = async; + exports.map = _rsvpMap.default; + exports.filter = _rsvpFilter.default; }); +enifed('rsvp.umd', ['exports', 'rsvp/platform', 'rsvp'], function (exports, _rsvpPlatform, _rsvp) { + 'use strict'; + + var RSVP = { + 'race': _rsvp.race, + 'Promise': _rsvp.Promise, + 'allSettled': _rsvp.allSettled, + 'hash': _rsvp.hash, + 'hashSettled': _rsvp.hashSettled, + 'denodeify': _rsvp.denodeify, + 'on': _rsvp.on, + 'off': _rsvp.off, + 'map': _rsvp.map, + 'filter': _rsvp.filter, + 'resolve': _rsvp.resolve, + 'reject': _rsvp.reject, + 'all': _rsvp.all, + 'rethrow': _rsvp.rethrow, + 'defer': _rsvp.defer, + 'EventTarget': _rsvp.EventTarget, + 'configure': _rsvp.configure, + 'async': _rsvp.async + }; + + /* global define:true module:true window: true */ + if (typeof define === 'function' && define['amd']) { + define(function () { + return RSVP; + }); + } else if (typeof module !== 'undefined' && module['exports']) { + module['exports'] = RSVP; + } else if (typeof _rsvpPlatform.default !== 'undefined') { + _rsvpPlatform.default['RSVP'] = RSVP; + } +}); enifed('rsvp/-internal', ['exports', 'rsvp/utils', 'rsvp/instrument', 'rsvp/config'], function (exports, _rsvpUtils, _rsvpInstrument, _rsvpConfig) { 'use strict'; function withOwnPromise() { return new TypeError('A promises callback cannot return that same promise.'); @@ -50508,267 +50593,10 @@ throw new Error('no global: `self` or `global` found'); } exports.default = platform; }); -enifed('rsvp/promise/all', ['exports', 'rsvp/enumerator'], function (exports, _rsvpEnumerator) { - 'use strict'; - - exports.default = all; - - /** - `RSVP.Promise.all` accepts an array of promises, and returns a new promise which - is fulfilled with an array of fulfillment values for the passed promises, or - rejected with the reason of the first passed promise to be rejected. It casts all - elements of the passed iterable to promises as it runs this algorithm. - - Example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.resolve(2); - var promise3 = RSVP.resolve(3); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.Promise.all(promises).then(function(array){ - // The array here would be [ 1, 2, 3 ]; - }); - ``` - - If any of the `promises` given to `RSVP.all` are rejected, the first promise - that is rejected will be given as an argument to the returned promises's - rejection handler. For example: - - Example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error("2")); - var promise3 = RSVP.reject(new Error("3")); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.Promise.all(promises).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(error) { - // error.message === "2" - }); - ``` - - @method all - @static - @param {Array} entries array of promises - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all `promises` have been - fulfilled, or rejected if any of them become rejected. - @static - */ - - function all(entries, label) { - return new _rsvpEnumerator.default(this, entries, true, /* abort on reject */label).promise; - } -}); -enifed('rsvp/promise/race', ['exports', 'rsvp/utils', 'rsvp/-internal'], function (exports, _rsvpUtils, _rsvpInternal) { - 'use strict'; - - exports.default = race; - - /** - `RSVP.Promise.race` returns a new promise which is settled in the same way as the - first passed promise to settle. - - Example: - - ```javascript - var promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - var promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 2'); - }, 100); - }); - - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // result === 'promise 2' because it was resolved before promise1 - // was resolved. - }); - ``` - - `RSVP.Promise.race` is deterministic in that only the state of the first - settled promise matters. For example, even if other promises given to the - `promises` array argument are resolved, but the first settled promise has - become rejected before the other promises became fulfilled, the returned - promise will become rejected: - - ```javascript - var promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); - - var promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - reject(new Error('promise 2')); - }, 100); - }); - - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // Code here never runs - }, function(reason){ - // reason.message === 'promise 2' because promise 2 became rejected before - // promise 1 became fulfilled - }); - ``` - - An example real-world use case is implementing timeouts: - - ```javascript - RSVP.Promise.race([ajax('foo.json'), timeout(5000)]) - ``` - - @method race - @static - @param {Array} entries array of promises to observe - @param {String} label optional string for describing the promise returned. - Useful for tooling. - @return {Promise} a promise which settles in the same way as the first passed - promise to settle. - */ - - function race(entries, label) { - /*jshint validthis:true */ - var Constructor = this; - - var promise = new Constructor(_rsvpInternal.noop, label); - - if (!_rsvpUtils.isArray(entries)) { - _rsvpInternal.reject(promise, new TypeError('You must pass an array to race.')); - return promise; - } - - var length = entries.length; - - function onFulfillment(value) { - _rsvpInternal.resolve(promise, value); - } - - function onRejection(reason) { - _rsvpInternal.reject(promise, reason); - } - - for (var i = 0; promise._state === _rsvpInternal.PENDING && i < length; i++) { - _rsvpInternal.subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); - } - - return promise; - } -}); -enifed('rsvp/promise/reject', ['exports', 'rsvp/-internal'], function (exports, _rsvpInternal) { - 'use strict'; - - exports.default = reject; - - /** - `RSVP.Promise.reject` returns a promise rejected with the passed `reason`. - It is shorthand for the following: - - ```javascript - var promise = new RSVP.Promise(function(resolve, reject){ - reject(new Error('WHOOPS')); - }); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - var promise = RSVP.Promise.reject(new Error('WHOOPS')); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - @method reject - @static - @param {*} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. - */ - - function reject(reason, label) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor(_rsvpInternal.noop, label); - _rsvpInternal.reject(promise, reason); - return promise; - } -}); -enifed('rsvp/promise/resolve', ['exports', 'rsvp/-internal'], function (exports, _rsvpInternal) { - 'use strict'; - - exports.default = resolve; - - /** - `RSVP.Promise.resolve` returns a promise that will become resolved with the - passed `value`. It is shorthand for the following: - - ```javascript - var promise = new RSVP.Promise(function(resolve, reject){ - resolve(1); - }); - - promise.then(function(value){ - // value === 1 - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - var promise = RSVP.Promise.resolve(1); - - promise.then(function(value){ - // value === 1 - }); - ``` - - @method resolve - @static - @param {*} object value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` - */ - - function resolve(object, label) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; - } - - var promise = new Constructor(_rsvpInternal.noop, label); - _rsvpInternal.resolve(promise, object); - return promise; - } -}); enifed('rsvp/promise-hash', ['exports', 'rsvp/enumerator', 'rsvp/-internal', 'rsvp/utils'], function (exports, _rsvpEnumerator, _rsvpInternal, _rsvpUtils) { 'use strict'; function PromiseHash(Constructor, object, label) { this._superConstructor(Constructor, object, true, label); @@ -51294,10 +51122,267 @@ }); }, label); } }; }); +enifed('rsvp/promise/all', ['exports', 'rsvp/enumerator'], function (exports, _rsvpEnumerator) { + 'use strict'; + + exports.default = all; + + /** + `RSVP.Promise.all` accepts an array of promises, and returns a new promise which + is fulfilled with an array of fulfillment values for the passed promises, or + rejected with the reason of the first passed promise to be rejected. It casts all + elements of the passed iterable to promises as it runs this algorithm. + + Example: + + ```javascript + var promise1 = RSVP.resolve(1); + var promise2 = RSVP.resolve(2); + var promise3 = RSVP.resolve(3); + var promises = [ promise1, promise2, promise3 ]; + + RSVP.Promise.all(promises).then(function(array){ + // The array here would be [ 1, 2, 3 ]; + }); + ``` + + If any of the `promises` given to `RSVP.all` are rejected, the first promise + that is rejected will be given as an argument to the returned promises's + rejection handler. For example: + + Example: + + ```javascript + var promise1 = RSVP.resolve(1); + var promise2 = RSVP.reject(new Error("2")); + var promise3 = RSVP.reject(new Error("3")); + var promises = [ promise1, promise2, promise3 ]; + + RSVP.Promise.all(promises).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(error) { + // error.message === "2" + }); + ``` + + @method all + @static + @param {Array} entries array of promises + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all `promises` have been + fulfilled, or rejected if any of them become rejected. + @static + */ + + function all(entries, label) { + return new _rsvpEnumerator.default(this, entries, true, /* abort on reject */label).promise; + } +}); +enifed('rsvp/promise/race', ['exports', 'rsvp/utils', 'rsvp/-internal'], function (exports, _rsvpUtils, _rsvpInternal) { + 'use strict'; + + exports.default = race; + + /** + `RSVP.Promise.race` returns a new promise which is settled in the same way as the + first passed promise to settle. + + Example: + + ```javascript + var promise1 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + var promise2 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 2'); + }, 100); + }); + + RSVP.Promise.race([promise1, promise2]).then(function(result){ + // result === 'promise 2' because it was resolved before promise1 + // was resolved. + }); + ``` + + `RSVP.Promise.race` is deterministic in that only the state of the first + settled promise matters. For example, even if other promises given to the + `promises` array argument are resolved, but the first settled promise has + become rejected before the other promises became fulfilled, the returned + promise will become rejected: + + ```javascript + var promise1 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + var promise2 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + reject(new Error('promise 2')); + }, 100); + }); + + RSVP.Promise.race([promise1, promise2]).then(function(result){ + // Code here never runs + }, function(reason){ + // reason.message === 'promise 2' because promise 2 became rejected before + // promise 1 became fulfilled + }); + ``` + + An example real-world use case is implementing timeouts: + + ```javascript + RSVP.Promise.race([ajax('foo.json'), timeout(5000)]) + ``` + + @method race + @static + @param {Array} entries array of promises to observe + @param {String} label optional string for describing the promise returned. + Useful for tooling. + @return {Promise} a promise which settles in the same way as the first passed + promise to settle. + */ + + function race(entries, label) { + /*jshint validthis:true */ + var Constructor = this; + + var promise = new Constructor(_rsvpInternal.noop, label); + + if (!_rsvpUtils.isArray(entries)) { + _rsvpInternal.reject(promise, new TypeError('You must pass an array to race.')); + return promise; + } + + var length = entries.length; + + function onFulfillment(value) { + _rsvpInternal.resolve(promise, value); + } + + function onRejection(reason) { + _rsvpInternal.reject(promise, reason); + } + + for (var i = 0; promise._state === _rsvpInternal.PENDING && i < length; i++) { + _rsvpInternal.subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); + } + + return promise; + } +}); +enifed('rsvp/promise/reject', ['exports', 'rsvp/-internal'], function (exports, _rsvpInternal) { + 'use strict'; + + exports.default = reject; + + /** + `RSVP.Promise.reject` returns a promise rejected with the passed `reason`. + It is shorthand for the following: + + ```javascript + var promise = new RSVP.Promise(function(resolve, reject){ + reject(new Error('WHOOPS')); + }); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + var promise = RSVP.Promise.reject(new Error('WHOOPS')); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + @method reject + @static + @param {*} reason value that the returned promise will be rejected with. + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. + */ + + function reject(reason, label) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(_rsvpInternal.noop, label); + _rsvpInternal.reject(promise, reason); + return promise; + } +}); +enifed('rsvp/promise/resolve', ['exports', 'rsvp/-internal'], function (exports, _rsvpInternal) { + 'use strict'; + + exports.default = resolve; + + /** + `RSVP.Promise.resolve` returns a promise that will become resolved with the + passed `value`. It is shorthand for the following: + + ```javascript + var promise = new RSVP.Promise(function(resolve, reject){ + resolve(1); + }); + + promise.then(function(value){ + // value === 1 + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + var promise = RSVP.Promise.resolve(1); + + promise.then(function(value){ + // value === 1 + }); + ``` + + @method resolve + @static + @param {*} object value that the returned promise will be resolved with + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` + */ + + function resolve(object, label) { + /*jshint validthis:true */ + var Constructor = this; + + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; + } + + var promise = new Constructor(_rsvpInternal.noop, label); + _rsvpInternal.resolve(promise, object); + return promise; + } +}); enifed('rsvp/race', ['exports', 'rsvp/promise'], function (exports, _rsvpPromise) { 'use strict'; exports.default = race; @@ -51460,96 +51545,9 @@ } F.prototype = o; return new F(); }; exports.o_create = o_create; -}); -enifed('rsvp', ['exports', 'rsvp/promise', 'rsvp/events', 'rsvp/node', 'rsvp/all', 'rsvp/all-settled', 'rsvp/race', 'rsvp/hash', 'rsvp/hash-settled', 'rsvp/rethrow', 'rsvp/defer', 'rsvp/config', 'rsvp/map', 'rsvp/resolve', 'rsvp/reject', 'rsvp/filter', 'rsvp/asap'], function (exports, _rsvpPromise, _rsvpEvents, _rsvpNode, _rsvpAll, _rsvpAllSettled, _rsvpRace, _rsvpHash, _rsvpHashSettled, _rsvpRethrow, _rsvpDefer, _rsvpConfig, _rsvpMap, _rsvpResolve, _rsvpReject, _rsvpFilter, _rsvpAsap) { - 'use strict'; - - // defaults - _rsvpConfig.config.async = _rsvpAsap.default; - _rsvpConfig.config.after = function (cb) { - setTimeout(cb, 0); - }; - var cast = _rsvpResolve.default; - function async(callback, arg) { - _rsvpConfig.config.async(callback, arg); - } - - function on() { - _rsvpConfig.config['on'].apply(_rsvpConfig.config, arguments); - } - - function off() { - _rsvpConfig.config['off'].apply(_rsvpConfig.config, arguments); - } - - // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` - if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { - var callbacks = window['__PROMISE_INSTRUMENTATION__']; - _rsvpConfig.configure('instrument', true); - for (var eventName in callbacks) { - if (callbacks.hasOwnProperty(eventName)) { - on(eventName, callbacks[eventName]); - } - } - } - - exports.cast = cast; - exports.Promise = _rsvpPromise.default; - exports.EventTarget = _rsvpEvents.default; - exports.all = _rsvpAll.default; - exports.allSettled = _rsvpAllSettled.default; - exports.race = _rsvpRace.default; - exports.hash = _rsvpHash.default; - exports.hashSettled = _rsvpHashSettled.default; - exports.rethrow = _rsvpRethrow.default; - exports.defer = _rsvpDefer.default; - exports.denodeify = _rsvpNode.default; - exports.configure = _rsvpConfig.configure; - exports.on = on; - exports.off = off; - exports.resolve = _rsvpResolve.default; - exports.reject = _rsvpReject.default; - exports.async = async; - exports.map = _rsvpMap.default; - exports.filter = _rsvpFilter.default; -}); -enifed('rsvp.umd', ['exports', 'rsvp/platform', 'rsvp'], function (exports, _rsvpPlatform, _rsvp) { - 'use strict'; - - var RSVP = { - 'race': _rsvp.race, - 'Promise': _rsvp.Promise, - 'allSettled': _rsvp.allSettled, - 'hash': _rsvp.hash, - 'hashSettled': _rsvp.hashSettled, - 'denodeify': _rsvp.denodeify, - 'on': _rsvp.on, - 'off': _rsvp.off, - 'map': _rsvp.map, - 'filter': _rsvp.filter, - 'resolve': _rsvp.resolve, - 'reject': _rsvp.reject, - 'all': _rsvp.all, - 'rethrow': _rsvp.rethrow, - 'defer': _rsvp.defer, - 'EventTarget': _rsvp.EventTarget, - 'configure': _rsvp.configure, - 'async': _rsvp.async - }; - - /* global define:true module:true window: true */ - if (typeof define === 'function' && define['amd']) { - define(function () { - return RSVP; - }); - } else if (typeof module !== 'undefined' && module['exports']) { - module['exports'] = RSVP; - } else if (typeof _rsvpPlatform.default !== 'undefined') { - _rsvpPlatform.default['RSVP'] = RSVP; - } }); enifed("vertex", ["exports"], function (exports) { /** * DAG Vertex *