From 14fa2cc70b6b36711f07cc2e8fbfc34df873cfdb Mon Sep 17 00:00:00 2001 From: Damien White Date: Mon, 6 Apr 2015 07:54:55 -0400 Subject: [PATCH 1/2] Changed helper to work with both Ember 1.10 and 1.11 --- lib/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/helper.js b/lib/helper.js index 07f2fb9..6966aae 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -1,5 +1,5 @@ Ember.Handlebars.registerHelper('flashMessage', function(options) { - var container = this._keywords.view.container, + var container = options.data.view.container, controller = container.lookup('controller:flashMessage'), parent = Ember.ContainerView.extend({ From 2a9ef5d52dc402d005780765e535d70b68ac77dd Mon Sep 17 00:00:00 2001 From: Damien White Date: Mon, 6 Apr 2015 07:56:35 -0400 Subject: [PATCH 2/2] Upgraded to Ember 1.11 with fix from https://github.com/emberjs/ember.js/issues/10310 --- vendor/js/ember-template-compiler.js | 1549 +- vendor/js/ember.js | 72233 ++++++++++++------------- 2 files changed, 35201 insertions(+), 38581 deletions(-) diff --git a/vendor/js/ember-template-compiler.js b/vendor/js/ember-template-compiler.js index d593bd0..f74036b 100644 --- a/vendor/js/ember-template-compiler.js +++ b/vendor/js/ember-template-compiler.js @@ -1,29 +1,42 @@ /*! * @overview Ember - JavaScript Application Framework - * @copyright Copyright 2011-2014 Tilde Inc. and contributors + * @copyright Copyright 2011-2015 Tilde Inc. and contributors * Portions Copyright 2006-2011 Strobe Inc. * Portions Copyright 2008-2011 Apple Inc. All rights reserved. * @license Licensed under MIT license * See https://raw.github.com/emberjs/ember.js/master/LICENSE - * @version 1.10.0 + * @version 1.11.0 */ (function() { -var define, requireModule, require, requirejs, Ember; +var enifed, requireModule, eriuqer, requirejs, Ember; +var mainContext = this; (function() { + Ember = this.Ember = this.Ember || {}; if (typeof Ember === 'undefined') { Ember = {}; }; function UNDEFINED() { } if (typeof Ember.__loader === 'undefined') { - var registry = {}, seen = {}; + var registry = {}; + var seen = {}; + + enifed = function(name, deps, callback) { + var value = { }; + + if (!callback) { + value.deps = []; + value.callback = deps; + } else { + value.deps = deps; + value.callback = callback; + } - define = function(name, deps, callback) { - registry[name] = { deps: deps, callback: callback }; + registry[name] = value; }; - requirejs = require = requireModule = function(name) { + requirejs = eriuqer = requireModule = function(name) { var s = seen[name]; if (s !== undefined) { return seen[name]; } @@ -65,9 +78,13 @@ var define, requireModule, require, requirejs, Ember; for (var i=0, l=parts.length; i 1) { - this.opcode('shareElement', ++this.elementNum); - this.element = null; // Set element to null so we don't cache it twice - } + // If our parent reference will be used more than once, cache its reference. + if (mustacheCount > 1) { + this.opcode('shareElement', ++this.elementNum); + this.element = null; // Set element to null so we don't cache it twice } + var isElementChecked = detectIsElementChecked(element); if (blankChildTextNodes.length > 0 || isElementChecked) { this.opcode( 'repairClonedNode', @@ -1304,23 +1334,42 @@ define("htmlbars-compiler/hydration-opcode-compiler", this.currentDOMChildIndex = -1; forEach(element.attributes, this.attribute, this); - forEach(element.helpers, this.elementHelper, this); + forEach(element.modifiers, this.elementModifier, this); }; - HydrationOpcodeCompiler.prototype.closeElement = function(element, pos, len, isSingleRoot) { + HydrationOpcodeCompiler.prototype.closeElement = function() { distributeMorphs(this.morphs, this.opcodes); - if (!isSingleRoot) { this.opcode('popParent'); } + this.opcode('popParent'); this.currentDOMChildIndex = this.paths.pop(); }; - HydrationOpcodeCompiler.prototype.block = function(block, childIndex, childrenLength) { - var sexpr = block.sexpr; + HydrationOpcodeCompiler.prototype.mustache = function(mustache, childIndex, childCount) { + this.pushMorphPlaceholderNode(childIndex, childCount); + + var sexpr = mustache.sexpr; + + var morphNum = this.morphNum++; + var start = this.currentDOMChildIndex; + var end = this.currentDOMChildIndex; + this.morphs.push([morphNum, this.paths.slice(), start, end, mustache.escaped]); + + if (isHelper(sexpr)) { + prepareSexpr(this, sexpr); + this.opcode('printInlineHook', morphNum); + } else { + preparePath(this, sexpr.path); + this.opcode('printContentHook', morphNum); + } + }; + + HydrationOpcodeCompiler.prototype.block = function(block, childIndex, childCount) { + this.pushMorphPlaceholderNode(childIndex, childCount); - var currentDOMChildIndex = this.currentDOMChildIndex; - var start = (currentDOMChildIndex < 0) ? null : currentDOMChildIndex; - var end = (childIndex === childrenLength - 1) ? null : currentDOMChildIndex + 1; + var sexpr = block.sexpr; var morphNum = this.morphNum++; + var start = this.currentDOMChildIndex; + var end = this.currentDOMChildIndex; this.morphs.push([morphNum, this.paths.slice(), start, end, true]); var templateId = this.templateId++; @@ -1330,15 +1379,15 @@ define("htmlbars-compiler/hydration-opcode-compiler", this.opcode('printBlockHook', morphNum, templateId, inverseId); }; - HydrationOpcodeCompiler.prototype.component = function(component, childIndex, childrenLength) { - var currentDOMChildIndex = this.currentDOMChildIndex; + HydrationOpcodeCompiler.prototype.component = function(component, childIndex, childCount) { + this.pushMorphPlaceholderNode(childIndex, childCount); + var program = component.program || {}; var blockParams = program.blockParams || []; - var start = (currentDOMChildIndex < 0 ? null : currentDOMChildIndex), - end = (childIndex === childrenLength - 1 ? null : currentDOMChildIndex + 1); - var morphNum = this.morphNum++; + var start = this.currentDOMChildIndex; + var end = this.currentDOMChildIndex; this.morphs.push([morphNum, this.paths.slice(), start, end, true]); var attrs = component.attributes; @@ -1392,8 +1441,8 @@ define("htmlbars-compiler/hydration-opcode-compiler", this.opcode('printAttributeHook', attrMorphNum, this.elementNum); }; - HydrationOpcodeCompiler.prototype.elementHelper = function(sexpr) { - prepareSexpr(this, sexpr); + HydrationOpcodeCompiler.prototype.elementModifier = function(modifier) { + prepareSexpr(this, modifier.sexpr); // If we have a helper in a node, and this element has not been cached, cache it if (this.element !== null) { @@ -1404,23 +1453,16 @@ define("htmlbars-compiler/hydration-opcode-compiler", this.opcode('printElementHook', this.elementNum); }; - HydrationOpcodeCompiler.prototype.mustache = function(mustache, childIndex, childrenLength) { - var sexpr = mustache.sexpr; - var currentDOMChildIndex = this.currentDOMChildIndex; - - var start = currentDOMChildIndex, - end = (childIndex === childrenLength - 1 ? -1 : currentDOMChildIndex + 1); - - var morphNum = this.morphNum++; - this.morphs.push([morphNum, this.paths.slice(), start, end, mustache.escaped]); - - if (isHelper(sexpr)) { - prepareSexpr(this, sexpr); - this.opcode('printInlineHook', morphNum); - } else { - preparePath(this, sexpr.path); - this.opcode('printContentHook', morphNum); + HydrationOpcodeCompiler.prototype.pushMorphPlaceholderNode = function(childIndex, childCount) { + if (this.paths.length === 0) { + if (childIndex === 0) { + this.opcode('openBoundary'); + } + if (childIndex === childCount - 1) { + this.opcode('closeBoundary'); + } } + this.comment(); }; HydrationOpcodeCompiler.prototype.SubExpression = function(sexpr) { @@ -1499,7 +1541,7 @@ define("htmlbars-compiler/hydration-opcode-compiler", morphs.length = 0; } }); -define("htmlbars-compiler/template-compiler", +enifed("htmlbars-compiler/template-compiler", ["./fragment-opcode-compiler","./fragment-javascript-compiler","./hydration-opcode-compiler","./hydration-javascript-compiler","./template-visitor","./utils","../htmlbars-util/quoting","exports"], function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { "use strict"; @@ -1513,6 +1555,7 @@ define("htmlbars-compiler/template-compiler", function TemplateCompiler(options) { this.options = options || {}; + this.revision = this.options.revision || "HTMLBars@v0.11.2"; this.fragmentOpcodeCompiler = new FragmentOpcodeCompiler(); this.fragmentCompiler = new FragmentJavaScriptCompiler(); this.hydrationOpcodeCompiler = new HydrationOpcodeCompiler(); @@ -1598,6 +1641,7 @@ define("htmlbars-compiler/template-compiler", this.getChildTemplateVars(indent + ' ') + indent+' return {\n' + indent+' isHTMLBars: true,\n' + + indent+' revision: "' + this.revision + '",\n' + indent+' blockParams: ' + blockParams.length + ',\n' + indent+' cachedFragment: null,\n' + indent+' hasRendered: false,\n' + @@ -1641,14 +1685,14 @@ define("htmlbars-compiler/template-compiler", this.hydrationOpcodeCompiler.closeElement(element, i, l, r); }; - TemplateCompiler.prototype.component = function(component, i, l) { - this.fragmentOpcodeCompiler.component(component, i, l); - this.hydrationOpcodeCompiler.component(component, i, l); + TemplateCompiler.prototype.component = function(component, i, l, s) { + this.fragmentOpcodeCompiler.component(component, i, l, s); + this.hydrationOpcodeCompiler.component(component, i, l, s); }; - TemplateCompiler.prototype.block = function(block, i, l) { - this.fragmentOpcodeCompiler.block(block, i, l); - this.hydrationOpcodeCompiler.block(block, i, l); + TemplateCompiler.prototype.block = function(block, i, l, s) { + this.fragmentOpcodeCompiler.block(block, i, l, s); + this.hydrationOpcodeCompiler.block(block, i, l, s); }; TemplateCompiler.prototype.text = function(string, i, l, r) { @@ -1661,16 +1705,16 @@ define("htmlbars-compiler/template-compiler", this.hydrationOpcodeCompiler.comment(string, i, l, r); }; - TemplateCompiler.prototype.mustache = function (mustache, i, l) { - this.fragmentOpcodeCompiler.mustache(mustache, i, l); - this.hydrationOpcodeCompiler.mustache(mustache, i, l); + TemplateCompiler.prototype.mustache = function (mustache, i, l, s) { + this.fragmentOpcodeCompiler.mustache(mustache, i, l, s); + this.hydrationOpcodeCompiler.mustache(mustache, i, l, s); }; TemplateCompiler.prototype.setNamespace = function(namespace) { this.fragmentOpcodeCompiler.setNamespace(namespace); }; }); -define("htmlbars-compiler/template-visitor", +enifed("htmlbars-compiler/template-visitor", ["exports"], function(__exports__) { "use strict"; @@ -1781,19 +1825,17 @@ define("htmlbars-compiler/template-visitor", TemplateVisitor.prototype.ElementNode = function(element) { var parentFrame = this.getCurrentFrame(); var elementFrame = this.pushFrame(); - var parentNode = parentFrame.parentNode; elementFrame.parentNode = element; elementFrame.children = element.children; elementFrame.childCount = element.children.length; - elementFrame.mustacheCount += element.helpers.length; + elementFrame.mustacheCount += element.modifiers.length; elementFrame.blankChildTextNodes = []; var actionArgs = [ element, parentFrame.childIndex, - parentFrame.childCount, - parentNode.type === 'Program' && parentFrame.childCount === 1 + parentFrame.childCount ]; elementFrame.actions.push(['closeElement', actionArgs]); @@ -1825,11 +1867,10 @@ define("htmlbars-compiler/template-visitor", TemplateVisitor.prototype.TextNode = function(text) { var frame = this.getCurrentFrame(); - var isSingleRoot = frame.parentNode.type === 'Program' && frame.childCount === 1; if (text.chars === '') { frame.blankChildTextNodes.push(domIndexOf(frame.children, text)); } - frame.actions.push(['text', [text, frame.childIndex, frame.childCount, isSingleRoot]]); + frame.actions.push(['text', [text, frame.childIndex, frame.childCount]]); }; TemplateVisitor.prototype.BlockStatement = function(node) { @@ -1860,9 +1901,7 @@ define("htmlbars-compiler/template-visitor", TemplateVisitor.prototype.CommentStatement = function(text) { var frame = this.getCurrentFrame(); - var isSingleRoot = frame.parentNode.type === 'Program' && frame.childCount === 1; - - frame.actions.push(['comment', [text, frame.childIndex, frame.childCount, isSingleRoot]]); + frame.actions.push(['comment', [text, frame.childIndex, frame.childCount]]); }; TemplateVisitor.prototype.MustacheStatement = function(mustache) { @@ -1912,7 +1951,7 @@ define("htmlbars-compiler/template-visitor", return -1; } }); -define("htmlbars-compiler/utils", +enifed("htmlbars-compiler/utils", ["exports"], function(__exports__) { "use strict"; @@ -1930,7 +1969,160 @@ define("htmlbars-compiler/utils", __exports__.processOpcodes = processOpcodes; }); -define("htmlbars-syntax", +enifed("htmlbars-runtime", + ["htmlbars-runtime/hooks","htmlbars-runtime/helpers","exports"], + function(__dependency1__, __dependency2__, __exports__) { + "use strict"; + var hooks = __dependency1__["default"]; + var helpers = __dependency2__["default"]; + + __exports__.hooks = hooks; + __exports__.helpers = helpers; + }); +enifed("htmlbars-runtime/helpers", + ["exports"], + function(__exports__) { + "use strict"; + function partial(params, hash, options, env) { + var template = env.partials[params[0]]; + return template.render(this, env, options.morph.contextualElement); + } + + __exports__.partial = partial;__exports__["default"] = { + partial: partial + }; + }); +enifed("htmlbars-runtime/hooks", + ["exports"], + function(__exports__) { + "use strict"; + function block(env, morph, context, path, params, hash, template, inverse) { + var options = { + morph: morph, + template: template, + inverse: inverse + }; + + var helper = lookupHelper(env, context, path); + var value = helper.call(context, params, hash, options, env); + + morph.setContent(value); + } + + __exports__.block = block;function inline(env, morph, context, path, params, hash) { + var helper = lookupHelper(env, context, path); + var value = helper.call(context, params, hash, { morph: morph }, env); + + morph.setContent(value); + } + + __exports__.inline = inline;function content(env, morph, context, path) { + var helper = lookupHelper(env, context, path); + + var value; + if (helper) { + value = helper.call(context, [], {}, { morph: morph }, env); + } else { + value = get(env, context, path); + } + + morph.setContent(value); + } + + __exports__.content = content;function element(env, domElement, context, path, params, hash) { + var helper = lookupHelper(env, context, path); + if (helper) { + helper.call(context, params, hash, { element: domElement }, env); + } + } + + __exports__.element = element;function attribute(env, attrMorph, domElement, name, value) { + attrMorph.setContent(value); + } + + __exports__.attribute = attribute;function subexpr(env, context, helperName, params, hash) { + var helper = lookupHelper(env, context, helperName); + if (helper) { + return helper.call(context, params, hash, {}, env); + } else { + return get(env, context, helperName); + } + } + + __exports__.subexpr = subexpr;function get(env, context, path) { + if (path === '') { + return context; + } + + var keys = path.split('.'); + var value = context; + for (var i = 0; i < keys.length; i++) { + if (value) { + value = value[keys[i]]; + } else { + break; + } + } + return value; + } + + __exports__.get = get;function set(env, context, name, value) { + context[name] = value; + } + + __exports__.set = set;function component(env, morph, context, tagName, attrs, template) { + var helper = lookupHelper(env, context, tagName); + + var value; + if (helper) { + var options = { + morph: morph, + template: template + }; + + value = helper.call(context, [], attrs, options, env); + } else { + value = componentFallback(env, morph, context, tagName, attrs, template); + } + + morph.setContent(value); + } + + __exports__.component = component;function concat(env, params) { + var value = ""; + for (var i = 0, l = params.length; i < l; i++) { + value += params[i]; + } + return value; + } + + __exports__.concat = concat;function componentFallback(env, morph, context, tagName, attrs, template) { + var element = env.dom.createElement(tagName); + for (var name in attrs) { + element.setAttribute(name, attrs[name]); + } + element.appendChild(template.render(context, env, morph.contextualElement)); + return element; + } + + function lookupHelper(env, context, helperName) { + return env.helpers[helperName]; + } + + __exports__["default"] = { + content: content, + block: block, + inline: inline, + component: component, + element: element, + attribute: attribute, + subexpr: subexpr, + concat: concat, + get: get, + set: set + }; + }); +enifed("htmlbars-syntax", ["./htmlbars-syntax/walker","./htmlbars-syntax/builders","./htmlbars-syntax/parser","exports"], function(__dependency1__, __dependency2__, __dependency3__, __exports__) { "use strict"; @@ -1942,7 +2134,7 @@ define("htmlbars-syntax", __exports__.builders = builders; __exports__.parse = parse; }); -define("htmlbars-syntax/builders", +enifed("htmlbars-syntax/builders", ["exports"], function(__exports__) { "use strict"; @@ -1980,22 +2172,28 @@ define("htmlbars-syntax/builders", }; } - __exports__.buildComment = buildComment; - function buildConcat(parts) { + __exports__.buildComment = buildComment;function buildConcat(parts) { return { type: "ConcatStatement", parts: parts || [] }; } - __exports__.buildConcat = buildConcat;// Nodes + __exports__.buildConcat = buildConcat;function buildElementModifier(sexpr) { + return { + type: "ElementModifierStatement", + sexpr: sexpr + }; + } + + __exports__.buildElementModifier = buildElementModifier;// Nodes - function buildElement(tag, attributes, helpers, children) { + function buildElement(tag, attributes, modifiers, children) { return { type: "ElementNode", tag: tag, attributes: attributes || [], - helpers: helpers || [], + modifiers: modifiers || [], children: children || [] }; } @@ -2098,6 +2296,7 @@ define("htmlbars-syntax/builders", partial: buildPartial, comment: buildComment, element: buildElement, + elementModifier: buildElementModifier, component: buildComponent, attr: buildAttr, text: buildText, @@ -2112,7 +2311,7 @@ define("htmlbars-syntax/builders", program: buildProgram }; }); -define("htmlbars-syntax/handlebars/compiler/ast", +enifed("htmlbars-syntax/handlebars/compiler/ast", ["../exception","exports"], function(__dependency1__, __exports__) { "use strict"; @@ -2232,7 +2431,7 @@ define("htmlbars-syntax/handlebars/compiler/ast", // most modify the object to operate properly. __exports__["default"] = AST; }); -define("htmlbars-syntax/handlebars/compiler/base", +enifed("htmlbars-syntax/handlebars/compiler/base", ["./parser","./ast","./whitespace-control","./helpers","../utils","exports"], function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { "use strict"; @@ -2264,7 +2463,7 @@ define("htmlbars-syntax/handlebars/compiler/base", __exports__.parse = parse; }); -define("htmlbars-syntax/handlebars/compiler/helpers", +enifed("htmlbars-syntax/handlebars/compiler/helpers", ["../exception","exports"], function(__dependency1__, __exports__) { "use strict"; @@ -2385,7 +2584,7 @@ define("htmlbars-syntax/handlebars/compiler/helpers", __exports__.prepareBlock = prepareBlock; }); -define("htmlbars-syntax/handlebars/compiler/parser", +enifed("htmlbars-syntax/handlebars/compiler/parser", ["exports"], function(__exports__) { "use strict"; @@ -2921,7 +3120,7 @@ define("htmlbars-syntax/handlebars/compiler/parser", })();__exports__["default"] = handlebars; /* jshint ignore:end */ }); -define("htmlbars-syntax/handlebars/compiler/visitor", +enifed("htmlbars-syntax/handlebars/compiler/visitor", ["exports"], function(__exports__) { "use strict"; @@ -2992,7 +3191,7 @@ define("htmlbars-syntax/handlebars/compiler/visitor", __exports__["default"] = Visitor; }); -define("htmlbars-syntax/handlebars/compiler/whitespace-control", +enifed("htmlbars-syntax/handlebars/compiler/whitespace-control", ["./visitor","exports"], function(__dependency1__, __exports__) { "use strict"; @@ -3207,7 +3406,7 @@ define("htmlbars-syntax/handlebars/compiler/whitespace-control", __exports__["default"] = WhitespaceControl; }); -define("htmlbars-syntax/handlebars/exception", +enifed("htmlbars-syntax/handlebars/exception", ["exports"], function(__exports__) { "use strict"; @@ -3242,7 +3441,7 @@ define("htmlbars-syntax/handlebars/exception", __exports__["default"] = Exception; }); -define("htmlbars-syntax/handlebars/safe-string", +enifed("htmlbars-syntax/handlebars/safe-string", ["exports"], function(__exports__) { "use strict"; @@ -3257,7 +3456,7 @@ define("htmlbars-syntax/handlebars/safe-string", __exports__["default"] = SafeString; }); -define("htmlbars-syntax/handlebars/utils", +enifed("htmlbars-syntax/handlebars/utils", ["./safe-string","exports"], function(__dependency1__, __exports__) { "use strict"; @@ -3349,7 +3548,7 @@ define("htmlbars-syntax/handlebars/utils", __exports__.appendContextPath = appendContextPath; }); -define("htmlbars-syntax/node-handlers", +enifed("htmlbars-syntax/node-handlers", ["./builders","../htmlbars-util/array-utils","./utils","exports"], function(__dependency1__, __dependency2__, __dependency3__, __exports__) { "use strict"; @@ -3358,7 +3557,6 @@ define("htmlbars-syntax/node-handlers", var buildHash = __dependency1__.buildHash; var forEach = __dependency2__.forEach; var appendChild = __dependency3__.appendChild; - var postprocessProgram = __dependency3__.postprocessProgram; var nodeHandlers = { @@ -3377,8 +3575,6 @@ define("htmlbars-syntax/node-handlers", this.acceptToken(this.tokenizer.tokenizeEOF()); - postprocessProgram(node); - // Ensure that that the element stack is balanced properly. var poppedNode = this.elementStack.pop(); if (poppedNode !== node) { @@ -3515,7 +3711,7 @@ define("htmlbars-syntax/node-handlers", __exports__["default"] = nodeHandlers; }); -define("htmlbars-syntax/parser", +enifed("htmlbars-syntax/parser", ["./handlebars/compiler/base","./tokenizer","../simple-html-tokenizer/entity-parser","../simple-html-tokenizer/char-refs/full","./node-handlers","./token-handlers","../htmlbars-syntax","exports"], function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { "use strict"; @@ -3622,7 +3818,7 @@ define("htmlbars-syntax/parser", return string.join('\n'); }; }); -define("htmlbars-syntax/token-handlers", +enifed("htmlbars-syntax/token-handlers", ["../htmlbars-util/array-utils","./builders","./utils","exports"], function(__dependency1__, __dependency2__, __dependency3__, __exports__) { "use strict"; @@ -3634,7 +3830,6 @@ define("htmlbars-syntax/token-handlers", var buildText = __dependency2__.buildText; var appendChild = __dependency3__.appendChild; var parseComponentBlockParams = __dependency3__.parseComponentBlockParams; - var postprocessProgram = __dependency3__.postprocessProgram; // The HTML elements in this list are speced by // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements, @@ -3663,7 +3858,7 @@ define("htmlbars-syntax/token-handlers", }, StartTag: function(tag) { - var element = buildElement(tag.tagName, tag.attributes, tag.helpers || [], []); + var element = buildElement(tag.tagName, tag.attributes, tag.modifiers || [], []); element.loc = { start: { line: tag.firstLine, column: tag.firstColumn}, end: { line: null, column: null} @@ -3689,20 +3884,20 @@ define("htmlbars-syntax/token-handlers", switch(tokenizer.state) { // Tag helpers case "tagName": - tokenizer.addTagHelper(mustache.sexpr); + tokenizer.addElementModifier(mustache); tokenizer.state = "beforeAttributeName"; return; case "beforeAttributeName": - tokenizer.addTagHelper(mustache.sexpr); + tokenizer.addElementModifier(mustache); return; case "attributeName": case "afterAttributeName": tokenizer.finalizeAttributeValue(); - tokenizer.addTagHelper(mustache.sexpr); + tokenizer.addElementModifier(mustache); tokenizer.state = "beforeAttributeName"; return; case "afterAttributeValueQuoted": - tokenizer.addTagHelper(mustache.sexpr); + tokenizer.addElementModifier(mustache); tokenizer.state = "beforeAttributeName"; return; @@ -3737,7 +3932,6 @@ define("htmlbars-syntax/token-handlers", } else { var program = buildProgram(element.children); parseComponentBlockParams(element, program); - postprocessProgram(program); var component = buildComponent(element.tag, element.attributes, program); appendChild(parent, component); } @@ -3769,7 +3963,7 @@ define("htmlbars-syntax/token-handlers", __exports__["default"] = tokenHandlers; }); -define("htmlbars-syntax/tokenizer", +enifed("htmlbars-syntax/tokenizer", ["../simple-html-tokenizer","./utils","../htmlbars-util/array-utils","./builders","exports"], function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { "use strict"; @@ -3830,9 +4024,13 @@ define("htmlbars-syntax/tokenizer", } }; - Tokenizer.prototype.addTagHelper = function(helper) { - var helpers = this.token.helpers = this.token.helpers || []; - helpers.push(helper); + Tokenizer.prototype.addElementModifier = function(mustache) { + if (!this.token.modifiers) { + this.token.modifiers = []; + } + + var modifier = builders.elementModifier(mustache.sexpr); + this.token.modifiers.push(modifier); }; function prepareAttributeValue(attr) { @@ -3873,12 +4071,11 @@ define("htmlbars-syntax/tokenizer", __exports__.unwrapMustache = unwrapMustache;__exports__.Tokenizer = Tokenizer; }); -define("htmlbars-syntax/utils", - ["./builders","../htmlbars-util/array-utils","exports"], - function(__dependency1__, __dependency2__, __exports__) { +enifed("htmlbars-syntax/utils", + ["../htmlbars-util/array-utils","exports"], + function(__dependency1__, __exports__) { "use strict"; - var buildText = __dependency1__.buildText; - var indexOfArray = __dependency2__.indexOfArray; + var indexOfArray = __dependency1__.indexOfArray; // Regex to validate the identifier for block parameters. // Based on the ID validation regex in Handlebars. @@ -3925,26 +4122,7 @@ define("htmlbars-syntax/utils", } } - __exports__.parseComponentBlockParams = parseComponentBlockParams;// Adds an empty text node at the beginning and end of a program. - // The empty text nodes *between* nodes are handled elsewhere. - - function postprocessProgram(program) { - var body = program.body; - - if (body.length === 0) { - return; - } - - if (usesMorph(body[0])) { - body.unshift(buildText('')); - } - - if (usesMorph(body[body.length-1])) { - body.push(buildText('')); - } - } - - __exports__.postprocessProgram = postprocessProgram;function childrenFor(node) { + __exports__.parseComponentBlockParams = parseComponentBlockParams;function childrenFor(node) { if (node.type === 'Program') { return node.body; } @@ -3953,23 +4131,8 @@ define("htmlbars-syntax/utils", } } - __exports__.childrenFor = childrenFor;function usesMorph(node) { - return node.type === 'MustacheStatement' || - node.type === 'BlockStatement' || - node.type === 'ComponentNode'; - } - - __exports__.usesMorph = usesMorph;function appendChild(parent, node) { - var children = childrenFor(parent); - - var len = children.length, last; - if (len > 0) { - last = children[len-1]; - if (usesMorph(last) && usesMorph(node)) { - children.push(buildText('')); - } - } - children.push(node); + __exports__.childrenFor = childrenFor;function appendChild(parent, node) { + childrenFor(parent).push(node); } __exports__.appendChild = appendChild;function isHelper(sexpr) { @@ -3979,7 +4142,7 @@ define("htmlbars-syntax/utils", __exports__.isHelper = isHelper; }); -define("htmlbars-syntax/walker", +enifed("htmlbars-syntax/walker", ["exports"], function(__exports__) { "use strict"; @@ -4038,7 +4201,7 @@ define("htmlbars-syntax/walker", } }; }); -define("htmlbars-test-helpers", +enifed("htmlbars-test-helpers", ["exports"], function(__exports__) { "use strict"; @@ -4150,7 +4313,7 @@ define("htmlbars-test-helpers", } __exports__.createObject = createObject; }); -define("htmlbars-util", +enifed("htmlbars-util", ["./htmlbars-util/safe-string","./htmlbars-util/handlebars/utils","./htmlbars-util/namespaces","exports"], function(__dependency1__, __dependency2__, __dependency3__, __exports__) { "use strict"; @@ -4162,7 +4325,7 @@ define("htmlbars-util", __exports__.escapeExpression = escapeExpression; __exports__.getAttrNamespace = getAttrNamespace; }); -define("htmlbars-util/array-utils", +enifed("htmlbars-util/array-utils", ["exports"], function(__exports__) { "use strict"; @@ -4214,7 +4377,7 @@ define("htmlbars-util/array-utils", var indexOfArray = getIdx; __exports__.indexOfArray = indexOfArray; }); -define("htmlbars-util/handlebars/safe-string", +enifed("htmlbars-util/handlebars/safe-string", ["exports"], function(__exports__) { "use strict"; @@ -4229,7 +4392,7 @@ define("htmlbars-util/handlebars/safe-string", __exports__["default"] = SafeString; }); -define("htmlbars-util/handlebars/utils", +enifed("htmlbars-util/handlebars/utils", ["./safe-string","exports"], function(__dependency1__, __exports__) { "use strict"; @@ -4321,7 +4484,7 @@ define("htmlbars-util/handlebars/utils", __exports__.appendContextPath = appendContextPath; }); -define("htmlbars-util/namespaces", +enifed("htmlbars-util/namespaces", ["exports"], function(__exports__) { "use strict"; @@ -4348,7 +4511,7 @@ define("htmlbars-util/namespaces", __exports__.getAttrNamespace = getAttrNamespace; }); -define("htmlbars-util/object-utils", +enifed("htmlbars-util/object-utils", ["exports"], function(__exports__) { "use strict"; @@ -4362,7 +4525,7 @@ define("htmlbars-util/object-utils", __exports__.merge = merge; }); -define("htmlbars-util/quoting", +enifed("htmlbars-util/quoting", ["exports"], function(__exports__) { "use strict"; @@ -4401,7 +4564,7 @@ define("htmlbars-util/quoting", __exports__.repeat = repeat; }); -define("htmlbars-util/safe-string", +enifed("htmlbars-util/safe-string", ["./handlebars/safe-string","exports"], function(__dependency1__, __exports__) { "use strict"; @@ -4409,7 +4572,7 @@ define("htmlbars-util/safe-string", __exports__["default"] = SafeString; }); -define("simple-html-tokenizer", +enifed("simple-html-tokenizer", ["./simple-html-tokenizer/tokenizer","./simple-html-tokenizer/tokenize","./simple-html-tokenizer/generator","./simple-html-tokenizer/generate","./simple-html-tokenizer/tokens","exports"], function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { "use strict"; @@ -4432,7 +4595,7 @@ define("simple-html-tokenizer", __exports__.Chars = Chars; __exports__.Comment = Comment; }); -define("simple-html-tokenizer/char-refs/full", +enifed("simple-html-tokenizer/char-refs/full", ["exports"], function(__exports__) { "use strict"; @@ -6564,7 +6727,7 @@ define("simple-html-tokenizer/char-refs/full", zwnj: [8204] }; }); -define("simple-html-tokenizer/char-refs/min", +enifed("simple-html-tokenizer/char-refs/min", ["exports"], function(__exports__) { "use strict"; @@ -6576,7 +6739,7 @@ define("simple-html-tokenizer/char-refs/min", gt: [62] }; }); -define("simple-html-tokenizer/entity-parser", +enifed("simple-html-tokenizer/entity-parser", ["exports"], function(__exports__) { "use strict"; @@ -6611,7 +6774,7 @@ define("simple-html-tokenizer/entity-parser", __exports__["default"] = EntityParser; }); -define("simple-html-tokenizer/generate", +enifed("simple-html-tokenizer/generate", ["./generator","exports"], function(__dependency1__, __exports__) { "use strict"; @@ -6622,7 +6785,7 @@ define("simple-html-tokenizer/generate", return generator.generate(tokens); } }); -define("simple-html-tokenizer/generator", +enifed("simple-html-tokenizer/generator", ["exports"], function(__exports__) { "use strict"; @@ -6721,7 +6884,7 @@ define("simple-html-tokenizer/generator", __exports__["default"] = Generator; }); -define("simple-html-tokenizer/tokenize", +enifed("simple-html-tokenizer/tokenize", ["./tokenizer","./entity-parser","./char-refs/full","exports"], function(__dependency1__, __dependency2__, __dependency3__, __exports__) { "use strict"; @@ -6734,7 +6897,7 @@ define("simple-html-tokenizer/tokenize", return tokenizer.tokenize(); } }); -define("simple-html-tokenizer/tokenizer", +enifed("simple-html-tokenizer/tokenizer", ["./utils","./tokens","exports"], function(__dependency1__, __dependency2__, __exports__) { "use strict"; @@ -7138,7 +7301,7 @@ define("simple-html-tokenizer/tokenizer", __exports__["default"] = Tokenizer; }); -define("simple-html-tokenizer/tokens", +enifed("simple-html-tokenizer/tokens", ["exports"], function(__exports__) { "use strict"; @@ -7166,7 +7329,7 @@ define("simple-html-tokenizer/tokens", __exports__.Comment = Comment; }); -define("simple-html-tokenizer/utils", +enifed("simple-html-tokenizer/utils", ["exports"], function(__exports__) { "use strict"; diff --git a/vendor/js/ember.js b/vendor/js/ember.js index 5c0e3e0..b26f893 100644 --- a/vendor/js/ember.js +++ b/vendor/js/ember.js @@ -1,26 +1,39 @@ /*! * @overview Ember - JavaScript Application Framework - * @copyright Copyright 2011-2014 Tilde Inc. and contributors + * @copyright Copyright 2011-2015 Tilde Inc. and contributors * Portions Copyright 2006-2011 Strobe Inc. * Portions Copyright 2008-2011 Apple Inc. All rights reserved. * @license Licensed under MIT license * See https://raw.github.com/emberjs/ember.js/master/LICENSE - * @version 1.10.0 + * @version 1.11.0 */ (function() { var enifed, requireModule, eriuqer, requirejs, Ember; +var mainContext = this; (function() { + Ember = this.Ember = this.Ember || {}; if (typeof Ember === 'undefined') { Ember = {}; }; function UNDEFINED() { } if (typeof Ember.__loader === 'undefined') { - var registry = {}, seen = {}; + var registry = {}; + var seen = {}; enifed = function(name, deps, callback) { - registry[name] = { deps: deps, callback: callback }; + var value = { }; + + if (!callback) { + value.deps = []; + value.callback = deps; + } else { + value.deps = deps; + value.callback = callback; + } + + registry[name] = value; }; requirejs = eriuqer = requireModule = function(name) { @@ -65,9 +78,13 @@ var enifed, requireModule, eriuqer, requirejs, Ember; for (var i=0, l=parts.length; i true - ```javascript - var container = new Container(); + // by default the container will return singletons + var twitter2 = container.lookup('api:twitter'); + twitter2 instanceof Twitter; // => true - container.register('model:user', Person, {singleton: false }); - container.register('fruit:favorite', Orange); - container.register('communication:main', Email, {singleton: false}); - ``` + twitter === twitter2; //=> true + ``` - @method register - @param {String} fullName - @param {Function} factory - @param {Object} options - */ - register: function(fullName, factory, options) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); + If singletons are not wanted an optional flag can be provided at lookup. - if (factory === undefined) { - throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`'); - } + ```javascript + var registry = new Registry(); + var container = registry.container(); - var normalizedName = this.normalize(fullName); + registry.register('api:twitter', Twitter); - if (normalizedName in this.cache) { - throw new Error('Cannot re-register: `' + fullName +'`, as it has already been looked up.'); - } + var twitter = container.lookup('api:twitter', { singleton: false }); + var twitter2 = container.lookup('api:twitter', { singleton: false }); - this.registry[normalizedName] = factory; - this._options[normalizedName] = (options || {}); - }, + twitter === twitter2; //=> false + ``` - /** - Unregister a fullName + @method lookup + @param {String} fullName + @param {Object} options + @return {any} + */ + lookup: function(fullName, options) { + Ember['default'].assert('fullName must be a proper full name', this._registry.validateFullName(fullName)); + return lookup(this, this._registry.normalize(fullName), options); + }, - ```javascript - var container = new Container(); - container.register('model:user', User); + /** + Given a fullName return the corresponding factory. - container.lookup('model:user') instanceof User //=> true + @method lookupFactory + @param {String} fullName + @return {any} + */ + lookupFactory: function(fullName) { + Ember['default'].assert('fullName must be a proper full name', this._registry.validateFullName(fullName)); + return factoryFor(this, this._registry.normalize(fullName)); + }, - container.unregister('model:user') - container.lookup('model:user') === undefined //=> true - ``` + /** + A depth first traversal, destroying the container, its descendant containers and all + their managed objects. - @method unregister - @param {String} fullName - */ - unregister: function(fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - - var normalizedName = this.normalize(fullName); - - delete this.registry[normalizedName]; - delete this.cache[normalizedName]; - delete this.factoryCache[normalizedName]; - delete this.resolveCache[normalizedName]; - delete this._options[normalizedName]; - - delete this.validationCache[normalizedName]; - - }, + @method destroy + */ + destroy: function() { + eachDestroyable(this, function(item) { + if (item.destroy) { + item.destroy(); + } + }); - /** - Given a fullName return the corresponding factory. + this.isDestroyed = true; + }, - By default `resolve` will retrieve the factory from - its container's registry. + /** + Clear either the entire cache or just the cache for a particular key. - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); + @method reset + @param {String} fullName optional key to reset; if missing, resets everything + */ + reset: function(fullName) { + if (arguments.length > 0) { + resetMember(this, this._registry.normalize(fullName)); + } else { + resetCache(this); + } + } + }; + + (function exposeRegistryMethods() { + var methods = [ + 'register', + 'unregister', + 'resolve', + 'normalize', + 'typeInjection', + 'injection', + 'factoryInjection', + 'factoryTypeInjection', + 'has', + 'options', + 'optionsForType' + ]; - container.resolve('api:twitter') // => Twitter - ``` + function exposeRegistryMethod(method) { + Container.prototype[method] = function() { + Ember['default'].deprecate(method + ' should be called on the registry instead of the container'); + return this._registry[method].apply(this._registry, arguments); + }; + } - Optionally the container can be provided with a custom resolver. - If provided, `resolve` will first provide the custom resolver - the opportunity to resolve the fullName, otherwise it will fallback - to the registry. + for (var i = 0, l = methods.length; i < l; i++) { + exposeRegistryMethod(methods[i]); + } + })(); - ```javascript - var container = new Container(); - container.resolver = function(fullName) { - // lookup via the module system of choice - }; + function lookup(container, fullName, options) { + options = options || {}; - // the twitter factory is added to the module system - container.resolve('api:twitter') // => Twitter - ``` + if (container.cache[fullName] && options.singleton !== false) { + return container.cache[fullName]; + } - @method resolve - @param {String} fullName - @return {Function} fullName's factory - */ - resolve: function(fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - return resolve(this, this.normalize(fullName)); - }, + var value = instantiate(container, fullName); - /** - A hook that can be used to describe how the resolver will - attempt to find the factory. + if (value === undefined) { return; } - For example, the default Ember `.describe` returns the full - class name (including namespace) where Ember's resolver expects - to find the `fullName`. + if (container._registry.getOption(fullName, 'singleton') !== false && options.singleton !== false) { + container.cache[fullName] = value; + } - @method describe - @param {String} fullName - @return {string} described fullName - */ - describe: function(fullName) { - return fullName; - }, + return value; + } - /** - A hook to enable custom fullName normalization behaviour + function buildInjections(container) { + var hash = {}; - @method normalizeFullName - @param {String} fullName - @return {string} normalized fullName - */ - normalizeFullName: function(fullName) { - return fullName; - }, + if (arguments.length > 1) { + var injectionArgs = Array.prototype.slice.call(arguments, 1); + var injections = []; + var injection; - /** - normalize a fullName based on the applications conventions + for (var i = 0, l = injectionArgs.length; i < l; i++) { + if (injectionArgs[i]) { + injections = injections.concat(injectionArgs[i]); + } + } - @method normalize - @param {String} fullName - @return {string} normalized fullName - */ - normalize: function(fullName) { - return this.normalizeCache[fullName] || ( - this.normalizeCache[fullName] = this.normalizeFullName(fullName) - ); - }, + container._registry.validateInjections(injections); - /** - @method makeToString + for (i = 0, l = injections.length; i < l; i++) { + injection = injections[i]; + hash[injection.property] = lookup(container, injection.fullName); + } + } - @param {any} factory - @param {string} fullName - @return {function} toString function - */ - makeToString: function(factory, fullName) { - return factory.toString(); - }, + return hash; + } - /** - Given a fullName return a corresponding instance. + function factoryFor(container, fullName) { + var cache = container.factoryCache; + if (cache[fullName]) { + return cache[fullName]; + } + var registry = container._registry; + var factory = registry.resolve(fullName); + if (factory === undefined) { return; } - The default behaviour is for lookup to return a singleton instance. - The singleton is scoped to the container, allowing multiple containers - to all have their own locally scoped singletons. + var type = fullName.split(':')[0]; + if (!factory || typeof factory.extend !== 'function' || (!Ember['default'].MODEL_FACTORY_INJECTIONS && type === 'model')) { + if (factory && typeof factory._onLookup === 'function') { + factory._onLookup(fullName); + } - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); + // TODO: think about a 'safe' merge style extension + // for now just fallback to create time injection + cache[fullName] = factory; + return factory; - var twitter = container.lookup('api:twitter'); + } else { + var injections = injectionsFor(container, fullName); + var factoryInjections = factoryInjectionsFor(container, fullName); - twitter instanceof Twitter; // => true + factoryInjections._toString = registry.makeToString(factory, fullName); - // by default the container will return singletons - var twitter2 = container.lookup('api:twitter'); - twitter2 instanceof Twitter; // => true + var injectedFactory = factory.extend(injections); + injectedFactory.reopenClass(factoryInjections); - twitter === twitter2; //=> true - ``` + if (factory && typeof factory._onLookup === 'function') { + factory._onLookup(fullName); + } - If singletons are not wanted an optional flag can be provided at lookup. + cache[fullName] = injectedFactory; - ```javascript - var container = new Container(); - container.register('api:twitter', Twitter); + return injectedFactory; + } + } - var twitter = container.lookup('api:twitter', { singleton: false }); - var twitter2 = container.lookup('api:twitter', { singleton: false }); + function injectionsFor(container, fullName) { + var registry = container._registry; + var splitName = fullName.split(':'); + var type = splitName[0]; - twitter === twitter2; //=> false - ``` + var injections = buildInjections(container, + registry.getTypeInjections(type), + registry.getInjections(fullName)); + injections._debugContainerKey = fullName; + injections.container = container; - @method lookup - @param {String} fullName - @param {Object} options - @return {any} - */ - lookup: function(fullName, options) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - return lookup(this, this.normalize(fullName), options); - }, + return injections; + } - /** - Given a fullName return the corresponding factory. + function factoryInjectionsFor(container, fullName) { + var registry = container._registry; + var splitName = fullName.split(':'); + var type = splitName[0]; - @method lookupFactory - @param {String} fullName - @return {any} - */ - lookupFactory: function(fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - return factoryFor(this, this.normalize(fullName)); - }, + var factoryInjections = buildInjections(container, + registry.getFactoryTypeInjections(type), + registry.getFactoryInjections(fullName)); + factoryInjections._debugContainerKey = fullName; - /** - Given a fullName check if the container is aware of its factory - or singleton instance. + return factoryInjections; + } - @method has - @param {String} fullName - @return {Boolean} - */ - has: function(fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - return has(this, this.normalize(fullName)); - }, + function instantiate(container, fullName) { + var factory = factoryFor(container, fullName); + var lazyInjections, validationCache; - /** - Allow registering options for all factories of a type. + if (container._registry.getOption(fullName, 'instantiate') === false) { + return factory; + } - ```javascript - var container = new Container(); + if (factory) { + if (typeof factory.create !== 'function') { + throw new Error('Failed to create an instance of \'' + fullName + '\'. ' + + 'Most likely an improperly defined class or an invalid module export.'); + } - // if all of type `connection` must not be singletons - container.optionsForType('connection', { singleton: false }); + validationCache = container.validationCache; - container.register('connection:twitter', TwitterConnection); - container.register('connection:facebook', FacebookConnection); + // Ensure that all lazy injections are valid at instantiation time + if (!validationCache[fullName] && typeof factory._lazyInjections === 'function') { + lazyInjections = factory._lazyInjections(); + lazyInjections = container._registry.normalizeInjectionsHash(lazyInjections); - var twitter = container.lookup('connection:twitter'); - var twitter2 = container.lookup('connection:twitter'); + container._registry.validateInjections(lazyInjections); + } - twitter === twitter2; // => false + validationCache[fullName] = true; - var facebook = container.lookup('connection:facebook'); - var facebook2 = container.lookup('connection:facebook'); + if (typeof factory.extend === 'function') { + // assume the factory was extendable and is already injected + return factory.create(); + } else { + // assume the factory was extendable + // to create time injections + // TODO: support new'ing for instantiation and merge injections for pure JS Functions + return factory.create(injectionsFor(container, fullName)); + } + } + } - facebook === facebook2; // => false - ``` + function eachDestroyable(container, callback) { + var cache = container.cache; + var keys = emberKeys['default'](cache); + var key, value; - @method optionsForType - @param {String} type - @param {Object} options - */ - optionsForType: function(type, options) { - if (this.parent) { illegalChildOperation('optionsForType'); } + for (var i = 0, l = keys.length; i < l; i++) { + key = keys[i]; + value = cache[key]; - this._typeOptions[type] = options; - }, + if (container._registry.getOption(key, 'instantiate') !== false) { + callback(value); + } + } + } - /** - @method options - @param {String} fullName - @param {Object} options - */ - options: function(fullName, options) { - options = options || {}; - var normalizedName = this.normalize(fullName); - this._options[normalizedName] = options; - }, + function resetCache(container) { + eachDestroyable(container, function(value) { + if (value.destroy) { + value.destroy(); + } + }); - /** - Used only via `injection`. + container.cache.dict = dictionary['default'](null); + } - Provides a specialized form of injection, specifically enabling - all objects of one type to be injected with a reference to another - object. + function resetMember(container, fullName) { + var member = container.cache[fullName]; - For example, provided each object of type `controller` needed a `router`. - one would do the following: + delete container.factoryCache[fullName]; - ```javascript - var container = new Container(); + if (member) { + delete container.cache[fullName]; - container.register('router:main', Router); - container.register('controller:user', UserController); - container.register('controller:post', PostController); + if (member.destroy) { + member.destroy(); + } + } + } - container.typeInjection('controller', 'router', 'router:main'); + exports['default'] = Container; - var user = container.lookup('controller:user'); - var post = container.lookup('controller:post'); +}); +enifed('container/registry', ['exports', 'ember-metal/core', 'ember-metal/dictionary', './container'], function (exports, Ember, dictionary, Container) { - user.router instanceof Router; //=> true - post.router instanceof Router; //=> true + 'use strict'; - // both controllers share the same router - user.router === post.router; //=> true - ``` + var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/; - @private - @method typeInjection - @param {String} type - @param {String} property - @param {String} fullName - */ - typeInjection: function(type, property, fullName) { - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); + var instanceInitializersFeatureEnabled; - if (this.parent) { illegalChildOperation('typeInjection'); } + /** + A lightweight registry used to store factory and option information keyed + by type. - var fullNameType = fullName.split(':')[0]; - if (fullNameType === type) { - throw new Error('Cannot inject a `' + fullName + - '` on other ' + type + - '(s). Register the `' + fullName + - '` as a different type and perform the typeInjection.'); - } + A `Registry` stores the factory and option information needed by a + `Container` to instantiate and cache objects. - addTypeInjection(this.typeInjections, type, property, fullName); - }, + The public API for `Registry` is still in flux and should not be considered + stable. - /** - Defines injection rules. + @private + @class Registry + @since 1.11.0 + */ + function Registry(options) { + this.fallback = options && options.fallback ? options.fallback : null; - These rules are used to inject dependencies onto objects when they - are instantiated. + this.resolver = options && options.resolver ? options.resolver : function() {}; - Two forms of injections are possible: + this.registrations = dictionary['default'](options && options.registrations ? options.registrations : null); - * Injecting one fullName on another fullName - * Injecting one fullName on a type + this._typeInjections = dictionary['default'](null); + this._injections = dictionary['default'](null); + this._factoryTypeInjections = dictionary['default'](null); + this._factoryInjections = dictionary['default'](null); - Example: + this._normalizeCache = dictionary['default'](null); + this._resolveCache = dictionary['default'](null); - ```javascript - var container = new Container(); + this._options = dictionary['default'](null); + this._typeOptions = dictionary['default'](null); + } - container.register('source:main', Source); - container.register('model:user', User); - container.register('model:post', Post); + Registry.prototype = { + /** + A backup registry for resolving registrations when no matches can be found. - // injecting one fullName on another fullName - // eg. each user model gets a post model - container.injection('model:user', 'post', 'model:post'); + @property fallback + @type Registry + */ + fallback: null, - // injecting one fullName on another type - container.injection('model', 'source', 'source:main'); + /** + @property resolver + @type function + */ + resolver: null, - var user = container.lookup('model:user'); - var post = container.lookup('model:post'); + /** + @property registrations + @type InheritingDict + */ + registrations: null, - user.source instanceof Source; //=> true - post.source instanceof Source; //=> true + /** + @private - user.post instanceof Post; //=> true + @property _typeInjections + @type InheritingDict + */ + _typeInjections: null, - // and both models share the same source - user.source === post.source; //=> true - ``` + /** + @private - @method injection - @param {String} factoryName - @param {String} property - @param {String} injectionName - */ - injection: function(fullName, property, injectionName) { - if (this.parent) { illegalChildOperation('injection'); } + @property _injections + @type InheritingDict + */ + _injections: null, - validateFullName(injectionName); - var normalizedInjectionName = this.normalize(injectionName); + /** + @private - if (fullName.indexOf(':') === -1) { - return this.typeInjection(fullName, property, normalizedInjectionName); - } + @property _factoryTypeInjections + @type InheritingDict + */ + _factoryTypeInjections: null, - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); - var normalizedName = this.normalize(fullName); + /** + @private - if (this.cache[normalizedName]) { - throw new Error("Attempted to register an injection for a type that has already been looked up. ('" + - normalizedName + "', '" + - property + "', '" + - injectionName + "')"); - } + @property _factoryInjections + @type InheritingDict + */ + _factoryInjections: null, - addInjection(initRules(this.injections, normalizedName), property, normalizedInjectionName); - }, + /** + @private + @property _normalizeCache + @type InheritingDict + */ + _normalizeCache: null, - /** - Used only via `factoryInjection`. + /** + @private - Provides a specialized form of injection, specifically enabling - all factory of one type to be injected with a reference to another - object. + @property _resolveCache + @type InheritingDict + */ + _resolveCache: null, - For example, provided each factory of type `model` needed a `store`. - one would do the following: + /** + @private - ```javascript - var container = new Container(); + @property _options + @type InheritingDict + */ + _options: null, - container.register('store:main', SomeStore); + /** + @private - container.factoryTypeInjection('model', 'store', 'store:main'); + @property _typeOptions + @type InheritingDict + */ + _typeOptions: null, - var store = container.lookup('store:main'); - var UserFactory = container.lookupFactory('model:user'); + /** + The first container created for this registry. - UserFactory.store instanceof SomeStore; //=> true - ``` + This allows deprecated access to `lookup` and `lookupFactory` to avoid + breaking compatibility for Ember 1.x initializers. - @private - @method factoryTypeInjection - @param {String} type - @param {String} property - @param {String} fullName - */ - factoryTypeInjection: function(type, property, fullName) { - if (this.parent) { illegalChildOperation('factoryTypeInjection'); } + @private + @property _defaultContainer + @type Container + */ + _defaultContainer: null, - addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName)); - }, + /** + Creates a container based on this registry. - /** - Defines factory injection rules. + @method container + @param {Object} options + @return {Container} created container + */ + container: function(options) { + var container = new Container['default'](this, options); - Similar to regular injection rules, but are run against factories, via - `Container#lookupFactory`. + // 2.0TODO - remove `registerContainer` + this.registerContainer(container); - These rules are used to inject objects onto factories when they - are looked up. + return container; + }, - Two forms of injections are possible: + /** + Register the first container created for a registery to allow deprecated + access to its `lookup` and `lookupFactory` methods to avoid breaking + compatibility for Ember 1.x initializers. - * Injecting one fullName on another fullName - * Injecting one fullName on a type + 2.0TODO: Remove this method. The bookkeeping is only needed to support + deprecated behavior. - Example: + @param {Container} newly created container + */ + registerContainer: function(container) { + if (!this._defaultContainer) { + this._defaultContainer = container; + } + if (this.fallback) { + this.fallback.registerContainer(container); + } + }, - ```javascript - var container = new Container(); + lookup: function(fullName, options) { + Ember['default'].assert('Create a container on the registry (with `registry.container()`) before calling `lookup`.', this._defaultContainer); - container.register('store:main', Store); - container.register('store:secondary', OtherStore); - container.register('model:user', User); - container.register('model:post', Post); + if (instanceInitializersFeatureEnabled) { + Ember['default'].deprecate( + '`lookup` was called on a Registry. The `initializer` API no longer receives a container, and you should use an `instanceInitializer` to look up objects from the container.', + false, + { url: "http://emberjs.com/guides/deprecations#toc_access-to-instances-in-initializers" } + ); + } - // injecting one fullName on another type - container.factoryInjection('model', 'store', 'store:main'); + return this._defaultContainer.lookup(fullName, options); + }, - // injecting one fullName on another fullName - container.factoryInjection('model:post', 'secondaryStore', 'store:secondary'); + lookupFactory: function(fullName) { + Ember['default'].assert('Create a container on the registry (with `registry.container()`) before calling `lookupFactory`.', this._defaultContainer); - var UserFactory = container.lookupFactory('model:user'); - var PostFactory = container.lookupFactory('model:post'); - var store = container.lookup('store:main'); + if (instanceInitializersFeatureEnabled) { + Ember['default'].deprecate( + '`lookupFactory` was called on a Registry. The `initializer` API no longer receives a container, and you should use an `instanceInitializer` to look up objects from the container.', + false, + { url: "http://emberjs.com/guides/deprecations#toc_access-to-instances-in-initializers" } + ); + } - UserFactory.store instanceof Store; //=> true - UserFactory.secondaryStore instanceof OtherStore; //=> false + return this._defaultContainer.lookupFactory(fullName); + }, - PostFactory.store instanceof Store; //=> true - PostFactory.secondaryStore instanceof OtherStore; //=> true + /** + Registers a factory for later injection. - // and both models share the same source instance - UserFactory.store === PostFactory.store; //=> true - ``` + Example: - @method factoryInjection - @param {String} factoryName - @param {String} property - @param {String} injectionName - */ - factoryInjection: function(fullName, property, injectionName) { - if (this.parent) { illegalChildOperation('injection'); } + ```javascript + var registry = new Registry(); - var normalizedName = this.normalize(fullName); - var normalizedInjectionName = this.normalize(injectionName); + registry.register('model:user', Person, {singleton: false }); + registry.register('fruit:favorite', Orange); + registry.register('communication:main', Email, {singleton: false}); + ``` - validateFullName(injectionName); + @method register + @param {String} fullName + @param {Function} factory + @param {Object} options + */ + register: function(fullName, factory, options) { + Ember['default'].assert('fullName must be a proper full name', this.validateFullName(fullName)); - if (fullName.indexOf(':') === -1) { - return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName); - } + if (factory === undefined) { + throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`'); + } - Ember.assert('fullName must be a proper full name', validateFullName(fullName)); + var normalizedName = this.normalize(fullName); - if (this.factoryCache[normalizedName]) { - throw new Error('Attempted to register a factoryInjection for a type that has already ' + - 'been looked up. (\'' + normalizedName + '\', \'' + property + '\', \'' + injectionName + '\')'); - } + if (this._resolveCache[normalizedName]) { + throw new Error('Cannot re-register: `' + fullName +'`, as it has already been resolved.'); + } - addInjection(initRules(this.factoryInjections, normalizedName), property, normalizedInjectionName); - }, + this.registrations[normalizedName] = factory; + this._options[normalizedName] = (options || {}); + }, - /** - A depth first traversal, destroying the container, its descendant containers and all - their managed objects. + /** + Unregister a fullName - @method destroy - */ - destroy: function() { - for (var i = 0, length = this.children.length; i < length; i++) { - this.children[i].destroy(); - } + ```javascript + var registry = new Registry(); + registry.register('model:user', User); - this.children = []; + registry.resolve('model:user').create() instanceof User //=> true - eachDestroyable(this, function(item) { - item.destroy(); - }); + registry.unregister('model:user') + registry.resolve('model:user') === undefined //=> true + ``` - this.parent = undefined; - this.isDestroyed = true; - }, + @method unregister + @param {String} fullName + */ + unregister: function(fullName) { + Ember['default'].assert('fullName must be a proper full name', this.validateFullName(fullName)); - /** - @method reset - */ - reset: function() { - for (var i = 0, length = this.children.length; i < length; i++) { - resetCache(this.children[i]); - } + var normalizedName = this.normalize(fullName); - resetCache(this); - } - }; + delete this.registrations[normalizedName]; + delete this._resolveCache[normalizedName]; + delete this._options[normalizedName]; + }, + + /** + Given a fullName return the corresponding factory. - function resolve(container, normalizedName) { - var cached = container.resolveCache[normalizedName]; - if (cached) { return cached; } + By default `resolve` will retrieve the factory from + the registry. - var resolved = container.resolver(normalizedName) || container.registry[normalizedName]; - container.resolveCache[normalizedName] = resolved; + ```javascript + var registry = new Registry(); + registry.register('api:twitter', Twitter); - return resolved; - } + registry.resolve('api:twitter') // => Twitter + ``` - function has(container, fullName){ - if (container.cache[fullName]) { - return true; - } + Optionally the registry can be provided with a custom resolver. + If provided, `resolve` will first provide the custom resolver + the opportunity to resolve the fullName, otherwise it will fallback + to the registry. - return container.resolve(fullName) !== undefined; - } + ```javascript + var registry = new Registry(); + registry.resolver = function(fullName) { + // lookup via the module system of choice + }; - function lookup(container, fullName, options) { - options = options || {}; + // the twitter factory is added to the module system + registry.resolve('api:twitter') // => Twitter + ``` - if (container.cache[fullName] && options.singleton !== false) { - return container.cache[fullName]; + @method resolve + @param {String} fullName + @return {Function} fullName's factory + */ + resolve: function(fullName) { + Ember['default'].assert('fullName must be a proper full name', this.validateFullName(fullName)); + var factory = resolve(this, this.normalize(fullName)); + if (factory === undefined && this.fallback) { + factory = this.fallback.resolve(fullName); } + return factory; + }, - var value = instantiate(container, fullName); + /** + A hook that can be used to describe how the resolver will + attempt to find the factory. - if (value === undefined) { return; } + For example, the default Ember `.describe` returns the full + class name (including namespace) where Ember's resolver expects + to find the `fullName`. - if (isSingleton(container, fullName) && options.singleton !== false) { - container.cache[fullName] = value; - } + @method describe + @param {String} fullName + @return {string} described fullName + */ + describe: function(fullName) { + return fullName; + }, - return value; - } + /** + A hook to enable custom fullName normalization behaviour - function illegalChildOperation(operation) { - throw new Error(operation + ' is not currently supported on child containers'); - } + @method normalizeFullName + @param {String} fullName + @return {string} normalized fullName + */ + normalizeFullName: function(fullName) { + return fullName; + }, - function isSingleton(container, fullName) { - var singleton = option(container, fullName, 'singleton'); + /** + normalize a fullName based on the applications conventions - return singleton !== false; - } + @method normalize + @param {String} fullName + @return {string} normalized fullName + */ + normalize: function(fullName) { + return this._normalizeCache[fullName] || ( + this._normalizeCache[fullName] = this.normalizeFullName(fullName) + ); + }, - function buildInjections(container, injections) { - var hash = {}; + /** + @method makeToString - if (!injections) { return hash; } + @param {any} factory + @param {string} fullName + @return {function} toString function + */ + makeToString: function(factory, fullName) { + return factory.toString(); + }, - validateInjections(container, injections); + /** + Given a fullName check if the container is aware of its factory + or singleton instance. - var injection; + @method has + @param {String} fullName + @return {Boolean} + */ + has: function(fullName) { + Ember['default'].assert('fullName must be a proper full name', this.validateFullName(fullName)); + return has(this, this.normalize(fullName)); + }, - for (var i = 0, length = injections.length; i < length; i++) { - injection = injections[i]; - hash[injection.property] = lookup(container, injection.fullName); - } + /** + Allow registering options for all factories of a type. - return hash; - } + ```javascript + var registry = new Registry(); + var container = registry.container(); - function validateInjections(container, injections) { - if (!injections) { return; } + // if all of type `connection` must not be singletons + registry.optionsForType('connection', { singleton: false }); - var fullName; + registry.register('connection:twitter', TwitterConnection); + registry.register('connection:facebook', FacebookConnection); - for (var i = 0, length = injections.length; i < length; i++) { - fullName = injections[i].fullName; + var twitter = container.lookup('connection:twitter'); + var twitter2 = container.lookup('connection:twitter'); - if (!container.has(fullName)) { - throw new Error('Attempting to inject an unknown injection: `' + fullName + '`'); - } + twitter === twitter2; // => false + + var facebook = container.lookup('connection:facebook'); + var facebook2 = container.lookup('connection:facebook'); + + facebook === facebook2; // => false + ``` + + @method optionsForType + @param {String} type + @param {Object} options + */ + optionsForType: function(type, options) { + this._typeOptions[type] = options; + }, + + getOptionsForType: function(type) { + var optionsForType = this._typeOptions[type]; + if (optionsForType === undefined && this.fallback) { + optionsForType = this.fallback.getOptionsForType(type); } - } + return optionsForType; + }, + + /** + @method options + @param {String} fullName + @param {Object} options + */ + options: function(fullName, options) { + options = options || {}; + var normalizedName = this.normalize(fullName); + this._options[normalizedName] = options; + }, + + getOptions: function(fullName) { + var normalizedName = this.normalize(fullName); + var options = this._options[normalizedName]; + if (options === undefined && this.fallback) { + options = this.fallback.getOptions(fullName); + } + return options; + }, - function option(container, fullName, optionName) { - var options = container._options[fullName]; + getOption: function(fullName, optionName) { + var options = this._options[fullName]; if (options && options[optionName] !== undefined) { return options[optionName]; } var type = fullName.split(':')[0]; - options = container._typeOptions[type]; + options = this._typeOptions[type]; - if (options) { + if (options && options[optionName] !== undefined) { return options[optionName]; - } - } - function factoryFor(container, fullName) { - var cache = container.factoryCache; - if (cache[fullName]) { - return cache[fullName]; + } else if (this.fallback) { + return this.fallback.getOption(fullName, optionName); } - var factory = container.resolve(fullName); - if (factory === undefined) { return; } + }, - var type = fullName.split(':')[0]; - if (!factory || typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) { - if (factory && typeof factory._onLookup === 'function') { - factory._onLookup(fullName); - } + option: function(fullName, optionName) { + Ember['default'].deprecate('`Registry.option()` has been deprecated. Call `Registry.getOption()` instead.'); + return this.getOption(fullName, optionName); + }, - // TODO: think about a 'safe' merge style extension - // for now just fallback to create time injection - cache[fullName] = factory; - return factory; - } else { - var injections = injectionsFor(container, fullName); - var factoryInjections = factoryInjectionsFor(container, fullName); + /** + Used only via `injection`. - factoryInjections._toString = container.makeToString(factory, fullName); + Provides a specialized form of injection, specifically enabling + all objects of one type to be injected with a reference to another + object. - var injectedFactory = factory.extend(injections); - injectedFactory.reopenClass(factoryInjections); + For example, provided each object of type `controller` needed a `router`. + one would do the following: - if (factory && typeof factory._onLookup === 'function') { - factory._onLookup(fullName); - } + ```javascript + var registry = new Registry(); + var container = registry.container(); + + registry.register('router:main', Router); + registry.register('controller:user', UserController); + registry.register('controller:post', PostController); + + registry.typeInjection('controller', 'router', 'router:main'); + + var user = container.lookup('controller:user'); + var post = container.lookup('controller:post'); + + user.router instanceof Router; //=> true + post.router instanceof Router; //=> true + + // both controllers share the same router + user.router === post.router; //=> true + ``` - cache[fullName] = injectedFactory; + @private + @method typeInjection + @param {String} type + @param {String} property + @param {String} fullName + */ + typeInjection: function(type, property, fullName) { + Ember['default'].assert('fullName must be a proper full name', this.validateFullName(fullName)); - return injectedFactory; + var fullNameType = fullName.split(':')[0]; + if (fullNameType === type) { + throw new Error('Cannot inject a `' + fullName + + '` on other ' + type + '(s).'); } - } - function injectionsFor(container, fullName) { - var splitName = fullName.split(':'); - var type = splitName[0]; - var injections = []; + var injections = this._typeInjections[type] || + (this._typeInjections[type] = []); + + injections.push({ + property: property, + fullName: fullName + }); + }, - injections = injections.concat(container.typeInjections[type] || []); - injections = injections.concat(container.injections[fullName] || []); + /** + Defines injection rules. - injections = buildInjections(container, injections); - injections._debugContainerKey = fullName; - injections.container = container; + These rules are used to inject dependencies onto objects when they + are instantiated. - return injections; - } + Two forms of injections are possible: - function factoryInjectionsFor(container, fullName) { - var splitName = fullName.split(':'); - var type = splitName[0]; - var factoryInjections = []; + * Injecting one fullName on another fullName + * Injecting one fullName on a type - factoryInjections = factoryInjections.concat(container.factoryTypeInjections[type] || []); - factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []); + Example: - factoryInjections = buildInjections(container, factoryInjections); - factoryInjections._debugContainerKey = fullName; + ```javascript + var registry = new Registry(); + var container = registry.container(); - return factoryInjections; - } + registry.register('source:main', Source); + registry.register('model:user', User); + registry.register('model:post', Post); - function normalizeInjectionsHash(hash) { - var injections = []; + // injecting one fullName on another fullName + // eg. each user model gets a post model + registry.injection('model:user', 'post', 'model:post'); - for (var key in hash) { - if (hash.hasOwnProperty(key)) { - Ember.assert("Expected a proper full name, given '" + hash[key] + "'", validateFullName(hash[key])); + // injecting one fullName on another type + registry.injection('model', 'source', 'source:main'); - addInjection(injections, key, hash[key]); - } - } + var user = container.lookup('model:user'); + var post = container.lookup('model:post'); - return injections; - } + user.source instanceof Source; //=> true + post.source instanceof Source; //=> true + + user.post instanceof Post; //=> true + + // and both models share the same source + user.source === post.source; //=> true + ``` - function instantiate(container, fullName) { - var factory = factoryFor(container, fullName); - var lazyInjections, validationCache; + @method injection + @param {String} factoryName + @param {String} property + @param {String} injectionName + */ + injection: function(fullName, property, injectionName) { + this.validateFullName(injectionName); + var normalizedInjectionName = this.normalize(injectionName); - if (option(container, fullName, 'instantiate') === false) { - return factory; + if (fullName.indexOf(':') === -1) { + return this.typeInjection(fullName, property, normalizedInjectionName); } - if (factory) { - if (typeof factory.create !== 'function') { - throw new Error('Failed to create an instance of \'' + fullName + '\'. ' + - 'Most likely an improperly defined class or an invalid module export.'); - } + Ember['default'].assert('fullName must be a proper full name', this.validateFullName(fullName)); + var normalizedName = this.normalize(fullName); - - validationCache = container.validationCache; + var injections = this._injections[normalizedName] || + (this._injections[normalizedName] = []); - // Ensure that all lazy injections are valid at instantiation time - if (!validationCache[fullName] && typeof factory._lazyInjections === 'function') { - lazyInjections = factory._lazyInjections(); + injections.push({ + property: property, + fullName: normalizedInjectionName + }); + }, - validateInjections(container, normalizeInjectionsHash(lazyInjections)); - } - validationCache[fullName] = true; - + /** + Used only via `factoryInjection`. - if (typeof factory.extend === 'function') { - // assume the factory was extendable and is already injected - return factory.create(); - } else { - // assume the factory was extendable - // to create time injections - // TODO: support new'ing for instantiation and merge injections for pure JS Functions - return factory.create(injectionsFor(container, fullName)); - } - } - } + Provides a specialized form of injection, specifically enabling + all factory of one type to be injected with a reference to another + object. - function eachDestroyable(container, callback) { - var cache = container.cache; - var keys = emberKeys(cache); - var key, value; + For example, provided each factory of type `model` needed a `store`. + one would do the following: - for (var i = 0, l = keys.length; i < l; i++) { - key = keys[i]; - value = cache[key]; + ```javascript + var registry = new Registry(); - if (option(container, key, 'instantiate') !== false) { - callback(value); - } - } - } + registry.register('store:main', SomeStore); - function resetCache(container) { - eachDestroyable(container, function(value) { - value.destroy(); + registry.factoryTypeInjection('model', 'store', 'store:main'); + + var store = registry.lookup('store:main'); + var UserFactory = registry.lookupFactory('model:user'); + + UserFactory.store instanceof SomeStore; //=> true + ``` + + @private + @method factoryTypeInjection + @param {String} type + @param {String} property + @param {String} fullName + */ + factoryTypeInjection: function(type, property, fullName) { + var injections = this._factoryTypeInjections[type] || + (this._factoryTypeInjections[type] = []); + + injections.push({ + property: property, + fullName: this.normalize(fullName) }); + }, - container.cache.dict = dictionary(null); - } + /** + Defines factory injection rules. + + Similar to regular injection rules, but are run against factories, via + `Registry#lookupFactory`. + + These rules are used to inject objects onto factories when they + are looked up. + + Two forms of injections are possible: - function addTypeInjection(rules, type, property, fullName) { - var injections = rules[type]; + * Injecting one fullName on another fullName + * Injecting one fullName on a type - if (!injections) { - injections = []; - rules[type] = injections; + Example: + + ```javascript + var registry = new Registry(); + var container = registry.container(); + + registry.register('store:main', Store); + registry.register('store:secondary', OtherStore); + registry.register('model:user', User); + registry.register('model:post', Post); + + // injecting one fullName on another type + registry.factoryInjection('model', 'store', 'store:main'); + + // injecting one fullName on another fullName + registry.factoryInjection('model:post', 'secondaryStore', 'store:secondary'); + + var UserFactory = container.lookupFactory('model:user'); + var PostFactory = container.lookupFactory('model:post'); + var store = container.lookup('store:main'); + + UserFactory.store instanceof Store; //=> true + UserFactory.secondaryStore instanceof OtherStore; //=> false + + PostFactory.store instanceof Store; //=> true + PostFactory.secondaryStore instanceof OtherStore; //=> true + + // and both models share the same source instance + UserFactory.store === PostFactory.store; //=> true + ``` + + @method factoryInjection + @param {String} factoryName + @param {String} property + @param {String} injectionName + */ + factoryInjection: function(fullName, property, injectionName) { + var normalizedName = this.normalize(fullName); + var normalizedInjectionName = this.normalize(injectionName); + + this.validateFullName(injectionName); + + if (fullName.indexOf(':') === -1) { + return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName); } + var injections = this._factoryInjections[normalizedName] || (this._factoryInjections[normalizedName] = []); + injections.push({ property: property, - fullName: fullName + fullName: normalizedInjectionName }); - } + }, - var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/; - function validateFullName(fullName) { + validateFullName: function(fullName) { if (!VALID_FULL_NAME_REGEXP.test(fullName)) { throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName); } return true; - } + }, - function initRules(rules, factoryName) { - return rules[factoryName] || (rules[factoryName] = []); - } + validateInjections: function(injections) { + if (!injections) { return; } - function addInjection(injections, property, injectionName) { - injections.push({ - property: property, - fullName: injectionName - }); + var fullName; + + for (var i = 0, length = injections.length; i < length; i++) { + fullName = injections[i].fullName; + + if (!this.has(fullName)) { + throw new Error('Attempting to inject an unknown injection: `' + fullName + '`'); + } + } + }, + + normalizeInjectionsHash: function(hash) { + var injections = []; + + for (var key in hash) { + if (hash.hasOwnProperty(key)) { + Ember['default'].assert("Expected a proper full name, given '" + hash[key] + "'", this.validateFullName(hash[key])); + + injections.push({ + property: key, + fullName: hash[key] + }); + } + } + + return injections; + }, + + getInjections: function(fullName) { + var injections = this._injections[fullName] || []; + if (this.fallback) { + injections = injections.concat(this.fallback.getInjections(fullName)); + } + return injections; + }, + + getTypeInjections: function(type) { + var injections = this._typeInjections[type] || []; + if (this.fallback) { + injections = injections.concat(this.fallback.getTypeInjections(type)); + } + return injections; + }, + + getFactoryInjections: function(fullName) { + var injections = this._factoryInjections[fullName] || []; + if (this.fallback) { + injections = injections.concat(this.fallback.getFactoryInjections(fullName)); + } + return injections; + }, + + getFactoryTypeInjections: function(type) { + var injections = this._factoryTypeInjections[type] || []; + if (this.fallback) { + injections = injections.concat(this.fallback.getFactoryTypeInjections(type)); + } + return injections; } + }; - __exports__["default"] = Container; - }); + function resolve(registry, normalizedName) { + var cached = registry._resolveCache[normalizedName]; + if (cached) { return cached; } + + var resolved = registry.resolver(normalizedName) || registry.registrations[normalizedName]; + registry._resolveCache[normalizedName] = resolved; + + return resolved; + } + + function has(registry, fullName) { + return registry.resolve(fullName) !== undefined; + } + + exports['default'] = Registry; + +}); enifed("dag-map", ["exports"], function(__exports__) { @@ -2205,45174 +2452,41376 @@ enifed("dag-map.umd", this['DAG'] = DAG; } }); -enifed("ember-application", - ["ember-metal/core","ember-runtime/system/lazy_load","ember-application/system/resolver","ember-application/system/application","ember-application/ext/controller"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) { - "use strict"; - var Ember = __dependency1__["default"]; - var runLoadHooks = __dependency2__.runLoadHooks; - - /** - Ember Application - - @module ember - @submodule ember-application - @requires ember-views, ember-routing - */ - - var Resolver = __dependency3__.Resolver; - var DefaultResolver = __dependency3__["default"]; - var Application = __dependency4__["default"]; - // side effect of extending ControllerMixin - - Ember.Application = Application; - Ember.Resolver = Resolver; - Ember.DefaultResolver = DefaultResolver; - - runLoadHooks('Ember.Application', Application); - }); -enifed("ember-application/ext/controller", - ["ember-metal/core","ember-metal/property_get","ember-metal/error","ember-metal/utils","ember-metal/computed","ember-runtime/mixins/controller","ember-routing/system/controller_for","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { +enifed("dom-helper", + ["./morph-range","./morph-attr","./dom-helper/build-html-dom","./dom-helper/classes","./dom-helper/prop","exports"], + function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { "use strict"; - /** - @module ember - @submodule ember-application - */ + var Morph = __dependency1__["default"]; + var AttrMorph = __dependency2__["default"]; + var buildHTMLDOM = __dependency3__.buildHTMLDOM; + var svgNamespace = __dependency3__.svgNamespace; + var svgHTMLIntegrationPoints = __dependency3__.svgHTMLIntegrationPoints; + var addClasses = __dependency4__.addClasses; + var removeClasses = __dependency4__.removeClasses; + var normalizeProperty = __dependency5__.normalizeProperty; + var isAttrRemovalValue = __dependency5__.isAttrRemovalValue; - var Ember = __dependency1__["default"]; - // Ember.assert - var get = __dependency2__.get; - var EmberError = __dependency3__["default"]; - var inspect = __dependency4__.inspect; - var computed = __dependency5__.computed; - var ControllerMixin = __dependency6__["default"]; - var meta = __dependency4__.meta; - var controllerFor = __dependency7__["default"]; + var doc = typeof document === 'undefined' ? false : document; - function verifyNeedsDependencies(controller, container, needs) { - var dependency, i, l; - var missing = []; + var deletesBlankTextNodes = doc && (function(document){ + var element = document.createElement('div'); + element.appendChild( document.createTextNode('') ); + var clonedElement = element.cloneNode(true); + return clonedElement.childNodes.length === 0; + })(doc); - for (i=0, l=needs.length; i 1 ? 'they' : 'it') + " could not be found"); + // This is not the namespace of the element, but of + // the elements inside that elements. + function interiorNamespace(element){ + if ( + element && + element.namespaceURI === svgNamespace && + !svgHTMLIntegrationPoints[element.tagName] + ) { + return svgNamespace; + } else { + return null; } } - var defaultControllersComputedProperty = computed(function() { - var controller = this; - - return { - needs: get(controller, 'needs'), - container: get(controller, 'container'), - unknownProperty: function(controllerName) { - var needs = this.needs; - var dependency, i, l; - - for (i=0, l=needs.length; i 0) { - Ember.assert(' `' + inspect(this) + ' specifies `needs`, but does ' + - "not have a container. Please ensure this controller was " + - "instantiated with a container.", - this.container || meta(this, false).descs.controllers !== defaultControllersComputedProperty); - - if (this.container) { - verifyNeedsDependencies(this, this.container, needs); - } + // The HTML spec allows for "omitted start tags". These tags are optional + // when their intended child is the first thing in the parent tag. For + // example, this is a tbody start tag: + // + // + // + // + // + // The tbody may be omitted, and the browser will accept and render: + // + //
+ // + // + // However, the omitted start tag will still be added to the DOM. Here + // we test the string and context to see if the browser is about to + // perform this cleanup. + // + // http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags + // describes which tags are omittable. The spec for tbody and colgroup + // explains this behavior: + // + // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-tbody-element + // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-colgroup-element + // - // if needs then initialize controllers proxy - get(this, 'controllers'); + var omittedStartTagChildTest = /<([\w:]+)/; + function detectOmittedStartTag(string, contextualElement){ + // Omitted start tags are only inside table tags. + if (contextualElement.tagName === 'TABLE') { + var omittedStartTagChildMatch = omittedStartTagChildTest.exec(string); + if (omittedStartTagChildMatch) { + var omittedStartTagChild = omittedStartTagChildMatch[1]; + // It is already asserted that the contextual element is a table + // and not the proper start tag. Just see if a tag was omitted. + return omittedStartTagChild === 'tr' || + omittedStartTagChild === 'col'; } - - this._super.apply(this, arguments); - }, - - /** - @method controllerFor - @see {Ember.Route#controllerFor} - @deprecated Use `needs` instead - */ - controllerFor: function(controllerName) { - Ember.deprecate("Controller#controllerFor is deprecated, please use Controller#needs instead"); - return controllerFor(get(this, 'container'), controllerName); - }, - - /** - Stores the instances of other controllers available from within - this controller. Any controller listed by name in the `needs` - property will be accessible by name through this property. - - ```javascript - App.CommentsController = Ember.ArrayController.extend({ - needs: ['post'], - postTitle: function(){ - var currentPost = this.get('controllers.post'); // instance of App.PostController - return currentPost.get('title'); - }.property('controllers.post.title') - }); - ``` - - @see {Ember.ControllerMixin#needs} - @property {Object} controllers - @default null - */ - controllers: defaultControllersComputedProperty - }); - - __exports__["default"] = ControllerMixin; - }); -enifed("ember-application/system/application", - ["dag-map","container/container","ember-metal","ember-metal/property_get","ember-metal/property_set","ember-runtime/system/lazy_load","ember-runtime/system/namespace","ember-runtime/mixins/deferred","ember-application/system/resolver","ember-metal/platform","ember-metal/run_loop","ember-metal/utils","ember-runtime/controllers/controller","ember-metal/enumerable_utils","ember-runtime/controllers/object_controller","ember-runtime/controllers/array_controller","ember-views/views/select","ember-views/system/event_dispatcher","ember-views/system/jquery","ember-routing/system/route","ember-routing/system/router","ember-routing/location/hash_location","ember-routing/location/history_location","ember-routing/location/auto_location","ember-routing/location/none_location","ember-routing/system/cache","ember-extension-support/container_debug_adapter","ember-metal/core","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __dependency17__, __dependency18__, __dependency19__, __dependency20__, __dependency21__, __dependency22__, __dependency23__, __dependency24__, __dependency25__, __dependency26__, __dependency27__, __dependency28__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-application - */ - var DAG = __dependency1__["default"]; - var Container = __dependency2__["default"]; - - - var Ember = __dependency3__["default"]; - // Ember.FEATURES, Ember.deprecate, Ember.assert, Ember.libraries, LOG_VERSION, Namespace, BOOTED - var get = __dependency4__.get; - var set = __dependency5__.set; - var runLoadHooks = __dependency6__.runLoadHooks; - var Namespace = __dependency7__["default"]; - var DeferredMixin = __dependency8__["default"]; - var DefaultResolver = __dependency9__["default"]; - var create = __dependency10__.create; - var run = __dependency11__["default"]; - var canInvoke = __dependency12__.canInvoke; - var Controller = __dependency13__["default"]; - var EnumerableUtils = __dependency14__["default"]; - var ObjectController = __dependency15__["default"]; - var ArrayController = __dependency16__["default"]; - var SelectView = __dependency17__["default"]; - var EventDispatcher = __dependency18__["default"]; - var jQuery = __dependency19__["default"]; - var Route = __dependency20__["default"]; - var Router = __dependency21__["default"]; - var HashLocation = __dependency22__["default"]; - var HistoryLocation = __dependency23__["default"]; - var AutoLocation = __dependency24__["default"]; - var NoneLocation = __dependency25__["default"]; - var BucketCache = __dependency26__["default"]; - - // this is technically incorrect (per @wycats) - // it should work properly with: - // `import ContainerDebugAdapter from 'ember-extension-support/container_debug_adapter';` but - // es6-module-transpiler 0.4.0 eagerly grabs the module (which is undefined) - - var ContainerDebugAdapter = __dependency27__["default"]; - - var K = __dependency28__.K; - - function props(obj) { - var properties = []; - - for (var key in obj) { - properties.push(key); } - - return properties; } - var librariesRegistered = false; - - /** - An instance of `Ember.Application` is the starting point for every Ember - application. It helps to instantiate, initialize and coordinate the many - objects that make up your app. + function buildSVGDOM(html, dom){ + var div = dom.document.createElement('div'); + div.innerHTML = ''+html+''; + return div.firstChild.childNodes; + } - Each Ember app has one and only one `Ember.Application` object. In fact, the - very first thing you should do in your application is create the instance: + /* + * A class wrapping DOM functions to address environment compatibility, + * namespaces, contextual elements for morph un-escaped content + * insertion. + * + * When entering a template, a DOMHelper should be passed: + * + * template(context, { hooks: hooks, dom: new DOMHelper() }); + * + * TODO: support foreignObject as a passed contextual element. It has + * a namespace (svg) that does not match its internal namespace + * (xhtml). + * + * @class DOMHelper + * @constructor + * @param {HTMLDocument} _document The document DOM methods are proxied to + */ + function DOMHelper(_document){ + this.document = _document || document; + if (!this.document) { + throw new Error("A document object must be passed to the DOMHelper, or available on the global scope"); + } + this.canClone = canClone; + this.namespace = null; + } - ```javascript - window.App = Ember.Application.create(); - ``` + var prototype = DOMHelper.prototype; + prototype.constructor = DOMHelper; - Typically, the application object is the only global variable. All other - classes in your app should be properties on the `Ember.Application` instance, - which highlights its first role: a global namespace. + prototype.getElementById = function(id, rootNode) { + rootNode = rootNode || this.document; + return rootNode.getElementById(id); + }; - For example, if you define a view class, it might look like this: + prototype.insertBefore = function(element, childElement, referenceChild) { + return element.insertBefore(childElement, referenceChild); + }; - ```javascript - App.MyView = Ember.View.extend(); - ``` + prototype.appendChild = function(element, childElement) { + return element.appendChild(childElement); + }; - By default, calling `Ember.Application.create()` will automatically initialize - your application by calling the `Ember.Application.initialize()` method. If - you need to delay initialization, you can call your app's `deferReadiness()` - method. When you are ready for your app to be initialized, call its - `advanceReadiness()` method. + prototype.childAt = function(element, indices) { + var child = element; - You can define a `ready` method on the `Ember.Application` instance, which - will be run by Ember when the application is initialized. + for (var i = 0; i < indices.length; i++) { + child = child.childNodes.item(indices[i]); + } - Because `Ember.Application` inherits from `Ember.Namespace`, any classes - you create will have useful string representations when calling `toString()`. - See the `Ember.Namespace` documentation for more information. + return child; + }; - While you can think of your `Ember.Application` as a container that holds the - other classes in your application, there are several other responsibilities - going on under-the-hood that you may want to understand. + // Note to a Fellow Implementor: + // Ahh, accessing a child node at an index. Seems like it should be so simple, + // doesn't it? Unfortunately, this particular method has caused us a surprising + // amount of pain. As you'll note below, this method has been modified to walk + // the linked list of child nodes rather than access the child by index + // directly, even though there are two (2) APIs in the DOM that do this for us. + // If you're thinking to yourself, "What an oversight! What an opportunity to + // optimize this code!" then to you I say: stop! For I have a tale to tell. + // + // First, this code must be compatible with simple-dom for rendering on the + // server where there is no real DOM. Previously, we accessed a child node + // directly via `element.childNodes[index]`. While we *could* in theory do a + // full-fidelity simulation of a live `childNodes` array, this is slow, + // complicated and error-prone. + // + // "No problem," we thought, "we'll just use the similar + // `childNodes.item(index)` API." Then, we could just implement our own `item` + // method in simple-dom and walk the child node linked list there, allowing + // us to retain the performance advantages of the (surely optimized) `item()` + // API in the browser. + // + // Unfortunately, an enterprising soul named Samy Alzahrani discovered that in + // IE8, accessing an item out-of-bounds via `item()` causes an exception where + // other browsers return null. This necessitated a... check of + // `childNodes.length`, bringing us back around to having to support a + // full-fidelity `childNodes` array! + // + // Worst of all, Kris Selden investigated how browsers are actualy implemented + // and discovered that they're all linked lists under the hood anyway. Accessing + // `childNodes` requires them to allocate a new live collection backed by that + // linked list, which is itself a rather expensive operation. Our assumed + // optimization had backfired! That is the danger of magical thinking about + // the performance of native implementations. + // + // And this, my friends, is why the following implementation just walks the + // linked list, as surprised as that may make you. Please ensure you understand + // the above before changing this and submitting a PR. + // + // Tom Dale, January 18th, 2015, Portland OR + prototype.childAtIndex = function(element, index) { + var node = element.firstChild; - ### Event Delegation + for (var idx = 0; node && idx < index; idx++) { + node = node.nextSibling; + } - Ember uses a technique called _event delegation_. This allows the framework - to set up a global, shared event listener instead of requiring each view to - do it manually. For example, instead of each view registering its own - `mousedown` listener on its associated element, Ember sets up a `mousedown` - listener on the `body`. + return node; + }; - If a `mousedown` event occurs, Ember will look at the target of the event and - start walking up the DOM node tree, finding corresponding views and invoking - their `mouseDown` method as it goes. + prototype.appendText = function(element, text) { + return element.appendChild(this.document.createTextNode(text)); + }; - `Ember.Application` has a number of default events that it listens for, as - well as a mapping from lowercase events to camel-cased view method names. For - example, the `keypress` event causes the `keyPress` method on the view to be - called, the `dblclick` event causes `doubleClick` to be called, and so on. + prototype.setAttribute = function(element, name, value) { + element.setAttribute(name, String(value)); + }; - If there is a bubbling browser event that Ember does not listen for by - default, you can specify custom events and their corresponding view method - names by setting the application's `customEvents` property: + prototype.setAttributeNS = function(element, namespace, name, value) { + element.setAttributeNS(namespace, name, String(value)); + }; - ```javascript - var App = Ember.Application.create({ - customEvents: { - // add support for the paste event - paste: 'paste' + if (canRemoveSvgViewBoxAttribute){ + prototype.removeAttribute = function(element, name) { + element.removeAttribute(name); + }; + } else { + prototype.removeAttribute = function(element, name) { + if (element.tagName === 'svg' && name === 'viewBox') { + element.setAttribute(name, null); + } else { + element.removeAttribute(name); } - }); - ``` - - By default, the application sets up these event listeners on the document - body. However, in cases where you are embedding an Ember application inside - an existing page, you may want it to set up the listeners on an element - inside the body. + }; + } - For example, if only events inside a DOM element with the ID of `ember-app` - should be delegated, set your application's `rootElement` property: + prototype.setPropertyStrict = function(element, name, value) { + element[name] = value; + }; - ```javascript - var App = Ember.Application.create({ - rootElement: '#ember-app' - }); - ``` - - The `rootElement` can be either a DOM element or a jQuery-compatible selector - string. Note that *views appended to the DOM outside the root element will - not receive events.* If you specify a custom root element, make sure you only - append views inside it! - - To learn more about the advantages of event delegation and the Ember view - layer, and a list of the event listeners that are setup by default, visit the - [Ember View Layer guide](http://emberjs.com/guides/understanding-ember/the-view-layer/#toc_event-delegation). - - ### Initializers - - Libraries on top of Ember can add initializers, like so: - - ```javascript - Ember.Application.initializer({ - name: 'api-adapter', - - initialize: function(container, application) { - application.register('api-adapter:main', ApiAdapter); - } - }); - ``` - - Initializers provide an opportunity to access the container, which - organizes the different components of an Ember application. Additionally - they provide a chance to access the instantiated application. Beyond - being used for libraries, initializers are also a great way to organize - dependency injection or setup in your own application. - - ### Routing - - In addition to creating your application's router, `Ember.Application` is - also responsible for telling the router when to start routing. Transitions - between routes can be logged with the `LOG_TRANSITIONS` flag, and more - detailed intra-transition logging can be logged with - the `LOG_TRANSITIONS_INTERNAL` flag: - - ```javascript - var App = Ember.Application.create({ - LOG_TRANSITIONS: true, // basic logging of successful transitions - LOG_TRANSITIONS_INTERNAL: true // detailed logging of all routing steps - }); - ``` - - By default, the router will begin trying to translate the current URL into - application state once the browser emits the `DOMContentReady` event. If you - need to defer routing, you can call the application's `deferReadiness()` - method. Once routing can begin, call the `advanceReadiness()` method. - - If there is any setup required before routing begins, you can implement a - `ready()` method on your app that will be invoked immediately before routing - begins. - - @class Application - @namespace Ember - @extends Ember.Namespace - */ - - var Application = Namespace.extend(DeferredMixin, { - _suppressDeferredDeprecation: true, - - /** - The root DOM element of the Application. This can be specified as an - element or a - [jQuery-compatible selector string](http://api.jquery.com/category/selectors/). - - This is the element that will be passed to the Application's, - `eventDispatcher`, which sets up the listeners for event delegation. Every - view in your application should be a child of the element you specify here. - - @property rootElement - @type DOMElement - @default 'body' - */ - rootElement: 'body', - - /** - The `Ember.EventDispatcher` responsible for delegating events to this - application's views. - - The event dispatcher is created by the application at initialization time - and sets up event listeners on the DOM element described by the - application's `rootElement` property. - - See the documentation for `Ember.EventDispatcher` for more information. - - @property eventDispatcher - @type Ember.EventDispatcher - @default null - */ - eventDispatcher: null, - - /** - The DOM events for which the event dispatcher should listen. - - By default, the application's `Ember.EventDispatcher` listens - for a set of standard DOM events, such as `mousedown` and - `keyup`, and delegates them to your application's `Ember.View` - instances. - - If you would like additional bubbling events to be delegated to your - views, set your `Ember.Application`'s `customEvents` property - to a hash containing the DOM event name as the key and the - corresponding view method name as the value. For example: - - ```javascript - var App = Ember.Application.create({ - customEvents: { - // add support for the paste event - paste: 'paste' - } - }); - ``` - - @property customEvents - @type Object - @default null - */ - customEvents: null, - - init: function() { - // Start off the number of deferrals at 1. This will be - // decremented by the Application's own `initialize` method. - this._readinessDeferrals = 1; - - if (!this.$) { - this.$ = jQuery; - } - this.__container__ = this.buildContainer(); - - this.Router = this.defaultRouter(); - - this._super(); - - this.scheduleInitialize(); - - if (!librariesRegistered) { - librariesRegistered = true; - Ember.libraries.registerCoreLibrary('jQuery', jQuery().jquery); - } - - if (Ember.LOG_VERSION) { - // we only need to see this once per Application#init - Ember.LOG_VERSION = false; - var libs = Ember.libraries._registry; - - var nameLengths = EnumerableUtils.map(libs, function(item) { - return get(item, 'name.length'); - }); - - var maxNameLength = Math.max.apply(this, nameLengths); - - Ember.debug('-------------------------------'); - for (var i = 0, l = libs.length; i < l; i++) { - var lib = libs[i]; - var spaces = new Array(maxNameLength - lib.name.length + 1).join(' '); - Ember.debug([lib.name, spaces, ' : ', lib.version].join('')); - } - Ember.debug('-------------------------------'); - } - }, - - /** - Build the container for the current application. - - Also register a default application view in case the application - itself does not. - - @private - @method buildContainer - @return {Ember.Container} the configured container - */ - buildContainer: function() { - var container = this.__container__ = Application.buildContainer(this); - - return container; - }, - - /** - If the application has not opted out of routing and has not explicitly - defined a router, supply a default router for the application author - to configure. - - This allows application developers to do: - - ```javascript - var App = Ember.Application.create(); - - App.Router.map(function() { - this.resource('posts'); - }); - ``` - - @private - @method defaultRouter - @return {Ember.Router} the default router - */ - - defaultRouter: function() { - if (this.Router === false) { return; } - var container = this.__container__; - - if (this.Router) { - container.unregister('router:main'); - container.register('router:main', this.Router); - } - - return container.lookupFactory('router:main'); - }, - - /** - Automatically initialize the application once the DOM has - become ready. - - The initialization itself is scheduled on the actions queue - which ensures that application loading finishes before - booting. - - If you are asynchronously loading code, you should call - `deferReadiness()` to defer booting, and then call - `advanceReadiness()` once all of your code has finished - loading. - - @private - @method scheduleInitialize - */ - scheduleInitialize: function() { - if (!this.$ || this.$.isReady) { - run.schedule('actions', this, '_initialize'); - } else { - this.$().ready(Ember.run.bind(this, '_initialize')); - } - }, - - /** - Use this to defer readiness until some condition is true. - - Example: - - ```javascript - var App = Ember.Application.create(); - - App.deferReadiness(); - // Ember.$ is a reference to the jQuery object/function - Ember.$.getJSON('/auth-token', function(token) { - App.token = token; - App.advanceReadiness(); - }); - ``` - - This allows you to perform asynchronous setup logic and defer - booting your application until the setup has finished. - - However, if the setup requires a loading UI, it might be better - to use the router for this purpose. - - @method deferReadiness - */ - deferReadiness: function() { - Ember.assert("You must call deferReadiness on an instance of Ember.Application", this instanceof Application); - Ember.assert("You cannot defer readiness since the `ready()` hook has already been called.", this._readinessDeferrals > 0); - this._readinessDeferrals++; - }, - - /** - Call `advanceReadiness` after any asynchronous setup logic has completed. - Each call to `deferReadiness` must be matched by a call to `advanceReadiness` - or the application will never become ready and routing will not begin. - - @method advanceReadiness - @see {Ember.Application#deferReadiness} - */ - advanceReadiness: function() { - Ember.assert("You must call advanceReadiness on an instance of Ember.Application", this instanceof Application); - this._readinessDeferrals--; - - if (this._readinessDeferrals === 0) { - run.once(this, this.didBecomeReady); - } - }, - - /** - Registers a factory that can be used for dependency injection (with - `App.inject`) or for service lookup. Each factory is registered with - a full name including two parts: `type:name`. - - A simple example: - - ```javascript - var App = Ember.Application.create(); - - App.Orange = Ember.Object.extend(); - App.register('fruit:favorite', App.Orange); - ``` - - Ember will resolve factories from the `App` namespace automatically. - For example `App.CarsController` will be discovered and returned if - an application requests `controller:cars`. - - An example of registering a controller with a non-standard name: - - ```javascript - var App = Ember.Application.create(); - var Session = Ember.Controller.extend(); - - App.register('controller:session', Session); - - // The Session controller can now be treated like a normal controller, - // despite its non-standard name. - App.ApplicationController = Ember.Controller.extend({ - needs: ['session'] - }); - ``` - - Registered factories are **instantiated** by having `create` - called on them. Additionally they are **singletons**, each time - they are looked up they return the same instance. - - Some examples modifying that default behavior: - - ```javascript - var App = Ember.Application.create(); - - App.Person = Ember.Object.extend(); - App.Orange = Ember.Object.extend(); - App.Email = Ember.Object.extend(); - App.session = Ember.Object.create(); - - App.register('model:user', App.Person, { singleton: false }); - App.register('fruit:favorite', App.Orange); - App.register('communication:main', App.Email, { singleton: false }); - App.register('session', App.session, { instantiate: false }); - ``` - - @method register - @param fullName {String} type:name (e.g., 'model:user') - @param factory {Function} (e.g., App.Person) - @param options {Object} (optional) disable instantiation or singleton usage - **/ - register: function() { - var container = this.__container__; - container.register.apply(container, arguments); - }, - - /** - Define a dependency injection onto a specific factory or all factories - of a type. - - When Ember instantiates a controller, view, or other framework component - it can attach a dependency to that component. This is often used to - provide services to a set of framework components. - - An example of providing a session object to all controllers: - - ```javascript - var App = Ember.Application.create(); - var Session = Ember.Object.extend({ isAuthenticated: false }); - - // A factory must be registered before it can be injected - App.register('session:main', Session); - - // Inject 'session:main' onto all factories of the type 'controller' - // with the name 'session' - App.inject('controller', 'session', 'session:main'); - - App.IndexController = Ember.Controller.extend({ - isLoggedIn: Ember.computed.alias('session.isAuthenticated') - }); - ``` - - Injections can also be performed on specific factories. - - ```javascript - App.inject(, , ) - App.inject('route', 'source', 'source:main') - App.inject('route:application', 'email', 'model:email') - ``` - - It is important to note that injections can only be performed on - classes that are instantiated by Ember itself. Instantiating a class - directly (via `create` or `new`) bypasses the dependency injection - system. - - **Note:** Ember-Data instantiates its models in a unique manner, and consequently - injections onto models (or all models) will not work as expected. Injections - on models can be enabled by setting `Ember.MODEL_FACTORY_INJECTIONS` - to `true`. - - @method inject - @param factoryNameOrType {String} - @param property {String} - @param injectionName {String} - **/ - inject: function() { - var container = this.__container__; - container.injection.apply(container, arguments); - }, - - /** - Calling initialize manually is not supported. - - Please see Ember.Application#advanceReadiness and - Ember.Application#deferReadiness. - - @private - @deprecated - @method initialize - **/ - initialize: function() { - Ember.deprecate('Calling initialize manually is not supported. Please see Ember.Application#advanceReadiness and Ember.Application#deferReadiness'); - }, - - /** - Initialize the application. This happens automatically. - - Run any initializers and run the application load hook. These hooks may - choose to defer readiness. For example, an authentication hook might want - to defer readiness until the auth token has been retrieved. - - @private - @method _initialize - */ - _initialize: function() { - if (this.isDestroyed) { return; } - - // At this point, the App.Router must already be assigned - if (this.Router) { - var container = this.__container__; - container.unregister('router:main'); - container.register('router:main', this.Router); - } - - this.runInitializers(); - runLoadHooks('application', this); - - // At this point, any initializers or load hooks that would have wanted - // to defer readiness have fired. In general, advancing readiness here - // will proceed to didBecomeReady. - this.advanceReadiness(); - - return this; - }, - - /** - Reset the application. This is typically used only in tests. It cleans up - the application in the following order: - - 1. Deactivate existing routes - 2. Destroy all objects in the container - 3. Create a new application container - 4. Re-route to the existing url - - Typical Example: - - ```javascript - var App; - - run(function() { - App = Ember.Application.create(); - }); - - module('acceptance test', { - setup: function() { - App.reset(); - } - }); - - test('first test', function() { - // App is freshly reset - }); - - test('second test', function() { - // App is again freshly reset - }); - ``` - - Advanced Example: - - Occasionally you may want to prevent the app from initializing during - setup. This could enable extra configuration, or enable asserting prior - to the app becoming ready. - - ```javascript - var App; - - run(function() { - App = Ember.Application.create(); - }); - - module('acceptance test', { - setup: function() { - run(function() { - App.reset(); - App.deferReadiness(); - }); - } - }); - - test('first test', function() { - ok(true, 'something before app is initialized'); - - run(function() { - App.advanceReadiness(); - }); - - ok(true, 'something after app is initialized'); - }); - ``` - - @method reset - **/ - reset: function() { - this._readinessDeferrals = 1; - - function handleReset() { - var router = this.__container__.lookup('router:main'); - router.reset(); - - run(this.__container__, 'destroy'); - - this.buildContainer(); - - run.schedule('actions', this, '_initialize'); - } - - run.join(this, handleReset); - }, - - /** - @private - @method runInitializers - */ - runInitializers: function() { - var initializersByName = get(this.constructor, 'initializers'); - var initializers = props(initializersByName); - var container = this.__container__; - var graph = new DAG(); - var namespace = this; - var initializer; - - for (var i = 0; i < initializers.length; i++) { - initializer = initializersByName[initializers[i]]; - graph.addEdges(initializer.name, initializer.initialize, initializer.before, initializer.after); - } - - graph.topsort(function (vertex) { - var initializer = vertex.value; - Ember.assert("No application initializer named '" + vertex.name + "'", !!initializer); - initializer(container, namespace); - }); - }, - - /** - @private - @method didBecomeReady - */ - didBecomeReady: function() { - this.setupEventDispatcher(); - this.ready(); // user hook - this.startRouting(); - - if (!Ember.testing) { - // Eagerly name all classes that are already loaded - Ember.Namespace.processAll(); - Ember.BOOTED = true; - } - - this.resolve(this); - }, - - /** - Setup up the event dispatcher to receive events on the - application's `rootElement` with any registered - `customEvents`. - - @private - @method setupEventDispatcher - */ - setupEventDispatcher: function() { - var customEvents = get(this, 'customEvents'); - var rootElement = get(this, 'rootElement'); - var dispatcher = this.__container__.lookup('event_dispatcher:main'); - - set(this, 'eventDispatcher', dispatcher); - dispatcher.setup(customEvents, rootElement); - }, - - /** - If the application has a router, use it to route to the current URL, and - trigger a new call to `route` whenever the URL changes. - - @private - @method startRouting - @property router {Ember.Router} - */ - startRouting: function() { - var router = this.__container__.lookup('router:main'); - if (!router) { return; } - - router.startRouting(); - }, - - handleURL: function(url) { - var router = this.__container__.lookup('router:main'); - - router.handleURL(url); - }, - - /** - Called when the Application has become ready. - The call will be delayed until the DOM has become ready. - - @event ready - */ - ready: K, - - /** - @deprecated Use 'Resolver' instead - Set this to provide an alternate class to `Ember.DefaultResolver` - - - @property resolver - */ - resolver: null, - - /** - Set this to provide an alternate class to `Ember.DefaultResolver` - - @property resolver - */ - Resolver: null, - - willDestroy: function() { - Ember.BOOTED = false; - // Ensure deactivation of routes before objects are destroyed - this.__container__.lookup('router:main').reset(); - - this.__container__.destroy(); - }, - - initializer: function(options) { - this.constructor.initializer(options); - }, - - /** - @method then - @private - @deprecated - */ - then: function() { - Ember.deprecate('Do not use `.then` on an instance of Ember.Application. Please use the `.ready` hook instead.', false, { url: 'http://emberjs.com/guides/deprecations/#toc_deprecate-code-then-code-on-ember-application' }); - - this._super.apply(this, arguments); - } - }); - - Application.reopenClass({ - initializers: create(null), - - /** - Initializer receives an object which has the following attributes: - `name`, `before`, `after`, `initialize`. The only required attribute is - `initialize, all others are optional. - - * `name` allows you to specify under which name the initializer is registered. - This must be a unique name, as trying to register two initializers with the - same name will result in an error. - - ```javascript - Ember.Application.initializer({ - name: 'namedInitializer', - - initialize: function(container, application) { - Ember.debug('Running namedInitializer!'); - } - }); - ``` - - * `before` and `after` are used to ensure that this initializer is ran prior - or after the one identified by the value. This value can be a single string - or an array of strings, referencing the `name` of other initializers. - - An example of ordering initializers, we create an initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'first', - - initialize: function(container, application) { - Ember.debug('First initializer!'); - } - }); - - // DEBUG: First initializer! - ``` - - We add another initializer named `second`, specifying that it should run - after the initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'second', - after: 'first', - - initialize: function(container, application) { - Ember.debug('Second initializer!'); - } - }); - - // DEBUG: First initializer! - // DEBUG: Second initializer! - ``` - - Afterwards we add a further initializer named `pre`, this time specifying - that it should run before the initializer named `first`: - - ```javascript - Ember.Application.initializer({ - name: 'pre', - before: 'first', - - initialize: function(container, application) { - Ember.debug('Pre initializer!'); - } - }); - - // DEBUG: Pre initializer! - // DEBUG: First initializer! - // DEBUG: Second initializer! - ``` - - Finally we add an initializer named `post`, specifying it should run after - both the `first` and the `second` initializers: - - ```javascript - Ember.Application.initializer({ - name: 'post', - after: ['first', 'second'], - - initialize: function(container, application) { - Ember.debug('Post initializer!'); - } - }); - - // DEBUG: Pre initializer! - // DEBUG: First initializer! - // DEBUG: Second initializer! - // DEBUG: Post initializer! - ``` - - * `initialize` is a callback function that receives two arguments, `container` - and `application` on which you can operate. - - Example of using `container` to preload data into the store: - - ```javascript - Ember.Application.initializer({ - name: 'preload-data', - - initialize: function(container, application) { - var store = container.lookup('store:main'); - - store.pushPayload(preloadedData); - } - }); - ``` - - Example of using `application` to register an adapter: - - ```javascript - Ember.Application.initializer({ - name: 'api-adapter', - - initialize: function(container, application) { - application.register('api-adapter:main', ApiAdapter); - } - }); - ``` - - @method initializer - @param initializer {Object} - */ - initializer: function(initializer) { - // If this is the first initializer being added to a subclass, we are going to reopen the class - // to make sure we have a new `initializers` object, which extends from the parent class' using - // prototypal inheritance. Without this, attempting to add initializers to the subclass would - // pollute the parent class as well as other subclasses. - if (this.superclass.initializers !== undefined && this.superclass.initializers === this.initializers) { - this.reopenClass({ - initializers: create(this.initializers) - }); - } - - Ember.assert("The initializer '" + initializer.name + "' has already been registered", !this.initializers[initializer.name]); - Ember.assert("An initializer cannot be registered without an initialize function", canInvoke(initializer, 'initialize')); - Ember.assert("An initializer cannot be registered without a name property", initializer.name !== undefined); - - this.initializers[initializer.name] = initializer; - }, - - /** - This creates a container with the default Ember naming conventions. - - It also configures the container: - - * registered views are created every time they are looked up (they are - not singletons) - * registered templates are not factories; the registered value is - returned directly. - * the router receives the application as its `namespace` property - * all controllers receive the router as their `target` and `controllers` - properties - * all controllers receive the application as their `namespace` property - * the application view receives the application controller as its - `controller` property - * the application view receives the application template as its - `defaultTemplate` property - - @private - @method buildContainer - @static - @param {Ember.Application} namespace the application to build the - container for. - @return {Ember.Container} the built container - */ - buildContainer: function(namespace) { - var container = new Container(); - - container.set = set; - container.resolver = resolverFor(namespace); - container.normalizeFullName = container.resolver.normalize; - container.describe = container.resolver.describe; - container.makeToString = container.resolver.makeToString; - - container.optionsForType('component', { singleton: false }); - container.optionsForType('view', { singleton: false }); - container.optionsForType('template', { instantiate: false }); - container.optionsForType('helper', { instantiate: false }); - - container.register('application:main', namespace, { instantiate: false }); - - container.register('controller:basic', Controller, { instantiate: false }); - container.register('controller:object', ObjectController, { instantiate: false }); - container.register('controller:array', ArrayController, { instantiate: false }); - - container.register('view:select', SelectView); - - container.register('route:basic', Route, { instantiate: false }); - container.register('event_dispatcher:main', EventDispatcher); - - container.register('router:main', Router); - container.injection('router:main', 'namespace', 'application:main'); - - container.register('location:auto', AutoLocation); - container.register('location:hash', HashLocation); - container.register('location:history', HistoryLocation); - container.register('location:none', NoneLocation); - - container.injection('controller', 'target', 'router:main'); - container.injection('controller', 'namespace', 'application:main'); - - container.register('-bucket-cache:main', BucketCache); - container.injection('router', '_bucketCache', '-bucket-cache:main'); - container.injection('route', '_bucketCache', '-bucket-cache:main'); - container.injection('controller', '_bucketCache', '-bucket-cache:main'); - - container.injection('route', 'router', 'router:main'); - container.injection('location', 'rootURL', '-location-setting:root-url'); - - // DEBUGGING - container.register('resolver-for-debugging:main', container.resolver.__resolver__, { instantiate: false }); - container.injection('container-debug-adapter:main', 'resolver', 'resolver-for-debugging:main'); - container.injection('data-adapter:main', 'containerDebugAdapter', 'container-debug-adapter:main'); - // Custom resolver authors may want to register their own ContainerDebugAdapter with this key - - container.register('container-debug-adapter:main', ContainerDebugAdapter); - - return container; - } - }); - - /** - This function defines the default lookup rules for container lookups: - - * templates are looked up on `Ember.TEMPLATES` - * other names are looked up on the application after classifying the name. - For example, `controller:post` looks up `App.PostController` by default. - * if the default lookup fails, look for registered classes on the container - - This allows the application to register default injections in the container - that could be overridden by the normal naming convention. - - @private - @method resolverFor - @param {Ember.Namespace} namespace the namespace to look for classes - @return {*} the resolved value for a given lookup - */ - function resolverFor(namespace) { - Ember.deprecate('Application.resolver is deprecated in favor of Application.Resolver', !namespace.get('resolver')); - - var ResolverClass = namespace.get('resolver') || namespace.get('Resolver') || DefaultResolver; - var resolver = ResolverClass.create({ - namespace: namespace - }); - - function resolve(fullName) { - return resolver.resolve(fullName); - } - - resolve.describe = function(fullName) { - return resolver.lookupDescription(fullName); - }; - - resolve.makeToString = function(factory, fullName) { - return resolver.makeToString(factory, fullName); - }; - - resolve.normalize = function(fullName) { - if (resolver.normalize) { - return resolver.normalize(fullName); - } else { - Ember.deprecate('The Resolver should now provide a \'normalize\' function', false); - return fullName; - } - }; - - resolve.__resolver__ = resolver; - - return resolve; - } - - __exports__["default"] = Application; - }); -enifed("ember-application/system/resolver", - ["ember-metal/core","ember-metal/property_get","ember-metal/logger","ember-runtime/system/string","ember-runtime/system/object","ember-runtime/system/namespace","ember-htmlbars/helpers","ember-metal/dictionary","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) { - "use strict"; - /** - @module ember - @submodule ember-application - */ - - var Ember = __dependency1__["default"]; - // Ember.TEMPLATES, Ember.assert - var get = __dependency2__.get; - var Logger = __dependency3__["default"]; - var classify = __dependency4__.classify; - var capitalize = __dependency4__.capitalize; - var decamelize = __dependency4__.decamelize; - var EmberObject = __dependency5__["default"]; - var Namespace = __dependency6__["default"]; - var helpers = __dependency7__["default"]; - - var Resolver = EmberObject.extend({ - /** - This will be set to the Application instance when it is - created. - - @property namespace - */ - namespace: null, - normalize: Ember.required(Function), - resolve: Ember.required(Function), - parseName: Ember.required(Function), - lookupDescription: Ember.required(Function), - makeToString: Ember.required(Function), - resolveOther: Ember.required(Function), - _logLookup: Ember.required(Function) - }); - __exports__.Resolver = Resolver; - /** - The DefaultResolver defines the default lookup rules to resolve - container lookups before consulting the container for registered - items: - - * templates are looked up on `Ember.TEMPLATES` - * other names are looked up on the application after converting - the name. For example, `controller:post` looks up - `App.PostController` by default. - * there are some nuances (see examples below) - - ### How Resolving Works - - The container calls this object's `resolve` method with the - `fullName` argument. - - It first parses the fullName into an object using `parseName`. - - Then it checks for the presence of a type-specific instance - method of the form `resolve[Type]` and calls it if it exists. - For example if it was resolving 'template:post', it would call - the `resolveTemplate` method. - - Its last resort is to call the `resolveOther` method. - - The methods of this object are designed to be easy to override - in a subclass. For example, you could enhance how a template - is resolved like so: - - ```javascript - App = Ember.Application.create({ - Resolver: Ember.DefaultResolver.extend({ - resolveTemplate: function(parsedName) { - var resolvedTemplate = this._super(parsedName); - if (resolvedTemplate) { return resolvedTemplate; } - return Ember.TEMPLATES['not_found']; - } - }) - }); - ``` - - Some examples of how names are resolved: - - ``` - 'template:post' //=> Ember.TEMPLATES['post'] - 'template:posts/byline' //=> Ember.TEMPLATES['posts/byline'] - 'template:posts.byline' //=> Ember.TEMPLATES['posts/byline'] - 'template:blogPost' //=> Ember.TEMPLATES['blogPost'] - // OR - // Ember.TEMPLATES['blog_post'] - 'controller:post' //=> App.PostController - 'controller:posts.index' //=> App.PostsIndexController - 'controller:blog/post' //=> Blog.PostController - 'controller:basic' //=> Ember.Controller - 'route:post' //=> App.PostRoute - 'route:posts.index' //=> App.PostsIndexRoute - 'route:blog/post' //=> Blog.PostRoute - 'route:basic' //=> Ember.Route - 'view:post' //=> App.PostView - 'view:posts.index' //=> App.PostsIndexView - 'view:blog/post' //=> Blog.PostView - 'view:basic' //=> Ember.View - 'foo:post' //=> App.PostFoo - 'model:post' //=> App.Post - ``` - - @class DefaultResolver - @namespace Ember - @extends Ember.Object - */ - var dictionary = __dependency8__["default"]; - - __exports__["default"] = EmberObject.extend({ - /** - This will be set to the Application instance when it is - created. - - @property namespace - */ - namespace: null, - - init: function() { - this._parseNameCache = dictionary(null); - }, - normalize: function(fullName) { - var split = fullName.split(':', 2); - var type = split[0]; - var name = split[1]; - - Ember.assert("Tried to normalize a container name without a colon (:) in it." + - " You probably tried to lookup a name that did not contain a type," + - " a colon, and a name. A proper lookup name would be `view:post`.", split.length === 2); - - if (type !== 'template') { - var result = name; - - if (result.indexOf('.') > -1) { - result = result.replace(/\.(.)/g, function(m) { - return m.charAt(1).toUpperCase(); - }); - } - - if (name.indexOf('_') > -1) { - result = result.replace(/_(.)/g, function(m) { - return m.charAt(1).toUpperCase(); - }); - } - - return type + ':' + result; - } else { - return fullName; - } - }, - - - /** - This method is called via the container's resolver method. - It parses the provided `fullName` and then looks up and - returns the appropriate template or class. - - @method resolve - @param {String} fullName the lookup string - @return {Object} the resolved factory - */ - resolve: function(fullName) { - var parsedName = this.parseName(fullName); - var resolveMethodName = parsedName.resolveMethodName; - var resolved; - - if (!(parsedName.name && parsedName.type)) { - throw new TypeError('Invalid fullName: `' + fullName + '`, must be of the form `type:name` '); - } - - if (this[resolveMethodName]) { - resolved = this[resolveMethodName](parsedName); - } - - if (!resolved) { - resolved = this.resolveOther(parsedName); - } - - if (parsedName.root && parsedName.root.LOG_RESOLVER) { - this._logLookup(resolved, parsedName); - } - - return resolved; - }, - /** - Convert the string name of the form 'type:name' to - a Javascript object with the parsed aspects of the name - broken out. - - @protected - @param {String} fullName the lookup string - @method parseName - */ - - parseName: function(fullName) { - return this._parseNameCache[fullName] || ( - this._parseNameCache[fullName] = this._parseName(fullName) - ); - }, - - _parseName: function(fullName) { - var nameParts = fullName.split(':'); - var type = nameParts[0], fullNameWithoutType = nameParts[1]; - var name = fullNameWithoutType; - var namespace = get(this, 'namespace'); - var root = namespace; - - if (type !== 'template' && name.indexOf('/') !== -1) { - var parts = name.split('/'); - name = parts[parts.length - 1]; - var namespaceName = capitalize(parts.slice(0, -1).join('.')); - root = Namespace.byName(namespaceName); - - Ember.assert('You are looking for a ' + name + ' ' + type + - ' in the ' + namespaceName + - ' namespace, but the namespace could not be found', root); - } - - return { - fullName: fullName, - type: type, - fullNameWithoutType: fullNameWithoutType, - name: name, - root: root, - resolveMethodName: 'resolve' + classify(type) - }; - }, - - /** - Returns a human-readable description for a fullName. Used by the - Application namespace in assertions to describe the - precise name of the class that Ember is looking for, rather than - container keys. - - @protected - @param {String} fullName the lookup string - @method lookupDescription - */ - lookupDescription: function(fullName) { - var parsedName = this.parseName(fullName); - var description; - - if (parsedName.type === 'template') { - return 'template at ' + parsedName.fullNameWithoutType.replace(/\./g, '/'); - } - - description = parsedName.root + '.' + classify(parsedName.name).replace(/\./g, ''); - - if (parsedName.type !== 'model') { - description += classify(parsedName.type); - } - - return description; - }, - - makeToString: function(factory, fullName) { - return factory.toString(); - }, - /** - Given a parseName object (output from `parseName`), apply - the conventions expected by `Ember.Router` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method useRouterNaming - */ - useRouterNaming: function(parsedName) { - parsedName.name = parsedName.name.replace(/\./g, '_'); - if (parsedName.name === 'basic') { - parsedName.name = ''; - } - }, - /** - Look up the template in Ember.TEMPLATES - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveTemplate - */ - resolveTemplate: function(parsedName) { - var templateName = parsedName.fullNameWithoutType.replace(/\./g, '/'); - - if (Ember.TEMPLATES[templateName]) { - return Ember.TEMPLATES[templateName]; - } - - templateName = decamelize(templateName); - if (Ember.TEMPLATES[templateName]) { - return Ember.TEMPLATES[templateName]; - } - }, - - /** - Lookup the view using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveView - */ - resolveView: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - - /** - Lookup the controller using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveController - */ - resolveController: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - /** - Lookup the route using `resolveOther` - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveRoute - */ - resolveRoute: function(parsedName) { - this.useRouterNaming(parsedName); - return this.resolveOther(parsedName); - }, - - /** - Lookup the model on the Application namespace - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveModel - */ - resolveModel: function(parsedName) { - var className = classify(parsedName.name); - var factory = get(parsedName.root, className); - - if (factory) { return factory; } - }, - /** - Look up the specified object (from parsedName) on the appropriate - namespace (usually on the Application) - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveHelper - */ - resolveHelper: function(parsedName) { - return this.resolveOther(parsedName) || helpers[parsedName.fullNameWithoutType]; - }, - /** - Look up the specified object (from parsedName) on the appropriate - namespace (usually on the Application) - - @protected - @param {Object} parsedName a parseName object with the parsed - fullName lookup string - @method resolveOther - */ - resolveOther: function(parsedName) { - var className = classify(parsedName.name) + classify(parsedName.type); - var factory = get(parsedName.root, className); - if (factory) { return factory; } - }, - - /** - @method _logLookup - @param {Boolean} found - @param {Object} parsedName - @private - */ - _logLookup: function(found, parsedName) { - var symbol, padding; - - if (found) { symbol = '[✓]'; } - else { symbol = '[ ]'; } - - if (parsedName.fullName.length > 60) { - padding = '.'; - } else { - padding = new Array(60 - parsedName.fullName.length).join('.'); - } - - Logger.info(symbol, parsedName.fullName, padding, this.lookupDescription(parsedName.fullName)); - } - }); - }); -enifed("ember-debug", - ["ember-metal/core","ember-metal/error","ember-metal/logger","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __exports__) { - "use strict"; - /*global __fail__*/ - - var Ember = __dependency1__["default"]; - var EmberError = __dependency2__["default"]; - var Logger = __dependency3__["default"]; - - /** - Ember Debug - - @module ember - @submodule ember-debug - */ - - /** - @class Ember - */ - - /** - Define an assertion that will throw an exception if the condition is not - met. Ember build tools will remove any calls to `Ember.assert()` when - doing a production build. Example: - - ```javascript - // Test for truthiness - Ember.assert('Must pass a valid object', obj); - - // Fail unconditionally - Ember.assert('This code path should never be run'); - ``` - - @method assert - @param {String} desc A description of the assertion. This will become - the text of the Error thrown if the assertion fails. - @param {Boolean} test Must be truthy for the assertion to pass. If - falsy, an exception will be thrown. - */ - Ember.assert = function(desc, test) { - var throwAssertion; - - if (Ember.typeOf(test) === 'function') { - throwAssertion = !test(); - } else { - throwAssertion = !test; - } - - if (throwAssertion) { - throw new EmberError("Assertion Failed: " + desc); - } - }; - - - /** - Display a warning with the provided message. Ember build tools will - remove any calls to `Ember.warn()` when doing a production build. - - @method warn - @param {String} message A warning to display. - @param {Boolean} test An optional boolean. If falsy, the warning - will be displayed. - */ - Ember.warn = function(message, test) { - if (!test) { - Logger.warn("WARNING: "+message); - if ('trace' in Logger) { - Logger.trace(); + prototype.setProperty = function(element, name, value, namespace) { + var lowercaseName = name.toLowerCase(); + if (element.namespaceURI === svgNamespace || lowercaseName === 'style') { + if (isAttrRemovalValue(value)) { + element.removeAttribute(name); + } else { + if (namespace) { + element.setAttributeNS(namespace, name, value); + } else { + element.setAttribute(name, value); + } } - } - }; - - /** - Display a debug notice. Ember build tools will remove any calls to - `Ember.debug()` when doing a production build. - - ```javascript - Ember.debug('I\'m a debug notice!'); - ``` - - @method debug - @param {String} message A debug message to display. - */ - Ember.debug = function(message) { - Logger.debug("DEBUG: "+message); - }; - - /** - Display a deprecation warning with the provided message and a stack trace - (Chrome and Firefox only). Ember build tools will remove any calls to - `Ember.deprecate()` when doing a production build. - - @method deprecate - @param {String} message A description of the deprecation. - @param {Boolean} test An optional boolean. If falsy, the deprecation - will be displayed. - @param {Object} options An optional object that can be used to pass - in a `url` to the transition guide on the emberjs.com website. - */ - Ember.deprecate = function(message, test, options) { - var noDeprecation; - - if (typeof test === 'function') { - noDeprecation = test(); } else { - noDeprecation = test; - } - - if (noDeprecation) { return; } - - if (Ember.ENV.RAISE_ON_DEPRECATION) { throw new EmberError(message); } - - var error; - - // When using new Error, we can't do the arguments check for Chrome. Alternatives are welcome - try { __fail__.fail(); } catch (e) { error = e; } - - if (arguments.length === 3) { - Ember.assert('options argument to Ember.deprecate should be an object', options && typeof options === 'object'); - if (options.url) { - message += ' See ' + options.url + ' for more details.'; - } - } - - if (Ember.LOG_STACKTRACE_ON_DEPRECATION && error.stack) { - var stack; - var stackStr = ''; - - if (error['arguments']) { - // Chrome - stack = error.stack.replace(/^\s+at\s+/gm, ''). - replace(/^([^\(]+?)([\n$])/gm, '{anonymous}($1)$2'). - replace(/^Object.\s*\(([^\)]+)\)/gm, '{anonymous}($1)').split('\n'); - stack.shift(); + var normalized = normalizeProperty(element, name); + if (normalized) { + element[normalized] = value; } else { - // Firefox - stack = error.stack.replace(/(?:\n@:0)?\s+$/m, ''). - replace(/^\(/gm, '{anonymous}(').split('\n'); - } - - stackStr = "\n " + stack.slice(2).join("\n "); - message = message + stackStr; - } - - Logger.warn("DEPRECATION: "+message); - }; - - - - /** - Alias an old, deprecated method with its new counterpart. - - Display a deprecation warning with the provided message and a stack trace - (Chrome and Firefox only) when the assigned method is called. - - Ember build tools will not remove calls to `Ember.deprecateFunc()`, though - no warnings will be shown in production. - - ```javascript - Ember.oldMethod = Ember.deprecateFunc('Please use the new, updated method', Ember.newMethod); - ``` - - @method deprecateFunc - @param {String} message A description of the deprecation. - @param {Function} func The new function called to replace its deprecated counterpart. - @return {Function} a new function that wrapped the original function with a deprecation warning - */ - Ember.deprecateFunc = function(message, func) { - return function() { - Ember.deprecate(message); - return func.apply(this, arguments); - }; - }; - - - /** - Run a function meant for debugging. Ember build tools will remove any calls to - `Ember.runInDebug()` when doing a production build. - - ```javascript - Ember.runInDebug(function() { - Ember.Handlebars.EachView.reopen({ - didInsertElement: function() { - console.log('I\'m happy'); - } - }); - }); - ``` - - @method runInDebug - @param {Function} func The function to be executed. - @since 1.5.0 - */ - Ember.runInDebug = function(func) { - func(); - }; - - /** - Will call `Ember.warn()` if ENABLE_ALL_FEATURES, ENABLE_OPTIONAL_FEATURES, or - any specific FEATURES flag is truthy. - - This method is called automatically in debug canary builds. - - @private - @method _warnIfUsingStrippedFeatureFlags - @return {void} - */ - function _warnIfUsingStrippedFeatureFlags(FEATURES, featuresWereStripped) { - if (featuresWereStripped) { - Ember.warn('Ember.ENV.ENABLE_ALL_FEATURES is only available in canary builds.', !Ember.ENV.ENABLE_ALL_FEATURES); - Ember.warn('Ember.ENV.ENABLE_OPTIONAL_FEATURES is only available in canary builds.', !Ember.ENV.ENABLE_OPTIONAL_FEATURES); - - for (var key in FEATURES) { - if (FEATURES.hasOwnProperty(key) && key !== 'isEnabled') { - Ember.warn('FEATURE["' + key + '"] is set as enabled, but FEATURE flags are only available in canary builds.', !FEATURES[key]); + if (isAttrRemovalValue(value)) { + element.removeAttribute(name); + } else { + if (namespace && element.setAttributeNS) { + element.setAttributeNS(namespace, name, value); + } else { + element.setAttribute(name, value); + } } } } - } - - __exports__._warnIfUsingStrippedFeatureFlags = _warnIfUsingStrippedFeatureFlags;if (!Ember.testing) { - // Complain if they're using FEATURE flags in builds other than canary - Ember.FEATURES['features-stripped-test'] = true; - var featuresWereStripped = true; - - - delete Ember.FEATURES['features-stripped-test']; - _warnIfUsingStrippedFeatureFlags(Ember.ENV.FEATURES, featuresWereStripped); - - // Inform the developer about the Ember Inspector if not installed. - var isFirefox = typeof InstallTrigger !== 'undefined'; - var isChrome = !!window.chrome && !window.opera; - - if (typeof window !== 'undefined' && (isFirefox || isChrome) && window.addEventListener) { - window.addEventListener("load", function() { - if (document.documentElement && document.documentElement.dataset && !document.documentElement.dataset.emberExtension) { - var downloadURL; - - if(isChrome) { - downloadURL = 'https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi'; - } else if(isFirefox) { - downloadURL = 'https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/'; - } + }; - Ember.debug('For more advanced debugging, install the Ember Inspector from ' + downloadURL); + if (doc && doc.createElementNS) { + // Only opt into namespace detection if a contextualElement + // is passed. + prototype.createElement = function(tagName, contextualElement) { + var namespace = this.namespace; + if (contextualElement) { + if (tagName === 'svg') { + namespace = svgNamespace; + } else { + namespace = interiorNamespace(contextualElement); } - }, false); - } - } - - /* - We are transitioning away from `ember.js` to `ember.debug.js` to make - it much clearer that it is only for local development purposes. - - This flag value is changed by the tooling (by a simple string replacement) - so that if `ember.js` (which must be output for backwards compat reasons) is - used a nice helpful warning message will be printed out. - */ - var runningNonEmberDebugJS = true; - __exports__.runningNonEmberDebugJS = runningNonEmberDebugJS;if (runningNonEmberDebugJS) { - Ember.warn('Please use `ember.debug.js` instead of `ember.js` for development and debugging.'); - } - }); -enifed("ember-extension-support", - ["ember-metal/core","ember-extension-support/data_adapter","ember-extension-support/container_debug_adapter"], - function(__dependency1__, __dependency2__, __dependency3__) { - "use strict"; - /** - Ember Extension Support - - @module ember - @submodule ember-extension-support - @requires ember-application - */ - - var Ember = __dependency1__["default"]; - var DataAdapter = __dependency2__["default"]; - var ContainerDebugAdapter = __dependency3__["default"]; - - Ember.DataAdapter = DataAdapter; - Ember.ContainerDebugAdapter = ContainerDebugAdapter; - }); -enifed("ember-extension-support/container_debug_adapter", - ["ember-metal/core","ember-runtime/system/native_array","ember-metal/utils","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __exports__) { - "use strict"; - var Ember = __dependency1__["default"]; - var emberA = __dependency2__.A; - var typeOf = __dependency3__.typeOf; - var dasherize = __dependency4__.dasherize; - var classify = __dependency4__.classify; - var Namespace = __dependency5__["default"]; - var EmberObject = __dependency6__["default"]; - - /** - @module ember - @submodule ember-extension-support - */ - - /** - The `ContainerDebugAdapter` helps the container and resolver interface - with tools that debug Ember such as the - [Ember Extension](https://github.com/tildeio/ember-extension) - for Chrome and Firefox. - - This class can be extended by a custom resolver implementer - to override some of the methods with library-specific code. - - The methods likely to be overridden are: - - * `canCatalogEntriesByType` - * `catalogEntriesByType` - - The adapter will need to be registered - in the application's container as `container-debug-adapter:main` - - Example: - - ```javascript - Application.initializer({ - name: "containerDebugAdapter", - - initialize: function(container, application) { - application.register('container-debug-adapter:main', require('app/container-debug-adapter')); } - }); - ``` - - @class ContainerDebugAdapter - @namespace Ember - @extends Ember.Object - @since 1.5.0 - */ - __exports__["default"] = EmberObject.extend({ - /** - The container of the application being debugged. - This property will be injected - on creation. - - @property container - @default null - */ - container: null, - - /** - The resolver instance of the application - being debugged. This property will be injected - on creation. - - @property resolver - @default null - */ - resolver: null, - - /** - Returns true if it is possible to catalog a list of available - classes in the resolver for a given type. - - @method canCatalogEntriesByType - @param {String} type The type. e.g. "model", "controller", "route" - @return {boolean} whether a list is available for this type. - */ - canCatalogEntriesByType: function(type) { - if (type === 'model' || type === 'template') return false; - return true; - }, - - /** - Returns the available classes a given type. - - @method catalogEntriesByType - @param {String} type The type. e.g. "model", "controller", "route" - @return {Array} An array of strings. - */ - catalogEntriesByType: function(type) { - var namespaces = emberA(Namespace.NAMESPACES), types = emberA(); - var typeSuffixRegex = new RegExp(classify(type) + "$"); - - namespaces.forEach(function(namespace) { - if (namespace !== Ember) { - for (var key in namespace) { - if (!namespace.hasOwnProperty(key)) { continue; } - if (typeSuffixRegex.test(key)) { - var klass = namespace[key]; - if (typeOf(klass) === 'class') { - types.push(dasherize(key.replace(typeSuffixRegex, ''))); - } - } - } - } - }); - return types; - } - }); - }); -enifed("ember-extension-support/data_adapter", - ["ember-metal/property_get","ember-metal/run_loop","ember-runtime/system/string","ember-runtime/system/namespace","ember-runtime/system/object","ember-runtime/system/native_array","ember-application/system/application","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __exports__) { - "use strict"; - var get = __dependency1__.get; - var run = __dependency2__["default"]; - var dasherize = __dependency3__.dasherize; - var Namespace = __dependency4__["default"]; - var EmberObject = __dependency5__["default"]; - var emberA = __dependency6__.A; - var Application = __dependency7__["default"]; - - /** - @module ember - @submodule ember-extension-support - */ - - /** - The `DataAdapter` helps a data persistence library - interface with tools that debug Ember such - as the [Ember Extension](https://github.com/tildeio/ember-extension) - for Chrome and Firefox. - - This class will be extended by a persistence library - which will override some of the methods with - library-specific code. - - The methods likely to be overridden are: - - * `getFilters` - * `detect` - * `columnsForType` - * `getRecords` - * `getRecordColumnValues` - * `getRecordKeywords` - * `getRecordFilterValues` - * `getRecordColor` - * `observeRecord` - - The adapter will need to be registered - in the application's container as `dataAdapter:main` - - Example: - - ```javascript - Application.initializer({ - name: "data-adapter", - - initialize: function(container, application) { - application.register('data-adapter:main', DS.DataAdapter); + if (namespace) { + return this.document.createElementNS(namespace, tagName); + } else { + return this.document.createElement(tagName); } - }); - ``` - - @class DataAdapter - @namespace Ember - @extends EmberObject - */ - __exports__["default"] = EmberObject.extend({ - init: function() { - this._super(); - this.releaseMethods = emberA(); - }, - - /** - The container of the application being debugged. - This property will be injected - on creation. - - @property container - @default null - @since 1.3.0 - */ - container: null, - - - /** - The container-debug-adapter which is used - to list all models. - - @property containerDebugAdapter - @default undefined - @since 1.5.0 - **/ - containerDebugAdapter: undefined, - - /** - Number of attributes to send - as columns. (Enough to make the record - identifiable). - - @private - @property attributeLimit - @default 3 - @since 1.3.0 - */ - attributeLimit: 3, - - /** - Stores all methods that clear observers. - These methods will be called on destruction. - - @private - @property releaseMethods - @since 1.3.0 - */ - releaseMethods: emberA(), - - /** - Specifies how records can be filtered. - Records returned will need to have a `filterValues` - property with a key for every name in the returned array. - - @public - @method getFilters - @return {Array} List of objects defining filters. - The object should have a `name` and `desc` property. - */ - getFilters: function() { - return emberA(); - }, - - /** - Fetch the model types and observe them for changes. + }; + prototype.setAttributeNS = function(element, namespace, name, value) { + element.setAttributeNS(namespace, name, String(value)); + }; + } else { + prototype.createElement = function(tagName) { + return this.document.createElement(tagName); + }; + prototype.setAttributeNS = function(element, namespace, name, value) { + element.setAttribute(name, String(value)); + }; + } - @public - @method watchModelTypes + prototype.addClasses = addClasses; + prototype.removeClasses = removeClasses; - @param {Function} typesAdded Callback to call to add types. - Takes an array of objects containing wrapped types (returned from `wrapModelType`). + prototype.setNamespace = function(ns) { + this.namespace = ns; + }; - @param {Function} typesUpdated Callback to call when a type has changed. - Takes an array of objects containing wrapped types. + prototype.detectNamespace = function(element) { + this.namespace = interiorNamespace(element); + }; - @return {Function} Method to call to remove all observers - */ - watchModelTypes: function(typesAdded, typesUpdated) { - var modelTypes = this.getModelTypes(); - var self = this; - var releaseMethods = emberA(); - var typesToSend; - - typesToSend = modelTypes.map(function(type) { - var klass = type.klass; - var wrapped = self.wrapModelType(klass, type.name); - releaseMethods.push(self.observeModelType(klass, typesUpdated)); - return wrapped; - }); + prototype.createDocumentFragment = function(){ + return this.document.createDocumentFragment(); + }; - typesAdded(typesToSend); + prototype.createTextNode = function(text){ + return this.document.createTextNode(text); + }; - var release = function() { - releaseMethods.forEach(function(fn) { fn(); }); - self.releaseMethods.removeObject(release); - }; - this.releaseMethods.pushObject(release); - return release; - }, + prototype.createComment = function(text){ + return this.document.createComment(text); + }; - _nameToClass: function(type) { - if (typeof type === 'string') { - type = this.container.lookupFactory('model:' + type); + prototype.repairClonedNode = function(element, blankChildTextNodes, isChecked){ + if (deletesBlankTextNodes && blankChildTextNodes.length > 0) { + for (var i=0, len=blankChildTextNodes.length;i 0) { + var currentNode = childNodes[0]; - /** - Get the columns for a given model type. + // We prepend an + + + ``` - aView = AView.create({ - controller: aController - }); - ``` + You can control which ` + + + ``` - Views can respond to user-initiated events in one of three ways: method - implementation, through an event manager, and through `{{action}}` helper use - in their template or layout. + The `value` attribute of the selected `
- // - // - // - // The tbody may be omitted, and the browser will accept and render: - // - //
- // - // - // However, the omitted start tag will still be added to the DOM. Here - // we test the string and context to see if the browser is about to - // perform this cleanup. - // - // http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags - // describes which tags are omittable. The spec for tbody and colgroup - // explains this behavior: - // - // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-tbody-element - // http://www.whatwg.org/specs/web-apps/current-work/multipage/tables.html#the-colgroup-element - // + /** + Called when the view is about to rerender, but before anything has + been torn down. This is a good opportunity to tear down any manual + observers you have installed based on the DOM state - var omittedStartTagChildTest = /<([\w:]+)/; - function detectOmittedStartTag(string, contextualElement){ - // Omitted start tags are only inside table tags. - if (contextualElement.tagName === 'TABLE') { - var omittedStartTagChildMatch = omittedStartTagChildTest.exec(string); - if (omittedStartTagChildMatch) { - var omittedStartTagChild = omittedStartTagChildMatch[1]; - // It is already asserted that the contextual element is a table - // and not the proper start tag. Just see if a tag was omitted. - return omittedStartTagChild === 'tr' || - omittedStartTagChild === 'col'; - } - } - } + @event willClearRender + */ + willClearRender: K, - function buildSVGDOM(html, dom){ - var div = dom.document.createElement('div'); - div.innerHTML = ''+html+''; - return div.firstChild.childNodes; - } + /** + Destroys any existing element along with the element for any child views + as well. If the view does not currently have a element, then this method + will do nothing. - /* - * A class wrapping DOM functions to address environment compatibility, - * namespaces, contextual elements for morph un-escaped content - * insertion. - * - * When entering a template, a DOMHelper should be passed: - * - * template(context, { hooks: hooks, dom: new DOMHelper() }); - * - * TODO: support foreignObject as a passed contextual element. It has - * a namespace (svg) that does not match its internal namespace - * (xhtml). - * - * @class DOMHelper - * @constructor - * @param {HTMLDocument} _document The document DOM methods are proxied to - */ - function DOMHelper(_document){ - this.document = _document || document; - if (!this.document) { - throw new Error("A document object must be passed to the DOMHelper, or available on the global scope"); - } - this.canClone = canClone; - this.namespace = null; - } + If you implement `willDestroyElement()` on your view, then this method will + be invoked on your view before your element is destroyed to give you a + chance to clean up any event handlers, etc. - var prototype = DOMHelper.prototype; - prototype.constructor = DOMHelper; + If you write a `willDestroyElement()` handler, you can assume that your + `didInsertElement()` handler was called earlier for the same element. - prototype.getElementById = function(id, rootNode) { - rootNode = rootNode || this.document; - return rootNode.getElementById(id); - }; + You should not call or override this method yourself, but you may + want to implement the above callbacks. - prototype.insertBefore = function(element, childElement, referenceChild) { - return element.insertBefore(childElement, referenceChild); - }; + @method destroyElement + @return {Ember.View} receiver + */ + destroyElement: function() { + return this.currentState.destroyElement(this); + }, - prototype.appendChild = function(element, childElement) { - return element.appendChild(childElement); - }; + /** + Called when the element of the view is going to be destroyed. Override + this function to do any teardown that requires an element, like removing + event listeners. - prototype.childAt = function(element, indices) { - var child = element; + Please note: any property changes made during this event will have no + effect on object observers. - for (var i = 0; i < indices.length; i++) { - child = child.childNodes.item(indices[i]); - } + @event willDestroyElement + */ + willDestroyElement: K, - return child; - }; + /** + Called when the parentView property has changed. - // Note to a Fellow Implementor: - // Ahh, accessing a child node at an index. Seems like it should be so simple, - // doesn't it? Unfortunately, this particular method has caused us a surprising - // amount of pain. As you'll note below, this method has been modified to walk - // the linked list of child nodes rather than access the child by index - // directly, even though there are two (2) APIs in the DOM that do this for us. - // If you're thinking to yourself, "What an oversight! What an opportunity to - // optimize this code!" then to you I say: stop! For I have a tale to tell. - // - // First, this code must be compatible with simple-dom for rendering on the - // server where there is no real DOM. Previously, we accessed a child node - // directly via `element.childNodes[index]`. While we *could* in theory do a - // full-fidelity simulation of a live `childNodes` array, this is slow, - // complicated and error-prone. - // - // "No problem," we thought, "we'll just use the similar - // `childNodes.item(index)` API." Then, we could just implement our own `item` - // method in simple-dom and walk the child node linked list there, allowing - // us to retain the performance advantages of the (surely optimized) `item()` - // API in the browser. - // - // Unfortunately, an enterprising soul named Samy Alzahrani discovered that in - // IE8, accessing an item out-of-bounds via `item()` causes an exception where - // other browsers return null. This necessitated a... check of - // `childNodes.length`, bringing us back around to having to support a - // full-fidelity `childNodes` array! - // - // Worst of all, Kris Selden investigated how browsers are actualy implemented - // and discovered that they're all linked lists under the hood anyway. Accessing - // `childNodes` requires them to allocate a new live collection backed by that - // linked list, which is itself a rather expensive operation. Our assumed - // optimization had backfired! That is the danger of magical thinking about - // the performance of native implementations. - // - // And this, my friends, is why the following implementation just walks the - // linked list, as surprised as that may make you. Please ensure you understand - // the above before changing this and submitting a PR. - // - // Tom Dale, January 18th, 2015, Portland OR - prototype.childAtIndex = function(element, index) { - var node = element.firstChild; + @event parentViewDidChange + */ + parentViewDidChange: K, - for (var idx = 0; node && idx < index; idx++) { - node = node.nextSibling; + applyAttributesToBuffer: function(buffer) { + // Creates observers for all registered class name and attribute bindings, + // then adds them to the element. + + this._applyClassNameBindings(); + + // Pass the render buffer so the method can apply attributes directly. + // This isn't needed for class name bindings because they use the + // existing classNames infrastructure. + this._applyAttributeBindings(buffer); + + buffer.setClasses(this.classNames); + buffer.id(this.elementId); + + var role = property_get.get(this, 'ariaRole'); + if (role) { + buffer.attr('role', role); + } + + if (property_get.get(this, 'isVisible') === false) { + buffer.style('display', 'none'); } + }, - return node; - }; + // .......................................................... + // STANDARD RENDER PROPERTIES + // - prototype.appendText = function(element, text) { - return element.appendChild(this.document.createTextNode(text)); - }; + /** + Tag name for the view's outer element. The tag name is only used when an + element is first created. If you change the `tagName` for an element, you + must destroy and recreate the view element. - prototype.setAttribute = function(element, name, value) { - element.setAttribute(name, String(value)); - }; + By default, the render buffer will use a `
` tag for views. - prototype.setAttributeNS = function(element, namespace, name, value) { - element.setAttributeNS(namespace, name, String(value)); - }; + @property tagName + @type String + @default null + */ - if (canRemoveSvgViewBoxAttribute){ - prototype.removeAttribute = function(element, name) { - element.removeAttribute(name); - }; - } else { - prototype.removeAttribute = function(element, name) { - if (element.tagName === 'svg' && name === 'viewBox') { - element.setAttribute(name, null); - } else { - element.removeAttribute(name); - } - }; - } + // We leave this null by default so we can tell the difference between + // the default case and a user-specified tag. + tagName: null, - prototype.setPropertyStrict = function(element, name, value) { - element[name] = value; - }; + /** + The WAI-ARIA role of the control represented by this view. For example, a + button may have a role of type 'button', or a pane may have a role of + type 'alertdialog'. This property is used by assistive software to help + visually challenged users navigate rich web applications. - prototype.setProperty = function(element, name, value, namespace) { - var lowercaseName = name.toLowerCase(); - if (element.namespaceURI === svgNamespace || lowercaseName === 'style') { - if (isAttrRemovalValue(value)) { - element.removeAttribute(name); - } else { - if (namespace) { - element.setAttributeNS(namespace, name, value); - } else { - element.setAttribute(name, value); - } - } - } else { - var normalized = normalizeProperty(element, name); - if (normalized) { - element[normalized] = value; - } else { - if (isAttrRemovalValue(value)) { - element.removeAttribute(name); - } else { - if (namespace && element.setAttributeNS) { - element.setAttributeNS(namespace, name, value); - } else { - element.setAttribute(name, value); - } - } - } - } - }; + The full list of valid WAI-ARIA roles is available at: + [http://www.w3.org/TR/wai-aria/roles#roles_categorization](http://www.w3.org/TR/wai-aria/roles#roles_categorization) - if (doc && doc.createElementNS) { - // Only opt into namespace detection if a contextualElement - // is passed. - prototype.createElement = function(tagName, contextualElement) { - var namespace = this.namespace; - if (contextualElement) { - if (tagName === 'svg') { - namespace = svgNamespace; - } else { - namespace = interiorNamespace(contextualElement); - } - } - if (namespace) { - return this.document.createElementNS(namespace, tagName); - } else { - return this.document.createElement(tagName); - } - }; - prototype.setAttributeNS = function(element, namespace, name, value) { - element.setAttributeNS(namespace, name, String(value)); - }; - } else { - prototype.createElement = function(tagName) { - return this.document.createElement(tagName); - }; - prototype.setAttributeNS = function(element, namespace, name, value) { - element.setAttribute(name, String(value)); - }; - } + @property ariaRole + @type String + @default null + */ + ariaRole: null, - prototype.addClasses = addClasses; - prototype.removeClasses = removeClasses; + // ....................................................... + // CORE DISPLAY METHODS + // - prototype.setNamespace = function(ns) { - this.namespace = ns; - }; + /** + Setup a view, but do not finish waking it up. - prototype.detectNamespace = function(element) { - this.namespace = interiorNamespace(element); - }; + * configure `childViews` + * register the view with the global views hash, which is used for event + dispatch - prototype.createDocumentFragment = function(){ - return this.document.createDocumentFragment(); - }; + @method init + @private + */ + init: function() { + if (!this.isVirtual && !this.elementId) { + this.elementId = utils.guidFor(this); + } - prototype.createTextNode = function(text){ - return this.document.createTextNode(text); - }; + this._super.apply(this, arguments); + }, - prototype.createComment = function(text){ - return this.document.createComment(text); - }; + __defineNonEnumerable: function(property) { + this[property.name] = property.descriptor.value; + }, - prototype.repairClonedNode = function(element, blankChildTextNodes, isChecked){ - if (deletesBlankTextNodes && blankChildTextNodes.length > 0) { - for (var i=0, len=blankChildTextNodes.length;i]*selected/; - return function detectAutoSelectedOption(select, option, html) { //jshint ignore:line - return select.selectedIndex === 0 && - !detectAutoSelectedOptionRegex.test(html); - }; - })(); - } else { - detectAutoSelectedOption = function detectAutoSelectedOption(select, option, html) { //jshint ignore:line - var selectedAttribute = option.getAttribute('selected'); - return select.selectedIndex === 0 && ( - selectedAttribute === null || - ( selectedAttribute !== '' && selectedAttribute.toLowerCase() !== 'selected' ) - ); - }; - } + View.removeMutationListener = function(callback) { + mutation.off('change', callback); + }; - 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 = '
'; - } catch (e) { - } finally { - tableNeedsInnerHTMLFix = (tableInnerHTMLTestElement.childNodes.length === 0); - } - if (tableNeedsInnerHTMLFix) { - tagNamesRequiringInnerHTMLFix = { - colgroup: ['table'], - table: [], - tbody: ['table'], - tfoot: ['table'], - thead: ['table'], - tr: ['table', 'tbody'] - }; - } + View.notifyMutationListeners = function() { + mutation.trigger('change'); + }; - // 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 = ''; - if (!selectInnerHTMLTestElement.childNodes[0]) { - tagNamesRequiringInnerHTMLFix = tagNamesRequiringInnerHTMLFix || {}; - tagNamesRequiringInnerHTMLFix.select = []; - } - return tagNamesRequiringInnerHTMLFix; - })(doc); + /** + Global views hash - function scriptSafeInnerHTML(element, html) { - // without a leading text node, IE will drop a leading script tag. - html = '­'+html; + @property views + @static + @type Hash + */ + View.views = {}; + + // If someone overrides the child views computed property when + // defining their class, we want to be able to process the user's + // supplied childViews and then restore the original computed property + // at view initialization time. This happens in Ember.ContainerView's init + // method. + View.childViewsProperty = view_child_views_support.childViewsProperty; + + exports['default'] = View; + + exports.ViewKeywordSupport = ViewKeywordSupport['default']; + exports.ViewStreamSupport = ViewStreamSupport['default']; + exports.ViewContextSupport = ViewContextSupport['default']; + exports.ViewChildViewsSupport = view_child_views_support["default"]; + exports.ViewStateSupport = ViewStateSupport['default']; + exports.TemplateRenderingSupport = TemplateRenderingSupport['default']; + exports.ClassNamesSupport = ClassNamesSupport['default']; + exports.AttributeBindingsSupport = AttributeBindingsSupport['default']; + +}); +enifed('ember-views/views/with_view', ['exports', 'ember-metal/property_set', 'ember-views/views/metamorph_view', 'ember-views/mixins/normalized_rerender_if_needed', 'ember-metal/run_loop', 'ember-htmlbars/system/render-view'], function (exports, property_set, _MetamorphView, NormalizedRerenderIfNeededSupport, run, renderView) { + + 'use strict'; + + /** + @module ember + @submodule ember-views + */ + + exports['default'] = _MetamorphView['default'].extend(NormalizedRerenderIfNeededSupport['default'], { + init: function() { + this._super.apply(this, arguments); + + var self = this; + + this.withValue.subscribe(this._wrapAsScheduled(function() { + run['default'].scheduleOnce('render', self, 'rerenderIfNeeded'); + })); - element.innerHTML = html; + var controllerName = this.controllerName; + if (controllerName) { + var controllerFactory = this.container.lookupFactory('controller:'+controllerName); + var controller = controllerFactory.create({ + parentController: this.previousContext, + target: this.previousContext + }); - var nodes = element.childNodes; + this._generatedController = controller; - // Look for ­ 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); + if (this.preserveContext) { + this._blockArguments = [controller]; + this.withValue.subscribe(function(modelStream) { + property_set.set(controller, 'model', modelStream.value()); + }); } else { - shyElement.parentNode.removeChild(shyElement); + property_set.set(this, 'controller', controller); + } + + property_set.set(controller, 'model', this.withValue.value()); + } else { + if (this.preserveContext) { + this._blockArguments = [this.withValue]; } } + }, - return nodes; - } + normalizedValue: function() { + return this.withValue.value(); + }, - function buildDOMWithFix(html, contextualElement){ - var tagName = contextualElement.tagName; + render: function(buffer) { + var withValue = this.normalizedValue(); + this._lastNormalizedValue = withValue; - // 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"; + if (!this.preserveContext && !this.controllerName) { + property_set.set(this, '_context', withValue); } - var wrappingTags = tagNamesRequiringInnerHTMLFix[tagName.toLowerCase()]; - var startTag = outerHTML.match(new RegExp("<"+tagName+"([^>]*)>", 'i'))[0]; - var endTag = ''; + var template = withValue ? this.mainTemplate : this.inverseTemplate; + renderView['default'](this, buffer, template); + }, - var wrappedHTML = [startTag, html, endTag]; + willDestroy: function() { + this._super.apply(this, arguments); - var i = wrappingTags.length; - var wrappedDepth = 1 + i; - while(i--) { - wrappedHTML.unshift('<'+wrappingTags[i]+'>'); - wrappedHTML.push(''); + if (this._generatedController) { + this._generatedController.destroy(); } + } + }); - 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; +}); +enifed('ember', ['ember-metal', 'ember-runtime', 'ember-views', 'ember-routing', 'ember-application', 'ember-extension-support', 'ember-htmlbars', 'ember-routing-htmlbars', 'ember-routing-views', 'ember-metal/environment', 'ember-runtime/system/lazy_load'], function (__dep0__, __dep1__, __dep2__, __dep3__, __dep4__, __dep5__, __dep6__, __dep7__, __dep8__, environment, lazy_load) { + + 'use strict'; + + // require the main entry points for each of these packages + // this is so that the global exports occur properly + if (Ember.__loader.registry['ember-template-compiler']) { + requireModule('ember-template-compiler'); + } + + // do this to ensure that Ember.Test is defined properly on the global + // if it is present. + if (Ember.__loader.registry['ember-testing']) { + requireModule('ember-testing'); + } + + lazy_load.runLoadHooks('Ember'); + + /** + Ember + + @module ember + */ + + Ember.deprecate( + 'Usage of Ember is deprecated for Internet Explorer 6 and 7, support will be removed in the next major version.', + !environment['default'].userAgent.match(/MSIE [67]/) + ); + +}); +enifed("htmlbars-util", + ["./htmlbars-util/safe-string","./htmlbars-util/handlebars/utils","./htmlbars-util/namespaces","exports"], + function(__dependency1__, __dependency2__, __dependency3__, __exports__) { + "use strict"; + var SafeString = __dependency1__["default"]; + var escapeExpression = __dependency2__.escapeExpression; + var getAttrNamespace = __dependency3__.getAttrNamespace; + + __exports__.SafeString = SafeString; + __exports__.escapeExpression = escapeExpression; + __exports__.getAttrNamespace = getAttrNamespace; + }); +enifed("htmlbars-util/array-utils", + ["exports"], + function(__exports__) { + "use strict"; + function forEach(array, callback, binding) { + var i, l; + if (binding === undefined) { + for (i = 0, l = array.length; i < l; i++) { + callback(array[i], i, array); + } + } else { + for (i = 0, l = array.length; i < l; i++) { + callback.call(binding, array[i], i, array); } } - while (element && element.tagName !== tagName) { - element = element.nextSibling; + } + + __exports__.forEach = forEach;function map(array, callback) { + var output = []; + var i, l; + + for (i = 0, l = array.length; i < l; i++) { + output.push(callback(array[i], i, array)); } - return element ? element.childNodes : []; + + return output; } - var buildDOM; - if (needsShy) { - buildDOM = function buildDOM(html, contextualElement, dom){ - contextualElement = dom.cloneNode(contextualElement, false); - scriptSafeInnerHTML(contextualElement, html); - return contextualElement.childNodes; + __exports__.map = map;var getIdx; + if (Array.prototype.indexOf) { + getIdx = function(array, obj, from){ + return array.indexOf(obj, from); }; } else { - buildDOM = function buildDOM(html, contextualElement, dom){ - contextualElement = dom.cloneNode(contextualElement, false); - contextualElement.innerHTML = html; - return contextualElement.childNodes; + getIdx = function(array, obj, from) { + if (from === undefined || from === null) { + from = 0; + } else if (from < 0) { + from = Math.max(0, array.length + from); + } + for (var i = from, l= array.length; i < l; i++) { + if (array[i] === obj) { + return i; + } + } + return -1; }; } - var 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*)()(\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); - } + var indexOfArray = getIdx; + __exports__.indexOfArray = indexOfArray; + }); +enifed("htmlbars-util/handlebars/safe-string", + ["exports"], + function(__exports__) { + "use strict"; + // Build out our basic SafeString type + function SafeString(string) { + this.string = string; + } - // 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 0) { - textNode = dom.document.createTextNode(spaceBefore); - scriptNode.parentNode.insertBefore(textNode, scriptNode); - } + __exports__["default"] = SafeString; + }); +enifed("htmlbars-util/handlebars/utils", + ["./safe-string","exports"], + function(__dependency1__, __exports__) { + "use strict"; + /*jshint -W004 */ + var SafeString = __dependency1__["default"]; - spaceAfter = spacesAfter[i]; - if (spaceAfter && spaceAfter.length > 0) { - textNode = dom.document.createTextNode(spaceAfter); - scriptNode.parentNode.insertBefore(textNode, scriptNode.nextSibling); - } - } + var escape = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; - return nodes; - }; - } else { - buildIESafeDOM = buildDOM; - } + var badChars = /[&<>"'`]/g; + var possible = /[&<>"'`]/; - // When parsing innerHTML, the browser may set up DOM with some things - // not desired. For example, with a select element context and option - // innerHTML the first option will be marked selected. - // - // This method cleans up some of that, resetting those values back to - // their defaults. - // - function buildSafeDOM(html, contextualElement, dom) { - var childNodes = buildIESafeDOM(html, contextualElement, dom); + function escapeChar(chr) { + return escape[chr]; + } - if (contextualElement.tagName === 'SELECT') { - // Walk child nodes - for (var i = 0; childNodes[i]; i++) { - // Find and process the first option child node - if (childNodes[i].tagName === 'OPTION') { - if (detectAutoSelectedOption(childNodes[i].parentNode, childNodes[i], html)) { - // If the first node is selected but does not have an attribute, - // presume it is not really selected. - childNodes[i].parentNode.selectedIndex = -1; - } - break; + function extend(obj /* , ...source */) { + for (var i = 1; i < arguments.length; i++) { + for (var key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; } } } - return childNodes; + return obj; } - var buildHTMLDOM; - if (needsIntegrationPointFix) { - buildHTMLDOM = function buildHTMLDOM(html, contextualElement, dom){ - if (svgHTMLIntegrationPoints[contextualElement.tagName]) { - return buildSafeDOM(html, document.createElement('div'), dom); - } else { - return buildSafeDOM(html, contextualElement, dom); - } + __exports__.extend = extend;var toString = Object.prototype.toString; + __exports__.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + var isFunction = function(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + /* istanbul ignore next */ + if (isFunction(/x/)) { + isFunction = function(value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; }; - } else { - buildHTMLDOM = buildSafeDOM; } + var isFunction; + __exports__.isFunction = isFunction; + /* istanbul ignore next */ + var isArray = Array.isArray || function(value) { + return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false; + }; + __exports__.isArray = isArray; - __exports__.buildHTMLDOM = buildHTMLDOM; - }); -enifed("morph/dom-helper/classes", - ["exports"], - function(__exports__) { - "use strict"; - var doc = typeof document === 'undefined' ? false : document; + function escapeExpression(string) { + // don't escape SafeStrings, since they're already safe + if (string && string.toHTML) { + return string.toHTML(); + } else if (string == null) { + return ""; + } else if (!string) { + return string + ''; + } - // 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) { + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = "" + string; + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + } + + __exports__.escapeExpression = escapeExpression;function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { 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(' ') : []; + __exports__.isEmpty = isEmpty;function appendContextPath(contextPath, id) { + return (contextPath ? contextPath + '.' : '') + id; } - function intersect(containingArray, valuesArray) { - var containingIndex = 0; - var containingLength = containingArray.length; - var valuesIndex = 0; - var valuesLength = valuesArray.length; + __exports__.appendContextPath = appendContextPath; + }); +enifed("htmlbars-util/namespaces", + ["exports"], + function(__exports__) { + "use strict"; + // ref http://dev.w3.org/html5/spec-LC/namespaces.html + var defaultNamespaces = { + html: 'http://www.w3.org/1999/xhtml', + mathml: 'http://www.w3.org/1998/Math/MathML', + svg: 'http://www.w3.org/2000/svg', + xlink: 'http://www.w3.org/1999/xlink', + xml: 'http://www.w3.org/XML/1998/namespace' + }; - var intersection = new Array(valuesLength); + function getAttrNamespace(attrName) { + var namespace; - // TODO: rewrite this loop in an optimal manner - for (;containingIndex 0 ? existingClasses.join(' ') : ''); - } + __exports__.merge = merge; + }); +enifed("htmlbars-util/quoting", + ["exports"], + function(__exports__) { + "use strict"; + function escapeString(str) { + str = str.replace(/\\/g, "\\\\"); + str = str.replace(/"/g, '\\"'); + str = str.replace(/\n/g, "\\n"); + return str; } - function removeClassesViaAttribute(element, classNames) { - var existingClasses = buildClassList(element); + __exports__.escapeString = escapeString; - var indexes = intersect(classNames, existingClasses); - var didChange = false; - var newClasses = []; + function string(str) { + return '"' + escapeString(str) + '"'; + } - for (var i=0, l=existingClasses.length; i 0 ? newClasses.join(' ') : ''); - } + function array(a) { + return "[" + a + "]"; } - var addClasses, removeClasses; - if (canClassList) { - 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); - } - }; - 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 { - addClasses = addClassesViaAttribute; - removeClasses = removeClassesViaAttribute; - } + __exports__.array = array; - __exports__.addClasses = addClasses; - __exports__.removeClasses = removeClasses; - }); -enifed("morph/dom-helper/prop", - ["exports"], - function(__exports__) { - "use strict"; - function isAttrRemovalValue(value) { - return value === null || value === undefined; + function hash(pairs) { + return "{" + pairs.join(", ") + "}"; } - __exports__.isAttrRemovalValue = isAttrRemovalValue;// TODO should this be an o_create kind of thing? - var propertyCaches = {}; - __exports__.propertyCaches = propertyCaches; - function normalizeProperty(element, attrName) { - var tagName = element.tagName; - var key; - var cache = propertyCaches[tagName]; - if (!cache) { - // TODO should this be an o_create kind of thing? - cache = {}; - for (key in element) { - cache[key.toLowerCase()] = key; - } - propertyCaches[tagName] = cache; + __exports__.hash = hash;function repeat(chars, times) { + var str = ""; + while (times--) { + str += chars; } - - // presumes that the attrName has been lowercased. - return cache[attrName]; + return str; } - __exports__.normalizeProperty = normalizeProperty; + __exports__.repeat = repeat; + }); +enifed("htmlbars-util/safe-string", + ["./handlebars/safe-string","exports"], + function(__dependency1__, __exports__) { + "use strict"; + var SafeString = __dependency1__["default"]; + + __exports__["default"] = SafeString; }); -enifed("morph/morph", - ["exports"], - function(__exports__) { +enifed("morph-attr", + ["./morph-attr/sanitize-attribute-value","./dom-helper/prop","./dom-helper/build-html-dom","./htmlbars-util","exports"], + function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { "use strict"; - var splice = Array.prototype.splice; + var sanitizeAttributeValue = __dependency1__.sanitizeAttributeValue; + var isAttrRemovalValue = __dependency2__.isAttrRemovalValue; + var normalizeProperty = __dependency2__.normalizeProperty; + var svgNamespace = __dependency3__.svgNamespace; + var getAttrNamespace = __dependency4__.getAttrNamespace; - function ensureStartEnd(start, end) { - if (start === null || end === null) { - throw new Error('a fragment parent must have boundary nodes in order to detect insertion'); - } + function updateProperty(value) { + this.domHelper.setPropertyStrict(this.element, this.attrName, value); } - function ensureContext(contextualElement) { - if (!contextualElement || contextualElement.nodeType !== 1) { - throw new Error('An element node must be provided for a contextualElement, you provided ' + - (contextualElement ? 'nodeType ' + contextualElement.nodeType : 'nothing')); + function updateAttribute(value) { + if (isAttrRemovalValue(value)) { + this.domHelper.removeAttribute(this.element, this.attrName); + } else { + this.domHelper.setAttribute(this.element, this.attrName, value); } } - // TODO: this is an internal API, this should be an assert - function Morph(parent, start, end, domHelper, contextualElement) { - if (parent.nodeType === 11) { - ensureStartEnd(start, end); - this.element = null; + function updateAttributeNS(value) { + if (isAttrRemovalValue(value)) { + this.domHelper.removeAttribute(this.element, this.attrName); } else { - this.element = parent; + this.domHelper.setAttributeNS(this.element, this.namespace, this.attrName, value); } - this._parent = parent; - this.start = start; - this.end = end; - this.domHelper = domHelper; - ensureContext(contextualElement); - this.contextualElement = contextualElement; - this.escaped = true; - this.reset(); } - Morph.prototype.reset = function() { - this.text = null; - this.owner = null; - this.morphs = null; - this.before = null; - this.after = null; - }; + function AttrMorph(element, attrName, domHelper, namespace) { + this.element = element; + this.domHelper = domHelper; + this.namespace = namespace !== undefined ? namespace : getAttrNamespace(attrName); + this.escaped = true; - Morph.prototype.parent = function () { - if (!this.element) { - var parent = this.start.parentNode; - if (this._parent !== parent) { - this._parent = parent; - } - if (parent.nodeType === 1) { - this.element = parent; + var normalizedAttrName = normalizeProperty(this.element, attrName); + if (this.namespace) { + this._update = updateAttributeNS; + this.attrName = attrName; + } else { + if (element.namespaceURI === svgNamespace || attrName === 'style' || !normalizedAttrName) { + this.attrName = attrName; + this._update = updateAttribute; + } else { + this.attrName = normalizedAttrName; + this._update = updateProperty; } } - return this._parent; - }; + } - Morph.prototype.destroy = function () { - if (this.owner) { - this.owner.removeMorph(this); + AttrMorph.prototype.setContent = function (value) { + if (this.escaped) { + var sanitized = sanitizeAttributeValue(this.domHelper, this.element, this.attrName, value); + this._update(sanitized, this.namespace); } else { - clear(this.element || this.parent(), this.start, this.end); + this._update(value, this.namespace); } }; - Morph.prototype.removeMorph = function (morph) { - var morphs = this.morphs; - for (var i=0, l=morphs.length; i 0 ? morphs[index-1] : null; - var after = index < morphs.length ? morphs[index] : null; - var start = before === null ? this.start : (before.end === null ? parent.lastChild : before.end.previousSibling); - var end = after === null ? this.end : (after.start === null ? parent.firstChild : after.start.nextSibling); - var morph = new Morph(parent, start, end, this.domHelper, this.contextualElement); - morph.owner = this; - morph._update(parent, node); + var previousFirstNode = this.firstNode; + if (previousFirstNode !== null) { - if (before !== null) { - morph.before = before; - before.end = start.nextSibling; - before.after = morph; + var parentNode = previousFirstNode.parentNode; + insertBefore(parentNode, firstNode, lastNode, previousFirstNode); + clear(parentNode, previousFirstNode, this.lastNode); } - if (after !== null) { - morph.after = after; - after.before = morph; - after.start = end.previousSibling; + this.firstNode = firstNode; + this.lastNode = lastNode; + + if (this.parentMorph) { + syncFirstNode(this); + syncLastNode(this); } - this.morphs.splice(index, 0, morph); - return morph; + return newNode; }; - Morph.prototype.replace = function (index, removedLength, addedNodes) { - if (this.morphs === null) { - this.morphs = []; - } - var parent = this.element || this.parent(); - var morphs = this.morphs; - var before = index > 0 ? morphs[index-1] : null; - var after = index+removedLength < morphs.length ? morphs[index+removedLength] : null; - var start = before === null ? this.start : (before.end === null ? parent.lastChild : before.end.previousSibling); - var end = after === null ? this.end : (after.start === null ? parent.firstChild : after.start.nextSibling); - var addedLength = addedNodes === undefined ? 0 : addedNodes.length; - var args, i, current; + function syncFirstNode(_morph) { + var morph = _morph; + var parentMorph; + while (parentMorph = morph.parentMorph) { + if (morph !== parentMorph.firstChildMorph) { + break; + } + if (morph.firstNode === parentMorph.firstNode) { + break; + } - if (removedLength > 0) { - clear(parent, start, end); + parentMorph.firstNode = morph.firstNode; + + morph = parentMorph; } + } - if (addedLength === 0) { - if (before !== null) { - before.after = after; - before.end = end; + function syncLastNode(_morph) { + var morph = _morph; + var parentMorph; + while (parentMorph = morph.parentMorph) { + if (morph !== parentMorph.lastChildMorph) { + break; } - if (after !== null) { - after.before = before; - after.start = start; + if (morph.lastNode === parentMorph.lastNode) { + break; } - morphs.splice(index, removedLength); - return; + + parentMorph.lastNode = morph.lastNode; + + morph = parentMorph; } + } - args = new Array(addedLength+2); - if (addedLength > 0) { - for (i=0; i 0) { - router._triggerWillChangeContext(changing, newTransition); } trigger(router, oldHandlers, true, ['willTransition', newTransition]); + + if (router.willTransition) { + router.willTransition(oldHandlers, newState.handlerInfos, newTransition); + } } __exports__["default"] = Router; @@ -49411,8 +45848,8 @@ enifed("router/transition-intent/named-transition-intent", }); }); enifed("router/transition-intent/url-transition-intent", - ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"], - function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) { + ["../transition-intent","../transition-state","../handler-info/factory","../utils","./../unrecognized-url-error","exports"], + function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { "use strict"; var TransitionIntent = __dependency1__["default"]; var TransitionState = __dependency2__["default"]; @@ -49420,6 +45857,7 @@ enifed("router/transition-intent/url-transition-intent", var oCreate = __dependency4__.oCreate; var merge = __dependency4__.merge; var subclass = __dependency4__.subclass; + var UnrecognizedURLError = __dependency5__["default"]; __exports__["default"] = subclass(TransitionIntent, { url: null, @@ -49470,15 +45908,6 @@ enifed("router/transition-intent/url-transition-intent", return newState; } }); - - /** - Promise reject reasons passed to promise rejection - handlers for failed transitions. - */ - function UnrecognizedURLError(message) { - this.message = (message || "UnrecognizedURLError"); - this.name = "UnrecognizedURLError"; - } }); enifed("router/transition-state", ["./handler-info","./utils","rsvp/promise","exports"], @@ -49908,6 +46337,26 @@ enifed("router/transition", __exports__.logAbort = logAbort; __exports__.TransitionAborted = TransitionAborted; }); +enifed("router/unrecognized-url-error", + ["./utils","exports"], + function(__dependency1__, __exports__) { + "use strict"; + var oCreate = __dependency1__.oCreate; + + /** + Promise reject reasons passed to promise rejection + handlers for failed transitions. + */ + function UnrecognizedURLError(message) { + this.message = (message || "UnrecognizedURLError"); + this.name = "UnrecognizedURLError"; + Error.call(this); + } + + UnrecognizedURLError.prototype = oCreate(Error.prototype); + + __exports__["default"] = UnrecognizedURLError; + }); enifed("router/utils", ["exports"], function(__exports__) { @@ -50107,15 +46556,23 @@ enifed("router/utils", obj[hookName] && hookName; } - function callHook(obj, hookName) { - var args = slice.call(arguments, 2); - return applyHook(obj, hookName, args); + function callHook(obj, _hookName, arg1, arg2) { + var hookName = resolveHook(obj, _hookName); + return hookName && obj[hookName].call(obj, arg1, arg2); } function applyHook(obj, _hookName, args) { var hookName = resolveHook(obj, _hookName); if (hookName) { - return obj[hookName].apply(obj, args); + if (args.length === 0) { + return obj[hookName].call(obj); + } else if (args.length === 1) { + return obj[hookName].call(obj, args[0]); + } else if (args.length === 2) { + return obj[hookName].call(obj, args[0], args[1]); + } else { + return obj[hookName].apply(obj, args); + } } } @@ -51992,7 +48449,7 @@ enifed("rsvp/promise", /** Promise objects represent the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its `then` method, which - registers callbacks to receive either a promise’s eventual value or the reason + registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled. Terminology @@ -52871,4 +49328,4 @@ enifed("rsvp/utils", }); requireModule("ember"); -})(); +})(); \ No newline at end of file