From df0a397539a437fddae5b33e6eba5a7acbc45619 Mon Sep 17 00:00:00 2001 From: Rob Eisenberg Date: Fri, 14 Aug 2015 03:22:33 -0400 Subject: [PATCH] chore(all): prepare release 0.14.0 --- bower.json | 14 +- config.js | 32 +- dist/amd/aurelia-templating.d.ts | 140 +++--- dist/amd/aurelia-templating.js | 636 +++++++++++++++---------- dist/aurelia-templating.d.ts | 140 +++--- dist/aurelia-templating.js | 535 +++++++++++++-------- dist/commonjs/aurelia-templating.d.ts | 140 +++--- dist/commonjs/aurelia-templating.js | 646 +++++++++++++++---------- dist/es6/aurelia-templating.d.ts | 140 +++--- dist/es6/aurelia-templating.js | 535 +++++++++++++-------- dist/system/aurelia-templating.d.ts | 140 +++--- dist/system/aurelia-templating.js | 648 ++++++++++++++++---------- doc/CHANGELOG.md | 23 + package.json | 14 +- 14 files changed, 2331 insertions(+), 1452 deletions(-) diff --git a/bower.json b/bower.json index 94efe63b..821f62ba 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "aurelia-templating", - "version": "0.13.16", + "version": "0.14.0", "description": "An extensible HTML templating engine supporting databinding, custom elements, attached behaviors and more.", "keywords": [ "aurelia", @@ -19,14 +19,14 @@ "url": "http://github.com/aurelia/templating" }, "dependencies": { - "aurelia-binding": "^0.8.3", - "aurelia-dependency-injection": "^0.9.1", + "aurelia-binding": "^0.8.6", + "aurelia-dependency-injection": "^0.9.2", "aurelia-html-template-element": "^0.2.0", - "aurelia-loader": "^0.8.3", - "aurelia-logging": "^0.6.2", - "aurelia-metadata": "^0.7.1", + "aurelia-loader": "^0.8.5", + "aurelia-logging": "^0.6.4", + "aurelia-metadata": "^0.7.3", "aurelia-path": "^0.8.1", - "aurelia-task-queue": "^0.6.1", + "aurelia-task-queue": "^0.6.2", "core-js": "zloirock/core-js" } } diff --git a/config.js b/config.js index a5566607..5d44d849 100644 --- a/config.js +++ b/config.js @@ -16,36 +16,36 @@ System.config({ System.config({ "map": { - "aurelia-binding": "github:aurelia/binding@0.8.3", - "aurelia-dependency-injection": "github:aurelia/dependency-injection@0.9.1", + "aurelia-binding": "github:aurelia/binding@0.8.6", + "aurelia-dependency-injection": "github:aurelia/dependency-injection@0.9.2", "aurelia-html-template-element": "github:aurelia/html-template-element@0.2.0", - "aurelia-loader": "github:aurelia/loader@0.8.3", - "aurelia-logging": "github:aurelia/logging@0.6.2", - "aurelia-metadata": "github:aurelia/metadata@0.7.1", + "aurelia-loader": "github:aurelia/loader@0.8.5", + "aurelia-logging": "github:aurelia/logging@0.6.4", + "aurelia-metadata": "github:aurelia/metadata@0.7.3", "aurelia-path": "github:aurelia/path@0.8.1", - "aurelia-task-queue": "github:aurelia/task-queue@0.6.1", + "aurelia-task-queue": "github:aurelia/task-queue@0.6.2", "babel": "npm:babel-core@5.2.2", "babel-runtime": "npm:babel-runtime@5.2.2", "core-js": "npm:core-js@0.9.18", - "github:aurelia/binding@0.8.3": { - "aurelia-dependency-injection": "github:aurelia/dependency-injection@0.9.1", - "aurelia-metadata": "github:aurelia/metadata@0.7.1", - "aurelia-task-queue": "github:aurelia/task-queue@0.6.1", + "github:aurelia/binding@0.8.6": { + "aurelia-dependency-injection": "github:aurelia/dependency-injection@0.9.2", + "aurelia-metadata": "github:aurelia/metadata@0.7.3", + "aurelia-task-queue": "github:aurelia/task-queue@0.6.2", "core-js": "npm:core-js@0.9.18" }, - "github:aurelia/dependency-injection@0.9.1": { - "aurelia-logging": "github:aurelia/logging@0.6.2", - "aurelia-metadata": "github:aurelia/metadata@0.7.1", + "github:aurelia/dependency-injection@0.9.2": { + "aurelia-logging": "github:aurelia/logging@0.6.4", + "aurelia-metadata": "github:aurelia/metadata@0.7.3", "core-js": "npm:core-js@0.9.18" }, - "github:aurelia/loader@0.8.3": { + "github:aurelia/loader@0.8.5": { "aurelia-html-template-element": "github:aurelia/html-template-element@0.2.0", - "aurelia-metadata": "github:aurelia/metadata@0.7.1", + "aurelia-metadata": "github:aurelia/metadata@0.7.3", "aurelia-path": "github:aurelia/path@0.8.1", "core-js": "npm:core-js@0.9.18", "webcomponentsjs": "github:webcomponents/webcomponentsjs@0.6.3" }, - "github:aurelia/metadata@0.7.1": { + "github:aurelia/metadata@0.7.3": { "core-js": "npm:core-js@0.9.18" }, "github:jspm/nodelibs-process@0.1.1": { diff --git a/dist/amd/aurelia-templating.d.ts b/dist/amd/aurelia-templating.d.ts index 802af35f..cd67272f 100644 --- a/dist/amd/aurelia-templating.d.ts +++ b/dist/amd/aurelia-templating.d.ts @@ -1,16 +1,27 @@ declare module 'aurelia-templating' { - import core from 'core-js'; + import * as core from 'core-js'; + import * as LogManager from 'aurelia-logging'; import { Metadata, Origin, Decorators } from 'aurelia-metadata'; import { relativeToFile } from 'aurelia-path'; import { TemplateRegistryEntry, Loader } from 'aurelia-loader'; + import { ValueConverter, bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { Container } from 'aurelia-dependency-injection'; - import { bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { TaskQueue } from 'aurelia-task-queue'; - import * as LogManager from 'aurelia-logging'; + + // this will be replaced soon + export interface ViewCreateInstruction { + suppressBind?: boolean; + systemControlled?: boolean; + enhance?: boolean; + partReplacements?: Object; + initiatedByBehavior?: boolean; + } export let DOMBoundary: any; - export function createTemplateFromMarkup(markup: any): any; - export function replaceNode(newNode: any, node: any, parentNode: any): any; - export function removeNode(node: any, parentNode: any): any; + export let hasShadowDOM: any; + export function nextElementSibling(element: Node): Element; + export function createTemplateFromMarkup(markup: string): HTMLTemplateElement; + export function replaceNode(newNode: Node, node: Node, parentNode: Node): void; + export function removeNode(node: Node, parentNode: Node): void; export const animationEvent: any; export class Animator { static configureDefault(container: any, animatorInstance: any): any; @@ -94,62 +105,83 @@ declare module 'aurelia-templating' { unregisterEffect(effectName: any): any; } export function hyphenate(name: any): any; - export function nextElementSibling(element: any): any; + export class ResourceLoadContext { + constructor(); + addDependency(url: string): void; + doesNotHaveDependency(url: string): boolean; + } + export class ViewCompileInstruction { + static normal: any; + constructor(targetShadowDOM?: boolean, compileSurrogate?: boolean, beforeCompile?: boolean); + } + export class BehaviorInstruction { + static normal: any; + static contentSelector: any; + static element(node: Node, type: HtmlBehaviorResource): BehaviorInstruction; + static attribute(attrName: string, type?: HtmlBehaviorResource): BehaviorInstruction; + static dynamic(host: any, executionContext: any, viewFactory: any): any; + constructor(suppressBind?: boolean); + } + export class TargetInstruction { + static noExpressions: any; + static contentSelector(node: Node, parentInjectorId: number): TargetInstruction; + static contentExpression(expression: any): TargetInstruction; + static lifting(parentInjectorId: number, liftingInstruction: BehaviorInstruction): TargetInstruction; + static normal(injectorId: any, parentInjectorId: any, providers: any, behaviorInstructions: any, expressions: any, elementInstruction: any): TargetInstruction; + static surrogate(providers: any, behaviorInstructions: any, expressions: any, values: any): TargetInstruction; + constructor(); + } export class ViewStrategy { static metadataKey: string; - makeRelativeTo(baseUrl: string): any; - static normalize(value: string | ViewStrategy): any; + makeRelativeTo(baseUrl: string): void; + static normalize(value: string | ViewStrategy): ViewStrategy; static getDefault(target: any): ViewStrategy; } export class UseViewStrategy extends ViewStrategy { constructor(path: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; - makeRelativeTo(file: string): any; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + makeRelativeTo(file: string): void; } export class ConventionalViewStrategy extends ViewStrategy { constructor(moduleId: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; static convertModuleIdToViewUrl(moduleId: string): string; } export class NoViewStrategy extends ViewStrategy { - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class TemplateRegistryViewStrategy extends ViewStrategy { constructor(moduleId: string, entry: TemplateRegistryEntry); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class InlineViewStrategy extends ViewStrategy { constructor(markup: string, dependencies?: Array, dependencyBaseUrl?: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BindingLanguage { inspectAttribute(resources: any, attrName: any, attrValue: any): any; createAttributeInstruction(resources: any, element: any, info: any, existingInstruction: any): any; parseText(resources: any, value: any): any; } - export class ResourceRegistry { - constructor(); - registerElement(tagName: any, behavior: any): any; - getElement(tagName: any): any; - registerAttribute(attribute: any, behavior: any, knownAttribute: any): any; - getAttribute(attribute: any): any; - registerValueConverter(name: any, valueConverter: any): any; - getValueConverter(name: any): any; - } - export class ViewResources extends ResourceRegistry { - constructor(parent: any, viewUrl: any); - relativeToView(path: any): any; - getElement(tagName: any): any; - mapAttribute(attribute: any): any; - getAttribute(attribute: any): any; - getValueConverter(name: any): any; + export class ViewResources { + constructor(parent?: ViewResources, viewUrl?: string); + getBindingLanguage(bindingLanguageFallback: any): any; + patchInParent(newParent: ViewResources): void; + relativeToView(path: string): string; + registerElement(tagName: string, behavior: HtmlBehaviorResource): void; + getElement(tagName: string): HtmlBehaviorResource; + mapAttribute(attribute: string): string; + registerAttribute(attribute: string, behavior: HtmlBehaviorResource, knownAttribute: string): void; + getAttribute(attribute: string): HtmlBehaviorResource; + registerValueConverter(name: string, valueConverter: ValueConverter): void; + getValueConverter(name: string): ValueConverter; } // NOTE: Adding a fragment to the document causes the nodes to be removed from the fragment. // NOTE: Adding to the fragment, causes the nodes to be removed from the document. export class View { constructor(container: any, fragment: any, behaviors: any, bindings: any, children: any, systemControlled: any, contentSelectors: any); - created(executionContext: any): any; + created(): any; bind(executionContext: any, systemUpdate: any): any; addBinding(binding: any): any; unbind(): any; @@ -189,17 +221,17 @@ declare module 'aurelia-templating' { contentSelectorRemoveAll(): any; } export class BoundViewFactory { - constructor(parentContainer: any, viewFactory: any, executionContext: any, partReplacements: any); - create(executionContext: any): any; + constructor(parentContainer: Container, viewFactory: ViewFactory, executionContext: Object, partReplacements?: Object); + create(executionContext?: Object): View; } export class ViewFactory { - constructor(template: any, instructions: any, resources: any); - create(container: any, executionContext: any, options?: any, element?: any): any; + constructor(template: DocumentFragment, instructions: Object, resources: ViewResources); + create(container: Container, executionContext?: Object, createInstruction?: ViewCreateInstruction, element?: Element): View; } export class ViewCompiler { static inject(): any; - constructor(bindingLanguage: any); - compile(templateOrFragment: any, resources: any, options?: any): any; + constructor(bindingLanguage: BindingLanguage, resources: ViewResources); + compile(source: HTMLTemplateElement | DocumentFragment | string, resources?: ViewResources, compileInstruction?: ViewCompileInstruction): ViewFactory; compileNode(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; compileSurrogate(node: any, resources: any): any; compileElement(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; @@ -210,12 +242,12 @@ declare module 'aurelia-templating' { } export class ViewEngine { static inject(): any; - constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ResourceRegistry); - enhance(container: any, element: any, resources: any, bindingContext: any): any; - loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileOptions?: Object, associatedModuleId?: string, loadContext?: string[]): Promise; - loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, associatedModuleId?: string, loadContext?: string[]): Promise; + constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ViewResources); + enhance(container: Container, element: Element, resources: ViewResources, bindingContext?: Object): View; + loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; importViewModelResource(moduleImport: string, moduleMember: string): Promise; - importViewResources(moduleIds: string[], names: string[], resources: ResourceRegistry, associatedModuleId?: string, loadContext?: string[]): Promise; + importViewResources(moduleIds: string[], names: string[], resources: ViewResources, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BehaviorInstance { constructor(behavior: any, executionContext: any, instruction: any); @@ -244,26 +276,26 @@ declare module 'aurelia-templating' { } export class HtmlBehaviorResource { constructor(); - static convention(name: string, existing?: HtmlBehaviorResource): any; - addChildBinding(behavior: BindingExpression): any; - analyze(container: Container, target: Function): any; - load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: string[]): Promise; - register(registry: ResourceRegistry, name?: string): any; - compile(compiler: ViewCompiler, resources: ResourceRegistry, node: Node, instruction: Object, parentNode?: Node): Node; - create(container: Container, instruction?: Object, element?: Element, bindings?: Binding[]): BehaviorInstance; + static convention(name: string, existing?: HtmlBehaviorResource): HtmlBehaviorResource; + addChildBinding(behavior: BindingExpression): void; + analyze(container: Container, target: Function): void; + load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: ResourceLoadContext): Promise; + register(registry: ViewResources, name?: string): void; + compile(compiler: ViewCompiler, resources: ViewResources, node: Node, instruction: BehaviorInstruction, parentNode?: Node): Node; + create(container: Container, instruction?: BehaviorInstruction, element?: Element, bindings?: Binding[]): BehaviorInstance; ensurePropertiesDefined(instance: Object, lookup: Object): any; } export class ResourceModule { constructor(moduleId: string); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise; } export class ResourceDescription { constructor(key: string, exportedValue: any, resourceTypeMeta: Object); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise | void; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise | void; static get(resource: any, key?: string): ResourceDescription; } export class ModuleAnalyzer { diff --git a/dist/amd/aurelia-templating.js b/dist/amd/aurelia-templating.js index 620e0e9c..c7540572 100644 --- a/dist/amd/aurelia-templating.js +++ b/dist/amd/aurelia-templating.js @@ -1,15 +1,15 @@ -define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader', 'aurelia-dependency-injection', 'aurelia-binding', 'aurelia-task-queue', 'aurelia-logging'], function (exports, _coreJs, _aureliaMetadata, _aureliaPath, _aureliaLoader, _aureliaDependencyInjection, _aureliaBinding, _aureliaTaskQueue, _aureliaLogging) { +define(['exports', 'core-js', 'aurelia-logging', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader', 'aurelia-binding', 'aurelia-dependency-injection', 'aurelia-task-queue'], function (exports, _coreJs, _aureliaLogging, _aureliaMetadata, _aureliaPath, _aureliaLoader, _aureliaBinding, _aureliaDependencyInjection, _aureliaTaskQueue) { 'use strict'; exports.__esModule = true; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + exports.nextElementSibling = nextElementSibling; exports.createTemplateFromMarkup = createTemplateFromMarkup; exports.replaceNode = replaceNode; exports.removeNode = removeNode; exports.hyphenate = hyphenate; - exports.nextElementSibling = nextElementSibling; exports.behavior = behavior; exports.customElement = customElement; exports.customAttribute = customAttribute; @@ -27,24 +27,34 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.noView = noView; exports.elementConfig = elementConfig; - function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - - function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } + function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - var _core = _interopRequireDefault(_coreJs); - var needsTemplateFixup = !('content' in document.createElement('template')); var shadowPoly = window.ShadowDOMPolyfill || null; var DOMBoundary = 'aurelia-dom-boundary'; - exports.DOMBoundary = DOMBoundary; + var hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; + + exports.hasShadowDOM = hasShadowDOM; + + function nextElementSibling(element) { + if (element.nextElementSibling) { + return element.nextElementSibling; + } + do { + element = element.nextSibling; + } while (element && element.nodeType !== 1); + return element; + } function createTemplateFromMarkup(markup) { - var temp = document.createElement('template'); - temp.innerHTML = markup; + var parser = document.createElement('div'); + parser.innerHTML = markup; + + var temp = parser.firstChild; if (needsTemplateFixup) { temp.content = document.createDocumentFragment(); @@ -157,22 +167,202 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade var capitalMatcher = /([A-Z])/g; function addHyphenAndLower(char) { - return '-' + char.toLowerCase(); + return "-" + char.toLowerCase(); } function hyphenate(name) { return (name.charAt(0).toLowerCase() + name.slice(1)).replace(capitalMatcher, addHyphenAndLower); } - function nextElementSibling(element) { - if (element.nextElementSibling) { - return element.nextElementSibling; + var ResourceLoadContext = (function () { + function ResourceLoadContext() { + _classCallCheck(this, ResourceLoadContext); + + this.dependencies = {}; } - do { - element = element.nextSibling; - } while (element && element.nodeType !== 1); - return element; - } + + ResourceLoadContext.prototype.addDependency = function addDependency(url) { + this.dependencies[url] = true; + }; + + ResourceLoadContext.prototype.doesNotHaveDependency = function doesNotHaveDependency(url) { + return !(url in this.dependencies); + }; + + return ResourceLoadContext; + })(); + + exports.ResourceLoadContext = ResourceLoadContext; + + var ViewCompileInstruction = (function () { + _createClass(ViewCompileInstruction, null, [{ + key: 'normal', + value: new ViewCompileInstruction(), + enumerable: true + }]); + + function ViewCompileInstruction() { + var targetShadowDOM = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; + var compileSurrogate = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; + var beforeCompile = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; + + _classCallCheck(this, ViewCompileInstruction); + + this.targetShadowDOM = targetShadowDOM; + this.compileSurrogate = compileSurrogate; + this.associatedModuleId = null; + this.beforeCompile = beforeCompile; + } + + return ViewCompileInstruction; + })(); + + exports.ViewCompileInstruction = ViewCompileInstruction; + + var BehaviorInstruction = (function () { + BehaviorInstruction.element = function element(node, type) { + var instruction = new BehaviorInstruction(true); + instruction.type = type; + instruction.attributes = {}; + instruction.anchorIsContainer = !(node.hasAttribute('containerless') || type.containerless); + instruction.initiatedByBehavior = true; + return instruction; + }; + + BehaviorInstruction.attribute = function attribute(attrName, type) { + var instruction = new BehaviorInstruction(true); + instruction.attrName = attrName; + instruction.type = type || null; + instruction.attributes = {}; + return instruction; + }; + + BehaviorInstruction.dynamic = function dynamic(host, executionContext, viewFactory) { + var instruction = new BehaviorInstruction(true); + instruction.host = host; + instruction.executionContext = executionContext; + instruction.viewFactory = viewFactory; + return instruction; + }; + + _createClass(BehaviorInstruction, null, [{ + key: 'normal', + value: new BehaviorInstruction(), + enumerable: true + }, { + key: 'contentSelector', + value: new BehaviorInstruction(true), + enumerable: true + }]); + + function BehaviorInstruction() { + var suppressBind = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; + + _classCallCheck(this, BehaviorInstruction); + + this.suppressBind = suppressBind; + this.initiatedByBehavior = false; + this.systemControlled = false; + this.enhance = false; + this.partReplacements = null; + this.viewFactory = null; + this.originalAttrName = null; + this.skipContentProcessing = false; + this.contentFactory = null; + this.executionContext = null; + this.anchorIsContainer = false; + this.host = null; + this.attributes = null; + this.type = null; + this.attrName = null; + } + + return BehaviorInstruction; + })(); + + exports.BehaviorInstruction = BehaviorInstruction; + + var TargetInstruction = (function () { + TargetInstruction.contentSelector = function contentSelector(node, parentInjectorId) { + var instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.contentSelector = true; + instruction.selector = node.getAttribute('select'); + instruction.suppressBind = true; + return instruction; + }; + + TargetInstruction.contentExpression = function contentExpression(expression) { + var instruction = new TargetInstruction(); + instruction.contentExpression = expression; + return instruction; + }; + + TargetInstruction.lifting = function lifting(parentInjectorId, liftingInstruction) { + var instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.expressions = TargetInstruction.noExpressions; + instruction.behaviorInstructions = [liftingInstruction]; + instruction.viewFactory = liftingInstruction.viewFactory; + instruction.providers = [liftingInstruction.type.target]; + return instruction; + }; + + TargetInstruction.normal = function normal(injectorId, parentInjectorId, providers, behaviorInstructions, expressions, elementInstruction) { + var instruction = new TargetInstruction(); + instruction.injectorId = injectorId; + instruction.parentInjectorId = parentInjectorId; + instruction.providers = providers; + instruction.behaviorInstructions = behaviorInstructions; + instruction.expressions = expressions; + instruction.anchorIsContainer = elementInstruction ? elementInstruction.anchorIsContainer : true; + instruction.elementInstruction = elementInstruction; + return instruction; + }; + + TargetInstruction.surrogate = function surrogate(providers, behaviorInstructions, expressions, values) { + var instruction = new TargetInstruction(); + instruction.expressions = expressions; + instruction.behaviorInstructions = behaviorInstructions; + instruction.providers = providers; + instruction.values = values; + return instruction; + }; + + _createClass(TargetInstruction, null, [{ + key: 'noExpressions', + value: Object.freeze([]), + enumerable: true + }]); + + function TargetInstruction() { + _classCallCheck(this, TargetInstruction); + + this.injectorId = null; + this.parentInjectorId = null; + + this.contentSelector = false; + this.selector = null; + this.suppressBind = false; + + this.contentExpression = null; + + this.expressions = null; + this.behaviorInstructions = null; + this.providers = null; + + this.viewFactory = null; + + this.anchorIsContainer = false; + this.elementInstruction = null; + + this.values = null; + } + + return TargetInstruction; + })(); + + exports.TargetInstruction = TargetInstruction; var ViewStrategy = (function () { function ViewStrategy() { @@ -228,6 +418,8 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.ViewStrategy = ViewStrategy; var UseViewStrategy = (function (_ViewStrategy) { + _inherits(UseViewStrategy, _ViewStrategy); + function UseViewStrategy(path) { _classCallCheck(this, UseViewStrategy); @@ -235,14 +427,13 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade this.path = path; } - _inherits(UseViewStrategy, _ViewStrategy); - - UseViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + UseViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { if (!this.absolutePath && this.moduleId) { this.absolutePath = _aureliaPath.relativeToFile(this.path, this.moduleId); } - return viewEngine.loadViewFactory(this.absolutePath || this.path, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.absolutePath || this.path, compileInstruction, loadContext); }; UseViewStrategy.prototype.makeRelativeTo = function makeRelativeTo(file) { @@ -255,6 +446,8 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.UseViewStrategy = UseViewStrategy; var ConventionalViewStrategy = (function (_ViewStrategy2) { + _inherits(ConventionalViewStrategy, _ViewStrategy2); + function ConventionalViewStrategy(moduleId) { _classCallCheck(this, ConventionalViewStrategy); @@ -263,10 +456,9 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade this.viewUrl = ConventionalViewStrategy.convertModuleIdToViewUrl(moduleId); } - _inherits(ConventionalViewStrategy, _ViewStrategy2); - - ConventionalViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { - return viewEngine.loadViewFactory(this.viewUrl, options, this.moduleId, loadContext); + ConventionalViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.viewUrl, compileInstruction, loadContext); }; ConventionalViewStrategy.convertModuleIdToViewUrl = function convertModuleIdToViewUrl(moduleId) { @@ -280,15 +472,15 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.ConventionalViewStrategy = ConventionalViewStrategy; var NoViewStrategy = (function (_ViewStrategy3) { + _inherits(NoViewStrategy, _ViewStrategy3); + function NoViewStrategy() { _classCallCheck(this, NoViewStrategy); _ViewStrategy3.apply(this, arguments); } - _inherits(NoViewStrategy, _ViewStrategy3); - - NoViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + NoViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { return Promise.resolve(null); }; @@ -298,6 +490,8 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.NoViewStrategy = NoViewStrategy; var TemplateRegistryViewStrategy = (function (_ViewStrategy4) { + _inherits(TemplateRegistryViewStrategy, _ViewStrategy4); + function TemplateRegistryViewStrategy(moduleId, entry) { _classCallCheck(this, TemplateRegistryViewStrategy); @@ -306,16 +500,15 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade this.entry = entry; } - _inherits(TemplateRegistryViewStrategy, _ViewStrategy4); - - TemplateRegistryViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + TemplateRegistryViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { var entry = this.entry; if (entry.isReady) { return Promise.resolve(entry.factory); } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); }; return TemplateRegistryViewStrategy; @@ -324,6 +517,8 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.TemplateRegistryViewStrategy = TemplateRegistryViewStrategy; var InlineViewStrategy = (function (_ViewStrategy5) { + _inherits(InlineViewStrategy, _ViewStrategy5); + function InlineViewStrategy(markup, dependencies, dependencyBaseUrl) { _classCallCheck(this, InlineViewStrategy); @@ -333,9 +528,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade this.dependencyBaseUrl = dependencyBaseUrl || ''; } - _inherits(InlineViewStrategy, _ViewStrategy5); - - InlineViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + InlineViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { var entry = this.entry, dependencies = this.dependencies; @@ -358,7 +551,8 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); }; return InlineViewStrategy; @@ -395,7 +589,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade var existing = lookup[name]; if (existing) { - if (existing != resource) { + if (existing !== resource) { throw new Error('Attempted to register ' + type + ' when one with the same name already exists. Name: ' + name + '.'); } @@ -405,81 +599,73 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade lookup[name] = resource; } - var ResourceRegistry = (function () { - function ResourceRegistry() { - _classCallCheck(this, ResourceRegistry); + var ViewResources = (function () { + function ViewResources(parent, viewUrl) { + _classCallCheck(this, ViewResources); + this.parent = parent || null; + this.hasParent = this.parent !== null; + this.viewUrl = viewUrl || ''; + this.valueConverterLookupFunction = this.getValueConverter.bind(this); this.attributes = {}; this.elements = {}; this.valueConverters = {}; this.attributeMap = {}; this.baseResourceUrl = ''; + this.bindingLanguage = null; } - ResourceRegistry.prototype.registerElement = function registerElement(tagName, behavior) { - register(this.elements, tagName, behavior, 'an Element'); + ViewResources.prototype.getBindingLanguage = function getBindingLanguage(bindingLanguageFallback) { + return this.bindingLanguage || (this.bindingLanguage = bindingLanguageFallback); }; - ResourceRegistry.prototype.getElement = function getElement(tagName) { - return this.elements[tagName]; - }; + ViewResources.prototype.patchInParent = function patchInParent(newParent) { + var originalParent = this.parent; - ResourceRegistry.prototype.registerAttribute = function registerAttribute(attribute, behavior, knownAttribute) { - this.attributeMap[attribute] = knownAttribute; - register(this.attributes, attribute, behavior, 'an Attribute'); - }; - - ResourceRegistry.prototype.getAttribute = function getAttribute(attribute) { - return this.attributes[attribute]; - }; - - ResourceRegistry.prototype.registerValueConverter = function registerValueConverter(name, valueConverter) { - register(this.valueConverters, name, valueConverter, 'a ValueConverter'); - }; + this.parent = newParent || null; + this.hasParent = this.parent !== null; - ResourceRegistry.prototype.getValueConverter = function getValueConverter(name) { - return this.valueConverters[name]; + if (newParent.parent === null) { + newParent.parent = originalParent; + newParent.hasParent = originalParent !== null; + } }; - return ResourceRegistry; - })(); - - exports.ResourceRegistry = ResourceRegistry; - - var ViewResources = (function (_ResourceRegistry) { - function ViewResources(parent, viewUrl) { - _classCallCheck(this, ViewResources); - - _ResourceRegistry.call(this); - this.parent = parent; - this.viewUrl = viewUrl; - this.valueConverterLookupFunction = this.getValueConverter.bind(this); - } - - _inherits(ViewResources, _ResourceRegistry); - ViewResources.prototype.relativeToView = function relativeToView(path) { return _aureliaPath.relativeToFile(path, this.viewUrl); }; + ViewResources.prototype.registerElement = function registerElement(tagName, behavior) { + register(this.elements, tagName, behavior, 'an Element'); + }; + ViewResources.prototype.getElement = function getElement(tagName) { - return this.elements[tagName] || this.parent.getElement(tagName); + return this.elements[tagName] || (this.hasParent ? this.parent.getElement(tagName) : null); }; ViewResources.prototype.mapAttribute = function mapAttribute(attribute) { - return this.attributeMap[attribute] || this.parent.attributeMap[attribute]; + return this.attributeMap[attribute] || (this.hasParent ? this.parent.mapAttribute(attribute) : null); + }; + + ViewResources.prototype.registerAttribute = function registerAttribute(attribute, behavior, knownAttribute) { + this.attributeMap[attribute] = knownAttribute; + register(this.attributes, attribute, behavior, 'an Attribute'); }; ViewResources.prototype.getAttribute = function getAttribute(attribute) { - return this.attributes[attribute] || this.parent.getAttribute(attribute); + return this.attributes[attribute] || (this.hasParent ? this.parent.getAttribute(attribute) : null); + }; + + ViewResources.prototype.registerValueConverter = function registerValueConverter(name, valueConverter) { + register(this.valueConverters, name, valueConverter, 'a ValueConverter'); }; ViewResources.prototype.getValueConverter = function getValueConverter(name) { - return this.valueConverters[name] || this.parent.getValueConverter(name); + return this.valueConverters[name] || (this.hasParent ? this.parent.getValueConverter(name) : null); }; return ViewResources; - })(ResourceRegistry); + })(); exports.ViewResources = ViewResources; @@ -500,12 +686,12 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade this.isAttached = false; } - View.prototype.created = function created(executionContext) { + View.prototype.created = function created() { var i, ii, behaviors = this.behaviors; for (i = 0, ii = behaviors.length; i < ii; ++i) { - behaviors[i].created(executionContext); + behaviors[i].created(this); } }; @@ -684,15 +870,6 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } var ContentSelector = (function () { - function ContentSelector(anchor, selector) { - _classCallCheck(this, ContentSelector); - - this.anchor = anchor; - this.selector = selector; - this.all = !this.selector; - this.groups = []; - } - ContentSelector.applySelectors = function applySelectors(view, contentSelectors, callback) { var currentChild = view.fragment.firstChild, contentMap = new Map(), @@ -734,6 +911,15 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } }; + function ContentSelector(anchor, selector) { + _classCallCheck(this, ContentSelector); + + this.anchor = anchor; + this.selector = selector; + this.all = !this.selector; + this.groups = []; + } + ContentSelector.prototype.copyForViewSlot = function copyForViewSlot() { return new ContentSelector(this.anchor, this.selector); }; @@ -803,7 +989,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade var ViewSlot = (function () { function ViewSlot(anchor, anchorIsContainer, executionContext) { - var animator = arguments[3] === undefined ? Animator.instance : arguments[3]; + var animator = arguments.length <= 3 || arguments[3] === undefined ? Animator.instance : arguments[3]; _classCallCheck(this, ViewSlot); @@ -1158,6 +1344,10 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade return this.viewResources; } + if (key === TargetInstruction) { + return this.instruction; + } + return this.superGet(key); } @@ -1186,10 +1376,10 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade return container; } - function makeElementIntoAnchor(element, isCustomElement) { + function makeElementIntoAnchor(element, elementInstruction) { var anchor = document.createComment('anchor'); - if (isCustomElement) { + if (elementInstruction) { anchor.hasAttribute = function (name) { return element.hasAttribute(name); }; @@ -1230,7 +1420,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade if (behaviorInstructions.length) { if (!instruction.anchorIsContainer) { - element = makeElementIntoAnchor(element, instruction.isCustomElement); + element = makeElementIntoAnchor(element, instruction.elementInstruction); } containers[instruction.injectorId] = elementContainer = createElementContainer(containers[instruction.parentInjectorId], element, instruction, executionContext, children, partReplacements, resources); @@ -1264,7 +1454,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade for (i = 0; i < attributes.length; i++) { current = attributes[i]; - firstIndexOfColon = current.indexOf(':'); + firstIndexOfColon = current.indexOf(":"); key = current.substring(0, firstIndexOfColon).trim(); value = current.substring(firstIndexOfColon + 1).trim(); target[key] = value; @@ -1314,8 +1504,8 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade element.setAttribute('style', styleObjectToString(styleObject)); } } else { - element.setAttribute(key, values[key]); - } + element.setAttribute(key, values[key]); + } } if (behaviorInstructions.length) { @@ -1343,16 +1533,16 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade this.parentContainer = parentContainer; this.viewFactory = viewFactory; this.executionContext = executionContext; - this.factoryOptions = { behaviorInstance: false, partReplacements: partReplacements }; + this.factoryCreateInstruction = { partReplacements: partReplacements }; } BoundViewFactory.prototype.create = function create(executionContext) { var childContainer = this.parentContainer.createChild(), context = executionContext || this.executionContext; - this.factoryOptions.systemControlled = !executionContext; + this.factoryCreateInstruction.systemControlled = !executionContext; - return this.viewFactory.create(childContainer, context, this.factoryOptions); + return this.viewFactory.create(childContainer, context, this.factoryCreateInstruction); }; return BoundViewFactory; @@ -1360,12 +1550,6 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.BoundViewFactory = BoundViewFactory; - var defaultFactoryOptions = { - systemControlled: false, - suppressBind: false, - enhance: false - }; - var ViewFactory = (function () { function ViewFactory(template, instructions, resources) { _classCallCheck(this, ViewFactory); @@ -1375,11 +1559,11 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade this.resources = resources; } - ViewFactory.prototype.create = function create(container, executionContext) { - var options = arguments[2] === undefined ? defaultFactoryOptions : arguments[2]; - var element = arguments[3] === undefined ? null : arguments[3]; + ViewFactory.prototype.create = function create(container, executionContext, createInstruction, element) { + createInstruction = createInstruction || BehaviorInstruction.normal; + element = element || null; - var fragment = options.enhance ? this.template : this.template.cloneNode(true), + var fragment = createInstruction.enhance ? this.template : this.template.cloneNode(true), instructables = fragment.querySelectorAll('.au-target'), instructions = this.instructions, resources = this.resources, @@ -1388,12 +1572,12 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade children = [], contentSelectors = [], containers = { root: container }, - partReplacements = options.partReplacements, - i, - ii, - view, - instructable, - instruction; + partReplacements = createInstruction.partReplacements, + i = undefined, + ii = undefined, + view = undefined, + instructable = undefined, + instruction = undefined; if (element !== null && this.surrogateInstruction !== null) { applySurrogateInstruction(container, element, this.surrogateInstruction, behaviors, bindings, children); @@ -1406,10 +1590,13 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade applyInstructions(containers, executionContext, instructable, instruction, behaviors, bindings, children, contentSelectors, partReplacements, resources); } - view = new View(container, fragment, behaviors, bindings, children, options.systemControlled, contentSelectors); - view.created(executionContext); + view = new View(container, fragment, behaviors, bindings, children, createInstruction.systemControlled, contentSelectors); + + if (!createInstruction.initiatedByBehavior) { + view.created(); + } - if (!options.suppressBind) { + if (!createInstruction.suppressBind) { view.bind(executionContext); } @@ -1421,10 +1608,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.ViewFactory = ViewFactory; - var nextInjectorId = 0, - defaultCompileOptions = { targetShadowDOM: false }, - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; - + var nextInjectorId = 0; function getNextInjectorId() { return ++nextInjectorId; } @@ -1474,49 +1658,51 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } var ViewCompiler = (function () { - function ViewCompiler(bindingLanguage) { + ViewCompiler.inject = function inject() { + return [BindingLanguage, ViewResources]; + }; + + function ViewCompiler(bindingLanguage, resources) { _classCallCheck(this, ViewCompiler); this.bindingLanguage = bindingLanguage; + this.resources = resources; } - ViewCompiler.inject = function inject() { - return [BindingLanguage]; - }; - - ViewCompiler.prototype.compile = function compile(templateOrFragment, resources) { - var options = arguments[2] === undefined ? defaultCompileOptions : arguments[2]; + ViewCompiler.prototype.compile = function compile(source, resources, compileInstruction) { + resources = resources || this.resources; + compileInstruction = compileInstruction || ViewCompileInstruction.normal; var instructions = {}, - targetShadowDOM = options.targetShadowDOM, - content, - part, - factory; + targetShadowDOM = compileInstruction.targetShadowDOM, + content = undefined, + part = undefined; targetShadowDOM = targetShadowDOM && hasShadowDOM; - if (options.beforeCompile) { - options.beforeCompile(templateOrFragment); + if (compileInstruction.beforeCompile) { + compileInstruction.beforeCompile(source); + console.warn('In a future release, the beforeCompile hook will be replaced by an alternate mechanism'); } - if (typeof templateOrFragment === 'string') { - templateOrFragment = createTemplateFromMarkup(templateOrFragment); + if (typeof source === 'string') { + source = createTemplateFromMarkup(source); } - if (templateOrFragment.content) { - part = templateOrFragment.getAttribute('part'); - content = document.adoptNode(templateOrFragment.content, true); + if (source.content) { + part = source.getAttribute('part'); + content = document.adoptNode(source.content, true); } else { - content = templateOrFragment; + content = source; } - this.compileNode(content, resources, instructions, templateOrFragment, 'root', !targetShadowDOM); + this.compileNode(content, resources, instructions, source, 'root', !targetShadowDOM); content.insertBefore(document.createComment(''), content.firstChild); content.appendChild(document.createComment('')); var factory = new ViewFactory(content, instructions, resources); - factory.surrogateInstruction = options.compileSurrogate ? this.compileSurrogate(templateOrFragment, resources) : null; + factory.surrogateInstruction = compileInstruction.compileSurrogate ? this.compileSurrogate(source, resources) : null; if (part) { factory.part = part; @@ -1530,13 +1716,13 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade case 1: return this.compileElement(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM); case 3: - var expression = this.bindingLanguage.parseText(resources, node.wholeText); + var expression = resources.getBindingLanguage(this.bindingLanguage).parseText(resources, node.wholeText); if (expression) { var marker = document.createElement('au-marker'), auTargetID = makeIntoInstructionTarget(marker); (node.parentNode || parentNode).insertBefore(marker, node); node.textContent = ' '; - instructions[auTargetID] = { contentExpression: expression }; + instructions[auTargetID] = TargetInstruction.contentExpression(expression); while (node.nextSibling && node.nextSibling.nodeType === 3) { (node.parentNode || parentNode).removeChild(node.nextSibling); @@ -1560,7 +1746,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade ViewCompiler.prototype.compileSurrogate = function compileSurrogate(node, resources) { var attributes = node.attributes, - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), knownAttribute = undefined, property = undefined, instruction = undefined, @@ -1626,7 +1812,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } } else { if (type) { - instruction = { attrName: attrName, type: type, attributes: {} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if (type.liftsContent) { @@ -1655,16 +1841,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } } - return { - anchorIsContainer: false, - isCustomElement: false, - injectorId: null, - parentInjectorId: null, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers, - values: values - }; + return TargetInstruction.surrogate(providers, behaviorInstructions, expressions, values); } return null; @@ -1677,7 +1854,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade expression, behaviorInstructions = [], providers = [], - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), liftingInstruction, viewFactory, type, @@ -1698,12 +1875,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade if (tagName === 'content') { if (targetLightDOM) { auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - parentInjectorId: parentInjectorId, - contentSelector: true, - selector: node.getAttribute('select'), - suppressBind: true - }; + instructions[auTargetID] = TargetInstruction.contentSelector(node, parentInjectorId); } return node.nextSibling; } else if (tagName === 'template') { @@ -1712,8 +1884,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } else { type = resources.getElement(tagName); if (type) { - elementInstruction = { type: type, attributes: {} }; - elementInstruction.anchorIsContainer = !node.hasAttribute('containerless') && !type.containerless; + elementInstruction = BehaviorInstruction.element(node, type); behaviorInstructions.push(elementInstruction); } } @@ -1740,15 +1911,11 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } } } else if (elementInstruction) { - elementProperty = elementInstruction.type.attributes[info.attrName]; - if (elementProperty) { - info.defaultBindingMode = elementProperty.defaultBindingMode; - - if (!info.command && !info.expression) { - info.command = elementProperty.hasOptions ? 'options' : null; + elementProperty = elementInstruction.type.attributes[info.attrName]; + if (elementProperty) { + info.defaultBindingMode = elementProperty.defaultBindingMode; } } - } if (elementProperty) { instruction = bindingLanguage.createAttributeInstruction(resources, node, info, elementInstruction); @@ -1783,7 +1950,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } } else { if (type) { - instruction = { attrName: attrName, type: type, attributes: {} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if (type.liftsContent) { @@ -1803,14 +1970,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade liftingInstruction.viewFactory = viewFactory; node = liftingInstruction.type.compile(this, resources, node, liftingInstruction, parentNode); auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: false, - parentInjectorId: parentInjectorId, - expressions: [], - behaviorInstructions: [liftingInstruction], - viewFactory: liftingInstruction.viewFactory, - providers: [liftingInstruction.type.target] - }; + instructions[auTargetID] = TargetInstruction.lifting(parentInjectorId, liftingInstruction); } else { if (expressions.length || behaviorInstructions.length) { injectorId = behaviorInstructions.length ? getNextInjectorId() : false; @@ -1829,15 +1989,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: elementInstruction ? elementInstruction.anchorIsContainer : true, - isCustomElement: !!elementInstruction, - injectorId: injectorId, - parentInjectorId: parentInjectorId, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers - }; + instructions[auTargetID] = TargetInstruction.normal(injectorId, parentInjectorId, providers, behaviorInstructions, expressions, elementInstruction); } if (elementInstruction && elementInstruction.skipContentProcessing) { @@ -1887,6 +2039,10 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade })(); var ViewEngine = (function () { + ViewEngine.inject = function inject() { + return [_aureliaLoader.Loader, _aureliaDependencyInjection.Container, ViewCompiler, ModuleAnalyzer, ViewResources]; + }; + function ViewEngine(loader, container, viewCompiler, moduleAnalyzer, appResources) { _classCallCheck(this, ViewEngine); @@ -1897,58 +2053,49 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade this.appResources = appResources; } - ViewEngine.inject = function inject() { - return [_aureliaLoader.Loader, _aureliaDependencyInjection.Container, ViewCompiler, ModuleAnalyzer, ResourceRegistry]; - }; - ViewEngine.prototype.enhance = function enhance(container, element, resources, bindingContext) { var instructions = {}; - this.viewCompiler.compileNode(element, resources, instructions, element.parentNode, 'root', true); var factory = new ViewFactory(element, instructions, resources); - var options = { - systemControlled: false, - suppressBind: false, - enhance: true - }; - - return factory.create(container, bindingContext, options); + return factory.create(container, bindingContext, { enhance: true }); }; - ViewEngine.prototype.loadViewFactory = function loadViewFactory(urlOrRegistryEntry, compileOptions, associatedModuleId, loadContext) { + ViewEngine.prototype.loadViewFactory = function loadViewFactory(urlOrRegistryEntry, compileInstruction, loadContext) { var _this5 = this; - loadContext = loadContext || []; + loadContext = loadContext || new ResourceLoadContext(); return ensureRegistryEntry(this.loader, urlOrRegistryEntry).then(function (viewRegistryEntry) { if (viewRegistryEntry.onReady) { - if (loadContext.indexOf(urlOrRegistryEntry) === -1) { - loadContext.push(urlOrRegistryEntry); + if (loadContext.doesNotHaveDependency(urlOrRegistryEntry)) { + loadContext.addDependency(urlOrRegistryEntry); return viewRegistryEntry.onReady; } return Promise.resolve(new ProxyViewFactory(viewRegistryEntry.onReady)); } - loadContext.push(urlOrRegistryEntry); + loadContext.addDependency(urlOrRegistryEntry); - return viewRegistryEntry.onReady = _this5.loadTemplateResources(viewRegistryEntry, associatedModuleId, loadContext).then(function (resources) { + return viewRegistryEntry.onReady = _this5.loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext).then(function (resources) { viewRegistryEntry.setResources(resources); - var viewFactory = _this5.viewCompiler.compile(viewRegistryEntry.template, resources, compileOptions); + var viewFactory = _this5.viewCompiler.compile(viewRegistryEntry.template, resources, compileInstruction); viewRegistryEntry.setFactory(viewFactory); return viewFactory; }); }); }; - ViewEngine.prototype.loadTemplateResources = function loadTemplateResources(viewRegistryEntry, associatedModuleId, loadContext) { + ViewEngine.prototype.loadTemplateResources = function loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext) { var resources = new ViewResources(this.appResources, viewRegistryEntry.id), dependencies = viewRegistryEntry.dependencies, importIds, names; - if (dependencies.length === 0 && !associatedModuleId) { + compileInstruction = compileInstruction || ViewCompileInstruction.normal; + + if (dependencies.length === 0 && !compileInstruction.associatedModuleId) { return Promise.resolve(resources); } @@ -1960,7 +2107,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade }); logger.debug('importing resources for ' + viewRegistryEntry.id, importIds); - return this.importViewResources(importIds, names, resources, associatedModuleId, loadContext); + return this.importViewResources(importIds, names, resources, compileInstruction, loadContext); }; ViewEngine.prototype.importViewModelResource = function importViewModelResource(moduleImport, moduleMember) { @@ -1980,10 +2127,11 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade }); }; - ViewEngine.prototype.importViewResources = function importViewResources(moduleIds, names, resources, associatedModuleId, loadContext) { + ViewEngine.prototype.importViewResources = function importViewResources(moduleIds, names, resources, compileInstruction, loadContext) { var _this7 = this; - loadContext = loadContext || []; + loadContext = loadContext || new ResourceLoadContext(); + compileInstruction = compileInstruction || ViewCompileInstruction.normal; return this.loader.loadAllModules(moduleIds).then(function (imports) { var i, @@ -2007,8 +2155,8 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade allAnalysis[i] = analysis; } - if (associatedModuleId) { - associatedModule = moduleAnalyzer.getAnalysis(associatedModuleId); + if (compileInstruction.associatedModuleId) { + associatedModule = moduleAnalyzer.getAnalysis(compileInstruction.associatedModuleId); if (associatedModule) { associatedModule.register(resources); @@ -2437,9 +2585,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade return BehaviorPropertyObserver; })(); - var defaultInstruction = { suppressBind: false }, - contentSelectorFactoryOptions = { suppressBind: true, enhance: false }, - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; + var contentSelectorViewCreateInstruction = { suppressBind: true, enhance: false }; function doProcessContent() { return true; @@ -2555,11 +2701,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade if (this.elementName !== null) { viewStrategy = viewStrategy || this.viewStrategy || ViewStrategy.getDefault(target); - options = { - targetShadowDOM: this.targetShadowDOM, - beforeCompile: target.beforeCompile, - compileSurrogate: true - }; + options = new ViewCompileInstruction(this.targetShadowDOM, true, target.beforeCompile); if (!viewStrategy.moduleId) { viewStrategy.moduleId = _aureliaMetadata.Origin.get(target).moduleId; @@ -2653,17 +2795,16 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } } - instruction.suppressBind = true; return node; }; - HtmlBehaviorResource.prototype.create = function create(container) { - var instruction = arguments[1] === undefined ? defaultInstruction : arguments[1]; - var element = arguments[2] === undefined ? null : arguments[2]; - var bindings = arguments[3] === undefined ? null : arguments[3]; - + HtmlBehaviorResource.prototype.create = function create(container, instruction, element, bindings) { var host = undefined; + instruction = instruction || BehaviorInstruction.normal; + element = element || null; + bindings = bindings || null; + if (this.elementName !== null && element) { if (this.usesShadowDOM) { host = element.createShadowRoot(); @@ -2698,7 +2839,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade if (behaviorInstance.view) { if (!this.usesShadowDOM) { if (instruction.contentFactory) { - var contentView = instruction.contentFactory.create(container, null, contentSelectorFactoryOptions); + var contentView = instruction.contentFactory.create(container, null, contentSelectorViewCreateInstruction); ContentSelector.applySelectors(contentView, behaviorInstance.view.contentSelectors, function (contentSelector, group) { return contentSelector.add(group); @@ -2753,6 +2894,10 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } } + if (instruction.initiatedByBehavior && viewFactory) { + behaviorInstance.view.created(); + } + return behaviorInstance; }; @@ -2914,7 +3059,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade }; ResourceDescription.get = function get(resource) { - var key = arguments[1] === undefined ? 'custom-resource' : arguments[1]; + var key = arguments.length <= 1 || arguments[1] === undefined ? 'custom-resource' : arguments[1]; var resourceTypeMeta = _aureliaMetadata.Metadata.get(_aureliaMetadata.Metadata.resource, resource), resourceDescription; @@ -3169,16 +3314,16 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade exports.ChildObserverBinder = ChildObserverBinder; var CompositionEngine = (function () { + CompositionEngine.inject = function inject() { + return [ViewEngine]; + }; + function CompositionEngine(viewEngine) { _classCallCheck(this, CompositionEngine); this.viewEngine = viewEngine; } - CompositionEngine.inject = function inject() { - return [ViewEngine]; - }; - CompositionEngine.prototype.activate = function activate(instruction) { if (instruction.skipActivation || typeof instruction.viewModel.activate !== 'function') { return Promise.resolve(); @@ -3238,12 +3383,7 @@ define(['exports', 'core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loade } return doneLoading.then(function (viewFactory) { - return metadata.create(childContainer, { - executionContext: viewModel, - viewFactory: viewFactory, - suppressBind: true, - host: instruction.host - }); + return metadata.create(childContainer, BehaviorInstruction.dynamic(instruction.host, viewModel, viewFactory)); }); }); }; diff --git a/dist/aurelia-templating.d.ts b/dist/aurelia-templating.d.ts index 802af35f..cd67272f 100644 --- a/dist/aurelia-templating.d.ts +++ b/dist/aurelia-templating.d.ts @@ -1,16 +1,27 @@ declare module 'aurelia-templating' { - import core from 'core-js'; + import * as core from 'core-js'; + import * as LogManager from 'aurelia-logging'; import { Metadata, Origin, Decorators } from 'aurelia-metadata'; import { relativeToFile } from 'aurelia-path'; import { TemplateRegistryEntry, Loader } from 'aurelia-loader'; + import { ValueConverter, bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { Container } from 'aurelia-dependency-injection'; - import { bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { TaskQueue } from 'aurelia-task-queue'; - import * as LogManager from 'aurelia-logging'; + + // this will be replaced soon + export interface ViewCreateInstruction { + suppressBind?: boolean; + systemControlled?: boolean; + enhance?: boolean; + partReplacements?: Object; + initiatedByBehavior?: boolean; + } export let DOMBoundary: any; - export function createTemplateFromMarkup(markup: any): any; - export function replaceNode(newNode: any, node: any, parentNode: any): any; - export function removeNode(node: any, parentNode: any): any; + export let hasShadowDOM: any; + export function nextElementSibling(element: Node): Element; + export function createTemplateFromMarkup(markup: string): HTMLTemplateElement; + export function replaceNode(newNode: Node, node: Node, parentNode: Node): void; + export function removeNode(node: Node, parentNode: Node): void; export const animationEvent: any; export class Animator { static configureDefault(container: any, animatorInstance: any): any; @@ -94,62 +105,83 @@ declare module 'aurelia-templating' { unregisterEffect(effectName: any): any; } export function hyphenate(name: any): any; - export function nextElementSibling(element: any): any; + export class ResourceLoadContext { + constructor(); + addDependency(url: string): void; + doesNotHaveDependency(url: string): boolean; + } + export class ViewCompileInstruction { + static normal: any; + constructor(targetShadowDOM?: boolean, compileSurrogate?: boolean, beforeCompile?: boolean); + } + export class BehaviorInstruction { + static normal: any; + static contentSelector: any; + static element(node: Node, type: HtmlBehaviorResource): BehaviorInstruction; + static attribute(attrName: string, type?: HtmlBehaviorResource): BehaviorInstruction; + static dynamic(host: any, executionContext: any, viewFactory: any): any; + constructor(suppressBind?: boolean); + } + export class TargetInstruction { + static noExpressions: any; + static contentSelector(node: Node, parentInjectorId: number): TargetInstruction; + static contentExpression(expression: any): TargetInstruction; + static lifting(parentInjectorId: number, liftingInstruction: BehaviorInstruction): TargetInstruction; + static normal(injectorId: any, parentInjectorId: any, providers: any, behaviorInstructions: any, expressions: any, elementInstruction: any): TargetInstruction; + static surrogate(providers: any, behaviorInstructions: any, expressions: any, values: any): TargetInstruction; + constructor(); + } export class ViewStrategy { static metadataKey: string; - makeRelativeTo(baseUrl: string): any; - static normalize(value: string | ViewStrategy): any; + makeRelativeTo(baseUrl: string): void; + static normalize(value: string | ViewStrategy): ViewStrategy; static getDefault(target: any): ViewStrategy; } export class UseViewStrategy extends ViewStrategy { constructor(path: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; - makeRelativeTo(file: string): any; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + makeRelativeTo(file: string): void; } export class ConventionalViewStrategy extends ViewStrategy { constructor(moduleId: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; static convertModuleIdToViewUrl(moduleId: string): string; } export class NoViewStrategy extends ViewStrategy { - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class TemplateRegistryViewStrategy extends ViewStrategy { constructor(moduleId: string, entry: TemplateRegistryEntry); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class InlineViewStrategy extends ViewStrategy { constructor(markup: string, dependencies?: Array, dependencyBaseUrl?: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BindingLanguage { inspectAttribute(resources: any, attrName: any, attrValue: any): any; createAttributeInstruction(resources: any, element: any, info: any, existingInstruction: any): any; parseText(resources: any, value: any): any; } - export class ResourceRegistry { - constructor(); - registerElement(tagName: any, behavior: any): any; - getElement(tagName: any): any; - registerAttribute(attribute: any, behavior: any, knownAttribute: any): any; - getAttribute(attribute: any): any; - registerValueConverter(name: any, valueConverter: any): any; - getValueConverter(name: any): any; - } - export class ViewResources extends ResourceRegistry { - constructor(parent: any, viewUrl: any); - relativeToView(path: any): any; - getElement(tagName: any): any; - mapAttribute(attribute: any): any; - getAttribute(attribute: any): any; - getValueConverter(name: any): any; + export class ViewResources { + constructor(parent?: ViewResources, viewUrl?: string); + getBindingLanguage(bindingLanguageFallback: any): any; + patchInParent(newParent: ViewResources): void; + relativeToView(path: string): string; + registerElement(tagName: string, behavior: HtmlBehaviorResource): void; + getElement(tagName: string): HtmlBehaviorResource; + mapAttribute(attribute: string): string; + registerAttribute(attribute: string, behavior: HtmlBehaviorResource, knownAttribute: string): void; + getAttribute(attribute: string): HtmlBehaviorResource; + registerValueConverter(name: string, valueConverter: ValueConverter): void; + getValueConverter(name: string): ValueConverter; } // NOTE: Adding a fragment to the document causes the nodes to be removed from the fragment. // NOTE: Adding to the fragment, causes the nodes to be removed from the document. export class View { constructor(container: any, fragment: any, behaviors: any, bindings: any, children: any, systemControlled: any, contentSelectors: any); - created(executionContext: any): any; + created(): any; bind(executionContext: any, systemUpdate: any): any; addBinding(binding: any): any; unbind(): any; @@ -189,17 +221,17 @@ declare module 'aurelia-templating' { contentSelectorRemoveAll(): any; } export class BoundViewFactory { - constructor(parentContainer: any, viewFactory: any, executionContext: any, partReplacements: any); - create(executionContext: any): any; + constructor(parentContainer: Container, viewFactory: ViewFactory, executionContext: Object, partReplacements?: Object); + create(executionContext?: Object): View; } export class ViewFactory { - constructor(template: any, instructions: any, resources: any); - create(container: any, executionContext: any, options?: any, element?: any): any; + constructor(template: DocumentFragment, instructions: Object, resources: ViewResources); + create(container: Container, executionContext?: Object, createInstruction?: ViewCreateInstruction, element?: Element): View; } export class ViewCompiler { static inject(): any; - constructor(bindingLanguage: any); - compile(templateOrFragment: any, resources: any, options?: any): any; + constructor(bindingLanguage: BindingLanguage, resources: ViewResources); + compile(source: HTMLTemplateElement | DocumentFragment | string, resources?: ViewResources, compileInstruction?: ViewCompileInstruction): ViewFactory; compileNode(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; compileSurrogate(node: any, resources: any): any; compileElement(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; @@ -210,12 +242,12 @@ declare module 'aurelia-templating' { } export class ViewEngine { static inject(): any; - constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ResourceRegistry); - enhance(container: any, element: any, resources: any, bindingContext: any): any; - loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileOptions?: Object, associatedModuleId?: string, loadContext?: string[]): Promise; - loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, associatedModuleId?: string, loadContext?: string[]): Promise; + constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ViewResources); + enhance(container: Container, element: Element, resources: ViewResources, bindingContext?: Object): View; + loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; importViewModelResource(moduleImport: string, moduleMember: string): Promise; - importViewResources(moduleIds: string[], names: string[], resources: ResourceRegistry, associatedModuleId?: string, loadContext?: string[]): Promise; + importViewResources(moduleIds: string[], names: string[], resources: ViewResources, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BehaviorInstance { constructor(behavior: any, executionContext: any, instruction: any); @@ -244,26 +276,26 @@ declare module 'aurelia-templating' { } export class HtmlBehaviorResource { constructor(); - static convention(name: string, existing?: HtmlBehaviorResource): any; - addChildBinding(behavior: BindingExpression): any; - analyze(container: Container, target: Function): any; - load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: string[]): Promise; - register(registry: ResourceRegistry, name?: string): any; - compile(compiler: ViewCompiler, resources: ResourceRegistry, node: Node, instruction: Object, parentNode?: Node): Node; - create(container: Container, instruction?: Object, element?: Element, bindings?: Binding[]): BehaviorInstance; + static convention(name: string, existing?: HtmlBehaviorResource): HtmlBehaviorResource; + addChildBinding(behavior: BindingExpression): void; + analyze(container: Container, target: Function): void; + load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: ResourceLoadContext): Promise; + register(registry: ViewResources, name?: string): void; + compile(compiler: ViewCompiler, resources: ViewResources, node: Node, instruction: BehaviorInstruction, parentNode?: Node): Node; + create(container: Container, instruction?: BehaviorInstruction, element?: Element, bindings?: Binding[]): BehaviorInstance; ensurePropertiesDefined(instance: Object, lookup: Object): any; } export class ResourceModule { constructor(moduleId: string); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise; } export class ResourceDescription { constructor(key: string, exportedValue: any, resourceTypeMeta: Object); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise | void; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise | void; static get(resource: any, key?: string): ResourceDescription; } export class ModuleAnalyzer { diff --git a/dist/aurelia-templating.js b/dist/aurelia-templating.js index 8cbdff0e..2a023862 100644 --- a/dist/aurelia-templating.js +++ b/dist/aurelia-templating.js @@ -1,19 +1,30 @@ -import core from 'core-js'; +import * as core from 'core-js'; +import * as LogManager from 'aurelia-logging'; import {Metadata,Origin,Decorators} from 'aurelia-metadata'; import {relativeToFile} from 'aurelia-path'; import {TemplateRegistryEntry,Loader} from 'aurelia-loader'; +import {ValueConverter,bindingMode,ObserverLocator,BindingExpression,Binding,ValueConverterResource,EventManager} from 'aurelia-binding'; import {Container} from 'aurelia-dependency-injection'; -import {bindingMode,ObserverLocator,BindingExpression,Binding,ValueConverterResource,EventManager} from 'aurelia-binding'; import {TaskQueue} from 'aurelia-task-queue'; let needsTemplateFixup = !('content' in document.createElement('template')); let shadowPoly = window.ShadowDOMPolyfill || null; export let DOMBoundary = 'aurelia-dom-boundary'; +export let hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; + +export function nextElementSibling(element:Node):Element { + if (element.nextElementSibling){ return element.nextElementSibling; } + do { element = element.nextSibling } + while (element && element.nodeType !== 1); + return element; +} -export function createTemplateFromMarkup(markup){ - let temp = document.createElement('template'); - temp.innerHTML = markup; +export function createTemplateFromMarkup(markup:string):HTMLTemplateElement{ + let parser = document.createElement('div'); + parser.innerHTML = markup; + + let temp = parser.firstChild; if(needsTemplateFixup){ temp.content = document.createDocumentFragment(); @@ -25,7 +36,7 @@ export function createTemplateFromMarkup(markup){ return temp; } -export function replaceNode(newNode, node, parentNode){ +export function replaceNode(newNode:Node, node:Node, parentNode:Node):void{ if(node.parentNode){ node.parentNode.replaceChild(newNode, node); }else if(shadowPoly){ //HACK: IE template element and shadow dom polyfills not quite right... @@ -38,7 +49,7 @@ export function replaceNode(newNode, node, parentNode){ } } -export function removeNode(node, parentNode) { +export function removeNode(node:Node, parentNode:Node):void { if(node.parentNode){ node.parentNode.removeChild(node); }else if(shadowPoly){ //HACK: IE template element and shadow dom polyfills not quite right... @@ -189,19 +200,165 @@ export function hyphenate(name){ return (name.charAt(0).toLowerCase() + name.slice(1)).replace(capitalMatcher, addHyphenAndLower); } -export function nextElementSibling(element) { - if (element.nextElementSibling){ return element.nextElementSibling; } - do { element = element.nextSibling } - while (element && element.nodeType !== 1); - return element; +export class ResourceLoadContext { + constructor(){ + this.dependencies = {}; + } + + addDependency(url:string):void{ + this.dependencies[url] = true; + } + + doesNotHaveDependency(url:string):boolean{ + return !(url in this.dependencies); + } +} + +export class ViewCompileInstruction { + static normal = new ViewCompileInstruction(); + + constructor(targetShadowDOM?:boolean=false, compileSurrogate?:boolean=false, beforeCompile?:boolean=null){ + this.targetShadowDOM = targetShadowDOM; + this.compileSurrogate = compileSurrogate; + this.associatedModuleId = null; + this.beforeCompile = beforeCompile; //this will be replaced soon + } +} + +interface ViewCreateInstruction { + suppressBind?:boolean; + systemControlled?:boolean; + enhance?:boolean; + partReplacements?:Object; + initiatedByBehavior?:boolean; +} + +export class BehaviorInstruction { + static normal = new BehaviorInstruction(); + static contentSelector = new BehaviorInstruction(true); + + static element(node:Node, type:HtmlBehaviorResource):BehaviorInstruction{ + let instruction = new BehaviorInstruction(true); + instruction.type = type; + instruction.attributes = {}; + instruction.anchorIsContainer = !(node.hasAttribute('containerless') || type.containerless); + instruction.initiatedByBehavior = true; + return instruction; + } + + static attribute(attrName:string, type?:HtmlBehaviorResource):BehaviorInstruction{ + let instruction = new BehaviorInstruction(true); + instruction.attrName = attrName; + instruction.type = type || null; + instruction.attributes = {}; + return instruction; + } + + static dynamic(host, executionContext, viewFactory){ + let instruction = new BehaviorInstruction(true); + instruction.host = host; + instruction.executionContext = executionContext; + instruction.viewFactory = viewFactory; + return instruction; + } + + constructor(suppressBind?:boolean=false){ + this.suppressBind = suppressBind; + this.initiatedByBehavior = false; + this.systemControlled = false; + this.enhance = false; + this.partReplacements = null; + this.viewFactory = null; + this.originalAttrName = null; + this.skipContentProcessing = false; + this.contentFactory = null; + this.executionContext = null; + this.anchorIsContainer = false; + this.host = null; + this.attributes = null; + this.type = null; + this.attrName = null; + } +} + +export class TargetInstruction { + static noExpressions = Object.freeze([]); + + static contentSelector(node:Node, parentInjectorId:number):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.contentSelector = true; + instruction.selector = node.getAttribute('select'); + instruction.suppressBind = true + return instruction; + } + + static contentExpression(expression):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.contentExpression = expression; + return instruction; + } + + static lifting(parentInjectorId:number, liftingInstruction:BehaviorInstruction):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.expressions = TargetInstruction.noExpressions; + instruction.behaviorInstructions = [liftingInstruction]; + instruction.viewFactory = liftingInstruction.viewFactory; + instruction.providers = [liftingInstruction.type.target]; + return instruction; + } + + static normal(injectorId, parentInjectorId, providers, behaviorInstructions, expressions, elementInstruction):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.injectorId = injectorId; + instruction.parentInjectorId = parentInjectorId; + instruction.providers = providers; + instruction.behaviorInstructions = behaviorInstructions; + instruction.expressions = expressions; + instruction.anchorIsContainer = elementInstruction ? elementInstruction.anchorIsContainer : true; + instruction.elementInstruction = elementInstruction; + return instruction; + } + + static surrogate(providers, behaviorInstructions, expressions, values):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.expressions = expressions; + instruction.behaviorInstructions = behaviorInstructions; + instruction.providers = providers; + instruction.values = values; + return instruction; + } + + constructor(){ + this.injectorId = null; + this.parentInjectorId = null; + + this.contentSelector = false; + this.selector = null; + this.suppressBind = false; + + this.contentExpression = null; + + this.expressions = null; + this.behaviorInstructions = null; + this.providers = null; + + this.viewFactory = null; + + this.anchorIsContainer = false; + this.elementInstruction = null; + + this.values = null; + } } export class ViewStrategy { static metadataKey:string = 'aurelia:view-strategy'; - makeRelativeTo(baseUrl:string){} + makeRelativeTo(baseUrl:string):void{} - static normalize(value:string|ViewStrategy){ + static normalize(value:string|ViewStrategy):ViewStrategy{ if(typeof value === 'string'){ value = new UseViewStrategy(value); } @@ -243,15 +400,16 @@ export class UseViewStrategy extends ViewStrategy { this.path = path; } - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ if(!this.absolutePath && this.moduleId){ this.absolutePath = relativeToFile(this.path, this.moduleId); } - return viewEngine.loadViewFactory(this.absolutePath || this.path, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.absolutePath || this.path, compileInstruction, loadContext); } - makeRelativeTo(file:string){ + makeRelativeTo(file:string):void{ this.absolutePath = relativeToFile(this.path, file); } } @@ -263,8 +421,9 @@ export class ConventionalViewStrategy extends ViewStrategy { this.viewUrl = ConventionalViewStrategy.convertModuleIdToViewUrl(moduleId); } - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ - return viewEngine.loadViewFactory(this.viewUrl, options, this.moduleId, loadContext); + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.viewUrl, compileInstruction, loadContext); } static convertModuleIdToViewUrl(moduleId:string):string{ @@ -274,7 +433,7 @@ export class ConventionalViewStrategy extends ViewStrategy { } export class NoViewStrategy extends ViewStrategy { - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ return Promise.resolve(null); } } @@ -286,14 +445,15 @@ export class TemplateRegistryViewStrategy extends ViewStrategy { this.entry = entry; } - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ let entry = this.entry; if(entry.isReady){ return Promise.resolve(entry.factory); } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); } } @@ -305,7 +465,7 @@ export class InlineViewStrategy extends ViewStrategy { this.dependencyBaseUrl = dependencyBaseUrl || ''; } - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ let entry = this.entry, dependencies = this.dependencies; @@ -328,7 +488,8 @@ export class InlineViewStrategy extends ViewStrategy { } } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); } } @@ -352,7 +513,7 @@ function register(lookup, name, resource, type){ var existing = lookup[name]; if(existing){ - if(existing != resource) { + if(existing !== resource) { throw new Error(`Attempted to register ${type} when one with the same name already exists. Name: ${name}.`); } @@ -362,67 +523,67 @@ function register(lookup, name, resource, type){ lookup[name] = resource; } -export class ResourceRegistry { - constructor(){ +export class ViewResources { + constructor(parent?:ViewResources, viewUrl?:string){ + this.parent = parent || null; + this.hasParent = this.parent !== null; + this.viewUrl = viewUrl || ''; + this.valueConverterLookupFunction = this.getValueConverter.bind(this); this.attributes = {}; this.elements = {}; this.valueConverters = {}; this.attributeMap = {}; this.baseResourceUrl = ''; + this.bindingLanguage = null; } - registerElement(tagName, behavior){ - register(this.elements, tagName, behavior, 'an Element'); + getBindingLanguage(bindingLanguageFallback){ + return this.bindingLanguage || (this.bindingLanguage = bindingLanguageFallback); } - getElement(tagName){ - return this.elements[tagName]; - } + patchInParent(newParent:ViewResources):void{ + let originalParent = this.parent; - registerAttribute(attribute, behavior, knownAttribute){ - this.attributeMap[attribute] = knownAttribute; - register(this.attributes, attribute, behavior, 'an Attribute'); - } + this.parent = newParent || null; + this.hasParent = this.parent !== null; - getAttribute(attribute){ - return this.attributes[attribute]; + if(newParent.parent === null){ + newParent.parent = originalParent; + newParent.hasParent = originalParent !== null; + } } - registerValueConverter(name, valueConverter){ - register(this.valueConverters, name, valueConverter, 'a ValueConverter'); + relativeToView(path:string):string{ + return relativeToFile(path, this.viewUrl); } - getValueConverter(name){ - return this.valueConverters[name]; + registerElement(tagName:string, behavior:HtmlBehaviorResource):void{ + register(this.elements, tagName, behavior, 'an Element'); } -} -export class ViewResources extends ResourceRegistry { - constructor(parent, viewUrl){ - super(); - this.parent = parent; - this.viewUrl = viewUrl; - this.valueConverterLookupFunction = this.getValueConverter.bind(this); + getElement(tagName:string):HtmlBehaviorResource{ + return this.elements[tagName] || (this.hasParent ? this.parent.getElement(tagName) : null); } - relativeToView(path){ - return relativeToFile(path, this.viewUrl); + mapAttribute(attribute:string):string{ + return this.attributeMap[attribute] || (this.hasParent ? this.parent.mapAttribute(attribute) : null); } - getElement(tagName){ - return this.elements[tagName] || this.parent.getElement(tagName); + registerAttribute(attribute:string, behavior:HtmlBehaviorResource, knownAttribute:string):void{ + this.attributeMap[attribute] = knownAttribute; + register(this.attributes, attribute, behavior, 'an Attribute'); } - mapAttribute(attribute){ - return this.attributeMap[attribute] || this.parent.attributeMap[attribute]; + getAttribute(attribute:string):HtmlBehaviorResource{ + return this.attributes[attribute] || (this.hasParent ? this.parent.getAttribute(attribute) : null); } - getAttribute(attribute){ - return this.attributes[attribute] || this.parent.getAttribute(attribute); + registerValueConverter(name:string, valueConverter:ValueConverter):void{ + register(this.valueConverters, name, valueConverter, 'a ValueConverter'); } - getValueConverter(name){ - return this.valueConverters[name] || this.parent.getValueConverter(name); + getValueConverter(name:string):ValueConverter{ + return this.valueConverters[name] || (this.hasParent ? this.parent.getValueConverter(name) : null); } } @@ -444,10 +605,10 @@ export class View { this.isAttached = false; } - created(executionContext){ + created(){ var i, ii, behaviors = this.behaviors; for(i = 0, ii = behaviors.length; i < ii; ++i){ - behaviors[i].created(executionContext); + behaviors[i].created(this); } } @@ -1067,6 +1228,10 @@ function elementContainerGet(key){ return this.viewResources; } + if(key === TargetInstruction){ + return this.instruction; + } + return this.superGet(key); } @@ -1095,10 +1260,10 @@ function createElementContainer(parent, element, instruction, executionContext, return container; } -function makeElementIntoAnchor(element, isCustomElement){ +function makeElementIntoAnchor(element, elementInstruction){ var anchor = document.createComment('anchor'); - if(isCustomElement){ + if(elementInstruction){ anchor.hasAttribute = function(name) { return element.hasAttribute(name); }; anchor.getAttribute = function(name){ return element.getAttribute(name); }; anchor.setAttribute = function(name, value) { element.setAttribute(name, value); }; @@ -1130,7 +1295,7 @@ function applyInstructions(containers, executionContext, element, instruction, if(behaviorInstructions.length){ if(!instruction.anchorIsContainer){ - element = makeElementIntoAnchor(element, instruction.isCustomElement); + element = makeElementIntoAnchor(element, instruction.elementInstruction); } containers[instruction.injectorId] = elementContainer = @@ -1245,38 +1410,35 @@ function applySurrogateInstruction(container, element, instruction, behaviors, b } export class BoundViewFactory { - constructor(parentContainer, viewFactory, executionContext, partReplacements){ + constructor(parentContainer:Container, viewFactory:ViewFactory, executionContext:Object, partReplacements?:Object){ this.parentContainer = parentContainer; this.viewFactory = viewFactory; this.executionContext = executionContext; - this.factoryOptions = { behaviorInstance:false, partReplacements:partReplacements }; + this.factoryCreateInstruction = { partReplacements:partReplacements }; } - create(executionContext){ + create(executionContext?:Object):View{ var childContainer = this.parentContainer.createChild(), context = executionContext || this.executionContext; - this.factoryOptions.systemControlled = !executionContext; + this.factoryCreateInstruction.systemControlled = !executionContext; - return this.viewFactory.create(childContainer, context, this.factoryOptions); + return this.viewFactory.create(childContainer, context, this.factoryCreateInstruction); } } -var defaultFactoryOptions = { - systemControlled:false, - suppressBind:false, - enhance:false -}; - export class ViewFactory{ - constructor(template, instructions, resources){ + constructor(template:DocumentFragment, instructions:Object, resources:ViewResources){ this.template = template; this.instructions = instructions; this.resources = resources; } - create(container, executionContext, options=defaultFactoryOptions, element=null){ - var fragment = options.enhance ? this.template : this.template.cloneNode(true), + create(container:Container, executionContext?:Object, createInstruction?:ViewCreateInstruction, element?:Element):View{ + createInstruction = createInstruction || BehaviorInstruction.normal; + element = element || null; + + let fragment = createInstruction.enhance ? this.template : this.template.cloneNode(true), instructables = fragment.querySelectorAll('.au-target'), instructions = this.instructions, resources = this.resources, @@ -1285,7 +1447,7 @@ export class ViewFactory{ children = [], contentSelectors = [], containers = { root:container }, - partReplacements = options.partReplacements, + partReplacements = createInstruction.partReplacements, i, ii, view, instructable, instruction; if(element !== null && this.surrogateInstruction !== null){ @@ -1300,10 +1462,15 @@ export class ViewFactory{ instruction, behaviors, bindings, children, contentSelectors, partReplacements, resources); } - view = new View(container, fragment, behaviors, bindings, children, options.systemControlled, contentSelectors); - view.created(executionContext); + view = new View(container, fragment, behaviors, bindings, children, createInstruction.systemControlled, contentSelectors); + + //if iniated by an element behavior, let the behavior trigger this callback once it's done creating the element + if(!createInstruction.initiatedByBehavior){ + view.created(); + } - if(!options.suppressBind){ + //if the view creation is part of a larger creation, wait to bind until the root view initiates binding + if(!createInstruction.suppressBind){ view.bind(executionContext); } @@ -1311,10 +1478,7 @@ export class ViewFactory{ } } -var nextInjectorId = 0, - defaultCompileOptions = { targetShadowDOM:false }, - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; - +let nextInjectorId = 0; function getNextInjectorId(){ return ++nextInjectorId; } @@ -1362,40 +1526,45 @@ function makeIntoInstructionTarget(element){ } export class ViewCompiler { - static inject() { return [BindingLanguage]; } - constructor(bindingLanguage){ + static inject() { return [BindingLanguage, ViewResources]; } + constructor(bindingLanguage:BindingLanguage, resources:ViewResources){ this.bindingLanguage = bindingLanguage; + this.resources = resources; } - compile(templateOrFragment, resources, options=defaultCompileOptions){ - var instructions = {}, - targetShadowDOM = options.targetShadowDOM, - content, part, factory; + compile(source:HTMLTemplateElement|DocumentFragment|string, resources?:ViewResources, compileInstruction?:ViewCompileInstruction):ViewFactory{ + resources = resources || this.resources; + compileInstruction = compileInstruction || ViewCompileInstruction.normal; + + let instructions = {}, + targetShadowDOM = compileInstruction.targetShadowDOM, + content, part; targetShadowDOM = targetShadowDOM && hasShadowDOM; - if(options.beforeCompile){ - options.beforeCompile(templateOrFragment); + if(compileInstruction.beforeCompile){ + compileInstruction.beforeCompile(source); + console.warn('In a future release, the beforeCompile hook will be replaced by an alternate mechanism'); } - if(typeof templateOrFragment === 'string'){ - templateOrFragment = createTemplateFromMarkup(templateOrFragment); + if(typeof source === 'string'){ + source = createTemplateFromMarkup(source); } - if(templateOrFragment.content){ - part = templateOrFragment.getAttribute('part'); - content = document.adoptNode(templateOrFragment.content, true); + if(source.content){ + part = source.getAttribute('part'); + content = document.adoptNode(source.content, true); }else{ - content = templateOrFragment; + content = source; } - this.compileNode(content, resources, instructions, templateOrFragment, 'root', !targetShadowDOM); + this.compileNode(content, resources, instructions, source, 'root', !targetShadowDOM); content.insertBefore(document.createComment(''), content.firstChild); content.appendChild(document.createComment('')); - var factory = new ViewFactory(content, instructions, resources); - factory.surrogateInstruction = options.compileSurrogate ? this.compileSurrogate(templateOrFragment, resources) : null; + let factory = new ViewFactory(content, instructions, resources); + factory.surrogateInstruction = compileInstruction.compileSurrogate ? this.compileSurrogate(source, resources) : null; if(part){ factory.part = part; @@ -1410,13 +1579,13 @@ export class ViewCompiler { return this.compileElement(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM); case 3: //text node //use wholeText to retrieve the textContent of all adjacent text nodes. - var expression = this.bindingLanguage.parseText(resources, node.wholeText); + var expression = resources.getBindingLanguage(this.bindingLanguage).parseText(resources, node.wholeText); if(expression){ let marker = document.createElement('au-marker'), auTargetID = makeIntoInstructionTarget(marker); (node.parentNode || parentNode).insertBefore(marker, node); node.textContent = ' '; - instructions[auTargetID] = { contentExpression:expression }; + instructions[auTargetID] = TargetInstruction.contentExpression(expression); //remove adjacent text nodes. while(node.nextSibling && node.nextSibling.nodeType === 3) { (node.parentNode || parentNode).removeChild(node.nextSibling); @@ -1441,7 +1610,7 @@ export class ViewCompiler { compileSurrogate(node, resources){ let attributes = node.attributes, - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), knownAttribute, property, instruction, i, ii, attr, attrName, attrValue, info, type, expressions = [], expression, @@ -1497,7 +1666,7 @@ export class ViewCompiler { } }else{ //NO BINDINGS if(type){ //templator or attached behavior found - instruction = { attrName:attrName, type:type, attributes:{} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if(type.liftsContent){ //template controller @@ -1526,16 +1695,7 @@ export class ViewCompiler { } } - return { - anchorIsContainer: false, - isCustomElement: false, - injectorId: null, - parentInjectorId: null, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers, - values:values - }; + return TargetInstruction.surrogate(providers, behaviorInstructions, expressions, values); } return null; @@ -1547,7 +1707,7 @@ export class ViewCompiler { expressions = [], expression, behaviorInstructions = [], providers = [], - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), liftingInstruction, viewFactory, type, elementInstruction, elementProperty, i, ii, attr, attrName, attrValue, instruction, info, property, knownAttribute, auTargetID, injectorId; @@ -1555,12 +1715,7 @@ export class ViewCompiler { if(tagName === 'content'){ if(targetLightDOM){ auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - parentInjectorId: parentInjectorId, - contentSelector: true, - selector:node.getAttribute('select'), - suppressBind: true - }; + instructions[auTargetID] = TargetInstruction.contentSelector(node, parentInjectorId); } return node.nextSibling; } else if(tagName === 'template'){ @@ -1569,8 +1724,7 @@ export class ViewCompiler { } else{ type = resources.getElement(tagName); if(type){ - elementInstruction = {type:type, attributes:{}}; - elementInstruction.anchorIsContainer = !node.hasAttribute('containerless') && !type.containerless; + elementInstruction = BehaviorInstruction.element(node, type); behaviorInstructions.push(elementInstruction); } } @@ -1600,10 +1754,6 @@ export class ViewCompiler { elementProperty = elementInstruction.type.attributes[info.attrName]; if(elementProperty){ //and this attribute is a custom property info.defaultBindingMode = elementProperty.defaultBindingMode; //set the default binding mode - - if(!info.command && !info.expression){ // if there is no command or detected expression - info.command = elementProperty.hasOptions ? 'options' : null; //and it is an optons property, set the options command - } } } @@ -1640,7 +1790,7 @@ export class ViewCompiler { } }else{ //NO BINDINGS if(type){ //templator or attached behavior found - instruction = { attrName:attrName, type:type, attributes:{} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if(type.liftsContent){ //template controller @@ -1662,14 +1812,7 @@ export class ViewCompiler { liftingInstruction.viewFactory = viewFactory; node = liftingInstruction.type.compile(this, resources, node, liftingInstruction, parentNode); auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: false, - parentInjectorId: parentInjectorId, - expressions: [], - behaviorInstructions: [liftingInstruction], - viewFactory: liftingInstruction.viewFactory, - providers: [liftingInstruction.type.target] - }; + instructions[auTargetID] = TargetInstruction.lifting(parentInjectorId, liftingInstruction); }else{ if(expressions.length || behaviorInstructions.length){ injectorId = behaviorInstructions.length ? getNextInjectorId() : false; @@ -1688,15 +1831,14 @@ export class ViewCompiler { } auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: elementInstruction ? elementInstruction.anchorIsContainer : true, - isCustomElement: !!elementInstruction, - injectorId: injectorId, - parentInjectorId: parentInjectorId, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers - }; + instructions[auTargetID] = TargetInstruction.normal( + injectorId, + parentInjectorId, + providers, + behaviorInstructions, + expressions, + elementInstruction + ); } if(elementInstruction && elementInstruction.skipContentProcessing){ @@ -1713,7 +1855,6 @@ export class ViewCompiler { } } -import * as LogManager from 'aurelia-logging'; var logger = LogManager.getLogger('templating'); function ensureRegistryEntry(loader, urlOrRegistryEntry){ @@ -1735,8 +1876,8 @@ class ProxyViewFactory { } export class ViewEngine { - static inject() { return [Loader, Container, ViewCompiler, ModuleAnalyzer, ResourceRegistry]; } - constructor(loader:Loader, container:Container, viewCompiler:ViewCompiler, moduleAnalyzer:ModuleAnalyzer, appResources:ResourceRegistry){ + static inject() { return [Loader, Container, ViewCompiler, ModuleAnalyzer, ViewResources]; } + constructor(loader:Loader, container:Container, viewCompiler:ViewCompiler, moduleAnalyzer:ModuleAnalyzer, appResources:ViewResources){ this.loader = loader; this.container = container; this.viewCompiler = viewCompiler; @@ -1744,51 +1885,46 @@ export class ViewEngine { this.appResources = appResources; } - enhance(container, element, resources, bindingContext){ + enhance(container:Container, element:Element, resources:ViewResources, bindingContext?:Object):View{ let instructions = {}; - this.viewCompiler.compileNode(element, resources, instructions, element.parentNode, 'root', true); let factory = new ViewFactory(element, instructions, resources); - let options = { - systemControlled:false, - suppressBind:false, - enhance:true - }; - - return factory.create(container, bindingContext, options); + return factory.create(container, bindingContext, { enhance:true }); } - loadViewFactory(urlOrRegistryEntry:string|TemplateRegistryEntry, compileOptions?:Object, associatedModuleId?:string, loadContext?:string[]):Promise{ - loadContext = loadContext || []; + loadViewFactory(urlOrRegistryEntry:string|TemplateRegistryEntry, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ + loadContext = loadContext || new ResourceLoadContext(); return ensureRegistryEntry(this.loader, urlOrRegistryEntry).then(viewRegistryEntry => { if(viewRegistryEntry.onReady){ - if(loadContext.indexOf(urlOrRegistryEntry) === -1){ - loadContext.push(urlOrRegistryEntry); + if(loadContext.doesNotHaveDependency(urlOrRegistryEntry)){ + loadContext.addDependency(urlOrRegistryEntry); return viewRegistryEntry.onReady; } return Promise.resolve(new ProxyViewFactory(viewRegistryEntry.onReady)); } - loadContext.push(urlOrRegistryEntry); + loadContext.addDependency(urlOrRegistryEntry); - return viewRegistryEntry.onReady = this.loadTemplateResources(viewRegistryEntry, associatedModuleId, loadContext).then(resources => { + return viewRegistryEntry.onReady = this.loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext).then(resources => { viewRegistryEntry.setResources(resources); - var viewFactory = this.viewCompiler.compile(viewRegistryEntry.template, resources, compileOptions); + var viewFactory = this.viewCompiler.compile(viewRegistryEntry.template, resources, compileInstruction); viewRegistryEntry.setFactory(viewFactory); return viewFactory; }); }); } - loadTemplateResources(viewRegistryEntry:TemplateRegistryEntry, associatedModuleId?:string, loadContext?:string[]):Promise{ + loadTemplateResources(viewRegistryEntry:TemplateRegistryEntry, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ var resources = new ViewResources(this.appResources, viewRegistryEntry.id), dependencies = viewRegistryEntry.dependencies, importIds, names; - if(dependencies.length === 0 && !associatedModuleId){ + compileInstruction = compileInstruction || ViewCompileInstruction.normal; + + if(dependencies.length === 0 && !compileInstruction.associatedModuleId){ return Promise.resolve(resources); } @@ -1796,7 +1932,7 @@ export class ViewEngine { names = dependencies.map(x => x.name); logger.debug(`importing resources for ${viewRegistryEntry.id}`, importIds); - return this.importViewResources(importIds, names, resources, associatedModuleId, loadContext); + return this.importViewResources(importIds, names, resources, compileInstruction, loadContext); } importViewModelResource(moduleImport:string, moduleMember:string):Promise{ @@ -1814,8 +1950,9 @@ export class ViewEngine { }); } - importViewResources(moduleIds:string[], names:string[], resources:ResourceRegistry, associatedModuleId?:string, loadContext?:string[]):Promise{ - loadContext = loadContext || []; + importViewResources(moduleIds:string[], names:string[], resources:ViewResources, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ + loadContext = loadContext || new ResourceLoadContext(); + compileInstruction = compileInstruction || ViewCompileInstruction.normal; return this.loader.loadAllModules(moduleIds).then(imports => { var i, ii, analysis, normalizedId, current, associatedModule, @@ -1837,8 +1974,8 @@ export class ViewEngine { allAnalysis[i] = analysis; } - if(associatedModuleId){ - associatedModule = moduleAnalyzer.getAnalysis(associatedModuleId); + if(compileInstruction.associatedModuleId){ + associatedModule = moduleAnalyzer.getAnalysis(compileInstruction.associatedModuleId); if(associatedModule){ associatedModule.register(resources); @@ -2233,9 +2370,7 @@ class BehaviorPropertyObserver { } } -var defaultInstruction = { suppressBind:false }, - contentSelectorFactoryOptions = { suppressBind:true, enhance:false }, - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; +var contentSelectorViewCreateInstruction = { suppressBind:true, enhance:false }; function doProcessContent(){ return true; @@ -2257,7 +2392,7 @@ export class HtmlBehaviorResource { this.attributes = {}; } - static convention(name:string, existing?:HtmlBehaviorResource){ + static convention(name:string, existing?:HtmlBehaviorResource):HtmlBehaviorResource{ var behavior; if(name.endsWith('CustomAttribute')){ @@ -2273,7 +2408,7 @@ export class HtmlBehaviorResource { return behavior; } - addChildBinding(behavior:BindingExpression){ + addChildBinding(behavior:BindingExpression):void{ if(this.childBindings === null){ this.childBindings = []; } @@ -2281,7 +2416,7 @@ export class HtmlBehaviorResource { this.childBindings.push(behavior); } - analyze(container:Container, target:Function){ + analyze(container:Container, target:Function):void{ var proto = target.prototype, properties = this.properties, attributeName = this.attributeName, @@ -2338,16 +2473,12 @@ export class HtmlBehaviorResource { } } - load(container:Container, target:Function, viewStrategy?:ViewStrategy, transientView?:boolean, loadContext?:string[]):Promise{ + load(container:Container, target:Function, viewStrategy?:ViewStrategy, transientView?:boolean, loadContext?:ResourceLoadContext):Promise{ var options; if(this.elementName !== null){ viewStrategy = viewStrategy || this.viewStrategy || ViewStrategy.getDefault(target); - options = { - targetShadowDOM:this.targetShadowDOM, - beforeCompile:target.beforeCompile, - compileSurrogate:true - }; + options = new ViewCompileInstruction(this.targetShadowDOM, true, target.beforeCompile); if(!viewStrategy.moduleId){ viewStrategy.moduleId = Origin.get(target).moduleId; @@ -2365,7 +2496,7 @@ export class HtmlBehaviorResource { return Promise.resolve(this); } - register(registry:ResourceRegistry, name?:string){ + register(registry:ViewResources, name?:string):void{ if(this.attributeName !== null) { registry.registerAttribute(name || this.attributeName, this, this.attributeName); } @@ -2375,7 +2506,7 @@ export class HtmlBehaviorResource { } } - compile(compiler:ViewCompiler, resources:ResourceRegistry, node:Node, instruction:Object, parentNode?:Node):Node{ + compile(compiler:ViewCompiler, resources:ViewResources, node:Node, instruction:BehaviorInstruction, parentNode?:Node):Node{ if(this.liftsContent){ if(!instruction.viewFactory){ var template = document.createElement('template'), @@ -2440,13 +2571,16 @@ export class HtmlBehaviorResource { } } - instruction.suppressBind = true; return node; } - create(container:Container, instruction?:Object=defaultInstruction, element?:Element=null, bindings?:Binding[]=null):BehaviorInstance{ + create(container:Container, instruction?:BehaviorInstruction, element?:Element, bindings?:Binding[]):BehaviorInstance{ let host; + instruction = instruction || BehaviorInstruction.normal; + element = element || null; + bindings = bindings || null; + if(this.elementName !== null && element){ if(this.usesShadowDOM) { host = element.createShadowRoot(); @@ -2483,7 +2617,7 @@ export class HtmlBehaviorResource { if(behaviorInstance.view){ if(!this.usesShadowDOM) { if(instruction.contentFactory){ - var contentView = instruction.contentFactory.create(container, null, contentSelectorFactoryOptions); + var contentView = instruction.contentFactory.create(container, null, contentSelectorViewCreateInstruction); ContentSelector.applySelectors( contentView, @@ -2543,6 +2677,10 @@ export class HtmlBehaviorResource { } } + if(instruction.initiatedByBehavior && viewFactory){ + behaviorInstance.view.created(); + } + return behaviorInstance; } @@ -2600,7 +2738,7 @@ export class ResourceModule { } } - register(registry:ResourceRegistry, name?:string){ + register(registry:ViewResources, name?:string){ var i, ii, resources = this.resources; if(this.mainResource){ @@ -2614,7 +2752,7 @@ export class ResourceModule { } } - load(container:Container, loadContext?:string[]):Promise{ + load(container:Container, loadContext?:ResourceLoadContext):Promise{ if(this.onLoaded){ return this.onLoaded; } @@ -2676,11 +2814,11 @@ export class ResourceDescription { } } - register(registry:ResourceRegistry, name?:string){ + register(registry:ViewResources, name?:string){ this.metadata.register(registry, name); } - load(container:Container, loadContext?:string[]):Promise|void{ + load(container:Container, loadContext?:ResourceLoadContext):Promise|void{ let metadata = this.metadata, value = this.value; @@ -2974,12 +3112,7 @@ export class CompositionEngine { } return doneLoading.then(viewFactory => { - return metadata.create(childContainer, { - executionContext:viewModel, - viewFactory:viewFactory, - suppressBind:true, - host:instruction.host - }); + return metadata.create(childContainer, BehaviorInstruction.dynamic(instruction.host, viewModel, viewFactory)); }); }); } diff --git a/dist/commonjs/aurelia-templating.d.ts b/dist/commonjs/aurelia-templating.d.ts index 802af35f..cd67272f 100644 --- a/dist/commonjs/aurelia-templating.d.ts +++ b/dist/commonjs/aurelia-templating.d.ts @@ -1,16 +1,27 @@ declare module 'aurelia-templating' { - import core from 'core-js'; + import * as core from 'core-js'; + import * as LogManager from 'aurelia-logging'; import { Metadata, Origin, Decorators } from 'aurelia-metadata'; import { relativeToFile } from 'aurelia-path'; import { TemplateRegistryEntry, Loader } from 'aurelia-loader'; + import { ValueConverter, bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { Container } from 'aurelia-dependency-injection'; - import { bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { TaskQueue } from 'aurelia-task-queue'; - import * as LogManager from 'aurelia-logging'; + + // this will be replaced soon + export interface ViewCreateInstruction { + suppressBind?: boolean; + systemControlled?: boolean; + enhance?: boolean; + partReplacements?: Object; + initiatedByBehavior?: boolean; + } export let DOMBoundary: any; - export function createTemplateFromMarkup(markup: any): any; - export function replaceNode(newNode: any, node: any, parentNode: any): any; - export function removeNode(node: any, parentNode: any): any; + export let hasShadowDOM: any; + export function nextElementSibling(element: Node): Element; + export function createTemplateFromMarkup(markup: string): HTMLTemplateElement; + export function replaceNode(newNode: Node, node: Node, parentNode: Node): void; + export function removeNode(node: Node, parentNode: Node): void; export const animationEvent: any; export class Animator { static configureDefault(container: any, animatorInstance: any): any; @@ -94,62 +105,83 @@ declare module 'aurelia-templating' { unregisterEffect(effectName: any): any; } export function hyphenate(name: any): any; - export function nextElementSibling(element: any): any; + export class ResourceLoadContext { + constructor(); + addDependency(url: string): void; + doesNotHaveDependency(url: string): boolean; + } + export class ViewCompileInstruction { + static normal: any; + constructor(targetShadowDOM?: boolean, compileSurrogate?: boolean, beforeCompile?: boolean); + } + export class BehaviorInstruction { + static normal: any; + static contentSelector: any; + static element(node: Node, type: HtmlBehaviorResource): BehaviorInstruction; + static attribute(attrName: string, type?: HtmlBehaviorResource): BehaviorInstruction; + static dynamic(host: any, executionContext: any, viewFactory: any): any; + constructor(suppressBind?: boolean); + } + export class TargetInstruction { + static noExpressions: any; + static contentSelector(node: Node, parentInjectorId: number): TargetInstruction; + static contentExpression(expression: any): TargetInstruction; + static lifting(parentInjectorId: number, liftingInstruction: BehaviorInstruction): TargetInstruction; + static normal(injectorId: any, parentInjectorId: any, providers: any, behaviorInstructions: any, expressions: any, elementInstruction: any): TargetInstruction; + static surrogate(providers: any, behaviorInstructions: any, expressions: any, values: any): TargetInstruction; + constructor(); + } export class ViewStrategy { static metadataKey: string; - makeRelativeTo(baseUrl: string): any; - static normalize(value: string | ViewStrategy): any; + makeRelativeTo(baseUrl: string): void; + static normalize(value: string | ViewStrategy): ViewStrategy; static getDefault(target: any): ViewStrategy; } export class UseViewStrategy extends ViewStrategy { constructor(path: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; - makeRelativeTo(file: string): any; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + makeRelativeTo(file: string): void; } export class ConventionalViewStrategy extends ViewStrategy { constructor(moduleId: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; static convertModuleIdToViewUrl(moduleId: string): string; } export class NoViewStrategy extends ViewStrategy { - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class TemplateRegistryViewStrategy extends ViewStrategy { constructor(moduleId: string, entry: TemplateRegistryEntry); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class InlineViewStrategy extends ViewStrategy { constructor(markup: string, dependencies?: Array, dependencyBaseUrl?: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BindingLanguage { inspectAttribute(resources: any, attrName: any, attrValue: any): any; createAttributeInstruction(resources: any, element: any, info: any, existingInstruction: any): any; parseText(resources: any, value: any): any; } - export class ResourceRegistry { - constructor(); - registerElement(tagName: any, behavior: any): any; - getElement(tagName: any): any; - registerAttribute(attribute: any, behavior: any, knownAttribute: any): any; - getAttribute(attribute: any): any; - registerValueConverter(name: any, valueConverter: any): any; - getValueConverter(name: any): any; - } - export class ViewResources extends ResourceRegistry { - constructor(parent: any, viewUrl: any); - relativeToView(path: any): any; - getElement(tagName: any): any; - mapAttribute(attribute: any): any; - getAttribute(attribute: any): any; - getValueConverter(name: any): any; + export class ViewResources { + constructor(parent?: ViewResources, viewUrl?: string); + getBindingLanguage(bindingLanguageFallback: any): any; + patchInParent(newParent: ViewResources): void; + relativeToView(path: string): string; + registerElement(tagName: string, behavior: HtmlBehaviorResource): void; + getElement(tagName: string): HtmlBehaviorResource; + mapAttribute(attribute: string): string; + registerAttribute(attribute: string, behavior: HtmlBehaviorResource, knownAttribute: string): void; + getAttribute(attribute: string): HtmlBehaviorResource; + registerValueConverter(name: string, valueConverter: ValueConverter): void; + getValueConverter(name: string): ValueConverter; } // NOTE: Adding a fragment to the document causes the nodes to be removed from the fragment. // NOTE: Adding to the fragment, causes the nodes to be removed from the document. export class View { constructor(container: any, fragment: any, behaviors: any, bindings: any, children: any, systemControlled: any, contentSelectors: any); - created(executionContext: any): any; + created(): any; bind(executionContext: any, systemUpdate: any): any; addBinding(binding: any): any; unbind(): any; @@ -189,17 +221,17 @@ declare module 'aurelia-templating' { contentSelectorRemoveAll(): any; } export class BoundViewFactory { - constructor(parentContainer: any, viewFactory: any, executionContext: any, partReplacements: any); - create(executionContext: any): any; + constructor(parentContainer: Container, viewFactory: ViewFactory, executionContext: Object, partReplacements?: Object); + create(executionContext?: Object): View; } export class ViewFactory { - constructor(template: any, instructions: any, resources: any); - create(container: any, executionContext: any, options?: any, element?: any): any; + constructor(template: DocumentFragment, instructions: Object, resources: ViewResources); + create(container: Container, executionContext?: Object, createInstruction?: ViewCreateInstruction, element?: Element): View; } export class ViewCompiler { static inject(): any; - constructor(bindingLanguage: any); - compile(templateOrFragment: any, resources: any, options?: any): any; + constructor(bindingLanguage: BindingLanguage, resources: ViewResources); + compile(source: HTMLTemplateElement | DocumentFragment | string, resources?: ViewResources, compileInstruction?: ViewCompileInstruction): ViewFactory; compileNode(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; compileSurrogate(node: any, resources: any): any; compileElement(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; @@ -210,12 +242,12 @@ declare module 'aurelia-templating' { } export class ViewEngine { static inject(): any; - constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ResourceRegistry); - enhance(container: any, element: any, resources: any, bindingContext: any): any; - loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileOptions?: Object, associatedModuleId?: string, loadContext?: string[]): Promise; - loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, associatedModuleId?: string, loadContext?: string[]): Promise; + constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ViewResources); + enhance(container: Container, element: Element, resources: ViewResources, bindingContext?: Object): View; + loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; importViewModelResource(moduleImport: string, moduleMember: string): Promise; - importViewResources(moduleIds: string[], names: string[], resources: ResourceRegistry, associatedModuleId?: string, loadContext?: string[]): Promise; + importViewResources(moduleIds: string[], names: string[], resources: ViewResources, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BehaviorInstance { constructor(behavior: any, executionContext: any, instruction: any); @@ -244,26 +276,26 @@ declare module 'aurelia-templating' { } export class HtmlBehaviorResource { constructor(); - static convention(name: string, existing?: HtmlBehaviorResource): any; - addChildBinding(behavior: BindingExpression): any; - analyze(container: Container, target: Function): any; - load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: string[]): Promise; - register(registry: ResourceRegistry, name?: string): any; - compile(compiler: ViewCompiler, resources: ResourceRegistry, node: Node, instruction: Object, parentNode?: Node): Node; - create(container: Container, instruction?: Object, element?: Element, bindings?: Binding[]): BehaviorInstance; + static convention(name: string, existing?: HtmlBehaviorResource): HtmlBehaviorResource; + addChildBinding(behavior: BindingExpression): void; + analyze(container: Container, target: Function): void; + load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: ResourceLoadContext): Promise; + register(registry: ViewResources, name?: string): void; + compile(compiler: ViewCompiler, resources: ViewResources, node: Node, instruction: BehaviorInstruction, parentNode?: Node): Node; + create(container: Container, instruction?: BehaviorInstruction, element?: Element, bindings?: Binding[]): BehaviorInstance; ensurePropertiesDefined(instance: Object, lookup: Object): any; } export class ResourceModule { constructor(moduleId: string); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise; } export class ResourceDescription { constructor(key: string, exportedValue: any, resourceTypeMeta: Object); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise | void; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise | void; static get(resource: any, key?: string): ResourceDescription; } export class ModuleAnalyzer { diff --git a/dist/commonjs/aurelia-templating.js b/dist/commonjs/aurelia-templating.js index 6a7980a1..f83a6968 100644 --- a/dist/commonjs/aurelia-templating.js +++ b/dist/commonjs/aurelia-templating.js @@ -4,11 +4,11 @@ exports.__esModule = true; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); +exports.nextElementSibling = nextElementSibling; exports.createTemplateFromMarkup = createTemplateFromMarkup; exports.replaceNode = replaceNode; exports.removeNode = removeNode; exports.hyphenate = hyphenate; -exports.nextElementSibling = nextElementSibling; exports.behavior = behavior; exports.customElement = customElement; exports.customAttribute = customAttribute; @@ -28,15 +28,17 @@ exports.elementConfig = elementConfig; function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _coreJs = require('core-js'); -var _coreJs2 = _interopRequireDefault(_coreJs); +var core = _interopRequireWildcard(_coreJs); + +var _aureliaLogging = require('aurelia-logging'); + +var LogManager = _interopRequireWildcard(_aureliaLogging); var _aureliaMetadata = require('aurelia-metadata'); @@ -44,26 +46,36 @@ var _aureliaPath = require('aurelia-path'); var _aureliaLoader = require('aurelia-loader'); -var _aureliaDependencyInjection = require('aurelia-dependency-injection'); - var _aureliaBinding = require('aurelia-binding'); -var _aureliaTaskQueue = require('aurelia-task-queue'); - -var _aureliaLogging = require('aurelia-logging'); +var _aureliaDependencyInjection = require('aurelia-dependency-injection'); -var LogManager = _interopRequireWildcard(_aureliaLogging); +var _aureliaTaskQueue = require('aurelia-task-queue'); var needsTemplateFixup = !('content' in document.createElement('template')); var shadowPoly = window.ShadowDOMPolyfill || null; var DOMBoundary = 'aurelia-dom-boundary'; - exports.DOMBoundary = DOMBoundary; +var hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; + +exports.hasShadowDOM = hasShadowDOM; + +function nextElementSibling(element) { + if (element.nextElementSibling) { + return element.nextElementSibling; + } + do { + element = element.nextSibling; + } while (element && element.nodeType !== 1); + return element; +} function createTemplateFromMarkup(markup) { - var temp = document.createElement('template'); - temp.innerHTML = markup; + var parser = document.createElement('div'); + parser.innerHTML = markup; + + var temp = parser.firstChild; if (needsTemplateFixup) { temp.content = document.createDocumentFragment(); @@ -176,22 +188,202 @@ exports.Animator = Animator; var capitalMatcher = /([A-Z])/g; function addHyphenAndLower(char) { - return '-' + char.toLowerCase(); + return "-" + char.toLowerCase(); } function hyphenate(name) { return (name.charAt(0).toLowerCase() + name.slice(1)).replace(capitalMatcher, addHyphenAndLower); } -function nextElementSibling(element) { - if (element.nextElementSibling) { - return element.nextElementSibling; +var ResourceLoadContext = (function () { + function ResourceLoadContext() { + _classCallCheck(this, ResourceLoadContext); + + this.dependencies = {}; } - do { - element = element.nextSibling; - } while (element && element.nodeType !== 1); - return element; -} + + ResourceLoadContext.prototype.addDependency = function addDependency(url) { + this.dependencies[url] = true; + }; + + ResourceLoadContext.prototype.doesNotHaveDependency = function doesNotHaveDependency(url) { + return !(url in this.dependencies); + }; + + return ResourceLoadContext; +})(); + +exports.ResourceLoadContext = ResourceLoadContext; + +var ViewCompileInstruction = (function () { + _createClass(ViewCompileInstruction, null, [{ + key: 'normal', + value: new ViewCompileInstruction(), + enumerable: true + }]); + + function ViewCompileInstruction() { + var targetShadowDOM = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; + var compileSurrogate = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; + var beforeCompile = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; + + _classCallCheck(this, ViewCompileInstruction); + + this.targetShadowDOM = targetShadowDOM; + this.compileSurrogate = compileSurrogate; + this.associatedModuleId = null; + this.beforeCompile = beforeCompile; + } + + return ViewCompileInstruction; +})(); + +exports.ViewCompileInstruction = ViewCompileInstruction; + +var BehaviorInstruction = (function () { + BehaviorInstruction.element = function element(node, type) { + var instruction = new BehaviorInstruction(true); + instruction.type = type; + instruction.attributes = {}; + instruction.anchorIsContainer = !(node.hasAttribute('containerless') || type.containerless); + instruction.initiatedByBehavior = true; + return instruction; + }; + + BehaviorInstruction.attribute = function attribute(attrName, type) { + var instruction = new BehaviorInstruction(true); + instruction.attrName = attrName; + instruction.type = type || null; + instruction.attributes = {}; + return instruction; + }; + + BehaviorInstruction.dynamic = function dynamic(host, executionContext, viewFactory) { + var instruction = new BehaviorInstruction(true); + instruction.host = host; + instruction.executionContext = executionContext; + instruction.viewFactory = viewFactory; + return instruction; + }; + + _createClass(BehaviorInstruction, null, [{ + key: 'normal', + value: new BehaviorInstruction(), + enumerable: true + }, { + key: 'contentSelector', + value: new BehaviorInstruction(true), + enumerable: true + }]); + + function BehaviorInstruction() { + var suppressBind = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; + + _classCallCheck(this, BehaviorInstruction); + + this.suppressBind = suppressBind; + this.initiatedByBehavior = false; + this.systemControlled = false; + this.enhance = false; + this.partReplacements = null; + this.viewFactory = null; + this.originalAttrName = null; + this.skipContentProcessing = false; + this.contentFactory = null; + this.executionContext = null; + this.anchorIsContainer = false; + this.host = null; + this.attributes = null; + this.type = null; + this.attrName = null; + } + + return BehaviorInstruction; +})(); + +exports.BehaviorInstruction = BehaviorInstruction; + +var TargetInstruction = (function () { + TargetInstruction.contentSelector = function contentSelector(node, parentInjectorId) { + var instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.contentSelector = true; + instruction.selector = node.getAttribute('select'); + instruction.suppressBind = true; + return instruction; + }; + + TargetInstruction.contentExpression = function contentExpression(expression) { + var instruction = new TargetInstruction(); + instruction.contentExpression = expression; + return instruction; + }; + + TargetInstruction.lifting = function lifting(parentInjectorId, liftingInstruction) { + var instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.expressions = TargetInstruction.noExpressions; + instruction.behaviorInstructions = [liftingInstruction]; + instruction.viewFactory = liftingInstruction.viewFactory; + instruction.providers = [liftingInstruction.type.target]; + return instruction; + }; + + TargetInstruction.normal = function normal(injectorId, parentInjectorId, providers, behaviorInstructions, expressions, elementInstruction) { + var instruction = new TargetInstruction(); + instruction.injectorId = injectorId; + instruction.parentInjectorId = parentInjectorId; + instruction.providers = providers; + instruction.behaviorInstructions = behaviorInstructions; + instruction.expressions = expressions; + instruction.anchorIsContainer = elementInstruction ? elementInstruction.anchorIsContainer : true; + instruction.elementInstruction = elementInstruction; + return instruction; + }; + + TargetInstruction.surrogate = function surrogate(providers, behaviorInstructions, expressions, values) { + var instruction = new TargetInstruction(); + instruction.expressions = expressions; + instruction.behaviorInstructions = behaviorInstructions; + instruction.providers = providers; + instruction.values = values; + return instruction; + }; + + _createClass(TargetInstruction, null, [{ + key: 'noExpressions', + value: Object.freeze([]), + enumerable: true + }]); + + function TargetInstruction() { + _classCallCheck(this, TargetInstruction); + + this.injectorId = null; + this.parentInjectorId = null; + + this.contentSelector = false; + this.selector = null; + this.suppressBind = false; + + this.contentExpression = null; + + this.expressions = null; + this.behaviorInstructions = null; + this.providers = null; + + this.viewFactory = null; + + this.anchorIsContainer = false; + this.elementInstruction = null; + + this.values = null; + } + + return TargetInstruction; +})(); + +exports.TargetInstruction = TargetInstruction; var ViewStrategy = (function () { function ViewStrategy() { @@ -247,6 +439,8 @@ var ViewStrategy = (function () { exports.ViewStrategy = ViewStrategy; var UseViewStrategy = (function (_ViewStrategy) { + _inherits(UseViewStrategy, _ViewStrategy); + function UseViewStrategy(path) { _classCallCheck(this, UseViewStrategy); @@ -254,14 +448,13 @@ var UseViewStrategy = (function (_ViewStrategy) { this.path = path; } - _inherits(UseViewStrategy, _ViewStrategy); - - UseViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + UseViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { if (!this.absolutePath && this.moduleId) { this.absolutePath = _aureliaPath.relativeToFile(this.path, this.moduleId); } - return viewEngine.loadViewFactory(this.absolutePath || this.path, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.absolutePath || this.path, compileInstruction, loadContext); }; UseViewStrategy.prototype.makeRelativeTo = function makeRelativeTo(file) { @@ -274,6 +467,8 @@ var UseViewStrategy = (function (_ViewStrategy) { exports.UseViewStrategy = UseViewStrategy; var ConventionalViewStrategy = (function (_ViewStrategy2) { + _inherits(ConventionalViewStrategy, _ViewStrategy2); + function ConventionalViewStrategy(moduleId) { _classCallCheck(this, ConventionalViewStrategy); @@ -282,10 +477,9 @@ var ConventionalViewStrategy = (function (_ViewStrategy2) { this.viewUrl = ConventionalViewStrategy.convertModuleIdToViewUrl(moduleId); } - _inherits(ConventionalViewStrategy, _ViewStrategy2); - - ConventionalViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { - return viewEngine.loadViewFactory(this.viewUrl, options, this.moduleId, loadContext); + ConventionalViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.viewUrl, compileInstruction, loadContext); }; ConventionalViewStrategy.convertModuleIdToViewUrl = function convertModuleIdToViewUrl(moduleId) { @@ -299,15 +493,15 @@ var ConventionalViewStrategy = (function (_ViewStrategy2) { exports.ConventionalViewStrategy = ConventionalViewStrategy; var NoViewStrategy = (function (_ViewStrategy3) { + _inherits(NoViewStrategy, _ViewStrategy3); + function NoViewStrategy() { _classCallCheck(this, NoViewStrategy); _ViewStrategy3.apply(this, arguments); } - _inherits(NoViewStrategy, _ViewStrategy3); - - NoViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + NoViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { return Promise.resolve(null); }; @@ -317,6 +511,8 @@ var NoViewStrategy = (function (_ViewStrategy3) { exports.NoViewStrategy = NoViewStrategy; var TemplateRegistryViewStrategy = (function (_ViewStrategy4) { + _inherits(TemplateRegistryViewStrategy, _ViewStrategy4); + function TemplateRegistryViewStrategy(moduleId, entry) { _classCallCheck(this, TemplateRegistryViewStrategy); @@ -325,16 +521,15 @@ var TemplateRegistryViewStrategy = (function (_ViewStrategy4) { this.entry = entry; } - _inherits(TemplateRegistryViewStrategy, _ViewStrategy4); - - TemplateRegistryViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + TemplateRegistryViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { var entry = this.entry; if (entry.isReady) { return Promise.resolve(entry.factory); } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); }; return TemplateRegistryViewStrategy; @@ -343,6 +538,8 @@ var TemplateRegistryViewStrategy = (function (_ViewStrategy4) { exports.TemplateRegistryViewStrategy = TemplateRegistryViewStrategy; var InlineViewStrategy = (function (_ViewStrategy5) { + _inherits(InlineViewStrategy, _ViewStrategy5); + function InlineViewStrategy(markup, dependencies, dependencyBaseUrl) { _classCallCheck(this, InlineViewStrategy); @@ -352,9 +549,7 @@ var InlineViewStrategy = (function (_ViewStrategy5) { this.dependencyBaseUrl = dependencyBaseUrl || ''; } - _inherits(InlineViewStrategy, _ViewStrategy5); - - InlineViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + InlineViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { var entry = this.entry, dependencies = this.dependencies; @@ -377,7 +572,8 @@ var InlineViewStrategy = (function (_ViewStrategy5) { } } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); }; return InlineViewStrategy; @@ -414,7 +610,7 @@ function register(lookup, name, resource, type) { var existing = lookup[name]; if (existing) { - if (existing != resource) { + if (existing !== resource) { throw new Error('Attempted to register ' + type + ' when one with the same name already exists. Name: ' + name + '.'); } @@ -424,81 +620,73 @@ function register(lookup, name, resource, type) { lookup[name] = resource; } -var ResourceRegistry = (function () { - function ResourceRegistry() { - _classCallCheck(this, ResourceRegistry); +var ViewResources = (function () { + function ViewResources(parent, viewUrl) { + _classCallCheck(this, ViewResources); + this.parent = parent || null; + this.hasParent = this.parent !== null; + this.viewUrl = viewUrl || ''; + this.valueConverterLookupFunction = this.getValueConverter.bind(this); this.attributes = {}; this.elements = {}; this.valueConverters = {}; this.attributeMap = {}; this.baseResourceUrl = ''; + this.bindingLanguage = null; } - ResourceRegistry.prototype.registerElement = function registerElement(tagName, behavior) { - register(this.elements, tagName, behavior, 'an Element'); - }; - - ResourceRegistry.prototype.getElement = function getElement(tagName) { - return this.elements[tagName]; - }; - - ResourceRegistry.prototype.registerAttribute = function registerAttribute(attribute, behavior, knownAttribute) { - this.attributeMap[attribute] = knownAttribute; - register(this.attributes, attribute, behavior, 'an Attribute'); + ViewResources.prototype.getBindingLanguage = function getBindingLanguage(bindingLanguageFallback) { + return this.bindingLanguage || (this.bindingLanguage = bindingLanguageFallback); }; - ResourceRegistry.prototype.getAttribute = function getAttribute(attribute) { - return this.attributes[attribute]; - }; + ViewResources.prototype.patchInParent = function patchInParent(newParent) { + var originalParent = this.parent; - ResourceRegistry.prototype.registerValueConverter = function registerValueConverter(name, valueConverter) { - register(this.valueConverters, name, valueConverter, 'a ValueConverter'); - }; + this.parent = newParent || null; + this.hasParent = this.parent !== null; - ResourceRegistry.prototype.getValueConverter = function getValueConverter(name) { - return this.valueConverters[name]; + if (newParent.parent === null) { + newParent.parent = originalParent; + newParent.hasParent = originalParent !== null; + } }; - return ResourceRegistry; -})(); - -exports.ResourceRegistry = ResourceRegistry; - -var ViewResources = (function (_ResourceRegistry) { - function ViewResources(parent, viewUrl) { - _classCallCheck(this, ViewResources); - - _ResourceRegistry.call(this); - this.parent = parent; - this.viewUrl = viewUrl; - this.valueConverterLookupFunction = this.getValueConverter.bind(this); - } - - _inherits(ViewResources, _ResourceRegistry); - ViewResources.prototype.relativeToView = function relativeToView(path) { return _aureliaPath.relativeToFile(path, this.viewUrl); }; + ViewResources.prototype.registerElement = function registerElement(tagName, behavior) { + register(this.elements, tagName, behavior, 'an Element'); + }; + ViewResources.prototype.getElement = function getElement(tagName) { - return this.elements[tagName] || this.parent.getElement(tagName); + return this.elements[tagName] || (this.hasParent ? this.parent.getElement(tagName) : null); }; ViewResources.prototype.mapAttribute = function mapAttribute(attribute) { - return this.attributeMap[attribute] || this.parent.attributeMap[attribute]; + return this.attributeMap[attribute] || (this.hasParent ? this.parent.mapAttribute(attribute) : null); + }; + + ViewResources.prototype.registerAttribute = function registerAttribute(attribute, behavior, knownAttribute) { + this.attributeMap[attribute] = knownAttribute; + register(this.attributes, attribute, behavior, 'an Attribute'); }; ViewResources.prototype.getAttribute = function getAttribute(attribute) { - return this.attributes[attribute] || this.parent.getAttribute(attribute); + return this.attributes[attribute] || (this.hasParent ? this.parent.getAttribute(attribute) : null); + }; + + ViewResources.prototype.registerValueConverter = function registerValueConverter(name, valueConverter) { + register(this.valueConverters, name, valueConverter, 'a ValueConverter'); }; ViewResources.prototype.getValueConverter = function getValueConverter(name) { - return this.valueConverters[name] || this.parent.getValueConverter(name); + return this.valueConverters[name] || (this.hasParent ? this.parent.getValueConverter(name) : null); }; return ViewResources; -})(ResourceRegistry); +})(); exports.ViewResources = ViewResources; @@ -519,12 +707,12 @@ var View = (function () { this.isAttached = false; } - View.prototype.created = function created(executionContext) { + View.prototype.created = function created() { var i, ii, behaviors = this.behaviors; for (i = 0, ii = behaviors.length; i < ii; ++i) { - behaviors[i].created(executionContext); + behaviors[i].created(this); } }; @@ -703,15 +891,6 @@ function findInsertionPoint(groups, index) { } var ContentSelector = (function () { - function ContentSelector(anchor, selector) { - _classCallCheck(this, ContentSelector); - - this.anchor = anchor; - this.selector = selector; - this.all = !this.selector; - this.groups = []; - } - ContentSelector.applySelectors = function applySelectors(view, contentSelectors, callback) { var currentChild = view.fragment.firstChild, contentMap = new Map(), @@ -753,6 +932,15 @@ var ContentSelector = (function () { } }; + function ContentSelector(anchor, selector) { + _classCallCheck(this, ContentSelector); + + this.anchor = anchor; + this.selector = selector; + this.all = !this.selector; + this.groups = []; + } + ContentSelector.prototype.copyForViewSlot = function copyForViewSlot() { return new ContentSelector(this.anchor, this.selector); }; @@ -822,7 +1010,7 @@ function getAnimatableElement(view) { var ViewSlot = (function () { function ViewSlot(anchor, anchorIsContainer, executionContext) { - var animator = arguments[3] === undefined ? Animator.instance : arguments[3]; + var animator = arguments.length <= 3 || arguments[3] === undefined ? Animator.instance : arguments[3]; _classCallCheck(this, ViewSlot); @@ -1177,6 +1365,10 @@ function elementContainerGet(key) { return this.viewResources; } + if (key === TargetInstruction) { + return this.instruction; + } + return this.superGet(key); } @@ -1205,10 +1397,10 @@ function createElementContainer(parent, element, instruction, executionContext, return container; } -function makeElementIntoAnchor(element, isCustomElement) { +function makeElementIntoAnchor(element, elementInstruction) { var anchor = document.createComment('anchor'); - if (isCustomElement) { + if (elementInstruction) { anchor.hasAttribute = function (name) { return element.hasAttribute(name); }; @@ -1249,7 +1441,7 @@ function applyInstructions(containers, executionContext, element, instruction, b if (behaviorInstructions.length) { if (!instruction.anchorIsContainer) { - element = makeElementIntoAnchor(element, instruction.isCustomElement); + element = makeElementIntoAnchor(element, instruction.elementInstruction); } containers[instruction.injectorId] = elementContainer = createElementContainer(containers[instruction.parentInjectorId], element, instruction, executionContext, children, partReplacements, resources); @@ -1283,7 +1475,7 @@ function styleStringToObject(style, target) { for (i = 0; i < attributes.length; i++) { current = attributes[i]; - firstIndexOfColon = current.indexOf(':'); + firstIndexOfColon = current.indexOf(":"); key = current.substring(0, firstIndexOfColon).trim(); value = current.substring(firstIndexOfColon + 1).trim(); target[key] = value; @@ -1333,8 +1525,8 @@ function applySurrogateInstruction(container, element, instruction, behaviors, b element.setAttribute('style', styleObjectToString(styleObject)); } } else { - element.setAttribute(key, values[key]); - } + element.setAttribute(key, values[key]); + } } if (behaviorInstructions.length) { @@ -1362,16 +1554,16 @@ var BoundViewFactory = (function () { this.parentContainer = parentContainer; this.viewFactory = viewFactory; this.executionContext = executionContext; - this.factoryOptions = { behaviorInstance: false, partReplacements: partReplacements }; + this.factoryCreateInstruction = { partReplacements: partReplacements }; } BoundViewFactory.prototype.create = function create(executionContext) { var childContainer = this.parentContainer.createChild(), context = executionContext || this.executionContext; - this.factoryOptions.systemControlled = !executionContext; + this.factoryCreateInstruction.systemControlled = !executionContext; - return this.viewFactory.create(childContainer, context, this.factoryOptions); + return this.viewFactory.create(childContainer, context, this.factoryCreateInstruction); }; return BoundViewFactory; @@ -1379,12 +1571,6 @@ var BoundViewFactory = (function () { exports.BoundViewFactory = BoundViewFactory; -var defaultFactoryOptions = { - systemControlled: false, - suppressBind: false, - enhance: false -}; - var ViewFactory = (function () { function ViewFactory(template, instructions, resources) { _classCallCheck(this, ViewFactory); @@ -1394,11 +1580,11 @@ var ViewFactory = (function () { this.resources = resources; } - ViewFactory.prototype.create = function create(container, executionContext) { - var options = arguments[2] === undefined ? defaultFactoryOptions : arguments[2]; - var element = arguments[3] === undefined ? null : arguments[3]; + ViewFactory.prototype.create = function create(container, executionContext, createInstruction, element) { + createInstruction = createInstruction || BehaviorInstruction.normal; + element = element || null; - var fragment = options.enhance ? this.template : this.template.cloneNode(true), + var fragment = createInstruction.enhance ? this.template : this.template.cloneNode(true), instructables = fragment.querySelectorAll('.au-target'), instructions = this.instructions, resources = this.resources, @@ -1407,12 +1593,12 @@ var ViewFactory = (function () { children = [], contentSelectors = [], containers = { root: container }, - partReplacements = options.partReplacements, - i, - ii, - view, - instructable, - instruction; + partReplacements = createInstruction.partReplacements, + i = undefined, + ii = undefined, + view = undefined, + instructable = undefined, + instruction = undefined; if (element !== null && this.surrogateInstruction !== null) { applySurrogateInstruction(container, element, this.surrogateInstruction, behaviors, bindings, children); @@ -1425,10 +1611,13 @@ var ViewFactory = (function () { applyInstructions(containers, executionContext, instructable, instruction, behaviors, bindings, children, contentSelectors, partReplacements, resources); } - view = new View(container, fragment, behaviors, bindings, children, options.systemControlled, contentSelectors); - view.created(executionContext); + view = new View(container, fragment, behaviors, bindings, children, createInstruction.systemControlled, contentSelectors); - if (!options.suppressBind) { + if (!createInstruction.initiatedByBehavior) { + view.created(); + } + + if (!createInstruction.suppressBind) { view.bind(executionContext); } @@ -1440,10 +1629,7 @@ var ViewFactory = (function () { exports.ViewFactory = ViewFactory; -var nextInjectorId = 0, - defaultCompileOptions = { targetShadowDOM: false }, - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; - +var nextInjectorId = 0; function getNextInjectorId() { return ++nextInjectorId; } @@ -1493,49 +1679,51 @@ function makeIntoInstructionTarget(element) { } var ViewCompiler = (function () { - function ViewCompiler(bindingLanguage) { + ViewCompiler.inject = function inject() { + return [BindingLanguage, ViewResources]; + }; + + function ViewCompiler(bindingLanguage, resources) { _classCallCheck(this, ViewCompiler); this.bindingLanguage = bindingLanguage; + this.resources = resources; } - ViewCompiler.inject = function inject() { - return [BindingLanguage]; - }; - - ViewCompiler.prototype.compile = function compile(templateOrFragment, resources) { - var options = arguments[2] === undefined ? defaultCompileOptions : arguments[2]; + ViewCompiler.prototype.compile = function compile(source, resources, compileInstruction) { + resources = resources || this.resources; + compileInstruction = compileInstruction || ViewCompileInstruction.normal; var instructions = {}, - targetShadowDOM = options.targetShadowDOM, - content, - part, - factory; + targetShadowDOM = compileInstruction.targetShadowDOM, + content = undefined, + part = undefined; targetShadowDOM = targetShadowDOM && hasShadowDOM; - if (options.beforeCompile) { - options.beforeCompile(templateOrFragment); + if (compileInstruction.beforeCompile) { + compileInstruction.beforeCompile(source); + console.warn('In a future release, the beforeCompile hook will be replaced by an alternate mechanism'); } - if (typeof templateOrFragment === 'string') { - templateOrFragment = createTemplateFromMarkup(templateOrFragment); + if (typeof source === 'string') { + source = createTemplateFromMarkup(source); } - if (templateOrFragment.content) { - part = templateOrFragment.getAttribute('part'); - content = document.adoptNode(templateOrFragment.content, true); + if (source.content) { + part = source.getAttribute('part'); + content = document.adoptNode(source.content, true); } else { - content = templateOrFragment; + content = source; } - this.compileNode(content, resources, instructions, templateOrFragment, 'root', !targetShadowDOM); + this.compileNode(content, resources, instructions, source, 'root', !targetShadowDOM); content.insertBefore(document.createComment(''), content.firstChild); content.appendChild(document.createComment('')); var factory = new ViewFactory(content, instructions, resources); - factory.surrogateInstruction = options.compileSurrogate ? this.compileSurrogate(templateOrFragment, resources) : null; + factory.surrogateInstruction = compileInstruction.compileSurrogate ? this.compileSurrogate(source, resources) : null; if (part) { factory.part = part; @@ -1549,13 +1737,13 @@ var ViewCompiler = (function () { case 1: return this.compileElement(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM); case 3: - var expression = this.bindingLanguage.parseText(resources, node.wholeText); + var expression = resources.getBindingLanguage(this.bindingLanguage).parseText(resources, node.wholeText); if (expression) { var marker = document.createElement('au-marker'), auTargetID = makeIntoInstructionTarget(marker); (node.parentNode || parentNode).insertBefore(marker, node); node.textContent = ' '; - instructions[auTargetID] = { contentExpression: expression }; + instructions[auTargetID] = TargetInstruction.contentExpression(expression); while (node.nextSibling && node.nextSibling.nodeType === 3) { (node.parentNode || parentNode).removeChild(node.nextSibling); @@ -1579,7 +1767,7 @@ var ViewCompiler = (function () { ViewCompiler.prototype.compileSurrogate = function compileSurrogate(node, resources) { var attributes = node.attributes, - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), knownAttribute = undefined, property = undefined, instruction = undefined, @@ -1645,7 +1833,7 @@ var ViewCompiler = (function () { } } else { if (type) { - instruction = { attrName: attrName, type: type, attributes: {} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if (type.liftsContent) { @@ -1674,16 +1862,7 @@ var ViewCompiler = (function () { } } - return { - anchorIsContainer: false, - isCustomElement: false, - injectorId: null, - parentInjectorId: null, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers, - values: values - }; + return TargetInstruction.surrogate(providers, behaviorInstructions, expressions, values); } return null; @@ -1696,7 +1875,7 @@ var ViewCompiler = (function () { expression, behaviorInstructions = [], providers = [], - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), liftingInstruction, viewFactory, type, @@ -1717,12 +1896,7 @@ var ViewCompiler = (function () { if (tagName === 'content') { if (targetLightDOM) { auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - parentInjectorId: parentInjectorId, - contentSelector: true, - selector: node.getAttribute('select'), - suppressBind: true - }; + instructions[auTargetID] = TargetInstruction.contentSelector(node, parentInjectorId); } return node.nextSibling; } else if (tagName === 'template') { @@ -1731,8 +1905,7 @@ var ViewCompiler = (function () { } else { type = resources.getElement(tagName); if (type) { - elementInstruction = { type: type, attributes: {} }; - elementInstruction.anchorIsContainer = !node.hasAttribute('containerless') && !type.containerless; + elementInstruction = BehaviorInstruction.element(node, type); behaviorInstructions.push(elementInstruction); } } @@ -1759,15 +1932,11 @@ var ViewCompiler = (function () { } } } else if (elementInstruction) { - elementProperty = elementInstruction.type.attributes[info.attrName]; - if (elementProperty) { - info.defaultBindingMode = elementProperty.defaultBindingMode; - - if (!info.command && !info.expression) { - info.command = elementProperty.hasOptions ? 'options' : null; + elementProperty = elementInstruction.type.attributes[info.attrName]; + if (elementProperty) { + info.defaultBindingMode = elementProperty.defaultBindingMode; } } - } if (elementProperty) { instruction = bindingLanguage.createAttributeInstruction(resources, node, info, elementInstruction); @@ -1802,7 +1971,7 @@ var ViewCompiler = (function () { } } else { if (type) { - instruction = { attrName: attrName, type: type, attributes: {} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if (type.liftsContent) { @@ -1822,14 +1991,7 @@ var ViewCompiler = (function () { liftingInstruction.viewFactory = viewFactory; node = liftingInstruction.type.compile(this, resources, node, liftingInstruction, parentNode); auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: false, - parentInjectorId: parentInjectorId, - expressions: [], - behaviorInstructions: [liftingInstruction], - viewFactory: liftingInstruction.viewFactory, - providers: [liftingInstruction.type.target] - }; + instructions[auTargetID] = TargetInstruction.lifting(parentInjectorId, liftingInstruction); } else { if (expressions.length || behaviorInstructions.length) { injectorId = behaviorInstructions.length ? getNextInjectorId() : false; @@ -1848,15 +2010,7 @@ var ViewCompiler = (function () { } auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: elementInstruction ? elementInstruction.anchorIsContainer : true, - isCustomElement: !!elementInstruction, - injectorId: injectorId, - parentInjectorId: parentInjectorId, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers - }; + instructions[auTargetID] = TargetInstruction.normal(injectorId, parentInjectorId, providers, behaviorInstructions, expressions, elementInstruction); } if (elementInstruction && elementInstruction.skipContentProcessing) { @@ -1906,6 +2060,10 @@ var ProxyViewFactory = (function () { })(); var ViewEngine = (function () { + ViewEngine.inject = function inject() { + return [_aureliaLoader.Loader, _aureliaDependencyInjection.Container, ViewCompiler, ModuleAnalyzer, ViewResources]; + }; + function ViewEngine(loader, container, viewCompiler, moduleAnalyzer, appResources) { _classCallCheck(this, ViewEngine); @@ -1916,58 +2074,49 @@ var ViewEngine = (function () { this.appResources = appResources; } - ViewEngine.inject = function inject() { - return [_aureliaLoader.Loader, _aureliaDependencyInjection.Container, ViewCompiler, ModuleAnalyzer, ResourceRegistry]; - }; - ViewEngine.prototype.enhance = function enhance(container, element, resources, bindingContext) { var instructions = {}; - this.viewCompiler.compileNode(element, resources, instructions, element.parentNode, 'root', true); var factory = new ViewFactory(element, instructions, resources); - var options = { - systemControlled: false, - suppressBind: false, - enhance: true - }; - - return factory.create(container, bindingContext, options); + return factory.create(container, bindingContext, { enhance: true }); }; - ViewEngine.prototype.loadViewFactory = function loadViewFactory(urlOrRegistryEntry, compileOptions, associatedModuleId, loadContext) { + ViewEngine.prototype.loadViewFactory = function loadViewFactory(urlOrRegistryEntry, compileInstruction, loadContext) { var _this5 = this; - loadContext = loadContext || []; + loadContext = loadContext || new ResourceLoadContext(); return ensureRegistryEntry(this.loader, urlOrRegistryEntry).then(function (viewRegistryEntry) { if (viewRegistryEntry.onReady) { - if (loadContext.indexOf(urlOrRegistryEntry) === -1) { - loadContext.push(urlOrRegistryEntry); + if (loadContext.doesNotHaveDependency(urlOrRegistryEntry)) { + loadContext.addDependency(urlOrRegistryEntry); return viewRegistryEntry.onReady; } return Promise.resolve(new ProxyViewFactory(viewRegistryEntry.onReady)); } - loadContext.push(urlOrRegistryEntry); + loadContext.addDependency(urlOrRegistryEntry); - return viewRegistryEntry.onReady = _this5.loadTemplateResources(viewRegistryEntry, associatedModuleId, loadContext).then(function (resources) { + return viewRegistryEntry.onReady = _this5.loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext).then(function (resources) { viewRegistryEntry.setResources(resources); - var viewFactory = _this5.viewCompiler.compile(viewRegistryEntry.template, resources, compileOptions); + var viewFactory = _this5.viewCompiler.compile(viewRegistryEntry.template, resources, compileInstruction); viewRegistryEntry.setFactory(viewFactory); return viewFactory; }); }); }; - ViewEngine.prototype.loadTemplateResources = function loadTemplateResources(viewRegistryEntry, associatedModuleId, loadContext) { + ViewEngine.prototype.loadTemplateResources = function loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext) { var resources = new ViewResources(this.appResources, viewRegistryEntry.id), dependencies = viewRegistryEntry.dependencies, importIds, names; - if (dependencies.length === 0 && !associatedModuleId) { + compileInstruction = compileInstruction || ViewCompileInstruction.normal; + + if (dependencies.length === 0 && !compileInstruction.associatedModuleId) { return Promise.resolve(resources); } @@ -1979,7 +2128,7 @@ var ViewEngine = (function () { }); logger.debug('importing resources for ' + viewRegistryEntry.id, importIds); - return this.importViewResources(importIds, names, resources, associatedModuleId, loadContext); + return this.importViewResources(importIds, names, resources, compileInstruction, loadContext); }; ViewEngine.prototype.importViewModelResource = function importViewModelResource(moduleImport, moduleMember) { @@ -1999,10 +2148,11 @@ var ViewEngine = (function () { }); }; - ViewEngine.prototype.importViewResources = function importViewResources(moduleIds, names, resources, associatedModuleId, loadContext) { + ViewEngine.prototype.importViewResources = function importViewResources(moduleIds, names, resources, compileInstruction, loadContext) { var _this7 = this; - loadContext = loadContext || []; + loadContext = loadContext || new ResourceLoadContext(); + compileInstruction = compileInstruction || ViewCompileInstruction.normal; return this.loader.loadAllModules(moduleIds).then(function (imports) { var i, @@ -2026,8 +2176,8 @@ var ViewEngine = (function () { allAnalysis[i] = analysis; } - if (associatedModuleId) { - associatedModule = moduleAnalyzer.getAnalysis(associatedModuleId); + if (compileInstruction.associatedModuleId) { + associatedModule = moduleAnalyzer.getAnalysis(compileInstruction.associatedModuleId); if (associatedModule) { associatedModule.register(resources); @@ -2456,9 +2606,7 @@ var BehaviorPropertyObserver = (function () { return BehaviorPropertyObserver; })(); -var defaultInstruction = { suppressBind: false }, - contentSelectorFactoryOptions = { suppressBind: true, enhance: false }, - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; +var contentSelectorViewCreateInstruction = { suppressBind: true, enhance: false }; function doProcessContent() { return true; @@ -2574,11 +2722,7 @@ var HtmlBehaviorResource = (function () { if (this.elementName !== null) { viewStrategy = viewStrategy || this.viewStrategy || ViewStrategy.getDefault(target); - options = { - targetShadowDOM: this.targetShadowDOM, - beforeCompile: target.beforeCompile, - compileSurrogate: true - }; + options = new ViewCompileInstruction(this.targetShadowDOM, true, target.beforeCompile); if (!viewStrategy.moduleId) { viewStrategy.moduleId = _aureliaMetadata.Origin.get(target).moduleId; @@ -2672,17 +2816,16 @@ var HtmlBehaviorResource = (function () { } } - instruction.suppressBind = true; return node; }; - HtmlBehaviorResource.prototype.create = function create(container) { - var instruction = arguments[1] === undefined ? defaultInstruction : arguments[1]; - var element = arguments[2] === undefined ? null : arguments[2]; - var bindings = arguments[3] === undefined ? null : arguments[3]; - + HtmlBehaviorResource.prototype.create = function create(container, instruction, element, bindings) { var host = undefined; + instruction = instruction || BehaviorInstruction.normal; + element = element || null; + bindings = bindings || null; + if (this.elementName !== null && element) { if (this.usesShadowDOM) { host = element.createShadowRoot(); @@ -2717,7 +2860,7 @@ var HtmlBehaviorResource = (function () { if (behaviorInstance.view) { if (!this.usesShadowDOM) { if (instruction.contentFactory) { - var contentView = instruction.contentFactory.create(container, null, contentSelectorFactoryOptions); + var contentView = instruction.contentFactory.create(container, null, contentSelectorViewCreateInstruction); ContentSelector.applySelectors(contentView, behaviorInstance.view.contentSelectors, function (contentSelector, group) { return contentSelector.add(group); @@ -2772,6 +2915,10 @@ var HtmlBehaviorResource = (function () { } } + if (instruction.initiatedByBehavior && viewFactory) { + behaviorInstance.view.created(); + } + return behaviorInstance; }; @@ -2933,7 +3080,7 @@ var ResourceDescription = (function () { }; ResourceDescription.get = function get(resource) { - var key = arguments[1] === undefined ? 'custom-resource' : arguments[1]; + var key = arguments.length <= 1 || arguments[1] === undefined ? 'custom-resource' : arguments[1]; var resourceTypeMeta = _aureliaMetadata.Metadata.get(_aureliaMetadata.Metadata.resource, resource), resourceDescription; @@ -3188,16 +3335,16 @@ var ChildObserverBinder = (function () { exports.ChildObserverBinder = ChildObserverBinder; var CompositionEngine = (function () { + CompositionEngine.inject = function inject() { + return [ViewEngine]; + }; + function CompositionEngine(viewEngine) { _classCallCheck(this, CompositionEngine); this.viewEngine = viewEngine; } - CompositionEngine.inject = function inject() { - return [ViewEngine]; - }; - CompositionEngine.prototype.activate = function activate(instruction) { if (instruction.skipActivation || typeof instruction.viewModel.activate !== 'function') { return Promise.resolve(); @@ -3257,12 +3404,7 @@ var CompositionEngine = (function () { } return doneLoading.then(function (viewFactory) { - return metadata.create(childContainer, { - executionContext: viewModel, - viewFactory: viewFactory, - suppressBind: true, - host: instruction.host - }); + return metadata.create(childContainer, BehaviorInstruction.dynamic(instruction.host, viewModel, viewFactory)); }); }); }; diff --git a/dist/es6/aurelia-templating.d.ts b/dist/es6/aurelia-templating.d.ts index 802af35f..cd67272f 100644 --- a/dist/es6/aurelia-templating.d.ts +++ b/dist/es6/aurelia-templating.d.ts @@ -1,16 +1,27 @@ declare module 'aurelia-templating' { - import core from 'core-js'; + import * as core from 'core-js'; + import * as LogManager from 'aurelia-logging'; import { Metadata, Origin, Decorators } from 'aurelia-metadata'; import { relativeToFile } from 'aurelia-path'; import { TemplateRegistryEntry, Loader } from 'aurelia-loader'; + import { ValueConverter, bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { Container } from 'aurelia-dependency-injection'; - import { bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { TaskQueue } from 'aurelia-task-queue'; - import * as LogManager from 'aurelia-logging'; + + // this will be replaced soon + export interface ViewCreateInstruction { + suppressBind?: boolean; + systemControlled?: boolean; + enhance?: boolean; + partReplacements?: Object; + initiatedByBehavior?: boolean; + } export let DOMBoundary: any; - export function createTemplateFromMarkup(markup: any): any; - export function replaceNode(newNode: any, node: any, parentNode: any): any; - export function removeNode(node: any, parentNode: any): any; + export let hasShadowDOM: any; + export function nextElementSibling(element: Node): Element; + export function createTemplateFromMarkup(markup: string): HTMLTemplateElement; + export function replaceNode(newNode: Node, node: Node, parentNode: Node): void; + export function removeNode(node: Node, parentNode: Node): void; export const animationEvent: any; export class Animator { static configureDefault(container: any, animatorInstance: any): any; @@ -94,62 +105,83 @@ declare module 'aurelia-templating' { unregisterEffect(effectName: any): any; } export function hyphenate(name: any): any; - export function nextElementSibling(element: any): any; + export class ResourceLoadContext { + constructor(); + addDependency(url: string): void; + doesNotHaveDependency(url: string): boolean; + } + export class ViewCompileInstruction { + static normal: any; + constructor(targetShadowDOM?: boolean, compileSurrogate?: boolean, beforeCompile?: boolean); + } + export class BehaviorInstruction { + static normal: any; + static contentSelector: any; + static element(node: Node, type: HtmlBehaviorResource): BehaviorInstruction; + static attribute(attrName: string, type?: HtmlBehaviorResource): BehaviorInstruction; + static dynamic(host: any, executionContext: any, viewFactory: any): any; + constructor(suppressBind?: boolean); + } + export class TargetInstruction { + static noExpressions: any; + static contentSelector(node: Node, parentInjectorId: number): TargetInstruction; + static contentExpression(expression: any): TargetInstruction; + static lifting(parentInjectorId: number, liftingInstruction: BehaviorInstruction): TargetInstruction; + static normal(injectorId: any, parentInjectorId: any, providers: any, behaviorInstructions: any, expressions: any, elementInstruction: any): TargetInstruction; + static surrogate(providers: any, behaviorInstructions: any, expressions: any, values: any): TargetInstruction; + constructor(); + } export class ViewStrategy { static metadataKey: string; - makeRelativeTo(baseUrl: string): any; - static normalize(value: string | ViewStrategy): any; + makeRelativeTo(baseUrl: string): void; + static normalize(value: string | ViewStrategy): ViewStrategy; static getDefault(target: any): ViewStrategy; } export class UseViewStrategy extends ViewStrategy { constructor(path: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; - makeRelativeTo(file: string): any; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + makeRelativeTo(file: string): void; } export class ConventionalViewStrategy extends ViewStrategy { constructor(moduleId: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; static convertModuleIdToViewUrl(moduleId: string): string; } export class NoViewStrategy extends ViewStrategy { - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class TemplateRegistryViewStrategy extends ViewStrategy { constructor(moduleId: string, entry: TemplateRegistryEntry); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class InlineViewStrategy extends ViewStrategy { constructor(markup: string, dependencies?: Array, dependencyBaseUrl?: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BindingLanguage { inspectAttribute(resources: any, attrName: any, attrValue: any): any; createAttributeInstruction(resources: any, element: any, info: any, existingInstruction: any): any; parseText(resources: any, value: any): any; } - export class ResourceRegistry { - constructor(); - registerElement(tagName: any, behavior: any): any; - getElement(tagName: any): any; - registerAttribute(attribute: any, behavior: any, knownAttribute: any): any; - getAttribute(attribute: any): any; - registerValueConverter(name: any, valueConverter: any): any; - getValueConverter(name: any): any; - } - export class ViewResources extends ResourceRegistry { - constructor(parent: any, viewUrl: any); - relativeToView(path: any): any; - getElement(tagName: any): any; - mapAttribute(attribute: any): any; - getAttribute(attribute: any): any; - getValueConverter(name: any): any; + export class ViewResources { + constructor(parent?: ViewResources, viewUrl?: string); + getBindingLanguage(bindingLanguageFallback: any): any; + patchInParent(newParent: ViewResources): void; + relativeToView(path: string): string; + registerElement(tagName: string, behavior: HtmlBehaviorResource): void; + getElement(tagName: string): HtmlBehaviorResource; + mapAttribute(attribute: string): string; + registerAttribute(attribute: string, behavior: HtmlBehaviorResource, knownAttribute: string): void; + getAttribute(attribute: string): HtmlBehaviorResource; + registerValueConverter(name: string, valueConverter: ValueConverter): void; + getValueConverter(name: string): ValueConverter; } // NOTE: Adding a fragment to the document causes the nodes to be removed from the fragment. // NOTE: Adding to the fragment, causes the nodes to be removed from the document. export class View { constructor(container: any, fragment: any, behaviors: any, bindings: any, children: any, systemControlled: any, contentSelectors: any); - created(executionContext: any): any; + created(): any; bind(executionContext: any, systemUpdate: any): any; addBinding(binding: any): any; unbind(): any; @@ -189,17 +221,17 @@ declare module 'aurelia-templating' { contentSelectorRemoveAll(): any; } export class BoundViewFactory { - constructor(parentContainer: any, viewFactory: any, executionContext: any, partReplacements: any); - create(executionContext: any): any; + constructor(parentContainer: Container, viewFactory: ViewFactory, executionContext: Object, partReplacements?: Object); + create(executionContext?: Object): View; } export class ViewFactory { - constructor(template: any, instructions: any, resources: any); - create(container: any, executionContext: any, options?: any, element?: any): any; + constructor(template: DocumentFragment, instructions: Object, resources: ViewResources); + create(container: Container, executionContext?: Object, createInstruction?: ViewCreateInstruction, element?: Element): View; } export class ViewCompiler { static inject(): any; - constructor(bindingLanguage: any); - compile(templateOrFragment: any, resources: any, options?: any): any; + constructor(bindingLanguage: BindingLanguage, resources: ViewResources); + compile(source: HTMLTemplateElement | DocumentFragment | string, resources?: ViewResources, compileInstruction?: ViewCompileInstruction): ViewFactory; compileNode(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; compileSurrogate(node: any, resources: any): any; compileElement(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; @@ -210,12 +242,12 @@ declare module 'aurelia-templating' { } export class ViewEngine { static inject(): any; - constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ResourceRegistry); - enhance(container: any, element: any, resources: any, bindingContext: any): any; - loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileOptions?: Object, associatedModuleId?: string, loadContext?: string[]): Promise; - loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, associatedModuleId?: string, loadContext?: string[]): Promise; + constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ViewResources); + enhance(container: Container, element: Element, resources: ViewResources, bindingContext?: Object): View; + loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; importViewModelResource(moduleImport: string, moduleMember: string): Promise; - importViewResources(moduleIds: string[], names: string[], resources: ResourceRegistry, associatedModuleId?: string, loadContext?: string[]): Promise; + importViewResources(moduleIds: string[], names: string[], resources: ViewResources, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BehaviorInstance { constructor(behavior: any, executionContext: any, instruction: any); @@ -244,26 +276,26 @@ declare module 'aurelia-templating' { } export class HtmlBehaviorResource { constructor(); - static convention(name: string, existing?: HtmlBehaviorResource): any; - addChildBinding(behavior: BindingExpression): any; - analyze(container: Container, target: Function): any; - load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: string[]): Promise; - register(registry: ResourceRegistry, name?: string): any; - compile(compiler: ViewCompiler, resources: ResourceRegistry, node: Node, instruction: Object, parentNode?: Node): Node; - create(container: Container, instruction?: Object, element?: Element, bindings?: Binding[]): BehaviorInstance; + static convention(name: string, existing?: HtmlBehaviorResource): HtmlBehaviorResource; + addChildBinding(behavior: BindingExpression): void; + analyze(container: Container, target: Function): void; + load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: ResourceLoadContext): Promise; + register(registry: ViewResources, name?: string): void; + compile(compiler: ViewCompiler, resources: ViewResources, node: Node, instruction: BehaviorInstruction, parentNode?: Node): Node; + create(container: Container, instruction?: BehaviorInstruction, element?: Element, bindings?: Binding[]): BehaviorInstance; ensurePropertiesDefined(instance: Object, lookup: Object): any; } export class ResourceModule { constructor(moduleId: string); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise; } export class ResourceDescription { constructor(key: string, exportedValue: any, resourceTypeMeta: Object); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise | void; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise | void; static get(resource: any, key?: string): ResourceDescription; } export class ModuleAnalyzer { diff --git a/dist/es6/aurelia-templating.js b/dist/es6/aurelia-templating.js index 8cbdff0e..2a023862 100644 --- a/dist/es6/aurelia-templating.js +++ b/dist/es6/aurelia-templating.js @@ -1,19 +1,30 @@ -import core from 'core-js'; +import * as core from 'core-js'; +import * as LogManager from 'aurelia-logging'; import {Metadata,Origin,Decorators} from 'aurelia-metadata'; import {relativeToFile} from 'aurelia-path'; import {TemplateRegistryEntry,Loader} from 'aurelia-loader'; +import {ValueConverter,bindingMode,ObserverLocator,BindingExpression,Binding,ValueConverterResource,EventManager} from 'aurelia-binding'; import {Container} from 'aurelia-dependency-injection'; -import {bindingMode,ObserverLocator,BindingExpression,Binding,ValueConverterResource,EventManager} from 'aurelia-binding'; import {TaskQueue} from 'aurelia-task-queue'; let needsTemplateFixup = !('content' in document.createElement('template')); let shadowPoly = window.ShadowDOMPolyfill || null; export let DOMBoundary = 'aurelia-dom-boundary'; +export let hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; + +export function nextElementSibling(element:Node):Element { + if (element.nextElementSibling){ return element.nextElementSibling; } + do { element = element.nextSibling } + while (element && element.nodeType !== 1); + return element; +} -export function createTemplateFromMarkup(markup){ - let temp = document.createElement('template'); - temp.innerHTML = markup; +export function createTemplateFromMarkup(markup:string):HTMLTemplateElement{ + let parser = document.createElement('div'); + parser.innerHTML = markup; + + let temp = parser.firstChild; if(needsTemplateFixup){ temp.content = document.createDocumentFragment(); @@ -25,7 +36,7 @@ export function createTemplateFromMarkup(markup){ return temp; } -export function replaceNode(newNode, node, parentNode){ +export function replaceNode(newNode:Node, node:Node, parentNode:Node):void{ if(node.parentNode){ node.parentNode.replaceChild(newNode, node); }else if(shadowPoly){ //HACK: IE template element and shadow dom polyfills not quite right... @@ -38,7 +49,7 @@ export function replaceNode(newNode, node, parentNode){ } } -export function removeNode(node, parentNode) { +export function removeNode(node:Node, parentNode:Node):void { if(node.parentNode){ node.parentNode.removeChild(node); }else if(shadowPoly){ //HACK: IE template element and shadow dom polyfills not quite right... @@ -189,19 +200,165 @@ export function hyphenate(name){ return (name.charAt(0).toLowerCase() + name.slice(1)).replace(capitalMatcher, addHyphenAndLower); } -export function nextElementSibling(element) { - if (element.nextElementSibling){ return element.nextElementSibling; } - do { element = element.nextSibling } - while (element && element.nodeType !== 1); - return element; +export class ResourceLoadContext { + constructor(){ + this.dependencies = {}; + } + + addDependency(url:string):void{ + this.dependencies[url] = true; + } + + doesNotHaveDependency(url:string):boolean{ + return !(url in this.dependencies); + } +} + +export class ViewCompileInstruction { + static normal = new ViewCompileInstruction(); + + constructor(targetShadowDOM?:boolean=false, compileSurrogate?:boolean=false, beforeCompile?:boolean=null){ + this.targetShadowDOM = targetShadowDOM; + this.compileSurrogate = compileSurrogate; + this.associatedModuleId = null; + this.beforeCompile = beforeCompile; //this will be replaced soon + } +} + +interface ViewCreateInstruction { + suppressBind?:boolean; + systemControlled?:boolean; + enhance?:boolean; + partReplacements?:Object; + initiatedByBehavior?:boolean; +} + +export class BehaviorInstruction { + static normal = new BehaviorInstruction(); + static contentSelector = new BehaviorInstruction(true); + + static element(node:Node, type:HtmlBehaviorResource):BehaviorInstruction{ + let instruction = new BehaviorInstruction(true); + instruction.type = type; + instruction.attributes = {}; + instruction.anchorIsContainer = !(node.hasAttribute('containerless') || type.containerless); + instruction.initiatedByBehavior = true; + return instruction; + } + + static attribute(attrName:string, type?:HtmlBehaviorResource):BehaviorInstruction{ + let instruction = new BehaviorInstruction(true); + instruction.attrName = attrName; + instruction.type = type || null; + instruction.attributes = {}; + return instruction; + } + + static dynamic(host, executionContext, viewFactory){ + let instruction = new BehaviorInstruction(true); + instruction.host = host; + instruction.executionContext = executionContext; + instruction.viewFactory = viewFactory; + return instruction; + } + + constructor(suppressBind?:boolean=false){ + this.suppressBind = suppressBind; + this.initiatedByBehavior = false; + this.systemControlled = false; + this.enhance = false; + this.partReplacements = null; + this.viewFactory = null; + this.originalAttrName = null; + this.skipContentProcessing = false; + this.contentFactory = null; + this.executionContext = null; + this.anchorIsContainer = false; + this.host = null; + this.attributes = null; + this.type = null; + this.attrName = null; + } +} + +export class TargetInstruction { + static noExpressions = Object.freeze([]); + + static contentSelector(node:Node, parentInjectorId:number):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.contentSelector = true; + instruction.selector = node.getAttribute('select'); + instruction.suppressBind = true + return instruction; + } + + static contentExpression(expression):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.contentExpression = expression; + return instruction; + } + + static lifting(parentInjectorId:number, liftingInstruction:BehaviorInstruction):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.expressions = TargetInstruction.noExpressions; + instruction.behaviorInstructions = [liftingInstruction]; + instruction.viewFactory = liftingInstruction.viewFactory; + instruction.providers = [liftingInstruction.type.target]; + return instruction; + } + + static normal(injectorId, parentInjectorId, providers, behaviorInstructions, expressions, elementInstruction):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.injectorId = injectorId; + instruction.parentInjectorId = parentInjectorId; + instruction.providers = providers; + instruction.behaviorInstructions = behaviorInstructions; + instruction.expressions = expressions; + instruction.anchorIsContainer = elementInstruction ? elementInstruction.anchorIsContainer : true; + instruction.elementInstruction = elementInstruction; + return instruction; + } + + static surrogate(providers, behaviorInstructions, expressions, values):TargetInstruction{ + let instruction = new TargetInstruction(); + instruction.expressions = expressions; + instruction.behaviorInstructions = behaviorInstructions; + instruction.providers = providers; + instruction.values = values; + return instruction; + } + + constructor(){ + this.injectorId = null; + this.parentInjectorId = null; + + this.contentSelector = false; + this.selector = null; + this.suppressBind = false; + + this.contentExpression = null; + + this.expressions = null; + this.behaviorInstructions = null; + this.providers = null; + + this.viewFactory = null; + + this.anchorIsContainer = false; + this.elementInstruction = null; + + this.values = null; + } } export class ViewStrategy { static metadataKey:string = 'aurelia:view-strategy'; - makeRelativeTo(baseUrl:string){} + makeRelativeTo(baseUrl:string):void{} - static normalize(value:string|ViewStrategy){ + static normalize(value:string|ViewStrategy):ViewStrategy{ if(typeof value === 'string'){ value = new UseViewStrategy(value); } @@ -243,15 +400,16 @@ export class UseViewStrategy extends ViewStrategy { this.path = path; } - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ if(!this.absolutePath && this.moduleId){ this.absolutePath = relativeToFile(this.path, this.moduleId); } - return viewEngine.loadViewFactory(this.absolutePath || this.path, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.absolutePath || this.path, compileInstruction, loadContext); } - makeRelativeTo(file:string){ + makeRelativeTo(file:string):void{ this.absolutePath = relativeToFile(this.path, file); } } @@ -263,8 +421,9 @@ export class ConventionalViewStrategy extends ViewStrategy { this.viewUrl = ConventionalViewStrategy.convertModuleIdToViewUrl(moduleId); } - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ - return viewEngine.loadViewFactory(this.viewUrl, options, this.moduleId, loadContext); + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.viewUrl, compileInstruction, loadContext); } static convertModuleIdToViewUrl(moduleId:string):string{ @@ -274,7 +433,7 @@ export class ConventionalViewStrategy extends ViewStrategy { } export class NoViewStrategy extends ViewStrategy { - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ return Promise.resolve(null); } } @@ -286,14 +445,15 @@ export class TemplateRegistryViewStrategy extends ViewStrategy { this.entry = entry; } - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ let entry = this.entry; if(entry.isReady){ return Promise.resolve(entry.factory); } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); } } @@ -305,7 +465,7 @@ export class InlineViewStrategy extends ViewStrategy { this.dependencyBaseUrl = dependencyBaseUrl || ''; } - loadViewFactory(viewEngine:ViewEngine, options:Object, loadContext?:string[]):Promise{ + loadViewFactory(viewEngine:ViewEngine, compileInstruction:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ let entry = this.entry, dependencies = this.dependencies; @@ -328,7 +488,8 @@ export class InlineViewStrategy extends ViewStrategy { } } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); } } @@ -352,7 +513,7 @@ function register(lookup, name, resource, type){ var existing = lookup[name]; if(existing){ - if(existing != resource) { + if(existing !== resource) { throw new Error(`Attempted to register ${type} when one with the same name already exists. Name: ${name}.`); } @@ -362,67 +523,67 @@ function register(lookup, name, resource, type){ lookup[name] = resource; } -export class ResourceRegistry { - constructor(){ +export class ViewResources { + constructor(parent?:ViewResources, viewUrl?:string){ + this.parent = parent || null; + this.hasParent = this.parent !== null; + this.viewUrl = viewUrl || ''; + this.valueConverterLookupFunction = this.getValueConverter.bind(this); this.attributes = {}; this.elements = {}; this.valueConverters = {}; this.attributeMap = {}; this.baseResourceUrl = ''; + this.bindingLanguage = null; } - registerElement(tagName, behavior){ - register(this.elements, tagName, behavior, 'an Element'); + getBindingLanguage(bindingLanguageFallback){ + return this.bindingLanguage || (this.bindingLanguage = bindingLanguageFallback); } - getElement(tagName){ - return this.elements[tagName]; - } + patchInParent(newParent:ViewResources):void{ + let originalParent = this.parent; - registerAttribute(attribute, behavior, knownAttribute){ - this.attributeMap[attribute] = knownAttribute; - register(this.attributes, attribute, behavior, 'an Attribute'); - } + this.parent = newParent || null; + this.hasParent = this.parent !== null; - getAttribute(attribute){ - return this.attributes[attribute]; + if(newParent.parent === null){ + newParent.parent = originalParent; + newParent.hasParent = originalParent !== null; + } } - registerValueConverter(name, valueConverter){ - register(this.valueConverters, name, valueConverter, 'a ValueConverter'); + relativeToView(path:string):string{ + return relativeToFile(path, this.viewUrl); } - getValueConverter(name){ - return this.valueConverters[name]; + registerElement(tagName:string, behavior:HtmlBehaviorResource):void{ + register(this.elements, tagName, behavior, 'an Element'); } -} -export class ViewResources extends ResourceRegistry { - constructor(parent, viewUrl){ - super(); - this.parent = parent; - this.viewUrl = viewUrl; - this.valueConverterLookupFunction = this.getValueConverter.bind(this); + getElement(tagName:string):HtmlBehaviorResource{ + return this.elements[tagName] || (this.hasParent ? this.parent.getElement(tagName) : null); } - relativeToView(path){ - return relativeToFile(path, this.viewUrl); + mapAttribute(attribute:string):string{ + return this.attributeMap[attribute] || (this.hasParent ? this.parent.mapAttribute(attribute) : null); } - getElement(tagName){ - return this.elements[tagName] || this.parent.getElement(tagName); + registerAttribute(attribute:string, behavior:HtmlBehaviorResource, knownAttribute:string):void{ + this.attributeMap[attribute] = knownAttribute; + register(this.attributes, attribute, behavior, 'an Attribute'); } - mapAttribute(attribute){ - return this.attributeMap[attribute] || this.parent.attributeMap[attribute]; + getAttribute(attribute:string):HtmlBehaviorResource{ + return this.attributes[attribute] || (this.hasParent ? this.parent.getAttribute(attribute) : null); } - getAttribute(attribute){ - return this.attributes[attribute] || this.parent.getAttribute(attribute); + registerValueConverter(name:string, valueConverter:ValueConverter):void{ + register(this.valueConverters, name, valueConverter, 'a ValueConverter'); } - getValueConverter(name){ - return this.valueConverters[name] || this.parent.getValueConverter(name); + getValueConverter(name:string):ValueConverter{ + return this.valueConverters[name] || (this.hasParent ? this.parent.getValueConverter(name) : null); } } @@ -444,10 +605,10 @@ export class View { this.isAttached = false; } - created(executionContext){ + created(){ var i, ii, behaviors = this.behaviors; for(i = 0, ii = behaviors.length; i < ii; ++i){ - behaviors[i].created(executionContext); + behaviors[i].created(this); } } @@ -1067,6 +1228,10 @@ function elementContainerGet(key){ return this.viewResources; } + if(key === TargetInstruction){ + return this.instruction; + } + return this.superGet(key); } @@ -1095,10 +1260,10 @@ function createElementContainer(parent, element, instruction, executionContext, return container; } -function makeElementIntoAnchor(element, isCustomElement){ +function makeElementIntoAnchor(element, elementInstruction){ var anchor = document.createComment('anchor'); - if(isCustomElement){ + if(elementInstruction){ anchor.hasAttribute = function(name) { return element.hasAttribute(name); }; anchor.getAttribute = function(name){ return element.getAttribute(name); }; anchor.setAttribute = function(name, value) { element.setAttribute(name, value); }; @@ -1130,7 +1295,7 @@ function applyInstructions(containers, executionContext, element, instruction, if(behaviorInstructions.length){ if(!instruction.anchorIsContainer){ - element = makeElementIntoAnchor(element, instruction.isCustomElement); + element = makeElementIntoAnchor(element, instruction.elementInstruction); } containers[instruction.injectorId] = elementContainer = @@ -1245,38 +1410,35 @@ function applySurrogateInstruction(container, element, instruction, behaviors, b } export class BoundViewFactory { - constructor(parentContainer, viewFactory, executionContext, partReplacements){ + constructor(parentContainer:Container, viewFactory:ViewFactory, executionContext:Object, partReplacements?:Object){ this.parentContainer = parentContainer; this.viewFactory = viewFactory; this.executionContext = executionContext; - this.factoryOptions = { behaviorInstance:false, partReplacements:partReplacements }; + this.factoryCreateInstruction = { partReplacements:partReplacements }; } - create(executionContext){ + create(executionContext?:Object):View{ var childContainer = this.parentContainer.createChild(), context = executionContext || this.executionContext; - this.factoryOptions.systemControlled = !executionContext; + this.factoryCreateInstruction.systemControlled = !executionContext; - return this.viewFactory.create(childContainer, context, this.factoryOptions); + return this.viewFactory.create(childContainer, context, this.factoryCreateInstruction); } } -var defaultFactoryOptions = { - systemControlled:false, - suppressBind:false, - enhance:false -}; - export class ViewFactory{ - constructor(template, instructions, resources){ + constructor(template:DocumentFragment, instructions:Object, resources:ViewResources){ this.template = template; this.instructions = instructions; this.resources = resources; } - create(container, executionContext, options=defaultFactoryOptions, element=null){ - var fragment = options.enhance ? this.template : this.template.cloneNode(true), + create(container:Container, executionContext?:Object, createInstruction?:ViewCreateInstruction, element?:Element):View{ + createInstruction = createInstruction || BehaviorInstruction.normal; + element = element || null; + + let fragment = createInstruction.enhance ? this.template : this.template.cloneNode(true), instructables = fragment.querySelectorAll('.au-target'), instructions = this.instructions, resources = this.resources, @@ -1285,7 +1447,7 @@ export class ViewFactory{ children = [], contentSelectors = [], containers = { root:container }, - partReplacements = options.partReplacements, + partReplacements = createInstruction.partReplacements, i, ii, view, instructable, instruction; if(element !== null && this.surrogateInstruction !== null){ @@ -1300,10 +1462,15 @@ export class ViewFactory{ instruction, behaviors, bindings, children, contentSelectors, partReplacements, resources); } - view = new View(container, fragment, behaviors, bindings, children, options.systemControlled, contentSelectors); - view.created(executionContext); + view = new View(container, fragment, behaviors, bindings, children, createInstruction.systemControlled, contentSelectors); + + //if iniated by an element behavior, let the behavior trigger this callback once it's done creating the element + if(!createInstruction.initiatedByBehavior){ + view.created(); + } - if(!options.suppressBind){ + //if the view creation is part of a larger creation, wait to bind until the root view initiates binding + if(!createInstruction.suppressBind){ view.bind(executionContext); } @@ -1311,10 +1478,7 @@ export class ViewFactory{ } } -var nextInjectorId = 0, - defaultCompileOptions = { targetShadowDOM:false }, - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; - +let nextInjectorId = 0; function getNextInjectorId(){ return ++nextInjectorId; } @@ -1362,40 +1526,45 @@ function makeIntoInstructionTarget(element){ } export class ViewCompiler { - static inject() { return [BindingLanguage]; } - constructor(bindingLanguage){ + static inject() { return [BindingLanguage, ViewResources]; } + constructor(bindingLanguage:BindingLanguage, resources:ViewResources){ this.bindingLanguage = bindingLanguage; + this.resources = resources; } - compile(templateOrFragment, resources, options=defaultCompileOptions){ - var instructions = {}, - targetShadowDOM = options.targetShadowDOM, - content, part, factory; + compile(source:HTMLTemplateElement|DocumentFragment|string, resources?:ViewResources, compileInstruction?:ViewCompileInstruction):ViewFactory{ + resources = resources || this.resources; + compileInstruction = compileInstruction || ViewCompileInstruction.normal; + + let instructions = {}, + targetShadowDOM = compileInstruction.targetShadowDOM, + content, part; targetShadowDOM = targetShadowDOM && hasShadowDOM; - if(options.beforeCompile){ - options.beforeCompile(templateOrFragment); + if(compileInstruction.beforeCompile){ + compileInstruction.beforeCompile(source); + console.warn('In a future release, the beforeCompile hook will be replaced by an alternate mechanism'); } - if(typeof templateOrFragment === 'string'){ - templateOrFragment = createTemplateFromMarkup(templateOrFragment); + if(typeof source === 'string'){ + source = createTemplateFromMarkup(source); } - if(templateOrFragment.content){ - part = templateOrFragment.getAttribute('part'); - content = document.adoptNode(templateOrFragment.content, true); + if(source.content){ + part = source.getAttribute('part'); + content = document.adoptNode(source.content, true); }else{ - content = templateOrFragment; + content = source; } - this.compileNode(content, resources, instructions, templateOrFragment, 'root', !targetShadowDOM); + this.compileNode(content, resources, instructions, source, 'root', !targetShadowDOM); content.insertBefore(document.createComment(''), content.firstChild); content.appendChild(document.createComment('')); - var factory = new ViewFactory(content, instructions, resources); - factory.surrogateInstruction = options.compileSurrogate ? this.compileSurrogate(templateOrFragment, resources) : null; + let factory = new ViewFactory(content, instructions, resources); + factory.surrogateInstruction = compileInstruction.compileSurrogate ? this.compileSurrogate(source, resources) : null; if(part){ factory.part = part; @@ -1410,13 +1579,13 @@ export class ViewCompiler { return this.compileElement(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM); case 3: //text node //use wholeText to retrieve the textContent of all adjacent text nodes. - var expression = this.bindingLanguage.parseText(resources, node.wholeText); + var expression = resources.getBindingLanguage(this.bindingLanguage).parseText(resources, node.wholeText); if(expression){ let marker = document.createElement('au-marker'), auTargetID = makeIntoInstructionTarget(marker); (node.parentNode || parentNode).insertBefore(marker, node); node.textContent = ' '; - instructions[auTargetID] = { contentExpression:expression }; + instructions[auTargetID] = TargetInstruction.contentExpression(expression); //remove adjacent text nodes. while(node.nextSibling && node.nextSibling.nodeType === 3) { (node.parentNode || parentNode).removeChild(node.nextSibling); @@ -1441,7 +1610,7 @@ export class ViewCompiler { compileSurrogate(node, resources){ let attributes = node.attributes, - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), knownAttribute, property, instruction, i, ii, attr, attrName, attrValue, info, type, expressions = [], expression, @@ -1497,7 +1666,7 @@ export class ViewCompiler { } }else{ //NO BINDINGS if(type){ //templator or attached behavior found - instruction = { attrName:attrName, type:type, attributes:{} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if(type.liftsContent){ //template controller @@ -1526,16 +1695,7 @@ export class ViewCompiler { } } - return { - anchorIsContainer: false, - isCustomElement: false, - injectorId: null, - parentInjectorId: null, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers, - values:values - }; + return TargetInstruction.surrogate(providers, behaviorInstructions, expressions, values); } return null; @@ -1547,7 +1707,7 @@ export class ViewCompiler { expressions = [], expression, behaviorInstructions = [], providers = [], - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), liftingInstruction, viewFactory, type, elementInstruction, elementProperty, i, ii, attr, attrName, attrValue, instruction, info, property, knownAttribute, auTargetID, injectorId; @@ -1555,12 +1715,7 @@ export class ViewCompiler { if(tagName === 'content'){ if(targetLightDOM){ auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - parentInjectorId: parentInjectorId, - contentSelector: true, - selector:node.getAttribute('select'), - suppressBind: true - }; + instructions[auTargetID] = TargetInstruction.contentSelector(node, parentInjectorId); } return node.nextSibling; } else if(tagName === 'template'){ @@ -1569,8 +1724,7 @@ export class ViewCompiler { } else{ type = resources.getElement(tagName); if(type){ - elementInstruction = {type:type, attributes:{}}; - elementInstruction.anchorIsContainer = !node.hasAttribute('containerless') && !type.containerless; + elementInstruction = BehaviorInstruction.element(node, type); behaviorInstructions.push(elementInstruction); } } @@ -1600,10 +1754,6 @@ export class ViewCompiler { elementProperty = elementInstruction.type.attributes[info.attrName]; if(elementProperty){ //and this attribute is a custom property info.defaultBindingMode = elementProperty.defaultBindingMode; //set the default binding mode - - if(!info.command && !info.expression){ // if there is no command or detected expression - info.command = elementProperty.hasOptions ? 'options' : null; //and it is an optons property, set the options command - } } } @@ -1640,7 +1790,7 @@ export class ViewCompiler { } }else{ //NO BINDINGS if(type){ //templator or attached behavior found - instruction = { attrName:attrName, type:type, attributes:{} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if(type.liftsContent){ //template controller @@ -1662,14 +1812,7 @@ export class ViewCompiler { liftingInstruction.viewFactory = viewFactory; node = liftingInstruction.type.compile(this, resources, node, liftingInstruction, parentNode); auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: false, - parentInjectorId: parentInjectorId, - expressions: [], - behaviorInstructions: [liftingInstruction], - viewFactory: liftingInstruction.viewFactory, - providers: [liftingInstruction.type.target] - }; + instructions[auTargetID] = TargetInstruction.lifting(parentInjectorId, liftingInstruction); }else{ if(expressions.length || behaviorInstructions.length){ injectorId = behaviorInstructions.length ? getNextInjectorId() : false; @@ -1688,15 +1831,14 @@ export class ViewCompiler { } auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: elementInstruction ? elementInstruction.anchorIsContainer : true, - isCustomElement: !!elementInstruction, - injectorId: injectorId, - parentInjectorId: parentInjectorId, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers - }; + instructions[auTargetID] = TargetInstruction.normal( + injectorId, + parentInjectorId, + providers, + behaviorInstructions, + expressions, + elementInstruction + ); } if(elementInstruction && elementInstruction.skipContentProcessing){ @@ -1713,7 +1855,6 @@ export class ViewCompiler { } } -import * as LogManager from 'aurelia-logging'; var logger = LogManager.getLogger('templating'); function ensureRegistryEntry(loader, urlOrRegistryEntry){ @@ -1735,8 +1876,8 @@ class ProxyViewFactory { } export class ViewEngine { - static inject() { return [Loader, Container, ViewCompiler, ModuleAnalyzer, ResourceRegistry]; } - constructor(loader:Loader, container:Container, viewCompiler:ViewCompiler, moduleAnalyzer:ModuleAnalyzer, appResources:ResourceRegistry){ + static inject() { return [Loader, Container, ViewCompiler, ModuleAnalyzer, ViewResources]; } + constructor(loader:Loader, container:Container, viewCompiler:ViewCompiler, moduleAnalyzer:ModuleAnalyzer, appResources:ViewResources){ this.loader = loader; this.container = container; this.viewCompiler = viewCompiler; @@ -1744,51 +1885,46 @@ export class ViewEngine { this.appResources = appResources; } - enhance(container, element, resources, bindingContext){ + enhance(container:Container, element:Element, resources:ViewResources, bindingContext?:Object):View{ let instructions = {}; - this.viewCompiler.compileNode(element, resources, instructions, element.parentNode, 'root', true); let factory = new ViewFactory(element, instructions, resources); - let options = { - systemControlled:false, - suppressBind:false, - enhance:true - }; - - return factory.create(container, bindingContext, options); + return factory.create(container, bindingContext, { enhance:true }); } - loadViewFactory(urlOrRegistryEntry:string|TemplateRegistryEntry, compileOptions?:Object, associatedModuleId?:string, loadContext?:string[]):Promise{ - loadContext = loadContext || []; + loadViewFactory(urlOrRegistryEntry:string|TemplateRegistryEntry, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ + loadContext = loadContext || new ResourceLoadContext(); return ensureRegistryEntry(this.loader, urlOrRegistryEntry).then(viewRegistryEntry => { if(viewRegistryEntry.onReady){ - if(loadContext.indexOf(urlOrRegistryEntry) === -1){ - loadContext.push(urlOrRegistryEntry); + if(loadContext.doesNotHaveDependency(urlOrRegistryEntry)){ + loadContext.addDependency(urlOrRegistryEntry); return viewRegistryEntry.onReady; } return Promise.resolve(new ProxyViewFactory(viewRegistryEntry.onReady)); } - loadContext.push(urlOrRegistryEntry); + loadContext.addDependency(urlOrRegistryEntry); - return viewRegistryEntry.onReady = this.loadTemplateResources(viewRegistryEntry, associatedModuleId, loadContext).then(resources => { + return viewRegistryEntry.onReady = this.loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext).then(resources => { viewRegistryEntry.setResources(resources); - var viewFactory = this.viewCompiler.compile(viewRegistryEntry.template, resources, compileOptions); + var viewFactory = this.viewCompiler.compile(viewRegistryEntry.template, resources, compileInstruction); viewRegistryEntry.setFactory(viewFactory); return viewFactory; }); }); } - loadTemplateResources(viewRegistryEntry:TemplateRegistryEntry, associatedModuleId?:string, loadContext?:string[]):Promise{ + loadTemplateResources(viewRegistryEntry:TemplateRegistryEntry, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ var resources = new ViewResources(this.appResources, viewRegistryEntry.id), dependencies = viewRegistryEntry.dependencies, importIds, names; - if(dependencies.length === 0 && !associatedModuleId){ + compileInstruction = compileInstruction || ViewCompileInstruction.normal; + + if(dependencies.length === 0 && !compileInstruction.associatedModuleId){ return Promise.resolve(resources); } @@ -1796,7 +1932,7 @@ export class ViewEngine { names = dependencies.map(x => x.name); logger.debug(`importing resources for ${viewRegistryEntry.id}`, importIds); - return this.importViewResources(importIds, names, resources, associatedModuleId, loadContext); + return this.importViewResources(importIds, names, resources, compileInstruction, loadContext); } importViewModelResource(moduleImport:string, moduleMember:string):Promise{ @@ -1814,8 +1950,9 @@ export class ViewEngine { }); } - importViewResources(moduleIds:string[], names:string[], resources:ResourceRegistry, associatedModuleId?:string, loadContext?:string[]):Promise{ - loadContext = loadContext || []; + importViewResources(moduleIds:string[], names:string[], resources:ViewResources, compileInstruction?:ViewCompileInstruction, loadContext?:ResourceLoadContext):Promise{ + loadContext = loadContext || new ResourceLoadContext(); + compileInstruction = compileInstruction || ViewCompileInstruction.normal; return this.loader.loadAllModules(moduleIds).then(imports => { var i, ii, analysis, normalizedId, current, associatedModule, @@ -1837,8 +1974,8 @@ export class ViewEngine { allAnalysis[i] = analysis; } - if(associatedModuleId){ - associatedModule = moduleAnalyzer.getAnalysis(associatedModuleId); + if(compileInstruction.associatedModuleId){ + associatedModule = moduleAnalyzer.getAnalysis(compileInstruction.associatedModuleId); if(associatedModule){ associatedModule.register(resources); @@ -2233,9 +2370,7 @@ class BehaviorPropertyObserver { } } -var defaultInstruction = { suppressBind:false }, - contentSelectorFactoryOptions = { suppressBind:true, enhance:false }, - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; +var contentSelectorViewCreateInstruction = { suppressBind:true, enhance:false }; function doProcessContent(){ return true; @@ -2257,7 +2392,7 @@ export class HtmlBehaviorResource { this.attributes = {}; } - static convention(name:string, existing?:HtmlBehaviorResource){ + static convention(name:string, existing?:HtmlBehaviorResource):HtmlBehaviorResource{ var behavior; if(name.endsWith('CustomAttribute')){ @@ -2273,7 +2408,7 @@ export class HtmlBehaviorResource { return behavior; } - addChildBinding(behavior:BindingExpression){ + addChildBinding(behavior:BindingExpression):void{ if(this.childBindings === null){ this.childBindings = []; } @@ -2281,7 +2416,7 @@ export class HtmlBehaviorResource { this.childBindings.push(behavior); } - analyze(container:Container, target:Function){ + analyze(container:Container, target:Function):void{ var proto = target.prototype, properties = this.properties, attributeName = this.attributeName, @@ -2338,16 +2473,12 @@ export class HtmlBehaviorResource { } } - load(container:Container, target:Function, viewStrategy?:ViewStrategy, transientView?:boolean, loadContext?:string[]):Promise{ + load(container:Container, target:Function, viewStrategy?:ViewStrategy, transientView?:boolean, loadContext?:ResourceLoadContext):Promise{ var options; if(this.elementName !== null){ viewStrategy = viewStrategy || this.viewStrategy || ViewStrategy.getDefault(target); - options = { - targetShadowDOM:this.targetShadowDOM, - beforeCompile:target.beforeCompile, - compileSurrogate:true - }; + options = new ViewCompileInstruction(this.targetShadowDOM, true, target.beforeCompile); if(!viewStrategy.moduleId){ viewStrategy.moduleId = Origin.get(target).moduleId; @@ -2365,7 +2496,7 @@ export class HtmlBehaviorResource { return Promise.resolve(this); } - register(registry:ResourceRegistry, name?:string){ + register(registry:ViewResources, name?:string):void{ if(this.attributeName !== null) { registry.registerAttribute(name || this.attributeName, this, this.attributeName); } @@ -2375,7 +2506,7 @@ export class HtmlBehaviorResource { } } - compile(compiler:ViewCompiler, resources:ResourceRegistry, node:Node, instruction:Object, parentNode?:Node):Node{ + compile(compiler:ViewCompiler, resources:ViewResources, node:Node, instruction:BehaviorInstruction, parentNode?:Node):Node{ if(this.liftsContent){ if(!instruction.viewFactory){ var template = document.createElement('template'), @@ -2440,13 +2571,16 @@ export class HtmlBehaviorResource { } } - instruction.suppressBind = true; return node; } - create(container:Container, instruction?:Object=defaultInstruction, element?:Element=null, bindings?:Binding[]=null):BehaviorInstance{ + create(container:Container, instruction?:BehaviorInstruction, element?:Element, bindings?:Binding[]):BehaviorInstance{ let host; + instruction = instruction || BehaviorInstruction.normal; + element = element || null; + bindings = bindings || null; + if(this.elementName !== null && element){ if(this.usesShadowDOM) { host = element.createShadowRoot(); @@ -2483,7 +2617,7 @@ export class HtmlBehaviorResource { if(behaviorInstance.view){ if(!this.usesShadowDOM) { if(instruction.contentFactory){ - var contentView = instruction.contentFactory.create(container, null, contentSelectorFactoryOptions); + var contentView = instruction.contentFactory.create(container, null, contentSelectorViewCreateInstruction); ContentSelector.applySelectors( contentView, @@ -2543,6 +2677,10 @@ export class HtmlBehaviorResource { } } + if(instruction.initiatedByBehavior && viewFactory){ + behaviorInstance.view.created(); + } + return behaviorInstance; } @@ -2600,7 +2738,7 @@ export class ResourceModule { } } - register(registry:ResourceRegistry, name?:string){ + register(registry:ViewResources, name?:string){ var i, ii, resources = this.resources; if(this.mainResource){ @@ -2614,7 +2752,7 @@ export class ResourceModule { } } - load(container:Container, loadContext?:string[]):Promise{ + load(container:Container, loadContext?:ResourceLoadContext):Promise{ if(this.onLoaded){ return this.onLoaded; } @@ -2676,11 +2814,11 @@ export class ResourceDescription { } } - register(registry:ResourceRegistry, name?:string){ + register(registry:ViewResources, name?:string){ this.metadata.register(registry, name); } - load(container:Container, loadContext?:string[]):Promise|void{ + load(container:Container, loadContext?:ResourceLoadContext):Promise|void{ let metadata = this.metadata, value = this.value; @@ -2974,12 +3112,7 @@ export class CompositionEngine { } return doneLoading.then(viewFactory => { - return metadata.create(childContainer, { - executionContext:viewModel, - viewFactory:viewFactory, - suppressBind:true, - host:instruction.host - }); + return metadata.create(childContainer, BehaviorInstruction.dynamic(instruction.host, viewModel, viewFactory)); }); }); } diff --git a/dist/system/aurelia-templating.d.ts b/dist/system/aurelia-templating.d.ts index 802af35f..cd67272f 100644 --- a/dist/system/aurelia-templating.d.ts +++ b/dist/system/aurelia-templating.d.ts @@ -1,16 +1,27 @@ declare module 'aurelia-templating' { - import core from 'core-js'; + import * as core from 'core-js'; + import * as LogManager from 'aurelia-logging'; import { Metadata, Origin, Decorators } from 'aurelia-metadata'; import { relativeToFile } from 'aurelia-path'; import { TemplateRegistryEntry, Loader } from 'aurelia-loader'; + import { ValueConverter, bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { Container } from 'aurelia-dependency-injection'; - import { bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager } from 'aurelia-binding'; import { TaskQueue } from 'aurelia-task-queue'; - import * as LogManager from 'aurelia-logging'; + + // this will be replaced soon + export interface ViewCreateInstruction { + suppressBind?: boolean; + systemControlled?: boolean; + enhance?: boolean; + partReplacements?: Object; + initiatedByBehavior?: boolean; + } export let DOMBoundary: any; - export function createTemplateFromMarkup(markup: any): any; - export function replaceNode(newNode: any, node: any, parentNode: any): any; - export function removeNode(node: any, parentNode: any): any; + export let hasShadowDOM: any; + export function nextElementSibling(element: Node): Element; + export function createTemplateFromMarkup(markup: string): HTMLTemplateElement; + export function replaceNode(newNode: Node, node: Node, parentNode: Node): void; + export function removeNode(node: Node, parentNode: Node): void; export const animationEvent: any; export class Animator { static configureDefault(container: any, animatorInstance: any): any; @@ -94,62 +105,83 @@ declare module 'aurelia-templating' { unregisterEffect(effectName: any): any; } export function hyphenate(name: any): any; - export function nextElementSibling(element: any): any; + export class ResourceLoadContext { + constructor(); + addDependency(url: string): void; + doesNotHaveDependency(url: string): boolean; + } + export class ViewCompileInstruction { + static normal: any; + constructor(targetShadowDOM?: boolean, compileSurrogate?: boolean, beforeCompile?: boolean); + } + export class BehaviorInstruction { + static normal: any; + static contentSelector: any; + static element(node: Node, type: HtmlBehaviorResource): BehaviorInstruction; + static attribute(attrName: string, type?: HtmlBehaviorResource): BehaviorInstruction; + static dynamic(host: any, executionContext: any, viewFactory: any): any; + constructor(suppressBind?: boolean); + } + export class TargetInstruction { + static noExpressions: any; + static contentSelector(node: Node, parentInjectorId: number): TargetInstruction; + static contentExpression(expression: any): TargetInstruction; + static lifting(parentInjectorId: number, liftingInstruction: BehaviorInstruction): TargetInstruction; + static normal(injectorId: any, parentInjectorId: any, providers: any, behaviorInstructions: any, expressions: any, elementInstruction: any): TargetInstruction; + static surrogate(providers: any, behaviorInstructions: any, expressions: any, values: any): TargetInstruction; + constructor(); + } export class ViewStrategy { static metadataKey: string; - makeRelativeTo(baseUrl: string): any; - static normalize(value: string | ViewStrategy): any; + makeRelativeTo(baseUrl: string): void; + static normalize(value: string | ViewStrategy): ViewStrategy; static getDefault(target: any): ViewStrategy; } export class UseViewStrategy extends ViewStrategy { constructor(path: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; - makeRelativeTo(file: string): any; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + makeRelativeTo(file: string): void; } export class ConventionalViewStrategy extends ViewStrategy { constructor(moduleId: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; static convertModuleIdToViewUrl(moduleId: string): string; } export class NoViewStrategy extends ViewStrategy { - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class TemplateRegistryViewStrategy extends ViewStrategy { constructor(moduleId: string, entry: TemplateRegistryEntry); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class InlineViewStrategy extends ViewStrategy { constructor(markup: string, dependencies?: Array, dependencyBaseUrl?: string); - loadViewFactory(viewEngine: ViewEngine, options: Object, loadContext?: string[]): Promise; + loadViewFactory(viewEngine: ViewEngine, compileInstruction: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BindingLanguage { inspectAttribute(resources: any, attrName: any, attrValue: any): any; createAttributeInstruction(resources: any, element: any, info: any, existingInstruction: any): any; parseText(resources: any, value: any): any; } - export class ResourceRegistry { - constructor(); - registerElement(tagName: any, behavior: any): any; - getElement(tagName: any): any; - registerAttribute(attribute: any, behavior: any, knownAttribute: any): any; - getAttribute(attribute: any): any; - registerValueConverter(name: any, valueConverter: any): any; - getValueConverter(name: any): any; - } - export class ViewResources extends ResourceRegistry { - constructor(parent: any, viewUrl: any); - relativeToView(path: any): any; - getElement(tagName: any): any; - mapAttribute(attribute: any): any; - getAttribute(attribute: any): any; - getValueConverter(name: any): any; + export class ViewResources { + constructor(parent?: ViewResources, viewUrl?: string); + getBindingLanguage(bindingLanguageFallback: any): any; + patchInParent(newParent: ViewResources): void; + relativeToView(path: string): string; + registerElement(tagName: string, behavior: HtmlBehaviorResource): void; + getElement(tagName: string): HtmlBehaviorResource; + mapAttribute(attribute: string): string; + registerAttribute(attribute: string, behavior: HtmlBehaviorResource, knownAttribute: string): void; + getAttribute(attribute: string): HtmlBehaviorResource; + registerValueConverter(name: string, valueConverter: ValueConverter): void; + getValueConverter(name: string): ValueConverter; } // NOTE: Adding a fragment to the document causes the nodes to be removed from the fragment. // NOTE: Adding to the fragment, causes the nodes to be removed from the document. export class View { constructor(container: any, fragment: any, behaviors: any, bindings: any, children: any, systemControlled: any, contentSelectors: any); - created(executionContext: any): any; + created(): any; bind(executionContext: any, systemUpdate: any): any; addBinding(binding: any): any; unbind(): any; @@ -189,17 +221,17 @@ declare module 'aurelia-templating' { contentSelectorRemoveAll(): any; } export class BoundViewFactory { - constructor(parentContainer: any, viewFactory: any, executionContext: any, partReplacements: any); - create(executionContext: any): any; + constructor(parentContainer: Container, viewFactory: ViewFactory, executionContext: Object, partReplacements?: Object); + create(executionContext?: Object): View; } export class ViewFactory { - constructor(template: any, instructions: any, resources: any); - create(container: any, executionContext: any, options?: any, element?: any): any; + constructor(template: DocumentFragment, instructions: Object, resources: ViewResources); + create(container: Container, executionContext?: Object, createInstruction?: ViewCreateInstruction, element?: Element): View; } export class ViewCompiler { static inject(): any; - constructor(bindingLanguage: any); - compile(templateOrFragment: any, resources: any, options?: any): any; + constructor(bindingLanguage: BindingLanguage, resources: ViewResources); + compile(source: HTMLTemplateElement | DocumentFragment | string, resources?: ViewResources, compileInstruction?: ViewCompileInstruction): ViewFactory; compileNode(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; compileSurrogate(node: any, resources: any): any; compileElement(node: any, resources: any, instructions: any, parentNode: any, parentInjectorId: any, targetLightDOM: any): any; @@ -210,12 +242,12 @@ declare module 'aurelia-templating' { } export class ViewEngine { static inject(): any; - constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ResourceRegistry); - enhance(container: any, element: any, resources: any, bindingContext: any): any; - loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileOptions?: Object, associatedModuleId?: string, loadContext?: string[]): Promise; - loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, associatedModuleId?: string, loadContext?: string[]): Promise; + constructor(loader: Loader, container: Container, viewCompiler: ViewCompiler, moduleAnalyzer: ModuleAnalyzer, appResources: ViewResources); + enhance(container: Container, element: Element, resources: ViewResources, bindingContext?: Object): View; + loadViewFactory(urlOrRegistryEntry: string | TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; + loadTemplateResources(viewRegistryEntry: TemplateRegistryEntry, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; importViewModelResource(moduleImport: string, moduleMember: string): Promise; - importViewResources(moduleIds: string[], names: string[], resources: ResourceRegistry, associatedModuleId?: string, loadContext?: string[]): Promise; + importViewResources(moduleIds: string[], names: string[], resources: ViewResources, compileInstruction?: ViewCompileInstruction, loadContext?: ResourceLoadContext): Promise; } export class BehaviorInstance { constructor(behavior: any, executionContext: any, instruction: any); @@ -244,26 +276,26 @@ declare module 'aurelia-templating' { } export class HtmlBehaviorResource { constructor(); - static convention(name: string, existing?: HtmlBehaviorResource): any; - addChildBinding(behavior: BindingExpression): any; - analyze(container: Container, target: Function): any; - load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: string[]): Promise; - register(registry: ResourceRegistry, name?: string): any; - compile(compiler: ViewCompiler, resources: ResourceRegistry, node: Node, instruction: Object, parentNode?: Node): Node; - create(container: Container, instruction?: Object, element?: Element, bindings?: Binding[]): BehaviorInstance; + static convention(name: string, existing?: HtmlBehaviorResource): HtmlBehaviorResource; + addChildBinding(behavior: BindingExpression): void; + analyze(container: Container, target: Function): void; + load(container: Container, target: Function, viewStrategy?: ViewStrategy, transientView?: boolean, loadContext?: ResourceLoadContext): Promise; + register(registry: ViewResources, name?: string): void; + compile(compiler: ViewCompiler, resources: ViewResources, node: Node, instruction: BehaviorInstruction, parentNode?: Node): Node; + create(container: Container, instruction?: BehaviorInstruction, element?: Element, bindings?: Binding[]): BehaviorInstance; ensurePropertiesDefined(instance: Object, lookup: Object): any; } export class ResourceModule { constructor(moduleId: string); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise; } export class ResourceDescription { constructor(key: string, exportedValue: any, resourceTypeMeta: Object); analyze(container: Container): any; - register(registry: ResourceRegistry, name?: string): any; - load(container: Container, loadContext?: string[]): Promise | void; + register(registry: ViewResources, name?: string): any; + load(container: Container, loadContext?: ResourceLoadContext): Promise | void; static get(resource: any, key?: string): ResourceDescription; } export class ModuleAnalyzer { diff --git a/dist/system/aurelia-templating.js b/dist/system/aurelia-templating.js index de2353a8..e4ca125c 100644 --- a/dist/system/aurelia-templating.js +++ b/dist/system/aurelia-templating.js @@ -1,10 +1,12 @@ -System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader', 'aurelia-dependency-injection', 'aurelia-binding', 'aurelia-task-queue', 'aurelia-logging'], function (_export) { +System.register(['core-js', 'aurelia-logging', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader', 'aurelia-binding', 'aurelia-dependency-injection', 'aurelia-task-queue'], function (_export) { 'use strict'; - var core, Metadata, Origin, Decorators, relativeToFile, TemplateRegistryEntry, Loader, Container, bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager, TaskQueue, LogManager, needsTemplateFixup, shadowPoly, DOMBoundary, animationEvent, Animator, capitalMatcher, ViewStrategy, UseViewStrategy, ConventionalViewStrategy, NoViewStrategy, TemplateRegistryViewStrategy, InlineViewStrategy, BindingLanguage, ResourceRegistry, ViewResources, View, proto, placeholder, ContentSelector, ViewSlot, BoundViewFactory, defaultFactoryOptions, ViewFactory, nextInjectorId, defaultCompileOptions, hasShadowDOM, lastAUTargetID, ViewCompiler, logger, ProxyViewFactory, ViewEngine, BehaviorInstance, BindableProperty, BehaviorPropertyObserver, defaultInstruction, contentSelectorFactoryOptions, hasShadowDOM, HtmlBehaviorResource, ResourceModule, ResourceDescription, ModuleAnalyzer, noMutations, ChildObserver, ChildObserverBinder, CompositionEngine, ElementConfigResource; + var core, LogManager, Metadata, Origin, Decorators, relativeToFile, TemplateRegistryEntry, Loader, ValueConverter, bindingMode, ObserverLocator, BindingExpression, Binding, ValueConverterResource, EventManager, Container, TaskQueue, needsTemplateFixup, shadowPoly, DOMBoundary, hasShadowDOM, animationEvent, Animator, capitalMatcher, ResourceLoadContext, ViewCompileInstruction, BehaviorInstruction, TargetInstruction, ViewStrategy, UseViewStrategy, ConventionalViewStrategy, NoViewStrategy, TemplateRegistryViewStrategy, InlineViewStrategy, BindingLanguage, ViewResources, View, proto, placeholder, ContentSelector, ViewSlot, BoundViewFactory, ViewFactory, nextInjectorId, lastAUTargetID, ViewCompiler, logger, ProxyViewFactory, ViewEngine, BehaviorInstance, BindableProperty, BehaviorPropertyObserver, contentSelectorViewCreateInstruction, HtmlBehaviorResource, ResourceModule, ResourceDescription, ModuleAnalyzer, noMutations, ChildObserver, ChildObserverBinder, CompositionEngine, ElementConfigResource; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + _export('nextElementSibling', nextElementSibling); + _export('createTemplateFromMarkup', createTemplateFromMarkup); _export('replaceNode', replaceNode); @@ -13,8 +15,6 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('hyphenate', hyphenate); - _export('nextElementSibling', nextElementSibling); - _export('behavior', behavior); _export('customElement', customElement); @@ -47,13 +47,25 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('elementConfig', elementConfig); - function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } + function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + function nextElementSibling(element) { + if (element.nextElementSibling) { + return element.nextElementSibling; + } + do { + element = element.nextSibling; + } while (element && element.nodeType !== 1); + return element; + } + function createTemplateFromMarkup(markup) { - var temp = document.createElement('template'); - temp.innerHTML = markup; + var parser = document.createElement('div'); + parser.innerHTML = markup; + + var temp = parser.firstChild; if (needsTemplateFixup) { temp.content = document.createDocumentFragment(); @@ -86,23 +98,13 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } function addHyphenAndLower(char) { - return '-' + char.toLowerCase(); + return "-" + char.toLowerCase(); } function hyphenate(name) { return (name.charAt(0).toLowerCase() + name.slice(1)).replace(capitalMatcher, addHyphenAndLower); } - function nextElementSibling(element) { - if (element.nextElementSibling) { - return element.nextElementSibling; - } - do { - element = element.nextSibling; - } while (element && element.nodeType !== 1); - return element; - } - function register(lookup, name, resource, type) { if (!name) { return; @@ -110,7 +112,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' var existing = lookup[name]; if (existing) { - if (existing != resource) { + if (existing !== resource) { throw new Error('Attempted to register ' + type + ' when one with the same name already exists. Name: ' + name + '.'); } @@ -178,6 +180,10 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' return this.viewResources; } + if (key === TargetInstruction) { + return this.instruction; + } + return this.superGet(key); } @@ -206,10 +212,10 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' return container; } - function makeElementIntoAnchor(element, isCustomElement) { + function makeElementIntoAnchor(element, elementInstruction) { var anchor = document.createComment('anchor'); - if (isCustomElement) { + if (elementInstruction) { anchor.hasAttribute = function (name) { return element.hasAttribute(name); }; @@ -250,7 +256,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' if (behaviorInstructions.length) { if (!instruction.anchorIsContainer) { - element = makeElementIntoAnchor(element, instruction.isCustomElement); + element = makeElementIntoAnchor(element, instruction.elementInstruction); } containers[instruction.injectorId] = elementContainer = createElementContainer(containers[instruction.parentInjectorId], element, instruction, executionContext, children, partReplacements, resources); @@ -284,7 +290,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' for (i = 0; i < attributes.length; i++) { current = attributes[i]; - firstIndexOfColon = current.indexOf(':'); + firstIndexOfColon = current.indexOf(":"); key = current.substring(0, firstIndexOfColon).trim(); value = current.substring(firstIndexOfColon + 1).trim(); target[key] = value; @@ -334,8 +340,8 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' element.setAttribute('style', styleObjectToString(styleObject)); } } else { - element.setAttribute(key, values[key]); - } + element.setAttribute(key, values[key]); + } } if (behaviorInstructions.length) { @@ -593,7 +599,9 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' return { setters: [function (_coreJs) { - core = _coreJs['default']; + core = _coreJs; + }, function (_aureliaLogging) { + LogManager = _aureliaLogging; }, function (_aureliaMetadata) { Metadata = _aureliaMetadata.Metadata; Origin = _aureliaMetadata.Origin; @@ -603,19 +611,18 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' }, function (_aureliaLoader) { TemplateRegistryEntry = _aureliaLoader.TemplateRegistryEntry; Loader = _aureliaLoader.Loader; - }, function (_aureliaDependencyInjection) { - Container = _aureliaDependencyInjection.Container; }, function (_aureliaBinding) { + ValueConverter = _aureliaBinding.ValueConverter; bindingMode = _aureliaBinding.bindingMode; ObserverLocator = _aureliaBinding.ObserverLocator; BindingExpression = _aureliaBinding.BindingExpression; Binding = _aureliaBinding.Binding; ValueConverterResource = _aureliaBinding.ValueConverterResource; EventManager = _aureliaBinding.EventManager; + }, function (_aureliaDependencyInjection) { + Container = _aureliaDependencyInjection.Container; }, function (_aureliaTaskQueue) { TaskQueue = _aureliaTaskQueue.TaskQueue; - }, function (_aureliaLogging) { - LogManager = _aureliaLogging; }], execute: function () { needsTemplateFixup = !('content' in document.createElement('template')); @@ -624,6 +631,10 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('DOMBoundary', DOMBoundary); + hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; + + _export('hasShadowDOM', hasShadowDOM); + animationEvent = { enterBegin: 'animation:enter:begin', enterActive: 'animation:enter:active', @@ -704,6 +715,196 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' capitalMatcher = /([A-Z])/g; + ResourceLoadContext = (function () { + function ResourceLoadContext() { + _classCallCheck(this, ResourceLoadContext); + + this.dependencies = {}; + } + + ResourceLoadContext.prototype.addDependency = function addDependency(url) { + this.dependencies[url] = true; + }; + + ResourceLoadContext.prototype.doesNotHaveDependency = function doesNotHaveDependency(url) { + return !(url in this.dependencies); + }; + + return ResourceLoadContext; + })(); + + _export('ResourceLoadContext', ResourceLoadContext); + + ViewCompileInstruction = (function () { + _createClass(ViewCompileInstruction, null, [{ + key: 'normal', + value: new ViewCompileInstruction(), + enumerable: true + }]); + + function ViewCompileInstruction() { + var targetShadowDOM = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; + var compileSurrogate = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; + var beforeCompile = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; + + _classCallCheck(this, ViewCompileInstruction); + + this.targetShadowDOM = targetShadowDOM; + this.compileSurrogate = compileSurrogate; + this.associatedModuleId = null; + this.beforeCompile = beforeCompile; + } + + return ViewCompileInstruction; + })(); + + _export('ViewCompileInstruction', ViewCompileInstruction); + + BehaviorInstruction = (function () { + BehaviorInstruction.element = function element(node, type) { + var instruction = new BehaviorInstruction(true); + instruction.type = type; + instruction.attributes = {}; + instruction.anchorIsContainer = !(node.hasAttribute('containerless') || type.containerless); + instruction.initiatedByBehavior = true; + return instruction; + }; + + BehaviorInstruction.attribute = function attribute(attrName, type) { + var instruction = new BehaviorInstruction(true); + instruction.attrName = attrName; + instruction.type = type || null; + instruction.attributes = {}; + return instruction; + }; + + BehaviorInstruction.dynamic = function dynamic(host, executionContext, viewFactory) { + var instruction = new BehaviorInstruction(true); + instruction.host = host; + instruction.executionContext = executionContext; + instruction.viewFactory = viewFactory; + return instruction; + }; + + _createClass(BehaviorInstruction, null, [{ + key: 'normal', + value: new BehaviorInstruction(), + enumerable: true + }, { + key: 'contentSelector', + value: new BehaviorInstruction(true), + enumerable: true + }]); + + function BehaviorInstruction() { + var suppressBind = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; + + _classCallCheck(this, BehaviorInstruction); + + this.suppressBind = suppressBind; + this.initiatedByBehavior = false; + this.systemControlled = false; + this.enhance = false; + this.partReplacements = null; + this.viewFactory = null; + this.originalAttrName = null; + this.skipContentProcessing = false; + this.contentFactory = null; + this.executionContext = null; + this.anchorIsContainer = false; + this.host = null; + this.attributes = null; + this.type = null; + this.attrName = null; + } + + return BehaviorInstruction; + })(); + + _export('BehaviorInstruction', BehaviorInstruction); + + TargetInstruction = (function () { + TargetInstruction.contentSelector = function contentSelector(node, parentInjectorId) { + var instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.contentSelector = true; + instruction.selector = node.getAttribute('select'); + instruction.suppressBind = true; + return instruction; + }; + + TargetInstruction.contentExpression = function contentExpression(expression) { + var instruction = new TargetInstruction(); + instruction.contentExpression = expression; + return instruction; + }; + + TargetInstruction.lifting = function lifting(parentInjectorId, liftingInstruction) { + var instruction = new TargetInstruction(); + instruction.parentInjectorId = parentInjectorId; + instruction.expressions = TargetInstruction.noExpressions; + instruction.behaviorInstructions = [liftingInstruction]; + instruction.viewFactory = liftingInstruction.viewFactory; + instruction.providers = [liftingInstruction.type.target]; + return instruction; + }; + + TargetInstruction.normal = function normal(injectorId, parentInjectorId, providers, behaviorInstructions, expressions, elementInstruction) { + var instruction = new TargetInstruction(); + instruction.injectorId = injectorId; + instruction.parentInjectorId = parentInjectorId; + instruction.providers = providers; + instruction.behaviorInstructions = behaviorInstructions; + instruction.expressions = expressions; + instruction.anchorIsContainer = elementInstruction ? elementInstruction.anchorIsContainer : true; + instruction.elementInstruction = elementInstruction; + return instruction; + }; + + TargetInstruction.surrogate = function surrogate(providers, behaviorInstructions, expressions, values) { + var instruction = new TargetInstruction(); + instruction.expressions = expressions; + instruction.behaviorInstructions = behaviorInstructions; + instruction.providers = providers; + instruction.values = values; + return instruction; + }; + + _createClass(TargetInstruction, null, [{ + key: 'noExpressions', + value: Object.freeze([]), + enumerable: true + }]); + + function TargetInstruction() { + _classCallCheck(this, TargetInstruction); + + this.injectorId = null; + this.parentInjectorId = null; + + this.contentSelector = false; + this.selector = null; + this.suppressBind = false; + + this.contentExpression = null; + + this.expressions = null; + this.behaviorInstructions = null; + this.providers = null; + + this.viewFactory = null; + + this.anchorIsContainer = false; + this.elementInstruction = null; + + this.values = null; + } + + return TargetInstruction; + })(); + + _export('TargetInstruction', TargetInstruction); + ViewStrategy = (function () { function ViewStrategy() { _classCallCheck(this, ViewStrategy); @@ -758,6 +959,8 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('ViewStrategy', ViewStrategy); UseViewStrategy = (function (_ViewStrategy) { + _inherits(UseViewStrategy, _ViewStrategy); + function UseViewStrategy(path) { _classCallCheck(this, UseViewStrategy); @@ -765,14 +968,13 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' this.path = path; } - _inherits(UseViewStrategy, _ViewStrategy); - - UseViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + UseViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { if (!this.absolutePath && this.moduleId) { this.absolutePath = relativeToFile(this.path, this.moduleId); } - return viewEngine.loadViewFactory(this.absolutePath || this.path, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.absolutePath || this.path, compileInstruction, loadContext); }; UseViewStrategy.prototype.makeRelativeTo = function makeRelativeTo(file) { @@ -785,6 +987,8 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('UseViewStrategy', UseViewStrategy); ConventionalViewStrategy = (function (_ViewStrategy2) { + _inherits(ConventionalViewStrategy, _ViewStrategy2); + function ConventionalViewStrategy(moduleId) { _classCallCheck(this, ConventionalViewStrategy); @@ -793,10 +997,9 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' this.viewUrl = ConventionalViewStrategy.convertModuleIdToViewUrl(moduleId); } - _inherits(ConventionalViewStrategy, _ViewStrategy2); - - ConventionalViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { - return viewEngine.loadViewFactory(this.viewUrl, options, this.moduleId, loadContext); + ConventionalViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(this.viewUrl, compileInstruction, loadContext); }; ConventionalViewStrategy.convertModuleIdToViewUrl = function convertModuleIdToViewUrl(moduleId) { @@ -810,15 +1013,15 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('ConventionalViewStrategy', ConventionalViewStrategy); NoViewStrategy = (function (_ViewStrategy3) { + _inherits(NoViewStrategy, _ViewStrategy3); + function NoViewStrategy() { _classCallCheck(this, NoViewStrategy); _ViewStrategy3.apply(this, arguments); } - _inherits(NoViewStrategy, _ViewStrategy3); - - NoViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + NoViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { return Promise.resolve(null); }; @@ -828,6 +1031,8 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('NoViewStrategy', NoViewStrategy); TemplateRegistryViewStrategy = (function (_ViewStrategy4) { + _inherits(TemplateRegistryViewStrategy, _ViewStrategy4); + function TemplateRegistryViewStrategy(moduleId, entry) { _classCallCheck(this, TemplateRegistryViewStrategy); @@ -836,16 +1041,15 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' this.entry = entry; } - _inherits(TemplateRegistryViewStrategy, _ViewStrategy4); - - TemplateRegistryViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + TemplateRegistryViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { var entry = this.entry; if (entry.isReady) { return Promise.resolve(entry.factory); } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); }; return TemplateRegistryViewStrategy; @@ -854,6 +1058,8 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('TemplateRegistryViewStrategy', TemplateRegistryViewStrategy); InlineViewStrategy = (function (_ViewStrategy5) { + _inherits(InlineViewStrategy, _ViewStrategy5); + function InlineViewStrategy(markup, dependencies, dependencyBaseUrl) { _classCallCheck(this, InlineViewStrategy); @@ -863,9 +1069,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' this.dependencyBaseUrl = dependencyBaseUrl || ''; } - _inherits(InlineViewStrategy, _ViewStrategy5); - - InlineViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, options, loadContext) { + InlineViewStrategy.prototype.loadViewFactory = function loadViewFactory(viewEngine, compileInstruction, loadContext) { var entry = this.entry, dependencies = this.dependencies; @@ -888,7 +1092,8 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } } - return viewEngine.loadViewFactory(entry, options, this.moduleId, loadContext); + compileInstruction.associatedModuleId = this.moduleId; + return viewEngine.loadViewFactory(entry, compileInstruction, loadContext); }; return InlineViewStrategy; @@ -918,81 +1123,73 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('BindingLanguage', BindingLanguage); - ResourceRegistry = (function () { - function ResourceRegistry() { - _classCallCheck(this, ResourceRegistry); + ViewResources = (function () { + function ViewResources(parent, viewUrl) { + _classCallCheck(this, ViewResources); + this.parent = parent || null; + this.hasParent = this.parent !== null; + this.viewUrl = viewUrl || ''; + this.valueConverterLookupFunction = this.getValueConverter.bind(this); this.attributes = {}; this.elements = {}; this.valueConverters = {}; this.attributeMap = {}; this.baseResourceUrl = ''; + this.bindingLanguage = null; } - ResourceRegistry.prototype.registerElement = function registerElement(tagName, behavior) { - register(this.elements, tagName, behavior, 'an Element'); - }; - - ResourceRegistry.prototype.getElement = function getElement(tagName) { - return this.elements[tagName]; + ViewResources.prototype.getBindingLanguage = function getBindingLanguage(bindingLanguageFallback) { + return this.bindingLanguage || (this.bindingLanguage = bindingLanguageFallback); }; - ResourceRegistry.prototype.registerAttribute = function registerAttribute(attribute, behavior, knownAttribute) { - this.attributeMap[attribute] = knownAttribute; - register(this.attributes, attribute, behavior, 'an Attribute'); - }; - - ResourceRegistry.prototype.getAttribute = function getAttribute(attribute) { - return this.attributes[attribute]; - }; + ViewResources.prototype.patchInParent = function patchInParent(newParent) { + var originalParent = this.parent; - ResourceRegistry.prototype.registerValueConverter = function registerValueConverter(name, valueConverter) { - register(this.valueConverters, name, valueConverter, 'a ValueConverter'); - }; + this.parent = newParent || null; + this.hasParent = this.parent !== null; - ResourceRegistry.prototype.getValueConverter = function getValueConverter(name) { - return this.valueConverters[name]; + if (newParent.parent === null) { + newParent.parent = originalParent; + newParent.hasParent = originalParent !== null; + } }; - return ResourceRegistry; - })(); - - _export('ResourceRegistry', ResourceRegistry); - - ViewResources = (function (_ResourceRegistry) { - function ViewResources(parent, viewUrl) { - _classCallCheck(this, ViewResources); - - _ResourceRegistry.call(this); - this.parent = parent; - this.viewUrl = viewUrl; - this.valueConverterLookupFunction = this.getValueConverter.bind(this); - } - - _inherits(ViewResources, _ResourceRegistry); - ViewResources.prototype.relativeToView = function relativeToView(path) { return relativeToFile(path, this.viewUrl); }; + ViewResources.prototype.registerElement = function registerElement(tagName, behavior) { + register(this.elements, tagName, behavior, 'an Element'); + }; + ViewResources.prototype.getElement = function getElement(tagName) { - return this.elements[tagName] || this.parent.getElement(tagName); + return this.elements[tagName] || (this.hasParent ? this.parent.getElement(tagName) : null); }; ViewResources.prototype.mapAttribute = function mapAttribute(attribute) { - return this.attributeMap[attribute] || this.parent.attributeMap[attribute]; + return this.attributeMap[attribute] || (this.hasParent ? this.parent.mapAttribute(attribute) : null); + }; + + ViewResources.prototype.registerAttribute = function registerAttribute(attribute, behavior, knownAttribute) { + this.attributeMap[attribute] = knownAttribute; + register(this.attributes, attribute, behavior, 'an Attribute'); }; ViewResources.prototype.getAttribute = function getAttribute(attribute) { - return this.attributes[attribute] || this.parent.getAttribute(attribute); + return this.attributes[attribute] || (this.hasParent ? this.parent.getAttribute(attribute) : null); + }; + + ViewResources.prototype.registerValueConverter = function registerValueConverter(name, valueConverter) { + register(this.valueConverters, name, valueConverter, 'a ValueConverter'); }; ViewResources.prototype.getValueConverter = function getValueConverter(name) { - return this.valueConverters[name] || this.parent.getValueConverter(name); + return this.valueConverters[name] || (this.hasParent ? this.parent.getValueConverter(name) : null); }; return ViewResources; - })(ResourceRegistry); + })(); _export('ViewResources', ViewResources); @@ -1013,12 +1210,12 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' this.isAttached = false; } - View.prototype.created = function created(executionContext) { + View.prototype.created = function created() { var i, ii, behaviors = this.behaviors; for (i = 0, ii = behaviors.length; i < ii; ++i) { - behaviors[i].created(executionContext); + behaviors[i].created(this); } }; @@ -1187,15 +1384,6 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' placeholder = []; ContentSelector = (function () { - function ContentSelector(anchor, selector) { - _classCallCheck(this, ContentSelector); - - this.anchor = anchor; - this.selector = selector; - this.all = !this.selector; - this.groups = []; - } - ContentSelector.applySelectors = function applySelectors(view, contentSelectors, callback) { var currentChild = view.fragment.firstChild, contentMap = new Map(), @@ -1237,6 +1425,15 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } }; + function ContentSelector(anchor, selector) { + _classCallCheck(this, ContentSelector); + + this.anchor = anchor; + this.selector = selector; + this.all = !this.selector; + this.groups = []; + } + ContentSelector.prototype.copyForViewSlot = function copyForViewSlot() { return new ContentSelector(this.anchor, this.selector); }; @@ -1292,7 +1489,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' ViewSlot = (function () { function ViewSlot(anchor, anchorIsContainer, executionContext) { - var animator = arguments[3] === undefined ? Animator.instance : arguments[3]; + var animator = arguments.length <= 3 || arguments[3] === undefined ? Animator.instance : arguments[3]; _classCallCheck(this, ViewSlot); @@ -1621,16 +1818,16 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' this.parentContainer = parentContainer; this.viewFactory = viewFactory; this.executionContext = executionContext; - this.factoryOptions = { behaviorInstance: false, partReplacements: partReplacements }; + this.factoryCreateInstruction = { partReplacements: partReplacements }; } BoundViewFactory.prototype.create = function create(executionContext) { var childContainer = this.parentContainer.createChild(), context = executionContext || this.executionContext; - this.factoryOptions.systemControlled = !executionContext; + this.factoryCreateInstruction.systemControlled = !executionContext; - return this.viewFactory.create(childContainer, context, this.factoryOptions); + return this.viewFactory.create(childContainer, context, this.factoryCreateInstruction); }; return BoundViewFactory; @@ -1638,12 +1835,6 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('BoundViewFactory', BoundViewFactory); - defaultFactoryOptions = { - systemControlled: false, - suppressBind: false, - enhance: false - }; - ViewFactory = (function () { function ViewFactory(template, instructions, resources) { _classCallCheck(this, ViewFactory); @@ -1653,11 +1844,11 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' this.resources = resources; } - ViewFactory.prototype.create = function create(container, executionContext) { - var options = arguments[2] === undefined ? defaultFactoryOptions : arguments[2]; - var element = arguments[3] === undefined ? null : arguments[3]; + ViewFactory.prototype.create = function create(container, executionContext, createInstruction, element) { + createInstruction = createInstruction || BehaviorInstruction.normal; + element = element || null; - var fragment = options.enhance ? this.template : this.template.cloneNode(true), + var fragment = createInstruction.enhance ? this.template : this.template.cloneNode(true), instructables = fragment.querySelectorAll('.au-target'), instructions = this.instructions, resources = this.resources, @@ -1666,12 +1857,12 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' children = [], contentSelectors = [], containers = { root: container }, - partReplacements = options.partReplacements, - i, - ii, - view, - instructable, - instruction; + partReplacements = createInstruction.partReplacements, + i = undefined, + ii = undefined, + view = undefined, + instructable = undefined, + instruction = undefined; if (element !== null && this.surrogateInstruction !== null) { applySurrogateInstruction(container, element, this.surrogateInstruction, behaviors, bindings, children); @@ -1684,10 +1875,13 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' applyInstructions(containers, executionContext, instructable, instruction, behaviors, bindings, children, contentSelectors, partReplacements, resources); } - view = new View(container, fragment, behaviors, bindings, children, options.systemControlled, contentSelectors); - view.created(executionContext); + view = new View(container, fragment, behaviors, bindings, children, createInstruction.systemControlled, contentSelectors); + + if (!createInstruction.initiatedByBehavior) { + view.created(); + } - if (!options.suppressBind) { + if (!createInstruction.suppressBind) { view.bind(executionContext); } @@ -1700,54 +1894,54 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('ViewFactory', ViewFactory); nextInjectorId = 0; - defaultCompileOptions = { targetShadowDOM: false }; - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; lastAUTargetID = 0; ViewCompiler = (function () { - function ViewCompiler(bindingLanguage) { + ViewCompiler.inject = function inject() { + return [BindingLanguage, ViewResources]; + }; + + function ViewCompiler(bindingLanguage, resources) { _classCallCheck(this, ViewCompiler); this.bindingLanguage = bindingLanguage; + this.resources = resources; } - ViewCompiler.inject = function inject() { - return [BindingLanguage]; - }; - - ViewCompiler.prototype.compile = function compile(templateOrFragment, resources) { - var options = arguments[2] === undefined ? defaultCompileOptions : arguments[2]; + ViewCompiler.prototype.compile = function compile(source, resources, compileInstruction) { + resources = resources || this.resources; + compileInstruction = compileInstruction || ViewCompileInstruction.normal; var instructions = {}, - targetShadowDOM = options.targetShadowDOM, - content, - part, - factory; + targetShadowDOM = compileInstruction.targetShadowDOM, + content = undefined, + part = undefined; targetShadowDOM = targetShadowDOM && hasShadowDOM; - if (options.beforeCompile) { - options.beforeCompile(templateOrFragment); + if (compileInstruction.beforeCompile) { + compileInstruction.beforeCompile(source); + console.warn('In a future release, the beforeCompile hook will be replaced by an alternate mechanism'); } - if (typeof templateOrFragment === 'string') { - templateOrFragment = createTemplateFromMarkup(templateOrFragment); + if (typeof source === 'string') { + source = createTemplateFromMarkup(source); } - if (templateOrFragment.content) { - part = templateOrFragment.getAttribute('part'); - content = document.adoptNode(templateOrFragment.content, true); + if (source.content) { + part = source.getAttribute('part'); + content = document.adoptNode(source.content, true); } else { - content = templateOrFragment; + content = source; } - this.compileNode(content, resources, instructions, templateOrFragment, 'root', !targetShadowDOM); + this.compileNode(content, resources, instructions, source, 'root', !targetShadowDOM); content.insertBefore(document.createComment(''), content.firstChild); content.appendChild(document.createComment('')); var factory = new ViewFactory(content, instructions, resources); - factory.surrogateInstruction = options.compileSurrogate ? this.compileSurrogate(templateOrFragment, resources) : null; + factory.surrogateInstruction = compileInstruction.compileSurrogate ? this.compileSurrogate(source, resources) : null; if (part) { factory.part = part; @@ -1761,13 +1955,13 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' case 1: return this.compileElement(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM); case 3: - var expression = this.bindingLanguage.parseText(resources, node.wholeText); + var expression = resources.getBindingLanguage(this.bindingLanguage).parseText(resources, node.wholeText); if (expression) { var marker = document.createElement('au-marker'), auTargetID = makeIntoInstructionTarget(marker); (node.parentNode || parentNode).insertBefore(marker, node); node.textContent = ' '; - instructions[auTargetID] = { contentExpression: expression }; + instructions[auTargetID] = TargetInstruction.contentExpression(expression); while (node.nextSibling && node.nextSibling.nodeType === 3) { (node.parentNode || parentNode).removeChild(node.nextSibling); @@ -1791,7 +1985,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' ViewCompiler.prototype.compileSurrogate = function compileSurrogate(node, resources) { var attributes = node.attributes, - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), knownAttribute = undefined, property = undefined, instruction = undefined, @@ -1857,7 +2051,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } } else { if (type) { - instruction = { attrName: attrName, type: type, attributes: {} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if (type.liftsContent) { @@ -1886,16 +2080,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } } - return { - anchorIsContainer: false, - isCustomElement: false, - injectorId: null, - parentInjectorId: null, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers, - values: values - }; + return TargetInstruction.surrogate(providers, behaviorInstructions, expressions, values); } return null; @@ -1908,7 +2093,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' expression, behaviorInstructions = [], providers = [], - bindingLanguage = this.bindingLanguage, + bindingLanguage = resources.getBindingLanguage(this.bindingLanguage), liftingInstruction, viewFactory, type, @@ -1929,12 +2114,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' if (tagName === 'content') { if (targetLightDOM) { auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - parentInjectorId: parentInjectorId, - contentSelector: true, - selector: node.getAttribute('select'), - suppressBind: true - }; + instructions[auTargetID] = TargetInstruction.contentSelector(node, parentInjectorId); } return node.nextSibling; } else if (tagName === 'template') { @@ -1943,8 +2123,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } else { type = resources.getElement(tagName); if (type) { - elementInstruction = { type: type, attributes: {} }; - elementInstruction.anchorIsContainer = !node.hasAttribute('containerless') && !type.containerless; + elementInstruction = BehaviorInstruction.element(node, type); behaviorInstructions.push(elementInstruction); } } @@ -1971,15 +2150,11 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } } } else if (elementInstruction) { - elementProperty = elementInstruction.type.attributes[info.attrName]; - if (elementProperty) { - info.defaultBindingMode = elementProperty.defaultBindingMode; - - if (!info.command && !info.expression) { - info.command = elementProperty.hasOptions ? 'options' : null; + elementProperty = elementInstruction.type.attributes[info.attrName]; + if (elementProperty) { + info.defaultBindingMode = elementProperty.defaultBindingMode; } } - } if (elementProperty) { instruction = bindingLanguage.createAttributeInstruction(resources, node, info, elementInstruction); @@ -2014,7 +2189,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } } else { if (type) { - instruction = { attrName: attrName, type: type, attributes: {} }; + instruction = BehaviorInstruction.attribute(attrName, type); instruction.attributes[resources.mapAttribute(attrName)] = attrValue; if (type.liftsContent) { @@ -2034,14 +2209,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' liftingInstruction.viewFactory = viewFactory; node = liftingInstruction.type.compile(this, resources, node, liftingInstruction, parentNode); auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: false, - parentInjectorId: parentInjectorId, - expressions: [], - behaviorInstructions: [liftingInstruction], - viewFactory: liftingInstruction.viewFactory, - providers: [liftingInstruction.type.target] - }; + instructions[auTargetID] = TargetInstruction.lifting(parentInjectorId, liftingInstruction); } else { if (expressions.length || behaviorInstructions.length) { injectorId = behaviorInstructions.length ? getNextInjectorId() : false; @@ -2060,15 +2228,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } auTargetID = makeIntoInstructionTarget(node); - instructions[auTargetID] = { - anchorIsContainer: elementInstruction ? elementInstruction.anchorIsContainer : true, - isCustomElement: !!elementInstruction, - injectorId: injectorId, - parentInjectorId: parentInjectorId, - expressions: expressions, - behaviorInstructions: behaviorInstructions, - providers: providers - }; + instructions[auTargetID] = TargetInstruction.normal(injectorId, parentInjectorId, providers, behaviorInstructions, expressions, elementInstruction); } if (elementInstruction && elementInstruction.skipContentProcessing) { @@ -2110,6 +2270,10 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' })(); ViewEngine = (function () { + ViewEngine.inject = function inject() { + return [Loader, Container, ViewCompiler, ModuleAnalyzer, ViewResources]; + }; + function ViewEngine(loader, container, viewCompiler, moduleAnalyzer, appResources) { _classCallCheck(this, ViewEngine); @@ -2120,58 +2284,49 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' this.appResources = appResources; } - ViewEngine.inject = function inject() { - return [Loader, Container, ViewCompiler, ModuleAnalyzer, ResourceRegistry]; - }; - ViewEngine.prototype.enhance = function enhance(container, element, resources, bindingContext) { var instructions = {}; - this.viewCompiler.compileNode(element, resources, instructions, element.parentNode, 'root', true); var factory = new ViewFactory(element, instructions, resources); - var options = { - systemControlled: false, - suppressBind: false, - enhance: true - }; - - return factory.create(container, bindingContext, options); + return factory.create(container, bindingContext, { enhance: true }); }; - ViewEngine.prototype.loadViewFactory = function loadViewFactory(urlOrRegistryEntry, compileOptions, associatedModuleId, loadContext) { + ViewEngine.prototype.loadViewFactory = function loadViewFactory(urlOrRegistryEntry, compileInstruction, loadContext) { var _this5 = this; - loadContext = loadContext || []; + loadContext = loadContext || new ResourceLoadContext(); return ensureRegistryEntry(this.loader, urlOrRegistryEntry).then(function (viewRegistryEntry) { if (viewRegistryEntry.onReady) { - if (loadContext.indexOf(urlOrRegistryEntry) === -1) { - loadContext.push(urlOrRegistryEntry); + if (loadContext.doesNotHaveDependency(urlOrRegistryEntry)) { + loadContext.addDependency(urlOrRegistryEntry); return viewRegistryEntry.onReady; } return Promise.resolve(new ProxyViewFactory(viewRegistryEntry.onReady)); } - loadContext.push(urlOrRegistryEntry); + loadContext.addDependency(urlOrRegistryEntry); - return viewRegistryEntry.onReady = _this5.loadTemplateResources(viewRegistryEntry, associatedModuleId, loadContext).then(function (resources) { + return viewRegistryEntry.onReady = _this5.loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext).then(function (resources) { viewRegistryEntry.setResources(resources); - var viewFactory = _this5.viewCompiler.compile(viewRegistryEntry.template, resources, compileOptions); + var viewFactory = _this5.viewCompiler.compile(viewRegistryEntry.template, resources, compileInstruction); viewRegistryEntry.setFactory(viewFactory); return viewFactory; }); }); }; - ViewEngine.prototype.loadTemplateResources = function loadTemplateResources(viewRegistryEntry, associatedModuleId, loadContext) { + ViewEngine.prototype.loadTemplateResources = function loadTemplateResources(viewRegistryEntry, compileInstruction, loadContext) { var resources = new ViewResources(this.appResources, viewRegistryEntry.id), dependencies = viewRegistryEntry.dependencies, importIds, names; - if (dependencies.length === 0 && !associatedModuleId) { + compileInstruction = compileInstruction || ViewCompileInstruction.normal; + + if (dependencies.length === 0 && !compileInstruction.associatedModuleId) { return Promise.resolve(resources); } @@ -2183,7 +2338,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' }); logger.debug('importing resources for ' + viewRegistryEntry.id, importIds); - return this.importViewResources(importIds, names, resources, associatedModuleId, loadContext); + return this.importViewResources(importIds, names, resources, compileInstruction, loadContext); }; ViewEngine.prototype.importViewModelResource = function importViewModelResource(moduleImport, moduleMember) { @@ -2203,10 +2358,11 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' }); }; - ViewEngine.prototype.importViewResources = function importViewResources(moduleIds, names, resources, associatedModuleId, loadContext) { + ViewEngine.prototype.importViewResources = function importViewResources(moduleIds, names, resources, compileInstruction, loadContext) { var _this7 = this; - loadContext = loadContext || []; + loadContext = loadContext || new ResourceLoadContext(); + compileInstruction = compileInstruction || ViewCompileInstruction.normal; return this.loader.loadAllModules(moduleIds).then(function (imports) { var i, @@ -2230,8 +2386,8 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' allAnalysis[i] = analysis; } - if (associatedModuleId) { - associatedModule = moduleAnalyzer.getAnalysis(associatedModuleId); + if (compileInstruction.associatedModuleId) { + associatedModule = moduleAnalyzer.getAnalysis(compileInstruction.associatedModuleId); if (associatedModule) { associatedModule.register(resources); @@ -2649,9 +2805,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' return BehaviorPropertyObserver; })(); - defaultInstruction = { suppressBind: false }; - contentSelectorFactoryOptions = { suppressBind: true, enhance: false }; - hasShadowDOM = !!HTMLElement.prototype.createShadowRoot; + contentSelectorViewCreateInstruction = { suppressBind: true, enhance: false }; HtmlBehaviorResource = (function () { function HtmlBehaviorResource() { @@ -2763,11 +2917,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' if (this.elementName !== null) { viewStrategy = viewStrategy || this.viewStrategy || ViewStrategy.getDefault(target); - options = { - targetShadowDOM: this.targetShadowDOM, - beforeCompile: target.beforeCompile, - compileSurrogate: true - }; + options = new ViewCompileInstruction(this.targetShadowDOM, true, target.beforeCompile); if (!viewStrategy.moduleId) { viewStrategy.moduleId = Origin.get(target).moduleId; @@ -2861,17 +3011,16 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } } - instruction.suppressBind = true; return node; }; - HtmlBehaviorResource.prototype.create = function create(container) { - var instruction = arguments[1] === undefined ? defaultInstruction : arguments[1]; - var element = arguments[2] === undefined ? null : arguments[2]; - var bindings = arguments[3] === undefined ? null : arguments[3]; - + HtmlBehaviorResource.prototype.create = function create(container, instruction, element, bindings) { var host = undefined; + instruction = instruction || BehaviorInstruction.normal; + element = element || null; + bindings = bindings || null; + if (this.elementName !== null && element) { if (this.usesShadowDOM) { host = element.createShadowRoot(); @@ -2906,7 +3055,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' if (behaviorInstance.view) { if (!this.usesShadowDOM) { if (instruction.contentFactory) { - var contentView = instruction.contentFactory.create(container, null, contentSelectorFactoryOptions); + var contentView = instruction.contentFactory.create(container, null, contentSelectorViewCreateInstruction); ContentSelector.applySelectors(contentView, behaviorInstance.view.contentSelectors, function (contentSelector, group) { return contentSelector.add(group); @@ -2961,6 +3110,10 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } } + if (instruction.initiatedByBehavior && viewFactory) { + behaviorInstance.view.created(); + } + return behaviorInstance; }; @@ -3122,7 +3275,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' }; ResourceDescription.get = function get(resource) { - var key = arguments[1] === undefined ? 'custom-resource' : arguments[1]; + var key = arguments.length <= 1 || arguments[1] === undefined ? 'custom-resource' : arguments[1]; var resourceTypeMeta = Metadata.get(Metadata.resource, resource), resourceDescription; @@ -3377,16 +3530,16 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' _export('ChildObserverBinder', ChildObserverBinder); CompositionEngine = (function () { + CompositionEngine.inject = function inject() { + return [ViewEngine]; + }; + function CompositionEngine(viewEngine) { _classCallCheck(this, CompositionEngine); this.viewEngine = viewEngine; } - CompositionEngine.inject = function inject() { - return [ViewEngine]; - }; - CompositionEngine.prototype.activate = function activate(instruction) { if (instruction.skipActivation || typeof instruction.viewModel.activate !== 'function') { return Promise.resolve(); @@ -3446,12 +3599,7 @@ System.register(['core-js', 'aurelia-metadata', 'aurelia-path', 'aurelia-loader' } return doneLoading.then(function (viewFactory) { - return metadata.create(childContainer, { - executionContext: viewModel, - viewFactory: viewFactory, - suppressBind: true, - host: instruction.host - }); + return metadata.create(childContainer, BehaviorInstruction.dynamic(instruction.host, viewModel, viewFactory)); }); }); }; diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 8a54cc5d..3f2526a7 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -1,3 +1,26 @@ +## 0.14.0 (2015-08-14) + + +#### Bug Fixes + +* **all:** + * cleanup and improving api ([9cb96ff8](http://github.com/aurelia/templating/commit/9cb96ff825519f38b9998d5936431c2b61038856)) + * code cleanup and api stabilization work ([c0220a8d](http://github.com/aurelia/templating/commit/c0220a8da78edee893800958df020da3888a2ed3)) +* **dom:** string parsing of views now requires a template tag ([45113364](http://github.com/aurelia/templating/commit/45113364cbe00f91790a64be3a2d0c07144c549c)) +* **templating:** Use correct import for core-js We were previously using `import core from core-j ([29e4a62b](http://github.com/aurelia/templating/commit/29e4a62b96e594431682682259d852256c46af4b)) +* **view-engine:** api cleanup ([a203455a](http://github.com/aurelia/templating/commit/a203455a0d0093e13cdd6289621d111134c8b0ad)) +* **view-factory:** cleanup and standardizing api for view creation ([1258f476](http://github.com/aurelia/templating/commit/1258f476fb9d11979b810d6d7b967c6bed00b006)) + + +#### Features + +* **view-compiler:** + * working on cleanup of api ([5654d1a1](http://github.com/aurelia/templating/commit/5654d1a13ed0cc58482e824c08357a72baebb8e0)) + * enable per-view binding languages ([e5e957d1](http://github.com/aurelia/templating/commit/e5e957d17493045b804b640903a4674595c20030)) +* **view-factory:** enable injection of TargetInstruction ([961604ab](http://github.com/aurelia/templating/commit/961604ab98e4f22326ad38d9cc369c80114c7921)) +* **view-resources:** remove ResourceRegistry and simplify class hierarchy ([bcba0896](http://github.com/aurelia/templating/commit/bcba08964bb7c5d188245fa028d1f7d8e2f2d20f)) + + ### 0.13.16 (2015-08-05) diff --git a/package.json b/package.json index 55aaf204..0ea05798 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aurelia-templating", - "version": "0.13.16", + "version": "0.14.0", "description": "An extensible HTML templating engine supporting databinding, custom elements, attached behaviors and more.", "keywords": [ "aurelia", @@ -27,14 +27,14 @@ "lib": "dist/amd" }, "dependencies": { - "aurelia-binding": "github:aurelia/binding@^0.8.3", - "aurelia-dependency-injection": "github:aurelia/dependency-injection@^0.9.1", + "aurelia-binding": "github:aurelia/binding@^0.8.6", + "aurelia-dependency-injection": "github:aurelia/dependency-injection@^0.9.2", "aurelia-html-template-element": "github:aurelia/html-template-element@^0.2.0", - "aurelia-loader": "github:aurelia/loader@^0.8.3", - "aurelia-logging": "github:aurelia/logging@^0.6.2", - "aurelia-metadata": "github:aurelia/metadata@^0.7.1", + "aurelia-loader": "github:aurelia/loader@^0.8.5", + "aurelia-logging": "github:aurelia/logging@^0.6.4", + "aurelia-metadata": "github:aurelia/metadata@^0.7.3", "aurelia-path": "github:aurelia/path@^0.8.1", - "aurelia-task-queue": "github:aurelia/task-queue@^0.6.1", + "aurelia-task-queue": "github:aurelia/task-queue@^0.6.2", "core-js": "npm:core-js@^0.9.5" }, "devDependencies": {