text: (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.on(events.join(' '), eventHandler);
  
        var animationTimeout = setTimeout(function() {
          if(timedOut) {
            finishAnimation();
          }
        }, 3000);
  
        function eventHandler(e) {
          if (element[0] === e.target) {
            clearTimeout(animationTimeout);
            finishAnimation();
          }
        }
  
        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;
          element.off(events.join(' '), eventHandler);
        }
  
  
        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);
        }
      }
    }
  
  })();
  