'use strict'; var $animateMinErr = minErr('$animate'); /** * @ngdoc object * @name ng.$animateProvider * * @description * Default implementation of $animate that doesn't perform any animations, instead just synchronously performs DOM * updates and calls done() callbacks. * * In order to enable animations the ngAnimate module has to be loaded. * * To see the functional implementation check out src/ngAnimate/animate.js */ var $AnimateProvider = ['$provide', function($provide) { this.$$selectors = {}; /** * @ngdoc function * @name ng.$animateProvider#register * @methodOf ng.$animateProvider * * @description * Registers a new injectable animation factory function. The factory function produces the animation object which * contains callback functions for each event that is expected to be animated. * * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction` must be called once the * element animation is complete. If a function is returned then the animation service will use this function to * cancel the animation whenever a cancel event is triggered. * * *
   *   return {
     *     eventFn : function(element, done) {
     *       //code to run the animation
     *       //once complete, then run done()
     *       return function cancellationFunction() {
     *         //code to cancel the animation
     *       }
     *     }
     *   }
   *
   *
   * @param {string} name The name of the animation.
   * @param {function} factory The factory function that will be executed to return the animation object.
   */
  this.register = function(name, factory) {
    var key = name + '-animation';
    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
        "Expecting class selector starting with '.' got '{0}'.", name);
    this.$$selectors[name.substr(1)] = key;
    $provide.factory(key, factory);
  };
  this.$get = ['$timeout', function($timeout) {
    /**
     * @ngdoc object
     * @name ng.$animate
     *
     * @description
     * The $animate service provides rudimentary DOM manipulation functions to insert, remove, move elements within
     * the DOM as well as adding and removing classes. This service is the core service used by the ngAnimate $animator
     * service which provides high-level animation hooks for CSS and JavaScript. 
     *
     * $animate is available in the AngularJS core, however, the ngAnimate module must be included to enable full out
     * animation support. Otherwise, $animate will only perform simple DOM manipulation operations.
     *
     * To learn more about enabling animation support, click here to visit the {@link ngAnimate ngAnimate module page}
     * as well as the {@link ngAnimate.$animate ngAnimate $animate service page}.
     */
    return {
      /**
       * @ngdoc function
       * @name ng.$animate#enter
       * @methodOf ng.$animate
       * @function
       *
       * @description
       * Inserts the element into the DOM either after the `after` element or within the `parent` element. Once complete,
       * the done() callback will be fired (if provided).
       *
       * @param {jQuery/jqLite element} element the element which will be inserted into the DOM
       * @param {jQuery/jqLite element} parent the parent element which will append the element as a child (if the after element is not present)
       * @param {jQuery/jqLite element} after the sibling element which will append the element after itself
       * @param {function=} done callback function that will be called after the element has been inserted into the DOM
       */
      enter : function(element, parent, after, done) {
        var afterNode = after && after[after.length - 1];
        var parentNode = parent && parent[0] || afterNode && afterNode.parentNode;
        // IE does not like undefined so we have to pass null.
        var afterNextSibling = (afterNode && afterNode.nextSibling) || null;
        forEach(element, function(node) {
          parentNode.insertBefore(node, afterNextSibling);
        });
        done && $timeout(done, 0, false);
      },
      /**
       * @ngdoc function
       * @name ng.$animate#leave
       * @methodOf ng.$animate
       * @function
       *
       * @description
       * Removes the element from the DOM. Once complete, the done() callback will be fired (if provided).
       *
       * @param {jQuery/jqLite element} element the element which will be removed from the DOM
       * @param {function=} done callback function that will be called after the element has been removed from the DOM
       */
      leave : function(element, done) {
        element.remove();
        done && $timeout(done, 0, false);
      },
      /**
       * @ngdoc function
       * @name ng.$animate#move
       * @methodOf ng.$animate
       * @function
       *
       * @description
       * Moves the position of the provided element within the DOM to be placed either after the `after` element or inside of the `parent` element.
       * Once complete, the done() callback will be fired (if provided).
       *
       * @param {jQuery/jqLite element} element the element which will be moved around within the DOM
       * @param {jQuery/jqLite element} parent the parent element where the element will be inserted into (if the after element is not present)
       * @param {jQuery/jqLite element} after the sibling element where the element will be positioned next to
       * @param {function=} done the callback function (if provided) that will be fired after the element has been moved to it's new position
       */
      move : function(element, parent, after, done) {
        // Do not remove element before insert. Removing will cause data associated with the
        // element to be dropped. Insert will implicitly do the remove.
        this.enter(element, parent, after, done);
      },
      /**
       * @ngdoc function
       * @name ng.$animate#addClass
       * @methodOf ng.$animate
       * @function
       *
       * @description
       * Adds the provided className CSS class value to the provided element. Once complete, the done() callback will be fired (if provided).
       *
       * @param {jQuery/jqLite element} element the element which will have the className value added to it
       * @param {string} className the CSS class which will be added to the element
       * @param {function=} done the callback function (if provided) that will be fired after the className value has been added to the element
       */
      addClass : function(element, className, done) {
        className = isString(className) ?
                      className :
                      isArray(className) ? className.join(' ') : '';
        element.addClass(className);
        done && $timeout(done, 0, false);
      },
      /**
       * @ngdoc function
       * @name ng.$animate#removeClass
       * @methodOf ng.$animate
       * @function
       *
       * @description
       * Removes the provided className CSS class value from the provided element. Once complete, the done() callback will be fired (if provided).
       *
       * @param {jQuery/jqLite element} element the element which will have the className value removed from it
       * @param {string} className the CSS class which will be removed from the element
       * @param {function=} done the callback function (if provided) that will be fired after the className value has been removed from the element
       */
      removeClass : function(element, className, done) {
        className = isString(className) ?
                      className :
                      isArray(className) ? className.join(' ') : '';
        element.removeClass(className);
        done && $timeout(done, 0, false);
      },
      enabled : noop
    };
  }];
}];