feat(animations): provide support for offline compilation

This commit is contained in:
Matias Niemelä 2016-05-31 09:15:17 -07:00
parent 155b88213c
commit fa0718ba9a
16 changed files with 380 additions and 156 deletions

View File

@ -0,0 +1,34 @@
import {Component, trigger, state, animate, transition, style} from '@angular/core';
@Component({
selector: "animate-cmp",
animations: [
trigger('openClose', [
state('closed, void',
style({ height:"0px", color: "maroon", borderColor: "maroon" })),
state('open',
style({ height:"*", borderColor:"green", color:"green" })),
transition("* => *", animate(500))
])
],
template: `
<button (click)="setAsOpen()">Open</button>
<button (click)="setAsClosed()">Closed</button>
<hr />
<div @openClose="stateExpression">
Look at this box
</div>
`
})
export class AnimateCmp {
stateExpression:string;
constructor() {
this.setAsClosed();
}
setAsOpen() {
this.stateExpression = 'open';
}
setAsClosed() {
this.stateExpression = 'closed';
}
}

View File

@ -0,0 +1,40 @@
require('reflect-metadata');
require('@angular/platform-server/src/parse5_adapter.js').Parse5DomAdapter.makeCurrent();
require('zone.js/dist/zone-node.js');
require('zone.js/dist/long-stack-trace-zone.js');
import {AnimateCmpNgFactory} from '../src/animate.ngfactory';
import {AUTO_STYLE, ReflectiveInjector, DebugElement, getDebugNode} from '@angular/core';
import {browserPlatform, BROWSER_APP_PROVIDERS} from '@angular/platform-browser';
describe("template codegen output", () => {
it("should apply the animate states to the element", (done) => {
const appInjector = ReflectiveInjector.resolveAndCreate(BROWSER_APP_PROVIDERS,
browserPlatform().injector);
var comp = AnimateCmpNgFactory.create(appInjector);
var debugElement = <DebugElement>getDebugNode(comp.location.nativeElement);
// the open-close-container is a child of the main container
// if the template changes then please update the location below
var targetDebugElement = <DebugElement>debugElement.children[3];
comp.instance.setAsOpen();
comp.changeDetectorRef.detectChanges();
setTimeout(() => {
expect(targetDebugElement.styles['height']).toEqual(AUTO_STYLE);
expect(targetDebugElement.styles['borderColor']).toEqual('green');
expect(targetDebugElement.styles['color']).toEqual('green');
comp.instance.setAsClosed();
comp.changeDetectorRef.detectChanges();
setTimeout(() => {
expect(targetDebugElement.styles['height']).toEqual("0px");
expect(targetDebugElement.styles['borderColor']).toEqual('maroon');
expect(targetDebugElement.styles['color']).toEqual('maroon');
done();
}, 0);
}, 0);
});
});

View File

@ -19,6 +19,7 @@ export class NodeReflectorHost implements StaticReflectorHost, ImportGenerator {
coreDecorators: '@angular/core/src/metadata',
diDecorators: '@angular/core/src/di/decorators',
diMetadata: '@angular/core/src/di/metadata',
animationMetadata: '@angular/core/src/animation/metadata',
provider: '@angular/core/src/di/provider'
};
}

View File

