*
* # 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
*

* Fade me in out
*

*
*
* ```
*
* Notice the CSS class **fade**? We can now create the CSS transition code that references this class:
*
* ```css
* /* The starting CSS styles for the enter animation */
* .fade.ng-enter {
* transition:0.5s linear all;
* opacity:0;
* }
*
* /* The starting CSS styles for the enter animation */
* .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
* /* now the element will fade out before it is removed from the DOM */
* .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
* /* there is no need to define anything inside of the destination
* CSS class since the keyframe will take charge of the animation */
* .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
*

* Show and hide me
*

*
*
*
* ```
*
* 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
*

* Highlight this box
*

*
*
*
* ```
*
* 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 {
* /* standard transition code */
* transition: 1s linear all;
* opacity:0;
* }
* .my-animation.ng-enter-stagger {
* /* this will have a 100ms delay between each successive leave animation */
* transition-delay: 0.1s;
*
* /* in case the stagger doesn't work then the duration value
* must be set to 0 to avoid an accidental CSS inheritance */
* transition-duration: 0s;
* }
* .my-animation.ng-enter.ng-enter-active {
* /* standard transition styles */
* 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
*

* ```
*
* ```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 suppliment for the
* lack of CSS animations by making use of 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',
* 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
* /* the transition tells ngAnimate to make the animation happen */
* .slide.ng-enter { transition:0.5s linear all; }
*
* /* this extra CSS class will be absorbed into the transition
* since the $animateCss code is adding the class */
* .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
*
*

*

*
*
*
*
*
*
*
*
* ```
*
* 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 {
* /* this animation will last for 1 second since there are
* two phases to the animation (an `in` and an `out` phase) */
* 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;
*
* /* the scale will be applied during the out animation,
* but will be animated away when the in animation runs */
* transform: scale(1.2);
* }
*
* .banner.ng-anchor-in {
* transition: 1s linear all;
* }
* ```
*
*
*
*
* ### Anchoring Demo
*
Home

Welcome to the home page

.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;
}
*
* ### 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 `` 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
* Hi there
* ```
*
* ```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
* /* normally we would create a CSS class to reference on the element */
* [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
* /* prefixed with animate- */
* .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', [])
.directive('ngAnimateChildren', $$AnimateChildrenDirective)
.factory('$$rAFMutex', $$rAFMutexFactory)
.factory('$$rAFScheduler', $$rAFSchedulerFactory)
.factory('$$AnimateRunner', $$AnimateRunnerFactory)
.provider('$$animateQueue', $$AnimateQueueProvider)
.provider('$$animation', $$AnimationProvider)
.provider('$animateCss', $AnimateCssProvider)
.provider('$$animateCssDriver', $$AnimateCssDriverProvider)
.provider('$$animateJs', $$AnimateJsProvider)
.provider('$$animateJsDriver', $$AnimateJsDriverProvider);
})(window, window.angular);