UNPKG

angular2

Version:

Angular 2 - a web framework for modern web apps

269 lines 11.8 kB
import { isBlank, isPresent, StringWrapper } from 'angular2/src/facade/lang'; import { DefaultRenderView, DefaultRenderFragmentRef } from './view'; import { ViewEncapsulation } from 'angular2/src/core/metadata'; import { ListWrapper } from 'angular2/src/facade/collection'; export function encapsulateStyles(componentTemplate) { var processedStyles = componentTemplate.styles; if (componentTemplate.encapsulation === ViewEncapsulation.Emulated) { processedStyles = ListWrapper.createFixedSize(componentTemplate.styles.length); for (var i = 0; i < componentTemplate.styles.length; i++) { processedStyles[i] = StringWrapper.replaceAll(componentTemplate.styles[i], COMPONENT_REGEX, componentTemplate.shortId); } } return processedStyles; } export function createRenderView(componentTemplate, cmds, inplaceElement, nodeFactory) { var view; var eventDispatcher = (boundElementIndex, eventName, event) => view.dispatchRenderEvent(boundElementIndex, eventName, event); var context = new BuildContext(eventDispatcher, nodeFactory, inplaceElement); context.build(componentTemplate, cmds); var fragments = []; for (var i = 0; i < context.fragments.length; i++) { fragments.push(new DefaultRenderFragmentRef(context.fragments[i])); } view = new DefaultRenderView(fragments, context.boundTextNodes, context.boundElements, context.nativeShadowRoots, context.globalEventAdders, context.rootContentInsertionPoints); return view; } class BuildContext { constructor(_eventDispatcher, factory, _inplaceElement) { this._eventDispatcher = _eventDispatcher; this.factory = factory; this._inplaceElement = _inplaceElement; this._builders = []; this.globalEventAdders = []; this.boundElements = []; this.boundTextNodes = []; this.nativeShadowRoots = []; this.fragments = []; this.rootContentInsertionPoints = []; this.componentCount = 0; this.isHost = isPresent((_inplaceElement)); } build(template, cmds) { this.enqueueRootBuilder(template, cmds); this._build(this._builders[0]); } _build(builder) { this._builders = []; builder.build(this); var enqueuedBuilders = this._builders; for (var i = 0; i < enqueuedBuilders.length; i++) { this._build(enqueuedBuilders[i]); } } enqueueComponentBuilder(component) { this.componentCount++; this._builders.push(new RenderViewBuilder(component, null, component.template, component.template.commands)); } enqueueFragmentBuilder(parentComponent, parentTemplate, commands) { var rootNodes = []; this.fragments.push(rootNodes); this._builders.push(new RenderViewBuilder(parentComponent, rootNodes, parentTemplate, commands)); } enqueueRootBuilder(template, cmds) { var rootNodes = []; this.fragments.push(rootNodes); this._builders.push(new RenderViewBuilder(null, rootNodes, template, cmds)); } consumeInplaceElement() { var result = this._inplaceElement; this._inplaceElement = null; return result; } addEventListener(boundElementIndex, target, eventName) { if (isPresent(target)) { var handler = createEventHandler(boundElementIndex, `${target}:${eventName}`, this._eventDispatcher); this.globalEventAdders.push(createGlobalEventAdder(target, eventName, handler, this.factory)); } else { var handler = createEventHandler(boundElementIndex, eventName, this._eventDispatcher); this.factory.on(this.boundElements[boundElementIndex], eventName, handler); } } } function createEventHandler(boundElementIndex, eventName, eventDispatcher) { return ($event) => eventDispatcher(boundElementIndex, eventName, $event); } function createGlobalEventAdder(target, eventName, eventHandler, nodeFactory) { return () => nodeFactory.globalOn(target, eventName, eventHandler); } class RenderViewBuilder { constructor(parentComponent, fragmentRootNodes, template, cmds) { this.parentComponent = parentComponent; this.fragmentRootNodes = fragmentRootNodes; this.template = template; this.cmds = cmds; var rootNodesParent = isPresent(fragmentRootNodes) ? null : parentComponent.shadowRoot; this.parentStack = [rootNodesParent]; } build(context) { var cmds = this.cmds; for (var i = 0; i < cmds.length; i++) { cmds[i].visit(this, context); } } get parent() { return this.parentStack[this.parentStack.length - 1]; } visitText(cmd, context) { var text = context.factory.createText(cmd.value); this._addChild(text, cmd.ngContentIndex, context); if (cmd.isBound) { context.boundTextNodes.push(text); } return null; } visitNgContent(cmd, context) { if (isPresent(this.parentComponent)) { if (this.parentComponent.isRoot) { var insertionPoint = context.factory.createRootContentInsertionPoint(); if (this.parent instanceof Component) { context.factory.appendChild(this.parent.shadowRoot, insertionPoint); } else { context.factory.appendChild(this.parent, insertionPoint); } context.rootContentInsertionPoints.push(insertionPoint); } else { var projectedNodes = this.parentComponent.project(cmd.index); for (var i = 0; i < projectedNodes.length; i++) { var node = projectedNodes[i]; this._addChild(node, cmd.ngContentIndex, context); } } } return null; } visitBeginElement(cmd, context) { this.parentStack.push(this._beginElement(cmd, context, null)); return null; } visitEndElement(context) { this._endElement(); return null; } visitBeginComponent(cmd, context) { var templateId = cmd.templateId; var tpl = context.factory.resolveComponentTemplate(templateId); var el = this._beginElement(cmd, context, tpl); var root = el; if (tpl.encapsulation === ViewEncapsulation.Native) { root = context.factory.createShadowRoot(el, templateId); context.nativeShadowRoots.push(root); } var isRoot = context.componentCount === 0 && context.isHost; var component = new Component(el, root, isRoot, tpl); context.enqueueComponentBuilder(component); this.parentStack.push(component); return null; } visitEndComponent(context) { this._endElement(); return null; } visitEmbeddedTemplate(cmd, context) { var el = context.factory.createTemplateAnchor(cmd.attrNameAndValues); this._addChild(el, cmd.ngContentIndex, context); context.boundElements.push(el); if (cmd.isMerged) { context.enqueueFragmentBuilder(this.parentComponent, this.template, cmd.children); } return null; } _beginElement(cmd, context, componentTemplate) { var el = context.consumeInplaceElement(); var attrNameAndValues = cmd.attrNameAndValues; var templateEmulatedEncapsulation = this.template.encapsulation === ViewEncapsulation.Emulated; var componentEmulatedEncapsulation = isPresent(componentTemplate) && componentTemplate.encapsulation === ViewEncapsulation.Emulated; var newAttrLength = attrNameAndValues.length + (templateEmulatedEncapsulation ? 2 : 0) + (componentEmulatedEncapsulation ? 2 : 0); if (newAttrLength > attrNameAndValues.length) { // Note: Need to clone attrNameAndValues to make it writable! var newAttrNameAndValues = ListWrapper.createFixedSize(newAttrLength); var attrIndex; for (attrIndex = 0; attrIndex < attrNameAndValues.length; attrIndex++) { newAttrNameAndValues[attrIndex] = attrNameAndValues[attrIndex]; } if (templateEmulatedEncapsulation) { newAttrNameAndValues[attrIndex++] = _shimContentAttribute(this.template.shortId); newAttrNameAndValues[attrIndex++] = ''; } if (componentEmulatedEncapsulation) { newAttrNameAndValues[attrIndex++] = _shimHostAttribute(componentTemplate.shortId); newAttrNameAndValues[attrIndex++] = ''; } attrNameAndValues = newAttrNameAndValues; } if (isPresent(el)) { context.factory.mergeElement(el, attrNameAndValues); this.fragmentRootNodes.push(el); } else { el = context.factory.createElement(cmd.name, attrNameAndValues); this._addChild(el, cmd.ngContentIndex, context); } if (cmd.isBound) { var boundElementIndex = context.boundElements.length; context.boundElements.push(el); for (var i = 0; i < cmd.eventTargetAndNames.length; i += 2) { var target = cmd.eventTargetAndNames[i]; var eventName = cmd.eventTargetAndNames[i + 1]; context.addEventListener(boundElementIndex, target, eventName); } } return el; } _endElement() { this.parentStack.pop(); } _addChild(node, ngContentIndex, context) { var parent = this.parent; if (isPresent(parent)) { if (parent instanceof Component) { parent.addContentNode(ngContentIndex, node, context); } else { context.factory.appendChild(parent, node); } } else { this.fragmentRootNodes.push(node); } } } class Component { constructor(hostElement, shadowRoot, isRoot, template) { this.hostElement = hostElement; this.shadowRoot = shadowRoot; this.isRoot = isRoot; this.template = template; this.contentNodesByNgContentIndex = []; } addContentNode(ngContentIndex, node, context) { if (isBlank(ngContentIndex)) { if (this.template.encapsulation === ViewEncapsulation.Native) { context.factory.appendChild(this.hostElement, node); } } else { while (this.contentNodesByNgContentIndex.length <= ngContentIndex) { this.contentNodesByNgContentIndex.push([]); } this.contentNodesByNgContentIndex[ngContentIndex].push(node); } } project(ngContentIndex) { return ngContentIndex < this.contentNodesByNgContentIndex.length ? this.contentNodesByNgContentIndex[ngContentIndex] : []; } } var COMPONENT_REGEX = /%COMP%/g; export const COMPONENT_VARIABLE = '%COMP%'; export const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`; export const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`; function _shimContentAttribute(componentShortId) { return StringWrapper.replaceAll(CONTENT_ATTR, COMPONENT_REGEX, componentShortId); } function _shimHostAttribute(componentShortId) { return StringWrapper.replaceAll(HOST_ATTR, COMPONENT_REGEX, componentShortId); } //# sourceMappingURL=view_factory.js.map