@ -20,6 +20,14 @@ import {
SelfMetadata,
SkipSelfMetadata,
InjectMetadata,
trigger,
state,
transition,
sequence,
group,
animate,
style,
keyframes
} from "@angular/core";
import {ReflectorReader} from "./core_private";
@ -50,7 +58,7 @@ export interface StaticReflectorHost {
getStaticSymbol(declarationFile: string, name: string): StaticSymbol;
angularImportLocations():
{coreDecorators: string, diDecorators: string, diMetadata: string, provider: string};
{coreDecorators: string, diDecorators: string, diMetadata: string, animationMetadata: string, provider: string};
}
/**
@ -181,8 +189,19 @@ export class StaticReflector implements ReflectorReader {
});
}
private registerFunction(type: StaticSymbol, fn: any): void {
this.conversionMap.set(type, (context: StaticSymbol, args: any[]) => {
let argValues: any[] = [];
args.forEach((arg, index) => {
let argValue = this.simplify(context, arg);
argValues.push(argValue);
});
return fn.apply(null, argValues);
});
}
private initializeConversionMap(): void {
const {coreDecorators, diDecorators, diMetadata, provider} = this.host.angularImportLocations();
const {coreDecorators, diDecorators, diMetadata, animationMetadata, provider} = this.host.angularImportLocations();
this.registerDecoratorOrConstructor(this.host.findDeclaration(provider, 'Provider'), Provider);
this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Host'),
@ -235,6 +254,15 @@ export class StaticReflector implements ReflectorReader {
SkipSelfMetadata);
this.registerDecoratorOrConstructor(this.host.findDeclaration(diMetadata, 'OptionalMetadata'),
OptionalMetadata);
this.registerFunction(this.host.findDeclaration(animationMetadata, 'trigger'), trigger);
this.registerFunction(this.host.findDeclaration(animationMetadata, 'state'), state);
this.registerFunction(this.host.findDeclaration(animationMetadata, 'transition'), transition);
this.registerFunction(this.host.findDeclaration(animationMetadata, 'style'), style);
this.registerFunction(this.host.findDeclaration(animationMetadata, 'animate'), animate);
this.registerFunction(this.host.findDeclaration(animationMetadata, 'keyframes'), keyframes);
this.registerFunction(this.host.findDeclaration(animationMetadata, 'sequence'), sequence);
this.registerFunction(this.host.findDeclaration(animationMetadata, 'group'), group);
}
/** @internal */

View File

