toolshed-8.x-1.x-dev/assets/Animate.es6.js

assets/Animate.es6.js
/**
 * Add animation methods to the Element wrapper class.
 */
(({ Toolshed: ts }) => {
  /**
   * Element has completed its CSS transition.
   *
   * @param {TransitionEvent} e
   *   The event object with the transition information.
   */
  function onTransitionEnd(e) {
    const prop = e.propertyName;
    if (prop === 'height' || prop === 'width') {
      const { style } = this;

      if (style[prop] === '0px') {
        style.display = 'none';
      }
      else {
        style.display = '';
        style.boxSizing = '';
        style[prop] = '';
      }

      style.overflow = '';
      style.transition = '';

      // Update statuses and check for any pending animations.
      this.isAnimating = false;
      const item = this.animateQueue.pop();
      if (item) {
        item[0].call(this, item[1]);
      }
    }
  };

  // Capture the current destructor to call in our override.
  const destroy = ts.Element.prototype.destroy;

  // Apply basic animation methods to the Element prototype.
  Object.assign(ts.Element.prototype, {
    destroy(detach) {
      // Terminate any in progress animations.
      if (this.isAnimating && this.el.Animation) this.el.Animation.cancel();
      if (this.animateQueue) delete this.animateQueue;

      // Call original destructor.
      destroy.call(this, detach);
    },

    /**
     * Collapse the height of the element (animate element close vertically).
     *
     * @param {float} duration A time in seconds for the transition to take place.
     */
    collapse(duration = '0.5s') {
      if (this.animating) this._queueAnimation(this.collapse, duration);
      else {
        // Capture the element height before starting the animation.
        const height = this.el.clientHeight;
        this._animate(
          {
            // Browsers are not able to perform transitions on elements with
            // auto-height, because the browser doesn't have a value to transition
            // between. Set the current height, wait for the an animation frame
            // from the change to take effect and then set the transition.
            height: `${height}px`,
            boxSizing: 'border-box',
            transition: 'none',
          },
          {
            height: '0px',
            paddingTop: '0px',
            paddingBottom: '0px',
            overflow: 'hidden',
          },
          (state) => {
            this.style.transition = `height ${duration}, padding ${duration}`;
            return state;
          }
        );
      }
    },

    /**
     * Expand the height of the element (animate element open vertically).
     *
     * @param {float} duration A time in seconds for the transition to take place.
     */
    expand(duration = '0.5s') {
      if (this.animating) this._queueAnimation(this.expand, duration);
      else {
        this._animate(
          {
            display: null,
            boxSizing: 'border-box',
            height: '0px',
            paddingTop: '0px',
            paddingBottom: '0px',
            transition: `height ${duration}, padding ${duration}`,
            overflow: 'hidden',
          },
          {
            height: `50px`,
            paddingTop: null,
            paddingBottom: null,
          },
          (state) => {
            state.height = `${this.el.scrollHeight||50}px`;
            return state;
          }
        );
      }
    },

    /**
     * Collapse the width of the element (animate element close horizontally).
     *
     * @param {float} duration A time in seconds for the transition to take place.
     */
    slideOut(duration = '0.5s') {
      if (this.animating) this._queueAnimation(this.slideOut, duration);
      else {
        // Capture the element height before starting the animation.
        const width = this.el.clientWidth;
        this._animate(
          {
            // Browsers are not able to perform transitions on elements with
            // auto-width, because the browser doesn't have a value to
            // transition to. Set the current height, wait for the an animation
            // frame from the change to take effect and then set the transition.
            width: `${width}px`,
            boxSizing: 'border-box',
            transition: 'none',
          },
          {
            width: '0px',
            paddingLeft: '0px',
            paddingRight: '0px',
            overflow: 'hidden',
          },
          (state) => {
            this.style.transition = `width ${duration}, padding ${duration}`;
            return state;
          }
        );
      }
    },

    /**
     * Expand the width of the element (animate element open horizontally).
     *
     * @param {float} duration A time in seconds for the transition to take place.
     */
    slideIn(duration = '0.5s') {
      if (this.animating) this._queueAnimation(this.slideIn, duration);

      else {
        this._animate(
          {
            display: null,
            boxSizing: 'border-box',
            width: '0px',
            paddingLeft: '0px',
            paddingRight: '0px',
            transition: `width ${duration}, padding ${duration}`,
            overflow: 'hidden',
          },
          {
            width: `50px`,
            paddingLeft: '',
            paddingRight: '',
          },
          (state) => {
            state.width = `${this.el.scrollWidth||50}px`;
            return state;
          }
        );
      }
    },

    /**
     * Initiate an animation sequence.
     *
     * @param {Object} init
     *   Initial states and styles to apply before starting the animation frames.
     * @param {Object} end
     *   The ending states and styles which complete the transition.
     * @param {function|closure=} transition
     *   An optional interframe callback to make adjustments to the ending
     *   transition states and alterations.
     */
    _animate(init, end, transition) {
      this.isAnimating = true;
      this._initAnimation();
      this.setStyles(init);

      requestAnimationFrame(() => {
        if (transition) {
          end = transition(end);
        }

        requestAnimationFrame(() => this.setStyles(end));
      });
    },

    /**
     * Initialize the element before the first animation is run.
     */
    _initAnimation() {
      if (!this.animateQueue) {
        this.animateQueue = [];
        this.on('transitionend', onTransitionEnd.bind(this));
      }
    },

    /**
     * Queue animations if pending animations are already in progress.
     *
     * @param {function|closure} method
     *   Animation method to add to the animation queue.
     * @param {string} duration
     *   The CSS transition time in seconds (ie "0.3s").
     */
    _queueAnimation(method, duration) {
      this._initAnimation();
      this.animateQueue.push([method, duration]);
    },
  });
})(Drupal);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc