chore(typing): extract abstract superclasses to replace @private constructors

This commit is contained in:
Alex Eagle
2015-10-06 06:53:39 -07:00
committed by vsavkin
parent ee32b1bc37
commit 6075509f26
65 changed files with 994 additions and 797 deletions
+29 -43
View File
@@ -13,12 +13,10 @@ import {Map} from 'angular2/src/core/facade/collection';
*
* <!-- TODO: this is created by Renderer#createProtoView in the new compiler -->
*/
// TODO(i): refactor this to an interface
export class RenderProtoViewRef {
/**
* @internal
*/
constructor() {}
export abstract class RenderProtoViewRef {}
export class RenderProtoViewRef_ extends RenderProtoViewRef {
constructor() { super(); }
}
@@ -152,6 +150,7 @@ export interface RenderElementRef {
* Reference to the Render View that contains this Element.
*/
renderView: RenderViewRef;
/**
* Index of the Element (in the depth-first order) inside the Render View.
*
@@ -173,17 +172,7 @@ export interface RenderElementRef {
*
* The default Renderer implementation is {@link DomRenderer}. Also see {@link WebWorkerRenderer}.
*/
export class Renderer {
/**
* @internal
*
* Private constructor is required so that this class gets converted into an interface in our
* public api.
*
* We implement this a class so that we have a DI token available for binding.
*/
constructor(){};
export abstract class Renderer {
/**
* Registers a component template represented as arrays of {@link RenderTemplateCmd}s and styles
* with the Renderer.
@@ -191,13 +180,13 @@ export class Renderer {
* Once a template is registered it can be referenced via {@link RenderBeginComponentCmd} when
* {@link #createProtoView creating Render ProtoView}.
*/
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[],
nativeShadow: boolean) {}
abstract registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[],
styles: string[], nativeShadow: boolean);
/**
* Creates a {@link RenderProtoViewRef} from an array of {@link RenderTemplateCmd}`s.
*/
createProtoView(cmds: RenderTemplateCmd[]): RenderProtoViewRef { return null; }
abstract createProtoView(cmds: RenderTemplateCmd[]): RenderProtoViewRef;
/**
* Creates a Root Host View based on the provided `hostProtoViewRef`.
@@ -211,10 +200,8 @@ export class Renderer {
*
* Returns an instance of {@link RenderViewWithFragments}, representing the Render View.
*/
createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
hostElementSelector: string): RenderViewWithFragments {
return null;
}
abstract createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
hostElementSelector: string): RenderViewWithFragments;
/**
* Creates a Render View based on the provided `protoViewRef`.
@@ -225,9 +212,8 @@ export class Renderer {
*
* Returns an instance of {@link RenderViewWithFragments}, representing the Render View.
*/
createView(protoViewRef: RenderProtoViewRef, fragmentCount: number): RenderViewWithFragments {
return null;
}
abstract createView(protoViewRef: RenderProtoViewRef, fragmentCount: number):
RenderViewWithFragments;
/**
* Destroys a Render View specified via `viewRef`.
@@ -239,18 +225,18 @@ export class Renderer {
* future operations. If the Renderer created any renderer-specific objects for this View, these
* objects should now be destroyed to prevent memory leaks.
*/
destroyView(viewRef: RenderViewRef) {}
abstract destroyView(viewRef: RenderViewRef);
/**
* Attaches the Nodes of a Render Fragment after the last Node of `previousFragmentRef`.
*/
attachFragmentAfterFragment(previousFragmentRef: RenderFragmentRef,
fragmentRef: RenderFragmentRef) {}
abstract attachFragmentAfterFragment(previousFragmentRef: RenderFragmentRef,
fragmentRef: RenderFragmentRef);
/**
* Attaches the Nodes of the Render Fragment after an Element.
*/
attachFragmentAfterElement(elementRef: RenderElementRef, fragmentRef: RenderFragmentRef) {}
abstract attachFragmentAfterElement(elementRef: RenderElementRef, fragmentRef: RenderFragmentRef);
/**
* Detaches the Nodes of a Render Fragment from their parent.
@@ -258,7 +244,7 @@ export class Renderer {
* This operations should be called only on a View that has been already
* {@link #dehydrateView dehydrated}.
*/
detachFragment(fragmentRef: RenderFragmentRef) {}
abstract detachFragment(fragmentRef: RenderFragmentRef);
/**
* Notifies a custom Renderer to initialize a Render View.
@@ -266,7 +252,7 @@ export class Renderer {
* This method is called by Angular after a Render View has been created, or when a previously
* dehydrated Render View is about to be reused.
*/
hydrateView(viewRef: RenderViewRef) {}
abstract hydrateView(viewRef: RenderViewRef);
/**
* Notifies a custom Renderer that a Render View is no longer active.
@@ -274,7 +260,7 @@ export class Renderer {
* This method is called by Angular before a Render View will be destroyed, or when a hydrated
* Render View is about to be put into a pool for future reuse.
*/
dehydrateView(viewRef: RenderViewRef) {}
abstract dehydrateView(viewRef: RenderViewRef);
/**
* Returns the underlying native element at the specified `location`, or `null` if direct access
@@ -293,38 +279,39 @@ export class Renderer {
* </p>
* </div>
*/
getNativeElementSync(location: RenderElementRef): any { return null; }
abstract getNativeElementSync(location: RenderElementRef): any;
/**
* Sets a property on the Element specified via `location`.
*/
setElementProperty(location: RenderElementRef, propertyName: string, propertyValue: any) {}
abstract setElementProperty(location: RenderElementRef, propertyName: string, propertyValue: any);
/**
* Sets an attribute on the Element specified via `location`.
*
* If `attributeValue` is `null`, the attribute is removed.
*/
setElementAttribute(location: RenderElementRef, attributeName: string, attributeValue: string) {}
abstract setElementAttribute(location: RenderElementRef, attributeName: string,
attributeValue: string);
/**
* Sets a (CSS) class on the Element specified via `location`.
*
* `isAdd` specifies if the class should be added or removed.
*/
setElementClass(location: RenderElementRef, className: string, isAdd: boolean) {}
abstract setElementClass(location: RenderElementRef, className: string, isAdd: boolean);
/**
* Sets a (CSS) inline style on the Element specified via `location`.
*
* If `styleValue` is `null`, the style is removed.
*/
setElementStyle(location: RenderElementRef, styleName: string, styleValue: string) {}
abstract setElementStyle(location: RenderElementRef, styleName: string, styleValue: string);
/**
* Calls a method on the Element specified via `location`.
*/
invokeElementMethod(location: RenderElementRef, methodName: string, args: any[]) {}
abstract invokeElementMethod(location: RenderElementRef, methodName: string, args: any[]);
/**
* Sets the value of an interpolated TextNode at the specified index to the `text` value.
@@ -332,7 +319,7 @@ export class Renderer {
* `textNodeIndex` is the depth-first index of the Node among interpolated Nodes in the Render
* View.
*/
setText(viewRef: RenderViewRef, textNodeIndex: number, text: string) {}
abstract setText(viewRef: RenderViewRef, textNodeIndex: number, text: string);
/**
* Sets a dispatcher to relay all events triggered in the given Render View.
@@ -340,10 +327,9 @@ export class Renderer {
* Each Render View can have only one Event Dispatcher, if this method is called multiple times,
* the last provided dispatcher will be used.
*/
setEventDispatcher(viewRef: RenderViewRef, dispatcher: RenderEventDispatcher) {}
abstract setEventDispatcher(viewRef: RenderViewRef, dispatcher: RenderEventDispatcher);
}
/**
* A dispatcher that relays all events that occur in a Render View.
*
@@ -32,74 +32,23 @@ import {createRenderView, NodeFactory} from '../view_factory';
import {DefaultRenderView, DefaultRenderFragmentRef, DefaultProtoViewRef} from '../view';
import {camelCaseToDashCase} from './util';
@Injectable()
export class DomRenderer implements Renderer, NodeFactory<Node> {
private _componentCmds: Map<number, RenderTemplateCmd[]> = new Map<number, RenderTemplateCmd[]>();
private _nativeShadowStyles: Map<number, string[]> = new Map<number, string[]>();
private _document;
export abstract class DomRenderer extends Renderer implements NodeFactory<Node> {
abstract registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[],
styles: string[], nativeShadow: boolean);
/**
* @internal
*/
constructor(private _eventManager: EventManager,
private _domSharedStylesHost: DomSharedStylesHost, private _animate: AnimationBuilder,
@Inject(DOCUMENT) document) {
this._document = document;
}
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[],
nativeShadow: boolean) {
this._componentCmds.set(templateId, commands);
if (nativeShadow) {
this._nativeShadowStyles.set(templateId, styles);
} else {
this._domSharedStylesHost.addStyles(styles);
}
}
resolveComponentTemplate(templateId: number): RenderTemplateCmd[] {
return this._componentCmds.get(templateId);
}
abstract resolveComponentTemplate(templateId: number): RenderTemplateCmd[];
createProtoView(cmds: RenderTemplateCmd[]): RenderProtoViewRef {
return new DefaultProtoViewRef(cmds);
}
_createRootHostViewScope: WtfScopeFn = wtfCreateScope('DomRenderer#createRootHostView()');
createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
hostElementSelector: string): RenderViewWithFragments {
var s = this._createRootHostViewScope();
var element = DOM.querySelector(this._document, hostElementSelector);
if (isBlank(element)) {
wtfLeave(s);
throw new BaseException(`The selector "${hostElementSelector}" did not match any elements`);
}
return wtfLeave(s, this._createView(hostProtoViewRef, element));
}
abstract createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
hostElementSelector: string): RenderViewWithFragments;
_createViewScope = wtfCreateScope('DomRenderer#createView()');
createView(protoViewRef: RenderProtoViewRef, fragmentCount: number): RenderViewWithFragments {
var s = this._createViewScope();
return wtfLeave(s, this._createView(protoViewRef, null));
}
abstract createView(protoViewRef: RenderProtoViewRef, fragmentCount: number):
RenderViewWithFragments;
private _createView(protoViewRef: RenderProtoViewRef,
inplaceElement: HTMLElement): RenderViewWithFragments {
var view = createRenderView((<DefaultProtoViewRef>protoViewRef).cmds, inplaceElement, this);
var sdRoots = view.nativeShadowRoots;
for (var i = 0; i < sdRoots.length; i++) {
this._domSharedStylesHost.addHost(sdRoots[i]);
}
return new RenderViewWithFragments(view, view.fragments);
}
destroyView(viewRef: RenderViewRef) {
var view = <DefaultRenderView<Node>>viewRef;
var sdRoots = view.nativeShadowRoots;
for (var i = 0; i < sdRoots.length; i++) {
this._domSharedStylesHost.removeHost(sdRoots[i]);
}
}
abstract destroyView(viewRef: RenderViewRef);
getNativeElementSync(location: RenderElementRef): any {
return resolveInternalDomView(location.renderView).boundElements[location.boundElementIndex];
@@ -130,35 +79,14 @@ export class DomRenderer implements Renderer, NodeFactory<Node> {
* Performs animations if necessary
* @param node
*/
animateNodeEnter(node: Node) {
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
DOM.addClass(node, 'ng-enter');
this._animate.css()
.addAnimationClass('ng-enter-active')
.start(<HTMLElement>node)
.onComplete(() => { DOM.removeClass(node, 'ng-enter'); });
}
}
abstract animateNodeEnter(node: Node);
/**
* If animations are necessary, performs animations then removes the element; otherwise, it just
* removes the element.
* @param node
*/
animateNodeLeave(node: Node) {
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
DOM.addClass(node, 'ng-leave');
this._animate.css()
.addAnimationClass('ng-leave-active')
.start(<HTMLElement>node)
.onComplete(() => {
DOM.removeClass(node, 'ng-leave');
DOM.remove(node);
});
} else {
DOM.remove(node);
}
}
abstract animateNodeLeave(node: Node);
attachFragmentAfterElement(elementRef: RenderElementRef, fragmentRef: RenderFragmentRef) {
var parentView = resolveInternalDomView(elementRef.renderView);
@@ -168,15 +96,7 @@ export class DomRenderer implements Renderer, NodeFactory<Node> {
this.animateNodesEnter(nodes);
}
_detachFragmentScope = wtfCreateScope('DomRenderer#detachFragment()');
detachFragment(fragmentRef: RenderFragmentRef) {
var s = this._detachFragmentScope();
var fragmentNodes = resolveInternalDomFragment(fragmentRef);
for (var i = 0; i < fragmentNodes.length; i++) {
this.animateNodeLeave(fragmentNodes[i]);
}
wtfLeave(s);
}
abstract detachFragment(fragmentRef: RenderFragmentRef);
hydrateView(viewRef: RenderViewRef) { resolveInternalDomView(viewRef).hydrate(); }
@@ -185,38 +105,13 @@ export class DomRenderer implements Renderer, NodeFactory<Node> {
createTemplateAnchor(attrNameAndValues: string[]): Node {
return this.createElement('script', attrNameAndValues);
}
createElement(name: string, attrNameAndValues: string[]): Node {
var el = DOM.createElement(name);
this._setAttributes(el, attrNameAndValues);
return el;
}
mergeElement(existing: Node, attrNameAndValues: string[]) {
DOM.clearNodes(existing);
this._setAttributes(existing, attrNameAndValues);
}
private _setAttributes(node: Node, attrNameAndValues: string[]) {
for (var attrIdx = 0; attrIdx < attrNameAndValues.length; attrIdx += 2) {
DOM.setAttribute(node, attrNameAndValues[attrIdx], attrNameAndValues[attrIdx + 1]);
}
}
createShadowRoot(host: Node, templateId: number): Node {
var sr = DOM.createShadowRoot(host);
var styles = this._nativeShadowStyles.get(templateId);
for (var i = 0; i < styles.length; i++) {
DOM.appendChild(sr, DOM.createStyleElement(styles[i]));
}
return sr;
}
abstract createElement(name: string, attrNameAndValues: string[]): Node;
abstract mergeElement(existing: Node, attrNameAndValues: string[]);
abstract createShadowRoot(host: Node, templateId: number): Node;
createText(value: string): Node { return DOM.createTextNode(isPresent(value) ? value : ''); }
appendChild(parent: Node, child: Node) { DOM.appendChild(parent, child); }
on(element: Node, eventName: string, callback: Function) {
this._eventManager.addEventListener(<HTMLElement>element, eventName,
decoratePreventDefault(callback));
}
globalOn(target: string, eventName: string, callback: Function): Function {
return this._eventManager.addGlobalEventListener(target, eventName,
decoratePreventDefault(callback));
}
abstract on(element: Node, eventName: string, callback: Function);
abstract globalOn(target: string, eventName: string, callback: Function): Function;
setElementProperty(location: RenderElementRef, propertyName: string, propertyValue: any): void {
var view = resolveInternalDomView(location.renderView);
@@ -273,6 +168,135 @@ export class DomRenderer implements Renderer, NodeFactory<Node> {
}
}
@Injectable()
export class DomRenderer_ extends DomRenderer {
private _componentCmds: Map<number, RenderTemplateCmd[]> = new Map<number, RenderTemplateCmd[]>();
private _nativeShadowStyles: Map<number, string[]> = new Map<number, string[]>();
private _document;
constructor(private _eventManager: EventManager,
private _domSharedStylesHost: DomSharedStylesHost, private _animate: AnimationBuilder,
@Inject(DOCUMENT) document) {
super();
this._document = document;
}
registerComponentTemplate(templateId: number, commands: RenderTemplateCmd[], styles: string[],
nativeShadow: boolean) {
this._componentCmds.set(templateId, commands);
if (nativeShadow) {
this._nativeShadowStyles.set(templateId, styles);
} else {
this._domSharedStylesHost.addStyles(styles);
}
}
resolveComponentTemplate(templateId: number): RenderTemplateCmd[] {
return this._componentCmds.get(templateId);
}
_createRootHostViewScope: WtfScopeFn = wtfCreateScope('DomRenderer#createRootHostView()');
createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
hostElementSelector: string): RenderViewWithFragments {
var s = this._createRootHostViewScope();
var element = DOM.querySelector(this._document, hostElementSelector);
if (isBlank(element)) {
wtfLeave(s);
throw new BaseException(`The selector "${hostElementSelector}" did not match any elements`);
}
return wtfLeave(s, this._createView(hostProtoViewRef, element));
}
_createViewScope = wtfCreateScope('DomRenderer#createView()');
createView(protoViewRef: RenderProtoViewRef, fragmentCount: number): RenderViewWithFragments {
var s = this._createViewScope();
return wtfLeave(s, this._createView(protoViewRef, null));
}
private _createView(protoViewRef: RenderProtoViewRef,
inplaceElement: HTMLElement): RenderViewWithFragments {
var view = createRenderView((<DefaultProtoViewRef>protoViewRef).cmds, inplaceElement, this);
var sdRoots = view.nativeShadowRoots;
for (var i = 0; i < sdRoots.length; i++) {
this._domSharedStylesHost.addHost(sdRoots[i]);
}
return new RenderViewWithFragments(view, view.fragments);
}
destroyView(viewRef: RenderViewRef) {
var view = <DefaultRenderView<Node>>viewRef;
var sdRoots = view.nativeShadowRoots;
for (var i = 0; i < sdRoots.length; i++) {
this._domSharedStylesHost.removeHost(sdRoots[i]);
}
}
animateNodeEnter(node: Node) {
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
DOM.addClass(node, 'ng-enter');
this._animate.css()
.addAnimationClass('ng-enter-active')
.start(<HTMLElement>node)
.onComplete(() => { DOM.removeClass(node, 'ng-enter'); });
}
}
animateNodeLeave(node: Node) {
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
DOM.addClass(node, 'ng-leave');
this._animate.css()
.addAnimationClass('ng-leave-active')
.start(<HTMLElement>node)
.onComplete(() => {
DOM.removeClass(node, 'ng-leave');
DOM.remove(node);
});
} else {
DOM.remove(node);
}
}
_detachFragmentScope = wtfCreateScope('DomRenderer#detachFragment()');
detachFragment(fragmentRef: RenderFragmentRef) {
var s = this._detachFragmentScope();
var fragmentNodes = resolveInternalDomFragment(fragmentRef);
for (var i = 0; i < fragmentNodes.length; i++) {
this.animateNodeLeave(fragmentNodes[i]);
}
wtfLeave(s);
}
createElement(name: string, attrNameAndValues: string[]): Node {
var el = DOM.createElement(name);
this._setAttributes(el, attrNameAndValues);
return el;
}
mergeElement(existing: Node, attrNameAndValues: string[]) {
DOM.clearNodes(existing);
this._setAttributes(existing, attrNameAndValues);
}
private _setAttributes(node: Node, attrNameAndValues: string[]) {
for (var attrIdx = 0; attrIdx < attrNameAndValues.length; attrIdx += 2) {
DOM.setAttribute(node, attrNameAndValues[attrIdx], attrNameAndValues[attrIdx + 1]);
}
}
createShadowRoot(host: Node, templateId: number): Node {
var sr = DOM.createShadowRoot(host);
var styles = this._nativeShadowStyles.get(templateId);
for (var i = 0; i < styles.length; i++) {
DOM.appendChild(sr, DOM.createStyleElement(styles[i]));
}
return sr;
}
on(element: Node, eventName: string, callback: Function) {
this._eventManager.addEventListener(<HTMLElement>element, eventName,
decoratePreventDefault(callback));
}
globalOn(target: string, eventName: string, callback: Function): Function {
return this._eventManager.addGlobalEventListener(target, eventName,
decoratePreventDefault(callback));
}
}
function resolveInternalDomView(viewRef: RenderViewRef): DefaultRenderView<Node> {
return <DefaultRenderView<Node>>viewRef;
}