feat(animate): cross-browser compatibility

Closes #4243
This commit is contained in:
Marc Laval
2015-09-18 00:49:56 +02:00
parent 4f56a01b3b
commit bffa2cb59b
6 changed files with 105 additions and 19 deletions

View File

@ -139,4 +139,7 @@ export class DomAdapter {
requestAnimationFrame(callback): number { throw _abstract(); }
cancelAnimationFrame(id) { throw _abstract(); }
performanceNow(): number { throw _abstract(); }
getAnimationPrefix(): string { throw _abstract(); }
getTransitionEnd(): string { throw _abstract(); }
supportsAnimation(): boolean { throw _abstract(); }
}

View File

@ -1,11 +1,44 @@
import {ListWrapper} from 'angular2/src/core/facade/collection';
import {isPresent, isFunction} from 'angular2/src/core/facade/lang';
import {ListWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
import {isPresent, isFunction, StringWrapper} from 'angular2/src/core/facade/lang';
import {DomAdapter} from './dom_adapter';
/**
* Provides DOM operations in any browser environment.
*/
export class GenericBrowserDomAdapter extends DomAdapter {
private _animationPrefix: string = null;
private _transitionEnd: string = null;
constructor() {
super();
try {
var element = this.createElement('div', this.defaultDoc());
if (isPresent(this.getStyle(element, 'animationName'))) {
this._animationPrefix = '';
} else {
var domPrefixes = ['Webkit', 'Moz', 'O', 'ms'];
for (var i = 0; i < domPrefixes.length; i++) {
if (isPresent(this.getStyle(element, domPrefixes[i] + 'AnimationName'))) {
this._animationPrefix = '-' + StringWrapper.toLowerCase(domPrefixes[i]) + '-';
break;
}
}
}
var transEndEventNames = {
WebkitTransition: 'webkitTransitionEnd',
MozTransition: 'transitionend',
OTransition: 'oTransitionEnd otransitionend',
transition: 'transitionend'
};
StringMapWrapper.forEach(transEndEventNames, (value, key) => {
if (isPresent(this.getStyle(element, key))) {
this._transitionEnd = value;
}
});
} catch (e) {
this._animationPrefix = null;
this._transitionEnd = null;
}
}
getDistributedNodes(el: HTMLElement): Node[] { return (<any>el).getDistributedNodes(); }
resolveAndSetHref(el: HTMLAnchorElement, baseUrl: string, href: string) {
el.href = href == null ? baseUrl : baseUrl + '/../' + href;
@ -37,4 +70,11 @@ export class GenericBrowserDomAdapter extends DomAdapter {
supportsNativeShadowDOM(): boolean {
return isFunction((<any>this.defaultDoc().body).createShadowRoot);
}
getAnimationPrefix(): string {
return isPresent(this._animationPrefix) ? this._animationPrefix : "";
}
getTransitionEnd(): string { return isPresent(this._transitionEnd) ? this._transitionEnd : ""; }
supportsAnimation(): boolean {
return isPresent(this._animationPrefix) && isPresent(this._transitionEnd);
}
}

View File

@ -435,4 +435,16 @@ class Html5LibDomAdapter implements DomAdapter {
performanceNow() {
throw 'not implemented';
}
getAnimationPrefix() {
throw 'not implemented';
}
getTransitionEnd() {
throw 'not implemented';
}
supportsAnimation() {
throw 'not implemented';
}
}

View File

@ -552,6 +552,9 @@ export class Parse5DomAdapter extends DomAdapter {
requestAnimationFrame(callback): number { return setTimeout(callback, 0); }
cancelAnimationFrame(id: number) { clearTimeout(id); }
performanceNow(): number { return DateWrapper.toMillis(DateWrapper.now()); }
getAnimationPrefix(): string { return ''; }
getTransitionEnd(): string { return 'transitionend'; }
supportsAnimation(): boolean { return true; }
}
// TODO: build a proper list, this one is all the keys of a HTMLInputElement