Files
2015-05-30 11:46:01 -05:00

154 lines
4.4 KiB
JavaScript

// Use Angular's promise which doesn't swallow exceptions
import {Promise} from 'angular2/src/facade/async';
const nativeRaf = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame;
const nativeCancelRaf = window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.webkitCancelRequestAnimationFrame;
export const raf = nativeRaf || function(callback) {
let timeCurrent = (new Date()).getTime(),
timeDelta;
/* Dynamically set delay on a per-tick basis to match 60fps. */
/* Technique by Erik Moller. MIT license: https://gist.github.com/paulirish/1579671 */
timeDelta = Math.max(0, 16 - (timeCurrent - timeLast));
timeLast = timeCurrent + timeDelta;
return setTimeout(function() { callback(timeCurrent + timeDelta); }, timeDelta);
}
export const rafCancel = nativeRaf ? nativeCancelRaf : function(id) {
return window.cancelTimeout(id);
}
export function rafPromise() {
return new Promise(resolve => raf(resolve));
}
export const isSVG = val => window.SVGElement && (val instanceof window.SVGElement);
// We only need to test for webkit in our supported browsers. Webkit is the
// only browser still using prefixes. Code adapted from angular-animate.js
export let CSS = {};
if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {
CSS.prefix = '-webkit-';
CSS.transition = 'webkitTransition';
CSS.transform = 'webkitTransform';
CSS.transitionEnd = 'webkitTransitionEnd transitionend';
} else {
CSS.prefix = '';
CSS.transform = 'transform';
CSS.transition = 'transition';
CSS.transitionEnd = 'transitionend';
}
if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {
CSS.animation = 'WebkitAnimation';
CSS.animationStart = 'webkitAnimationStart animationstart';
CSS.animationEnd = 'webkitAnimationEnd animationend';
} else {
CSS.animation = 'animation';
CSS.animationStart = 'animationstart';
CSS.animationEnd = 'animationend';
}
export function transitionEnd(el:Element) {
return cssPromise(el, CSS.transitionEnd);
}
export function animationStart(el:Element, animationName) {
return cssPromise(el, CSS.animationStart, animationName);
}
export function animationEnd(el:Element, animationName) {
return cssPromise(el, CSS.animationEnd, animationName);
}
function cssPromise(el:Element, eventNames, animationName) {
return new Promise(resolve => {
eventNames.split(' ').forEach(eventName => {
el.addEventListener(eventName, onEvent);
})
function onEvent(ev) {
if (ev.animationName && animationName) {
// do not resolve if a bubbled up ev.animationName
// is not the same as the passed in animationName arg
if (ev.animationName !== animationName) {
return;
}
} else if (ev.target !== el) {
// do not resolve if the event's target element is not
// the same as the element the listener was added to
return;
}
ev.stopPropagation();
eventNames.split(' ').forEach(eventName => {
el.removeEventListener(eventName, onEvent);
})
resolve(ev);
}
});
}
export function ready() {
return new Promise(resolve => {
if (document.readyState === 'complete' || document.readyState === 'interactive') {
setTimeout(resolve);
} else {
function completed() {
document.removeEventListener('DOMContentLoaded', completed, false);
window.removeEventListener('load', completed, false);
resolve();
}
document.addEventListener('DOMContentLoaded', completed, false);
window.addEventListener('load', completed, false);
}
})
}
export function windowLoad() {
return new Promise(resolve => {
if (document.readyState === 'complete') {
setTimeout(resolve);
} else {
function completed() {
window.removeEventListener('load', completed, false);
resolve();
}
window.addEventListener('load', completed, false);
}
});
}
export function hasAttribute(el: Element, attributeName) {
return el.hasAttribute(attributeName);
}
export function addClass(el: Element, ...classNames) {
for (let c of classNames) {
el.classList.add(c);
}
}
export function getChildIndex(el: Element) {
let child;
let parent = el.parentNode;
for(let i = 0, j = parent.children.length; i < j; i++) {
child = parent.children[i];
if(child === el) {
return i;
}
}
return -1;
}