text: 'use strict';
  
  /* global angularAnimateModule: true,
  
     $$BodyProvider,
     $$rAFMutexFactory,
     $$AnimateChildrenDirective,
     $$AnimateRunnerFactory,
     $$AnimateQueueProvider,
     $$AnimationProvider,
     $AnimateCssProvider,
     $$AnimateCssDriverProvider,
     $$AnimateJsProvider,
     $$AnimateJsDriverProvider,
  */
  
  /**
   * @ngdoc module
   * @name ngAnimate
   * @description
   *
   * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via
   * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` then the animation hooks are enabled for an Angular app.
   *
   * <div doc-module-components="ngAnimate"></div>
   *
   * # Usage
   * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based
   * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For
   * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within
   * the HTML element that the animation will be triggered on.
   *
   * ## Directive Support
   * The following directives are "animation aware":
   *
   * | Directive                                                                                                | Supported Animations                                                     |
   * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
   * | {@link ng.directive:ngRepeat#animations ngRepeat}                                                        | enter, leave and move                                                    |
   * | {@link ngRoute.directive:ngView#animations ngView}                                                       | enter and leave                                                          |
   * | {@link ng.directive:ngInclude#animations ngInclude}                                                      | enter and leave                                                          |
   * | {@link ng.directive:ngSwitch#animations ngSwitch}                                                        | enter and leave                                                          |
   * | {@link ng.directive:ngIf#animations ngIf}                                                                | enter and leave                                                          |
   * | {@link ng.directive:ngClass#animations ngClass}                                                          | add and remove (the CSS class(es) present)                               |
   * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide}            | add and remove (the ng-hide class value)                                 |
   * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel}    | add and remove (dirty, pristine, valid, invalid & all other validations) |
   * | {@link module:ngMessages#animations ngMessages}                                                          | add and remove (ng-active & ng-inactive)                                 |
   * | {@link module:ngMessages#animations ngMessage}                                                           | enter and leave                                                          |
   *
   * (More information can be found by visiting each the documentation associated with each directive.)
   *
   * ## CSS-based Animations
   *
   * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML
   * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation.
   *
   * The example below shows how an `enter` animation can be made possible on a element using `ng-if`:
   *
   * ```html
   * <div ng-if="bool" class="fade">
   *    Fade me in out
   * </div>
   * <button ng-click="bool=true">Fade In!</button>
   * <button ng-click="bool=false">Fade Out!</button>
   * ```
   *
   * Notice the CSS class **fade**? We can now create the CSS transition code that references this class:
   *
   * ```css
   * /&#42; The starting CSS styles for the enter animation &#42;/
   * .fade.ng-enter {
   *   transition:0.5s linear all;
   *   opacity:0;
   * }
   *
   * /&#42; The finishing CSS styles for the enter animation &#42;/
   * .fade.ng-enter.ng-enter-active {
   *   opacity:1;
   * }
   * ```
   *
   * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two
   * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition
   * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards.
   *
   * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions:
   *
   * ```css
   * /&#42; now the element will fade out before it is removed from the DOM &#42;/
   * .fade.ng-leave {
   *   transition:0.5s linear all;
   *   opacity:1;
   * }
   * .fade.ng-leave.ng-leave-active {
   *   opacity:0;
   * }
   * ```
   *
   * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class:
   *
   * ```css
   * /&#42; there is no need to define anything inside of the destination
   * CSS class since the keyframe will take charge of the animation &#42;/
   * .fade.ng-leave {
   *   animation: my_fade_animation 0.5s linear;
   *   -webkit-animation: my_fade_animation 0.5s linear;
   * }
   *
   * @keyframes my_fade_animation {
   *   from { opacity:1; }
   *   to { opacity:0; }
   * }
   *
   * @-webkit-keyframes my_fade_animation {
   *   from { opacity:1; }
   *   to { opacity:0; }
   * }
   * ```
   *
   * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element.
   *
   * ### CSS Class-based Animations
   *
   * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different
   * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added
   * and removed.
   *
   * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class:
   *
   * ```html
   * <div ng-show="bool" class="fade">
   *   Show and hide me
   * </div>
   * <button ng-click="bool=true">Toggle</button>
   *
   * <style>
   * .fade.ng-hide {
   *   transition:0.5s linear all;
   *   opacity:0;
   * }
   * </style>
   * ```
   *
   * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since
   * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest.
   *
   * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation
   * with CSS styles.
   *
   * ```html
   * <div ng-class="{on:onOff}" class="highlight">
   *   Highlight this box
   * </div>
   * <button ng-click="onOff=!onOff">Toggle</button>
   *
   * <style>
   * .highlight {
   *   transition:0.5s linear all;
   * }
   * .highlight.on-add {
   *   background:white;
   * }
   * .highlight.on {
   *   background:yellow;
   * }
   * .highlight.on-remove {
   *   background:black;
   * }
   * </style>
   * ```
   *
   * We can also make use of CSS keyframes by placing them within the CSS classes.
   *
   *
   * ### CSS Staggering Animations
   * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a
   * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be
   * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for
   * the animation. The style property expected within the stagger class can either be a **transition-delay** or an
   * **animation-delay** property (or both if your animation contains both transitions and keyframe animations).
   *
   * ```css
   * .my-animation.ng-enter {
   *   /&#42; standard transition code &#42;/
   *   transition: 1s linear all;
   *   opacity:0;
   * }
   * .my-animation.ng-enter-stagger {
   *   /&#42; this will have a 100ms delay between each successive leave animation &#42;/
   *   transition-delay: 0.1s;
   *
   *   /&#42; in case the stagger doesn't work then the duration value
   *    must be set to 0 to avoid an accidental CSS inheritance &#42;/
   *   transition-duration: 0s;
   * }
   * .my-animation.ng-enter.ng-enter-active {
   *   /&#42; standard transition styles &#42;/
   *   opacity:1;
   * }
   * ```
   *
   * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations
   * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this
   * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation
   * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired.
   *
   * The following code will issue the **ng-leave-stagger** event on the element provided:
   *
   * ```js
   * var kids = parent.children();
   *
   * $animate.leave(kids[0]); //stagger index=0
   * $animate.leave(kids[1]); //stagger index=1
   * $animate.leave(kids[2]); //stagger index=2
   * $animate.leave(kids[3]); //stagger index=3
   * $animate.leave(kids[4]); //stagger index=4
   *
   * window.requestAnimationFrame(function() {
   *   //stagger has reset itself
   *   $animate.leave(kids[5]); //stagger index=0
   *   $animate.leave(kids[6]); //stagger index=1
   *
   *   $scope.$digest();
   * });
   * ```
   *
   * Stagger animations are currently only supported within CSS-defined animations.
   *
   * ### The `ng-animate` CSS class
   *
   * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation.
   * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations).
   *
   * Therefore, animations can be applied to an element using this temporary class directly via CSS.
   *
   * ```css
   * .zipper.ng-animate {
   *   transition:0.5s linear all;
   * }
   * .zipper.ng-enter {
   *   opacity:0;
   * }
   * .zipper.ng-enter.ng-enter-active {
   *   opacity:1;
   * }
   * .zipper.ng-leave {
   *   opacity:1;
   * }
   * .zipper.ng-leave.ng-leave-active {
   *   opacity:0;
   * }
   * ```
   *
   * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove
   * the CSS class once an animation has completed.)
   *
   *
   * ## JavaScript-based Animations
   *
   * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared
   * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the
   * `module.animation()` module function we can register the ainmation.
   *
   * Let's see an example of a enter/leave animation using `ngRepeat`:
   *
   * ```html
   * <div ng-repeat="item in items" class="slide">
   *   {{ item }}
   * </div>
   * ```
   *
   * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`:
   *
   * ```js
   * myModule.animation('.slide', [function() {
   *   return {
   *     // make note that other events (like addClass/removeClass)
   *     // have different function input parameters
   *     enter: function(element, doneFn) {
   *       jQuery(element).fadeIn(1000, doneFn);
   *
   *       // remember to call doneFn so that angular
   *       // knows that the animation has concluded
   *     },
   *
   *     move: function(element, doneFn) {
   *       jQuery(element).fadeIn(1000, doneFn);
   *     },
   *
   *     leave: function(element, doneFn) {
   *       jQuery(element).fadeOut(1000, doneFn);
   *     }
   *   }
   * }]
   * ```
   *
   * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as
   * greensock.js and velocity.js.
   *
   * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define
   * our animations inside of the same registered animation, however, the function input arguments are a bit different:
   *
   * ```html
   * <div ng-class="color" class="colorful">
   *   this box is moody
   * </div>
   * <button ng-click="color='red'">Change to red</button>
   * <button ng-click="color='blue'">Change to blue</button>
   * <button ng-click="color='green'">Change to green</button>
   * ```
   *
   * ```js
   * myModule.animation('.colorful', [function() {
   *   return {
   *     addClass: function(element, className, doneFn) {
   *       // do some cool animation and call the doneFn
   *     },
   *     removeClass: function(element, className, doneFn) {
   *       // do some cool animation and call the doneFn
   *     },
   *     setClass: function(element, addedClass, removedClass, doneFn) {
   *       // do some cool animation and call the doneFn
   *     }
   *   }
   * }]
   * ```
   *
   * ## CSS + JS Animations Together
   *
   * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular,
   * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking
   * charge of the animation**:
   *
   * ```html
   * <div ng-if="bool" class="slide">
   *   Slide in and out
   * </div>
   * ```
   *
   * ```js
   * myModule.animation('.slide', [function() {
   *   return {
   *     enter: function(element, doneFn) {
   *       jQuery(element).slideIn(1000, doneFn);
   *     }
   *   }
   * }]
   * ```
   *
   * ```css
   * .slide.ng-enter {
   *   transition:0.5s linear all;
   *   transform:translateY(-100px);
   * }
   * .slide.ng-enter.ng-enter-active {
   *   transform:translateY(0);
   * }
   * ```
   *
   * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the
   * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from
   * our own JS-based animation code:
   *
   * ```js
   * myModule.animation('.slide', ['$animateCss', function($animateCss) {
   *   return {
   *     enter: function(element, doneFn) {
  *        // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`.
   *       var runner = $animateCss(element, {
   *         event: 'enter',
   *         structural: true
   *       }).start();
  *        runner.done(doneFn);
   *     }
   *   }
   * }]
   * ```
   *
   * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework.
   *
   * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or
   * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that
   * data into `$animateCss` directly:
   *
   * ```js
   * myModule.animation('.slide', ['$animateCss', function($animateCss) {
   *   return {
   *     enter: function(element, doneFn) {
   *       var runner = $animateCss(element, {
   *         event: 'enter',
   *         structural: true,
   *         addClass: 'maroon-setting',
   *         from: { height:0 },
   *         to: { height: 200 }
   *       }).start();
   *
   *       runner.done(doneFn);
   *     }
   *   }
   * }]
   * ```
   *
   * Now we can fill in the rest via our transition CSS code:
   *
   * ```css
   * /&#42; the transition tells ngAnimate to make the animation happen &#42;/
   * .slide.ng-enter { transition:0.5s linear all; }
   *
   * /&#42; this extra CSS class will be absorbed into the transition
   * since the $animateCss code is adding the class &#42;/
   * .maroon-setting { background:red; }
   * ```
   *
   * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over.
   *
   * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}.
   *
   * ## Animation Anchoring (via `ng-animate-ref`)
   *
   * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between
   * structural areas of an application (like views) by pairing up elements using an attribute
   * called `ng-animate-ref`.
   *
   * Let's say for example we have two views that are managed by `ng-view` and we want to show
   * that there is a relationship between two components situated in within these views. By using the
   * `ng-animate-ref` attribute we can identify that the two components are paired together and we
   * can then attach an animation, which is triggered when the view changes.
   *
   * Say for example we have the following template code:
   *
   * ```html
   * <!-- index.html -->
   * <div ng-view class="view-animation">
   * </div>
   *
   * <!-- home.html -->
   * <a href="#/banner-page">
   *   <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
   * </a>
   *
   * <!-- banner-page.html -->
   * <img src="./banner.jpg" class="banner" ng-animate-ref="banner">
   * ```
   *
   * Now, when the view changes (once the link is clicked), ngAnimate will examine the
   * HTML contents to see if there is a match reference between any components in the view
   * that is leaving and the view that is entering. It will scan both the view which is being
   * removed (leave) and inserted (enter) to see if there are any paired DOM elements that
   * contain a matching ref value.
   *
   * The two images match since they share the same ref value. ngAnimate will now create a
   * transport element (which is a clone of the first image element) and it will then attempt
   * to animate to the position of the second image element in the next view. For the animation to
   * work a special CSS class called `ng-anchor` will be added to the transported element.
   *
   * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then
   * ngAnimate will handle the entire transition for us as well as the addition and removal of
   * any changes of CSS classes between the elements:
   *
   * ```css
   * .banner.ng-anchor {
   *   /&#42; this animation will last for 1 second since there are
   *          two phases to the animation (an `in` and an `out` phase) &#42;/
   *   transition:0.5s linear all;
   * }
   * ```
   *
   * We also **must** include animations for the views that are being entered and removed
   * (otherwise anchoring wouldn't be possible since the new view would be inserted right away).
   *
   * ```css
   * .view-animation.ng-enter, .view-animation.ng-leave {
   *   transition:0.5s linear all;
   *   position:fixed;
   *   left:0;
   *   top:0;
   *   width:100%;
   * }
   * .view-animation.ng-enter {
   *   transform:translateX(100%);
   * }
   * .view-animation.ng-leave,
   * .view-animation.ng-enter.ng-enter-active {
   *   transform:translateX(0%);
   * }
   * .view-animation.ng-leave.ng-leave-active {
   *   transform:translateX(-100%);
   * }
   * ```
   *
   * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur:
   * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away
   * from its origin. Once that animation is over then the `in` stage occurs which animates the
   * element to its destination. The reason why there are two animations is to give enough time
   * for the enter animation on the new element to be ready.
   *
   * The example above sets up a transition for both the in and out phases, but we can also target the out or
   * in phases directly via `ng-anchor-out` and `ng-anchor-in`.
   *
   * ```css
   * .banner.ng-anchor-out {
   *   transition: 0.5s linear all;
   *
   *   /&#42; the scale will be applied during the out animation,
   *          but will be animated away when the in animation runs &#42;/
   *   transform: scale(1.2);
   * }
   *
   * .banner.ng-anchor-in {
   *   transition: 1s linear all;
   * }
   * ```
   *
   *
   *
   *
   * ### Anchoring Demo
   *
    <example module="anchoringExample"
             name="anchoringExample"
             id="anchoringExample"
             deps="angular-animate.js;angular-route.js"
             animations="true">
      <file name="index.html">
        <a href="#/">Home</a>
        <hr />
        <div class="view-container">
          <div ng-view class="view"></div>
        </div>
      </file>
      <file name="script.js">
        angular.module('anchoringExample', ['ngAnimate', 'ngRoute'])
          .config(['$routeProvider', function($routeProvider) {
            $routeProvider.when('/', {
              templateUrl: 'home.html',
              controller: 'HomeController as home'
            });
            $routeProvider.when('/profile/:id', {
              templateUrl: 'profile.html',
              controller: 'ProfileController as profile'
            });
          }])
          .run(['$rootScope', function($rootScope) {
            $rootScope.records = [
              { id:1, title: "Miss Beulah Roob" },
              { id:2, title: "Trent Morissette" },
              { id:3, title: "Miss Ava Pouros" },
              { id:4, title: "Rod Pouros" },
              { id:5, title: "Abdul Rice" },
              { id:6, title: "Laurie Rutherford Sr." },
              { id:7, title: "Nakia McLaughlin" },
              { id:8, title: "Jordon Blanda DVM" },
              { id:9, title: "Rhoda Hand" },
              { id:10, title: "Alexandrea Sauer" }
            ];
          }])
          .controller('HomeController', [function() {
            //empty
          }])
          .controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) {
            var index = parseInt($routeParams.id, 10);
            var record = $rootScope.records[index - 1];
  
            this.title = record.title;
            this.id = record.id;
          }]);
      </file>
      <file name="home.html">
        <h2>Welcome to the home page</h1>
        <p>Please click on an element</p>
        <a class="record"
           ng-href="#/profile/{{ record.id }}"
           ng-animate-ref="{{ record.id }}"
           ng-repeat="record in records">
          {{ record.title }}
        </a>
      </file>
      <file name="profile.html">
        <div class="profile record" ng-animate-ref="{{ profile.id }}">
          {{ profile.title }}
        </div>
      </file>
      <file name="animations.css">
        .record {
          display:block;
          font-size:20px;
        }
        .profile {
          background:black;
          color:white;
          font-size:100px;
        }
        .view-container {
          position:relative;
        }
        .view-container > .view.ng-animate {
          position:absolute;
          top:0;
          left:0;
          width:100%;
          min-height:500px;
        }
        .view.ng-enter, .view.ng-leave,
        .record.ng-anchor {
          transition:0.5s linear all;
        }
        .view.ng-enter {
          transform:translateX(100%);
        }
        .view.ng-enter.ng-enter-active, .view.ng-leave {
          transform:translateX(0%);
        }
        .view.ng-leave.ng-leave-active {
          transform:translateX(-100%);
        }
        .record.ng-anchor-out {
          background:red;
        }
      </file>
    </example>
   *
   * ### How is the element transported?
   *
   * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting
   * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element
   * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The
   * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match
   * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied
   * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class
   * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element
   * will become visible since the shim class will be removed.
   *
   * ### How is the morphing handled?
   *
   * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out
   * what CSS classes differ between the starting element and the destination element. These different CSS classes
   * will be added/removed on the anchor element and a transition will be applied (the transition that is provided
   * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will
   * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that
   * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since
   * the cloned element is placed inside of root element which is likely close to the body element).
   *
   * Note that if the root element is on the `<html>` element then the cloned node will be placed inside of body.
   *
   *
   * ## Using $animate in your directive code
   *
   * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application?
   * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's
   * imagine we have a greeting box that shows and hides itself when the data changes
   *
   * ```html
   * <greeting-box active="onOrOff">Hi there</greeting-box>
   * ```
   *
   * ```js
   * ngModule.directive('greetingBox', ['$animate', function($animate) {
   *   return function(scope, element, attrs) {
   *     attrs.$observe('active', function(value) {
   *       value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on');
   *     });
   *   });
   * }]);
   * ```
   *
   * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element
   * in our HTML code then we can trigger a CSS or JS animation to happen.
   *
   * ```css
   * /&#42; normally we would create a CSS class to reference on the element &#42;/
   * greeting-box.on { transition:0.5s linear all; background:green; color:white; }
   * ```
   *
   * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's
   * possible be sure to visit the {@link ng.$animate $animate service API page}.
   *
   *
   * ### Preventing Collisions With Third Party Libraries
   *
   * Some third-party frameworks place animation duration defaults across many element or className
   * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which
   * is expecting actual animations on these elements and has to wait for their completion.
   *
   * You can prevent this unwanted behavior by using a prefix on all your animation classes:
   *
   * ```css
   * /&#42; prefixed with animate- &#42;/
   * .animate-fade-add.animate-fade-add-active {
   *   transition:1s linear all;
   *   opacity:0;
   * }
   * ```
   *
   * You then configure `$animate` to enforce this prefix:
   *
   * ```js
   * $animateProvider.classNameFilter(/animate-/);
   * ```
   *
   * This also may provide your application with a speed boost since only specific elements containing CSS class prefix
   * will be evaluated for animation when any DOM changes occur in the application.
   *
   * ## Callbacks and Promises
   *
   * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger
   * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has
   * ended by chaining onto the returned promise that animation method returns.
   *
   * ```js
   * // somewhere within the depths of the directive
   * $animate.enter(element, parent).then(function() {
   *   //the animation has completed
   * });
   * ```
   *
   * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case
   * anymore.)
   *
   * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering
   * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view
   * routing controller to hook into that:
   *
   * ```js
   * ngModule.controller('HomePageController', ['$animate', function($animate) {
   *   $animate.on('enter', ngViewElement, function(element) {
   *     // the animation for this route has completed
   *   }]);
   * }])
   * ```
   *
   * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.)
   */
  
  /**
   * @ngdoc service
   * @name $animate
   * @kind object
   *
   * @description
   * The ngAnimate `$animate` service documentation is the same for the core `$animate` service.
   *
   * Click here {@link ng.$animate $animate to learn more about animations with `$animate`}.
   */
  angular.module('ngAnimate', [])
    .provider('$$body', $$BodyProvider)
  
    .directive('ngAnimateChildren', $$AnimateChildrenDirective)
  
    .factory('$$rAFMutex', $$rAFMutexFactory)
  
    .factory('$$AnimateRunner', $$AnimateRunnerFactory)
  
    .provider('$$animateQueue', $$AnimateQueueProvider)
    .provider('$$animation', $$AnimationProvider)
  
    .provider('$animateCss', $AnimateCssProvider)
    .provider('$$animateCssDriver', $$AnimateCssDriverProvider)
  
    .provider('$$animateJs', $$AnimateJsProvider)
    .provider('$$animateJsDriver', $$AnimateJsDriverProvider);
  