(function() { 'use strict'; angular.module('foundation.core.animation', []) .service('FoundationAnimation', FoundationAnimation) ; function FoundationAnimation() { var animations = []; var service = {}; var initClasses = ['ng-enter', 'ng-leave']; var activeClasses = ['ng-enter-active', 'ng-leave-active']; var activeGenericClass = 'is-active'; var events = [ 'webkitAnimationEnd', 'mozAnimationEnd', 'MSAnimationEnd', 'oanimationend', 'animationend', 'webkitTransitionEnd', 'otransitionend', 'transitionend' ]; service.animate = animate; service.toggleAnimation = toggleAnimation; return service; function toggleAnimation(element, futureState) { if(futureState) { element.addClass(activeGenericClass); } else { element.removeClass(activeGenericClass); } } function animate(element, futureState, animationIn, animationOut) { var timedOut = true; var self = this; self.cancelAnimation = cancelAnimation; var animationClass = futureState ? animationIn: animationOut; var activation = futureState; var initClass = activation ? initClasses[0] : initClasses[1]; var activeClass = activation ? activeClasses[0] : activeClasses[1]; //stop animation registerElement(element); reset(); element.addClass(animationClass); element.addClass(initClass); element.addClass(activeGenericClass); //force a "tick" reflow(); //activate element[0].style.transitionDuration = ''; element.addClass(activeClass); element.one(events.join(' '), function() { finishAnimation(); }); setTimeout(function() { if(timedOut) { finishAnimation(); } }, 3000); function finishAnimation() { deregisterElement(element); reset(); //reset all classes element[0].style.transitionDuration = ''; element.removeClass(!activation ? activeGenericClass : ''); //if not active, remove active class reflow(); timedOut = false; } function cancelAnimation(element) { deregisterElement(element); angular.element(element).off(events.join(' ')); //kill all animation event handlers timedOut = false; } function registerElement(el) { var elObj = { el: el, animation: self }; //kill in progress animations var inProgress = animations.filter(function(obj) { return obj.el === el; }); if(inProgress.length > 0) { var target = inProgress[0].el[0]; inProgress[0].animation.cancelAnimation(target); } animations.push(elObj); } function deregisterElement(el) { var index; var currentAnimation = animations.filter(function(obj, ind) { if(obj.el === el) { index = ind; } }); if(index >= 0) { animations.splice(index, 1); } } function reflow() { return element[0].offsetWidth; } function reset() { element[0].style.transitionDuration = 0; element.removeClass(initClasses.join(' ') + ' ' + activeClasses.join(' ') + ' ' + animationIn + ' ' + animationOut); } } } })();