135 lines
4.6 KiB
TypeScript
135 lines
4.6 KiB
TypeScript
|
/**
|
||
|
* @license
|
||
|
* Copyright Google Inc. All Rights Reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by an MIT-style license that can be
|
||
|
* found in the LICENSE file at https://angular.io/license
|
||
|
*/
|
||
|
import {AnimationTriggerMetadata} from '@angular/animations';
|
||
|
import {Injectable, RendererFactoryV2, RendererTypeV2, RendererV2} from '@angular/core';
|
||
|
|
||
|
import {AnimationEngine} from './animation_engine';
|
||
|
|
||
|
@Injectable()
|
||
|
export class AnimationRendererFactory implements RendererFactoryV2 {
|
||
|
constructor(private delegate: RendererFactoryV2, private _engine: AnimationEngine) {}
|
||
|
|
||
|
createRenderer(hostElement: any, type: RendererTypeV2): RendererV2 {
|
||
|
let delegate = this.delegate.createRenderer(hostElement, type);
|
||
|
if (!hostElement || !type) return delegate;
|
||
|
|
||
|
let animationRenderer = type.data['__animationRenderer__'] as any as AnimationRenderer;
|
||
|
if (animationRenderer && delegate == animationRenderer.delegate) {
|
||
|
return animationRenderer;
|
||
|
}
|
||
|
const animationTriggers = type.data['animation'] as AnimationTriggerMetadata[];
|
||
|
animationRenderer = (type.data as any)['__animationRenderer__'] =
|
||
|
new AnimationRenderer(delegate, this._engine, animationTriggers);
|
||
|
return animationRenderer;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export class AnimationRenderer implements RendererV2 {
|
||
|
public destroyNode: (node: any) => (void|any) = null;
|
||
|
|
||
|
constructor(
|
||
|
public delegate: RendererV2, private _engine: AnimationEngine,
|
||
|
_triggers: AnimationTriggerMetadata[] = null) {
|
||
|
this.destroyNode = this.delegate.destroyNode ? (n) => delegate.destroyNode(n) : null;
|
||
|
if (_triggers) {
|
||
|
_triggers.forEach(trigger => _engine.registerTrigger(trigger));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
destroy(): void { this.delegate.destroy(); }
|
||
|
|
||
|
createElement(name: string, namespace?: string): any {
|
||
|
return this.delegate.createElement(name, namespace);
|
||
|
}
|
||
|
|
||
|
createComment(value: string): any { return this.delegate.createComment(value); }
|
||
|
|
||
|
createText(value: string): any { return this.delegate.createText(value); }
|
||
|
|
||
|
selectRootElement(selectorOrNode: string|any): any {
|
||
|
return this.delegate.selectRootElement(selectorOrNode);
|
||
|
}
|
||
|
|
||
|
parentNode(node: any): any { return this.delegate.parentNode(node); }
|
||
|
|
||
|
nextSibling(node: any): any { return this.delegate.nextSibling(node); }
|
||
|
|
||
|
setAttribute(el: any, name: string, value: string, namespace?: string): void {
|
||
|
this.delegate.setAttribute(el, name, value, namespace);
|
||
|
}
|
||
|
|
||
|
removeAttribute(el: any, name: string, namespace?: string): void {
|
||
|
this.delegate.removeAttribute(el, name, namespace);
|
||
|
}
|
||
|
|
||
|
addClass(el: any, name: string): void { this.delegate.addClass(el, name); }
|
||
|
|
||
|
removeClass(el: any, name: string): void { this.delegate.removeClass(el, name); }
|
||
|
|
||
|
setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean):
|
||
|
void {
|
||
|
this.delegate.setStyle(el, style, value, hasVendorPrefix, hasImportant);
|
||
|
}
|
||
|
|
||
|
removeStyle(el: any, style: string, hasVendorPrefix: boolean): void {
|
||
|
this.delegate.removeStyle(el, style, hasVendorPrefix);
|
||
|
}
|
||
|
|
||
|
setValue(node: any, value: string): void { this.delegate.setValue(node, value); }
|
||
|
|
||
|
appendChild(parent: any, newChild: any): void {
|
||
|
this._engine.onInsert(newChild, () => this.delegate.appendChild(parent, newChild));
|
||
|
}
|
||
|
|
||
|
insertBefore(parent: any, newChild: any, refChild: any): void {
|
||
|
this._engine.onInsert(newChild, () => this.delegate.insertBefore(parent, newChild, refChild));
|
||
|
}
|
||
|
|
||
|
removeChild(parent: any, oldChild: any): void {
|
||
|
this._engine.onRemove(oldChild, () => this.delegate.removeChild(parent, oldChild));
|
||
|
}
|
||
|
|
||
|
setProperty(el: any, name: string, value: any): void {
|
||
|
if (name.charAt(0) == '@') {
|
||
|
this._engine.setProperty(el, name.substr(1), value);
|
||
|
} else {
|
||
|
this.delegate.setProperty(el, name, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
listen(target: 'window'|'document'|'body'|any, eventName: string, callback: (event: any) => any):
|
||
|
() => void {
|
||
|
if (eventName.charAt(0) == '@') {
|
||
|
const element = resolveElementFromTarget(target);
|
||
|
const [name, phase] = parseTriggerCallbackName(eventName.substr(1));
|
||
|
return this._engine.listen(element, name, phase, callback);
|
||
|
}
|
||
|
return this.delegate.listen(target, eventName, callback);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function resolveElementFromTarget(target: 'window' | 'document' | 'body' | any): any {
|
||
|
switch (target) {
|
||
|
case 'body':
|
||
|
return document.body;
|
||
|
case 'document':
|
||
|
return document;
|
||
|
case 'window':
|
||
|
return window;
|
||
|
default:
|
||
|
return target;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function parseTriggerCallbackName(triggerName: string) {
|
||
|
const dotIndex = triggerName.indexOf('.');
|
||
|
const trigger = triggerName.substring(0, dotIndex);
|
||
|
const phase = triggerName.substr(dotIndex + 1);
|
||
|
return [trigger, phase];
|
||
|
}
|