module_matrix-1.0.2/js/module-matrix/animation-manager.js

js/module-matrix/animation-manager.js
/**
 * @file animation-manager.js
 * Animation and transition management
 */

window.ModuleMatrix = window.ModuleMatrix || {};

window.ModuleMatrix.AnimationManager = {

  /**
   * Animate visible modules in the list
   */
  animateVisibleModules(mainList) {
    const { SELECTORS, CLASSES } = window.ModuleMatrix.Constants;
    const visibleModules = mainList.querySelectorAll(`${SELECTORS.moduleItem}:not(.${CLASSES.hidden})`);

    visibleModules.forEach(module => {
      this.animateModule(module);
    });
  },

  /**
   * Animate individual module
   */
  animateModule(module) {
    const { CLASSES } = window.ModuleMatrix.Constants;

    module.classList.add(CLASSES.animate);

    module.addEventListener('animationend', () => {
      module.classList.remove(CLASSES.animate);
    }, { once: true });
  },

  /**
   * Initialize expandable details animation
   */
  initializeDetailsAnimation() {
    const { SELECTORS } = window.ModuleMatrix.Constants;
    const detailsElements = document.querySelectorAll(SELECTORS.moduleDetails);

    detailsElements.forEach(details => {
      this.setupDetailsElement(details);
    });
  },

  /**
   * Setup individual details element for animation
   */
  setupDetailsElement(details) {
    const { SELECTORS } = window.ModuleMatrix.Constants;
    const header = details.querySelector(SELECTORS.detailsHeader);
    const content = details.querySelector(SELECTORS.detailsContent);

    if (!header || !content) return;

    header.addEventListener('click', () => {
      this.toggleDetailsElement(details, header, content);
    });
  },

  /**
   * Toggle details element open/closed with animation
   */
  toggleDetailsElement(details, header, content) {
    const { CLASSES } = window.ModuleMatrix.Constants;
    const isOpen = details.classList.toggle(CLASSES.open);

    header.setAttribute('aria-expanded', isOpen.toString());

    if (isOpen) {
      this.expandDetails(content);
    } else {
      this.collapseDetails(content);
    }
  },

  /**
   * Expand details content with smooth animation
   */
  expandDetails(content) {
    content.style.height = content.scrollHeight + 'px';

    content.addEventListener('transitionend', function onExpand() {
      content.style.height = 'auto';
      content.removeEventListener('transitionend', onExpand);
    });
  },

  /**
   * Collapse details content with smooth animation
   */
  collapseDetails(content) {
    content.style.height = content.scrollHeight + 'px';

    requestAnimationFrame(() => {
      content.style.height = '0px';
    });
  },

  /**
   * Animate module list transitions
   */
  animateListTransition(mainList, callback) {
    const { SELECTORS } = window.ModuleMatrix.Constants;
    const modules = mainList.querySelectorAll(SELECTORS.moduleItem);

    // Add transition class to all modules
    modules.forEach(module => {
      module.style.transition = 'opacity 0.2s ease-in-out, transform 0.2s ease-in-out';
    });

    // Execute callback after brief delay
    setTimeout(() => {
      if (callback) callback();

      // Remove transition after animation
      setTimeout(() => {
        modules.forEach(module => {
          module.style.transition = '';
        });
      }, 200);
    }, 50);
  },

  /**
   * Fade in elements
   */
  fadeIn(elements, duration = 300) {
    const elementsArray = Array.isArray(elements) ? elements : [elements];

    elementsArray.forEach(element => {
      element.style.opacity = '0';
      element.style.transition = `opacity ${duration}ms ease-in-out`;

      requestAnimationFrame(() => {
        element.style.opacity = '1';
      });

      setTimeout(() => {
        element.style.transition = '';
      }, duration);
    });
  },

  /**
   * Fade out elements
   */
  fadeOut(elements, duration = 300) {
    const elementsArray = Array.isArray(elements) ? elements : [elements];

    return new Promise(resolve => {
      elementsArray.forEach((element, index) => {
        element.style.transition = `opacity ${duration}ms ease-in-out`;
        element.style.opacity = '0';

        if (index === elementsArray.length - 1) {
          setTimeout(() => {
            element.style.transition = '';
            resolve();
          }, duration);
        }
      });
    });
  },

  /**
   * Slide down animation
   */
  slideDown(element, duration = 300) {
    element.style.height = '0px';
    element.style.overflow = 'hidden';
    element.style.transition = `height ${duration}ms ease-in-out`;

    requestAnimationFrame(() => {
      element.style.height = element.scrollHeight + 'px';
    });

    setTimeout(() => {
      element.style.height = 'auto';
      element.style.overflow = '';
      element.style.transition = '';
    }, duration);
  },

  /**
   * Slide up animation
   */
  slideUp(element, duration = 300) {
    element.style.height = element.offsetHeight + 'px';
    element.style.overflow = 'hidden';
    element.style.transition = `height ${duration}ms ease-in-out`;

    requestAnimationFrame(() => {
      element.style.height = '0px';
    });

    setTimeout(() => {
      element.style.overflow = '';
      element.style.transition = '';
    }, duration);
  },

  /**
   * Staggered animation for multiple elements
   */
  staggerAnimation(elements, animationClass, staggerDelay = 50) {
    const elementsArray = Array.from(elements);

    elementsArray.forEach((element, index) => {
      setTimeout(() => {
        this.animateModule(element);
      }, index * staggerDelay);
    });
  },

  /**
   * Check if animations are supported
   */
  supportsAnimations() {
    const testElement = document.createElement('div');
    return 'animationName' in testElement.style || 'webkitAnimationName' in testElement.style;
  },

  /**
   * Disable animations (for accessibility)
   */
  disableAnimations() {
    const style = document.createElement('style');
    style.textContent = `
      *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
      }
    `;
    document.head.appendChild(style);
  }
};

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

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