code: function animate ( eles, props, options ) {
  
      eles = _.castArray ( eles );
      options = _.merge ( {}, $.animate.defaults, options );
  
      let easing = $.animate.easings[options.easing],
          propsKeys = Object.keys ( props ),
          startTime = Date.now (),
          isStart = true,
          endedNr = 0;
  
      eles.forEach ( ele => {
  
        let startProps = {},
            deltaProps = {};
  
        propsKeys.forEach ( prop => {
          startProps[prop] = options.internals.getProp ( ele, prop );
          deltaProps[prop] = props[prop] - startProps[prop];
        });
  
        function tick () {
  
          /* START */
  
          if ( isStart ) {
  
            options.callbacks.start ();
  
            isStart = false;
  
          }
  
          /* TICK */
  
          let currTime = Date.now (),
              currDuration = Math.min ( options.duration, currTime - startTime );
  
          propsKeys.forEach ( prop => {
  
            let value = easing ( null, currDuration, startProps[prop], deltaProps[prop], options.duration );
  
            options.internals.setProp ( ele, prop, value );
  
          });
  
          options.callbacks.tick ();
  
          /* END */
  
          let isEnd = ( currDuration >= options.duration );
  
          if ( isEnd ) {
  
            endedNr += 1;
  
            if ( endedNr === eles.length ) {
  
              options.callbacks.end ();
  
            }
  
          } else {
  
            requestAnimationFrame ( tick );
  
          }
  
        }
  
        tick ();
  
      });
  
    }
docs: /* ANIMATE