@ -15,6 +15,8 @@ import {
StaticSymbol
} from '@angular/compiler-cli/src/static_reflector';
import {transition, sequence, group, trigger, state, style, animate, keyframes} from '@angular/core';
describe('StaticReflector', () => {
let noContext = new StaticSymbol('', '');
let host: StaticReflectorHost;
@ -62,6 +64,19 @@ describe('StaticReflector', () => {
expect(annotation.selector).toEqual('my-hero-detail');
expect(annotation.directives)
.toEqual([[host.findDeclaration('angular2/src/common/directives/ng_for', 'NgFor')]]);
expect(annotation.animations).toEqual([
trigger("myAnimation", [
state("state1", style({ "background": "white" })),
transition("* => *", sequence([
group([
animate("1s 0.5s", keyframes([
style({ "background": "blue"}),
style({ "background": "red"})
]))
])
]))
])
]);
});
it('should throw and exception for unsupported metadata versions', () => {
@ -252,6 +267,7 @@ class MockReflectorHost implements StaticReflectorHost {
coreDecorators: 'angular2/src/core/metadata',
diDecorators: 'angular2/src/core/di/decorators',
diMetadata: 'angular2/src/core/di/metadata',
animationMetadata: 'angular2/src/core/animation/metadata',
provider: 'angular2/src/core/di/provider'
};
}
@ -405,11 +421,100 @@ class MockReflectorHost implements StaticReflectorHost {
"name": "FORM_DIRECTIVES",
"module": "angular2/src/common/forms/directives"
}
],
"animations": [{
"__symbolic": "call",
"expression": {
"__symbolic": "reference",
"name": "trigger",
"module": "angular2/src/core/animation/metadata"
},
"arguments": [
"myAnimation",
[{ "__symbolic": "call",
"expression": {
"__symbolic": "reference",
"name": "state",
"module": "angular2/src/core/animation/metadata"
},
"arguments": [
"state1",
{ "__symbolic": "call",
"expression": {
"__symbolic": "reference",
"name": "style",
"module": "angular2/src/core/animation/metadata"
},
"arguments": [
{ "background":"white" }
]
}
]
}, {
"__symbolic": "call",
"expression": {
"__symbolic":"reference",
"name":"transition",
"module": "angular2/src/core/animation/metadata"
},
"arguments": [
"* => *",
{
"__symbolic":"call",
"expression":{
"__symbolic":"reference",
"name":"sequence",
"module": "angular2/src/core/animation/metadata"
},
"arguments":[[{ "__symbolic": "call",
"expression": {
"__symbolic":"reference",
"name":"group",
"module": "angular2/src/core/animation/metadata"
},
"arguments":[[{
"__symbolic": "call",
"expression": {
"__symbolic":"reference",
"name":"animate",
"module": "angular2/src/core/animation/metadata"
},
"arguments":[
"1s 0.5s",
{ "__symbolic": "call",
"expression": {
"__symbolic":"reference",
"name":"keyframes",
"module": "angular2/src/core/animation/metadata"
},
"arguments":[[{ "__symbolic": "call",
"expression": {
"__symbolic":"reference",
"name":"style",
"module": "angular2/src/core/animation/metadata"
},
"arguments":[ { "background": "blue"} ]
}, {
"__symbolic": "call",
"expression": {
"__symbolic":"reference",
"name":"style",
"module": "angular2/src/core/animation/metadata"
},
"arguments":[ { "background": "red"} ]
}]]
}
]
}]]
}]]
}
]
}
]
]
}
]
}
],
}]
}]
}],
"members": {
"hero": [
{

View File

@ -74,10 +74,13 @@ export type AnimationGroupPlayer = t.AnimationGroupPlayer;
export var AnimationGroupPlayer: typeof t.AnimationGroupPlayer = r.AnimationGroupPlayer;
export type AnimationKeyframe = t.AnimationKeyframe;
export var AnimationKeyframe: typeof t.AnimationKeyframe = r.AnimationKeyframe;
export type AnimationStyleUtil = t.AnimationStyleUtil;
export var AnimationStyleUtil: typeof t.AnimationStyleUtil = r.AnimationStyleUtil;
export type AnimationStylrs = t.AnimationStyles;
export type AnimationStyles = t.AnimationStyles;
export var AnimationStyles: typeof t.AnimationStyles = r.AnimationStyles;
export var ANY_STATE = r.ANY_STATE;
export var EMPTY_STATE = r.EMPTY_STATE;
export var FILL_STYLE_FLAG = r.FILL_STYLE_FLAG;
export var balanceAnimationStyles: typeof t.balanceAnimationStyles = r.balanceAnimationStyles;
export var balanceAnimationKeyframes: typeof t.balanceAnimationKeyframes = r.balanceAnimationKeyframes;
export var flattenStyles: typeof t.flattenStyles = r.flattenStyles;
export var clearStyles: typeof t.clearStyles = r.clearStyles;
export var collectAndResolveStyles: typeof r.collectAndResolveStyles = r.collectAndResolveStyles;

View File

@ -249,7 +249,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
statements.push(
_ANIMATION_FACTORY_RENDERER_VAR.callMethod('setElementStyles', [
_ANIMATION_FACTORY_ELEMENT_VAR,
o.importExpr(Identifiers.clearAnimationStyles).callFn([_ANIMATION_START_STATE_STYLES_VAR])
o.importExpr(Identifiers.clearStyles).callFn([_ANIMATION_START_STATE_STYLES_VAR])
]).toStmt());
ast.stateTransitions.forEach(transAst => statements.push(transAst.visit(this, context)));
@ -287,7 +287,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
]).toStmt());
return o.fn([
new o.FnParam(_ANIMATION_FACTORY_VIEW_VAR.name, o.importType(Identifiers.AppView)),
new o.FnParam(_ANIMATION_FACTORY_VIEW_VAR.name, o.importType(Identifiers.AppView, [o.DYNAMIC_TYPE])),
new o.FnParam(_ANIMATION_FACTORY_ELEMENT_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(_ANIMATION_CURRENT_STATE_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(_ANIMATION_NEXT_STATE_VAR.name, o.DYNAMIC_TYPE)

View File

@ -45,7 +45,10 @@ import {
NoOpAnimationPlayer as NoOpAnimationPlayer_,
AnimationGroupPlayer as AnimationGroupPlayer_,
AnimationSequencePlayer as AnimationSequencePlayer_,
AnimationStyleUtil,
balanceAnimationStyles as impBalanceAnimationStyles,
balanceAnimationKeyframes as impBalanceAnimationKeyframes,
clearStyles as impClearStyles,
collectAndResolveStyles as impCollectAndResolveStyles,
SecurityContext
} from '../core_private';
@ -245,22 +248,22 @@ export class Identifiers {
static balanceAnimationStyles = new CompileIdentifierMetadata({
name: 'balanceAnimationStyles',
moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL,
runtime: AnimationStyleUtil.balanceStyles
runtime: impBalanceAnimationStyles
});
static balanceAnimationKeyframes = new CompileIdentifierMetadata({
name: 'balanceAnimationKeyframes',
moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL,
runtime: AnimationStyleUtil.balanceKeyframes
runtime: impBalanceAnimationKeyframes
});
static clearAnimationStyles = new CompileIdentifierMetadata({
name: 'clearAnimationStyles',
static clearStyles = new CompileIdentifierMetadata({
name: 'clearStyles',
moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL,
runtime: AnimationStyleUtil.clearStyles
runtime: impClearStyles
});
static collectAndResolveStyles = new CompileIdentifierMetadata({
name: 'collectAndResolveStyles',
moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL,
runtime: AnimationStyleUtil.collectAndResolveStyles
runtime: impCollectAndResolveStyles
});
}

View File

@ -44,7 +44,7 @@ import {
AnimationStepAst
} from '../../src/animation/animation_ast';
import {FILL_STYLE_FLAG, AnimationStyleUtil} from '../../core_private';
import {FILL_STYLE_FLAG, flattenStyles} from '../../core_private';
import {StringMapWrapper} from '../../src/facade/collection';
@ -348,7 +348,7 @@ export function main() {
var kf1 = keyframesStep.keyframes[0];
var kf2 = keyframesStep.keyframes[1];
expect(AnimationStyleUtil.flattenStyles(kf1.styles.styles)).toEqual({
expect(flattenStyles(kf1.styles.styles)).toEqual({
"color": "red",
"background": FILL_STYLE_FLAG
});
@ -368,7 +368,7 @@ export function main() {
var kf2 = keyframesStep.keyframes[1];
var kf3 = keyframesStep.keyframes[2];
expect(AnimationStyleUtil.flattenStyles(kf3.styles.styles)).toEqual({
expect(flattenStyles(kf3.styles.styles)).toEqual({
"background": "blue",
"color": "red",
"border-color": "white"
@ -390,7 +390,7 @@ export function main() {
var kf3 = keyframesStep.keyframes[2];
expect(kf1.offset).toEqual(0);
expect(AnimationStyleUtil.flattenStyles(kf1.styles.styles)).toEqual({
expect(flattenStyles(kf1.styles.styles)).toEqual({
"font-size": FILL_STYLE_FLAG,
"background": FILL_STYLE_FLAG,
"color": FILL_STYLE_FLAG
@ -412,7 +412,7 @@ export function main() {
var kf3 = keyframesStep.keyframes[2];
expect(kf3.offset).toEqual(1);
expect(AnimationStyleUtil.flattenStyles(kf3.styles.styles)).toEqual({
expect(flattenStyles(kf3.styles.styles)).toEqual({
"color": "orange",
"background": "red",
"transform": "rotate(360deg)",

View File

@ -35,8 +35,8 @@ import {
import {AnimationSequencePlayer as AnimationSequencePlayer_} from './src/animation/animation_sequence_player';
import {AnimationGroupPlayer as AnimationGroupPlayer_} from './src/animation/animation_group_player';
import {AnimationKeyframe as AnimationKeyframe_} from './src/animation/animation_keyframe';
import {AnimationStyleUtil as AnimationStyleUtil_} from './src/animation/animation_style_util';
import {AnimationStyles as AnimationStyles_} from './src/animation/animation_styles';
import * as animationUtils from './src/animation/animation_style_util';
import {
ANY_STATE as ANY_STATE_,
EMPTY_STATE as EMPTY_STATE_,
@ -121,8 +121,11 @@ export declare namespace __core_private_types__ {
export var AnimationGroupPlayer: typeof AnimationGroupPlayer_;
export type AnimationKeyframe = AnimationKeyframe_;
export var AnimationKeyframe: typeof AnimationKeyframe_;
export type AnimationStyleUtil = AnimationStyleUtil_;
export var AnimationStyleUtil: typeof AnimationStyleUtil_;
export var balanceAnimationStyles: typeof animationUtils.balanceAnimationStyles;
export var balanceAnimationKeyframes: typeof animationUtils.balanceAnimationKeyframes;
export var flattenStyles: typeof animationUtils.flattenStyles;
export var clearStyles: typeof animationUtils.clearStyles;
export var collectAndResolveStyles: typeof animationUtils.collectAndResolveStyles;
export type AnimationStyles = AnimationStyles_;
export var AnimationStyles: typeof AnimationStyles_;
export var ANY_STATE: typeof ANY_STATE_;
@ -187,7 +190,11 @@ export var __core_private__ = {
AnimationSequencePlayer: AnimationSequencePlayer_,
AnimationGroupPlayer: AnimationGroupPlayer_,
AnimationKeyframe: AnimationKeyframe_,
AnimationStyleUtil: AnimationStyleUtil_,
balanceAnimationStyles: animationUtils.balanceAnimationStyles,
balanceAnimationKeyframes: animationUtils.balanceAnimationKeyframes,
flattenStyles: animationUtils.flattenStyles,
clearStyles: animationUtils.clearStyles,
collectAndResolveStyles: animationUtils.collectAndResolveStyles,
AnimationStyles: AnimationStyles_,
ANY_STATE: ANY_STATE_,
EMPTY_STATE: EMPTY_STATE_,

View File

@ -3,111 +3,110 @@ import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {AUTO_STYLE} from './metadata';
import {FILL_STYLE_FLAG} from './animation_constants';
export class AnimationStyleUtil {
static balanceStyles(previousStyles: {[key: string]: string|number},
newStyles: {[key: string]: string|number},
nullValue = null): {[key: string]: string|number} {
var finalStyles: {[key: string]: string|number} = {};
export function balanceAnimationStyles(previousStyles: {[key: string]: string|number},
newStyles: {[key: string]: string|number},
nullValue = null): {[key: string]: string} {
var finalStyles: {[key: string]: string} = {};
StringMapWrapper.forEach(newStyles, (value, prop) => {
StringMapWrapper.forEach(newStyles, (value, prop) => {
finalStyles[prop] = value.toString();
});
StringMapWrapper.forEach(previousStyles, (value, prop) => {
if (!isPresent(finalStyles[prop])) {
finalStyles[prop] = nullValue;
}
});
return finalStyles;
}
export function balanceAnimationKeyframes(collectedStyles: {[key: string]: string|number},
finalStateStyles: {[key: string]: string|number},
keyframes: any[]): any[] {
var limit = keyframes.length - 1;
var firstKeyframe = keyframes[0];
// phase 1: copy all the styles from the first keyframe into the lookup map
var flatenedFirstKeyframeStyles = flattenStyles(firstKeyframe.styles.styles);
var extraFirstKeyframeStyles = {};
var hasExtraFirstStyles = false;
StringMapWrapper.forEach(collectedStyles, (value, prop) => {
// if the style is already defined in the first keyframe then
// we do not replace it.
if (!flatenedFirstKeyframeStyles[prop]) {
flatenedFirstKeyframeStyles[prop] = value;
extraFirstKeyframeStyles[prop] = value;
hasExtraFirstStyles = true;
}
});
var keyframeCollectedStyles = StringMapWrapper.merge({}, flatenedFirstKeyframeStyles);
// phase 2: normalize the final keyframe
var finalKeyframe = keyframes[limit];
ListWrapper.insert(finalKeyframe.styles.styles, 0, finalStateStyles);
var flatenedFinalKeyframeStyles = flattenStyles(finalKeyframe.styles.styles);
var extraFinalKeyframeStyles = {};
var hasExtraFinalStyles = false;
StringMapWrapper.forEach(keyframeCollectedStyles, (value, prop) => {
if (!isPresent(flatenedFinalKeyframeStyles[prop])) {
extraFinalKeyframeStyles[prop] = AUTO_STYLE;
hasExtraFinalStyles = true;
}
});
if (hasExtraFinalStyles) {
finalKeyframe.styles.styles.push(extraFinalKeyframeStyles);
}
StringMapWrapper.forEach(flatenedFinalKeyframeStyles, (value, prop) => {
if (!isPresent(flatenedFirstKeyframeStyles[prop])) {
extraFirstKeyframeStyles[prop] = AUTO_STYLE;
hasExtraFirstStyles = true;
}
});
if (hasExtraFirstStyles) {
firstKeyframe.styles.styles.push(extraFirstKeyframeStyles);
}
return keyframes;
}
export function clearStyles(styles: {[key: string]: string|number}): {[key: string]: string} {
var finalStyles: {[key: string]: string} = {};
StringMapWrapper.keys(styles).forEach(key => {
finalStyles[key] = null;
});
return finalStyles;
}
export function collectAndResolveStyles(collection: {[key: string]: string|number}, styles: {[key: string]: string|number}[]) {
return styles.map(entry => {
var stylesObj = {};
StringMapWrapper.forEach(entry, (value, prop) => {
if (value == FILL_STYLE_FLAG) {
value = collection[prop];
if (!isPresent(value)) {
value = AUTO_STYLE;
}
}
collection[prop] = value;
stylesObj[prop] = value;
});
return stylesObj;
});
}
export function flattenStyles(styles: {[key: string]: string|number}[]) {
var finalStyles = {};
styles.forEach(entry => {
StringMapWrapper.forEach(entry, (value, prop) => {
finalStyles[prop] = value;
});
StringMapWrapper.forEach(previousStyles, (value, prop) => {
if (!isPresent(finalStyles[prop])) {
finalStyles[prop] = nullValue;
}
});
return finalStyles;
}
static balanceKeyframes(collectedStyles: {[key: string]: string|number},
finalStateStyles: {[key: string]: string|number},
keyframes: any[]): any[] {
var limit = keyframes.length - 1;
var firstKeyframe = keyframes[0];
// phase 1: copy all the styles from the first keyframe into the lookup map
var flatenedFirstKeyframeStyles = AnimationStyleUtil.flattenStyles(firstKeyframe.styles.styles);
var extraFirstKeyframeStyles = {};
var hasExtraFirstStyles = false;
StringMapWrapper.forEach(collectedStyles, (value, prop) => {
// if the style is already defined in the first keyframe then
// we do not replace it.
if (!flatenedFirstKeyframeStyles[prop]) {
flatenedFirstKeyframeStyles[prop] = value;
extraFirstKeyframeStyles[prop] = value;
hasExtraFirstStyles = true;
}
});
var keyframeCollectedStyles = StringMapWrapper.merge({}, flatenedFirstKeyframeStyles);
// phase 2: normalize the final keyframe
var finalKeyframe = keyframes[limit];
ListWrapper.insert(finalKeyframe.styles.styles, 0, finalStateStyles);
var flatenedFinalKeyframeStyles = AnimationStyleUtil.flattenStyles(finalKeyframe.styles.styles);
var extraFinalKeyframeStyles = {};
var hasExtraFinalStyles = false;
StringMapWrapper.forEach(keyframeCollectedStyles, (value, prop) => {
if (!isPresent(flatenedFinalKeyframeStyles[prop])) {
extraFinalKeyframeStyles[prop] = AUTO_STYLE;
hasExtraFinalStyles = true;
}
});
if (hasExtraFinalStyles) {
finalKeyframe.styles.styles.push(extraFinalKeyframeStyles);
}
StringMapWrapper.forEach(flatenedFinalKeyframeStyles, (value, prop) => {
if (!isPresent(flatenedFirstKeyframeStyles[prop])) {
extraFirstKeyframeStyles[prop] = AUTO_STYLE;
hasExtraFirstStyles = true;
}
});
if (hasExtraFirstStyles) {
firstKeyframe.styles.styles.push(extraFirstKeyframeStyles);
}
return keyframes;
}
static clearStyles(styles: {[key: string]: string|number}): {[key: string]: string|number} {
var finalStyles: {[key: string]: string|number} = {};
StringMapWrapper.keys(styles).forEach(key => {
finalStyles[key] = null;
});
return finalStyles;
}
static collectAndResolveStyles(collection: {[key: string]: string|number}, styles: {[key: string]: string|number}[]) {
return styles.map(entry => {
var stylesObj = {};
StringMapWrapper.forEach(entry, (value, prop) => {
if (value == FILL_STYLE_FLAG) {
value = collection[prop];
if (!isPresent(value)) {
value = AUTO_STYLE;
}
}
collection[prop] = value;
stylesObj[prop] = value;
});
return stylesObj;
});
}
static flattenStyles(styles: {[key: string]: string|number}[]) {
var finalStyles = {};
styles.forEach(entry => {
StringMapWrapper.forEach(entry, (value, prop) => {
finalStyles[prop] = value;
});
});
return finalStyles;
}
});
return finalStyles;
}

View File

@ -33,8 +33,6 @@ import {AnimationDriver} from '../../src/animation/animation_driver';
import {MockAnimationDriver} from '../../testing/animation/mock_animation_driver';
import {trigger, state, transition, keyframes, style, animate, group, sequence, AnimationEntryMetadata} from '../../src/animation/metadata';
import {AnimationStyleUtil} from '../../src/animation/animation_style_util';
import {AUTO_STYLE} from '../../src/animation/metadata';
export function main() {

View File

@ -21,7 +21,7 @@ import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {isPresent} from '../../src/facade/lang';
import {MockAnimationPlayer} from '../../testing/animation/mock_animation_player';
import {AnimationStyleUtil} from '../../src/animation/animation_style_util';
import * as animationUtils from '../../src/animation/animation_style_util';
import {AnimationKeyframe} from '../../src/animation/animation_keyframe';
import {AnimationStyles} from '../../src/animation/animation_styles';
@ -29,14 +29,14 @@ import {FILL_STYLE_FLAG} from '../../src/animation/animation_constants';
import {AUTO_STYLE} from '../../src/animation/metadata';
export function main() {
describe('AnimationStyleUtil', function() {
describe('Animation Style Utils', function() {
describe('balanceStyles', () => {
describe('balanceAnimationStyles', () => {
it('should set all non-shared styles to the provided null value between the two sets of styles', () => {
var styles = { opacity: 0, color: 'red' };
var newStyles = { background: 'red' };
var flag = '*';
var result = AnimationStyleUtil.balanceStyles(styles, newStyles, flag);
var result = animationUtils.balanceAnimationStyles(styles, newStyles, flag);
expect(result).toEqual({
opacity:flag,
color:flag,
@ -47,17 +47,17 @@ export function main() {
it('should handle an empty set of styles', () => {
var value = '*';
expect(AnimationStyleUtil.balanceStyles({}, { opacity: 0 }, value)).toEqual({
opacity: 0
expect(animationUtils.balanceAnimationStyles({}, { opacity: '0' }, value)).toEqual({
opacity: '0'
});
expect(AnimationStyleUtil.balanceStyles({ opacity: 0 }, {}, value)).toEqual({
expect(animationUtils.balanceAnimationStyles({ opacity: '0' }, {}, value)).toEqual({
opacity: value
});
});
});
describe('balanceKeyframes', () => {
describe('balanceAnimationKeyframes', () => {
it('should balance both the starting and final keyframes with thep provided styles', () => {
var collectedStyles = {
width: 100,
@ -74,9 +74,9 @@ export function main() {
new AnimationKeyframe(1, new AnimationStyles([{ background: 'blue', left: '100px', top: '100px' }]))
];
var result = AnimationStyleUtil.balanceKeyframes(collectedStyles, finalStyles, keyframes);
var result = animationUtils.balanceAnimationKeyframes(collectedStyles, finalStyles, keyframes);
expect(AnimationStyleUtil.flattenStyles(result[0].styles.styles)).toEqual({
expect(animationUtils.flattenStyles(result[0].styles.styles)).toEqual({
"width": 100,
"height": 100,
"opacity": 1,
@ -86,7 +86,7 @@ export function main() {
"top": '*'
});
expect(AnimationStyleUtil.flattenStyles(result[1].styles.styles)).toEqual({
expect(animationUtils.flattenStyles(result[1].styles.styles)).toEqual({
"width": '*',
"height": '*',
"opacity": '*',
@ -103,15 +103,15 @@ export function main() {
new AnimationKeyframe(1, new AnimationStyles([{ width: 100 }]))
];
var result = AnimationStyleUtil.balanceKeyframes({}, {}, keyframes);
var result = animationUtils.balanceAnimationKeyframes({}, {}, keyframes);
expect(AnimationStyleUtil.flattenStyles(result[0].styles.styles)).toEqual({
expect(animationUtils.flattenStyles(result[0].styles.styles)).toEqual({
"height": 100,
"opacity": 1,
"width": "*"
});
expect(AnimationStyleUtil.flattenStyles(result[1].styles.styles)).toEqual({
expect(animationUtils.flattenStyles(result[1].styles.styles)).toEqual({
"width": 100,
"height": "*",
"opacity": "*"
@ -131,11 +131,11 @@ export function main() {
"width": null,
"color": null
};
expect(AnimationStyleUtil.clearStyles(styles)).toEqual(expectedResult);
expect(animationUtils.clearStyles(styles)).toEqual(expectedResult);
});
it('should handle an empty set of styles', () => {
expect(AnimationStyleUtil.clearStyles({})).toEqual({});
expect(animationUtils.clearStyles({})).toEqual({});
});
});
@ -153,13 +153,13 @@ export function main() {
var collection: {[key: string]: string|number} = {};
expect(AnimationStyleUtil.collectAndResolveStyles(collection, styles1)).toEqual(styles1);
expect(animationUtils.collectAndResolveStyles(collection, styles1)).toEqual(styles1);
expect(collection).toEqual({
"opacity": 0,
"width": 100
});
expect(AnimationStyleUtil.collectAndResolveStyles(collection, styles2)).toEqual(styles2);
expect(animationUtils.collectAndResolveStyles(collection, styles2)).toEqual(styles2);
expect(collection).toEqual({
"opacity": 1,
"width": 100,
@ -180,12 +180,12 @@ export function main() {
var collection = {};
expect(AnimationStyleUtil.collectAndResolveStyles(collection, styles1)).toEqual([{
expect(animationUtils.collectAndResolveStyles(collection, styles1)).toEqual([{
"opacity": 0,
"width": AUTO_STYLE
}]);
expect(AnimationStyleUtil.collectAndResolveStyles(collection, styles2)).toEqual([{
expect(animationUtils.collectAndResolveStyles(collection, styles2)).toEqual([{
"opacity": 0,
"height": 999
}]);

View File

@ -28,7 +28,10 @@ export type AnimationGroupPlayer = t.AnimationGroupPlayer;
export var AnimationGroupPlayer: typeof t.AnimationGroupPlayer = r.AnimationGroupPlayer;
export type AnimationKeyframe = t.AnimationKeyframe;
export var AnimationKeyframe: typeof t.AnimationKeyframe = r.AnimationKeyframe;
export type AnimationStyleUtil = t.AnimationStyleUtil;
export var AnimationStyleUtil: typeof t.AnimationStyleUtil = r.AnimationStyleUtil;
export type AnimationStyles = t.AnimationStyles;
export var AnimationStyles: typeof t.AnimationStyles = r.AnimationStyles;
export var balanceAnimationStyles: typeof t.balanceAnimationStyles = r.balanceAnimationStyles;
export var balanceAnimationKeyframes: typeof t.balanceAnimationKeyframes = r.balanceAnimationKeyframes;
export var flattenStyles: typeof t.flattenStyles = r.flattenStyles;
export var clearStyles: typeof t.clearStyles = r.clearStyles;
export var collectAndResolveStyles: typeof r.collectAndResolveStyles = r.collectAndResolveStyles;

View File

@ -553,7 +553,7 @@ export class Parse5DomAdapter extends DomAdapter {
setGlobalVar(path: string, value: any) { setValueOnPath(global, path, value); }
requestAnimationFrame(callback): number { return setTimeout(callback, 0); }
cancelAnimationFrame(id: number) { clearTimeout(id); }
supportsWebAnimation(): boolean { return true; }
supportsWebAnimation(): boolean { return false; }
performanceNow(): number { return DateWrapper.toMillis(DateWrapper.now()); }
getAnimationPrefix(): string { return ''; }
getTransitionEnd(): string { return 'transitionend'; }
@ -567,6 +567,7 @@ export class Parse5DomAdapter extends DomAdapter {
supportsCookies(): boolean { return false; }
getCookie(name: string): string { throw new Error('not implemented'); }
setCookie(name: string, value: string) { throw new Error('not implemented'); }
animate(element: any, keyframes: any[], options: any): any { throw new Error('not implemented'); }
}
// TODO: build a proper list, this one is all the keys of a HTMLInputElement

View File

@ -181,6 +181,7 @@ const CORE = [
'DebugElement.queryAll(predicate:Predicate<DebugElement>):DebugElement[]',
'DebugElement.queryAllNodes(predicate:Predicate<DebugNode>):DebugNode[]',
'DebugElement.removeChild(child:DebugNode):any',
'DebugElement.styles:{[key:string]:string}',
'DebugElement.triggerEventHandler(eventName:string, eventObj:any):any',
'DebugNode',
'DebugNode.componentInstance:any',
@ -1651,6 +1652,7 @@ const PLATFORM_SERVER = [
'Parse5DomAdapter',
'Parse5DomAdapter.addClass(element:any, className:string):any',
'Parse5DomAdapter.adoptNode(node:any):any',
'Parse5DomAdapter.animate(element:any, keyframes:any[], options:any):any',
'Parse5DomAdapter.appendChild(el:any, node:any):any',
'Parse5DomAdapter.attrToPropMap:any',
'Parse5DomAdapter.attributeMap(element:any):Map<string, string>',