import {isPresent} from 'angular2/src/facade/lang'; import {Promise} from 'angular2/src/facade/async'; import {List, Map} from 'angular2/src/facade/collection'; import {ASTWithSource} from 'angular2/change_detection'; /** * General notes: * * The methods for creating / destroying views in this API are used in the AppViewHydrator * and RenderViewHydrator as well. * * We are already parsing expressions on the render side: * - this makes the ElementBinders more compact * (e.g. no need to distinguish interpolations from regular expressions from literals) * - allows to retrieve which properties should be accessed from the event * by looking at the expression * - we need the parse at least for the `template` attribute to match * directives in it * - render compiler is not on the critical path as * its output will be stored in precompiled templates. */ export class EventBinding { fullName: string; // name/target:name, e.g "click", "window:resize" source: ASTWithSource; constructor(fullName :string, source: ASTWithSource) { this.fullName = fullName; this.source = source; } } export class ElementBinder { index:number; parentIndex:number; distanceToParent:number; directives:List; nestedProtoView:ProtoViewDto; propertyBindings: Map; variableBindings: Map; // Note: this contains a preprocessed AST // that replaced the values that should be extracted from the element // with a local name eventBindings: List; textBindings: List; readAttributes: Map; constructor({ index, parentIndex, distanceToParent, directives, nestedProtoView, propertyBindings, variableBindings, eventBindings, textBindings, readAttributes }) { this.index = index; this.parentIndex = parentIndex; this.distanceToParent = distanceToParent; this.directives = directives; this.nestedProtoView = nestedProtoView; this.propertyBindings = propertyBindings; this.variableBindings = variableBindings; this.eventBindings = eventBindings; this.textBindings = textBindings; this.readAttributes = readAttributes; } } export class DirectiveBinder { // Index into the array of directives in the View instance directiveIndex:any; propertyBindings: Map; // Note: this contains a preprocessed AST // that replaced the values that should be extracted from the element // with a local name eventBindings: List; constructor({ directiveIndex, propertyBindings, eventBindings }) { this.directiveIndex = directiveIndex; this.propertyBindings = propertyBindings; this.eventBindings = eventBindings; } } export class ProtoViewDto { // A view that contains the host element with bound // component directive. // Contains a view of type #COMPONENT_VIEW_TYPE. static get HOST_VIEW_TYPE() { return 0; } // The view of the component // Can contain 0 to n views of type #EMBEDDED_VIEW_TYPE static get COMPONENT_VIEW_TYPE() { return 1; } // A view that is included via a Viewport directive // inside of a component view static get EMBEDDED_VIEW_TYPE() { return 1; } render: ProtoViewRef; elementBinders:List; variableBindings: Map; type: number; constructor({render, elementBinders, variableBindings, type}={}) { this.render = render; this.elementBinders = elementBinders; this.variableBindings = variableBindings; this.type = type; } } export class DirectiveMetadata { static get DECORATOR_TYPE() { return 0; } static get COMPONENT_TYPE() { return 1; } static get VIEWPORT_TYPE() { return 2; } id:any; selector:string; compileChildren:boolean; hostListeners:Map; properties:Map; setters:List; readAttributes:List; type:number; constructor({id, selector, compileChildren, hostListeners, properties, setters, readAttributes, type}) { this.id = id; this.selector = selector; this.compileChildren = isPresent(compileChildren) ? compileChildren : true; this.hostListeners = hostListeners; this.properties = properties; this.setters = setters; this.readAttributes = readAttributes; this.type = type; } } // An opaque reference to a RenderProtoView export class ProtoViewRef {} // An opaque reference to a RenderView export class ViewRef {} export class ViewContainerRef { view:ViewRef; elementIndex:number; constructor(view:ViewRef, elementIndex: number) { this.view = view; this.elementIndex = elementIndex; } } export class ViewDefinition { componentId: string; absUrl: string; template: string; directives: List; constructor({componentId, absUrl, template, directives}) { this.componentId = componentId; this.absUrl = absUrl; this.template = template; this.directives = directives; } } export class Renderer { /** * Creats a ProtoViewDto that contains a single nested component with the given componentId. */ createHostProtoView(componentId):Promise { return null; } /** * Creats a ProtoViewDto for a component that will use an imperative View using the given * renderer. * Note: Rigth now, the renderer argument is ignored, but will be used in the future to define * a custom handler. */ createImperativeComponentProtoView(rendererId):Promise { return null; } /** * Compiles a single RenderProtoView. Non recursive so that * we don't need to serialize all possible components over the wire, * but only the needed ones based on previous calls. */ compile(template:ViewDefinition):Promise { return null; } /** * Sets the preset nested components, * which will be instantiated when this protoView is instantiated. * Note: We can't create new ProtoViewRefs here as we need to support cycles / recursive components. * @param {List} protoViewRefs * RenderProtoView for every element with a component in this protoView or in a view container's protoView */ mergeChildComponentProtoViews(protoViewRef:ProtoViewRef, componentProtoViewRefs:List) { return null; } /** * Creates a view and inserts it into a ViewContainer. * @param {ViewContainerRef} viewContainerRef * @param {ProtoViewRef} protoViewRef A ProtoViewRef of type ProtoViewDto.HOST_VIEW_TYPE or ProtoViewDto.EMBEDDED_VIEW_TYPE * @param {number} atIndex * @return {List} the view and all of its nested child component views */ createViewInContainer(vcRef:ViewContainerRef, atIndex:number, protoViewRef:ProtoViewRef):List { return null; } /** * Destroys the view in the given ViewContainer */ destroyViewInContainer(vcRef:ViewContainerRef, atIndex:number):void {} /** * Inserts a detached view into a viewContainer. */ insertViewIntoContainer(vcRef:ViewContainerRef, atIndex:number, view:ViewRef):void {} /** * Detaches a view from a container so that it can be inserted later on */ detachViewFromContainer(vcRef:ViewContainerRef, atIndex:number):void {} /** * Creates a view and * installs it as a shadow view for an element. * * Note: only allowed if there is a dynamic component directive at this place. * @param {ViewRef} hostView * @param {number} elementIndex * @param {ProtoViewRef} componentProtoViewRef A ProtoViewRef of type ProtoViewDto.COMPONENT_VIEW_TYPE * @return {List} the view and all of its nested child component views */ createDynamicComponentView(hostViewRef:ViewRef, elementIndex:number, componentProtoViewRef:ProtoViewRef):List { return null; } /** * Destroys the component view at the given index * * Note: only allowed if there is a dynamic component directive at this place. */ destroyDynamicComponentView(hostViewRef:ViewRef, elementIndex:number):void {} /** * Creates a host view that includes the given element. * @param {ViewRef} parentViewRef (might be null) * @param {any} hostElementSelector element or css selector for the host element * @param {ProtoViewRef} hostProtoView a ProtoViewRef of type ProtoViewDto.HOST_VIEW_TYPE * @return {List} the view and all of its nested child component views */ createInPlaceHostView(parentViewRef:ViewRef, hostElementSelector, hostProtoViewRef:ProtoViewRef):List { return null; } /** * Destroys the given host view in the given parent view. */ destroyInPlaceHostView(parentViewRef:ViewRef, hostViewRef:ViewRef):void {} /** * Sets a property on an element. * Note: This will fail if the property was not mentioned previously as a propertySetter * in the View. */ setElementProperty(view:ViewRef, elementIndex:number, propertyName:string, propertyValue:any):void {} /** * This will set the value for a text node. * Note: This needs to be separate from setElementProperty as we don't have ElementBinders * for text nodes in the RenderProtoView either. */ setText(view:ViewRef, textNodeIndex:number, text:string):void {} /** * Sets the dispatcher for all events that have been defined in the template or in directives * in the given view. */ setEventDispatcher(viewRef:ViewRef, dispatcher:any/*EventDispatcher*/):void {} /** * To be called at the end of the VmTurn so the API can buffer calls */ flush():void {} } /** * A dispatcher for all events happening in a view. */ export class EventDispatcher { /** * Called when an event was triggered for a on-* attribute on an element. * @param {Map} locals Locals to be used to evaluate the * event expressions */ dispatchEvent( elementIndex:number, eventName:string, locals:Map ):void {} }