countdown-8.x-1.8/js/countdown-preview-cleanup.js

js/countdown-preview-cleanup.js
/**
 * @file
 * Handles cleanup of countdown preview instances.
 *
 * Ensures proper disposal of countdown instances to prevent memory leaks.
 */

(function (Drupal, once) {
  'use strict';

  // Track active countdown instances.
  var activeInstances = new WeakMap();

  /**
   * Clean up countdown instances before AJAX updates.
   */
  Drupal.behaviors.countdownPreviewCleanup = {
    attach: function (context) {
      // Initialize cleanup tracking for new elements.
      once('countdown-cleanup-init', '.countdown-preview-container', context)
        .forEach(function (container) {
          // Mark container as tracked.
          container.setAttribute('data-cleanup-tracked', 'true');
        });
    },

    detach: function (context, settings, trigger) {
      // Only cleanup on unload or before AJAX refresh.
      if (trigger === 'unload' || trigger === 'ajax') {
        var containers = context.querySelectorAll('.countdown-preview-container[data-cleanup-tracked]');

        containers.forEach(function (container) {
          cleanupContainer(container);
        });
      }
    }
  };

  /**
   * Clean up all countdown instances in a container.
   *
   * @param {HTMLElement} container
   *   The container element to clean up.
   */
  function cleanupContainer(container) {
    console.log('Cleaning up countdown instance for:', container);

    // Find all countdown elements within the container.
    var countdowns = container.querySelectorAll('[data-countdown-instance]');

    countdowns.forEach(function (element) {
      cleanupInstance(element);
    });

    // Clear the container's tracked state.
    container.removeAttribute('data-cleanup-tracked');

    // Remove any stored references.
    if (activeInstances.has(container)) {
      activeInstances.delete(container);
    }
  }

  /**
   * Clean up a specific countdown instance.
   *
   * @param {HTMLElement} element
   *   The countdown element to clean up.
   */
  function cleanupInstance(element) {
    // Clean up Tick instances.
    if (element.tickInstance && typeof element.tickInstance.destroy === 'function') {
      element.tickInstance.destroy();
      delete element.tickInstance;
    }

    // Clean up FlipClock instances.
    if (element.flipClock && typeof element.flipClock.stop === 'function') {
      element.flipClock.stop();
      delete element.flipClock;
    }

    // Clean up FlipDown instances.
    if (element.flipDown) {
      delete element.flipDown;
    }

    // Clean up Flip instances.
    if (element.flipInstance) {
      delete element.flipInstance;
    }

    // Clean up any timers.
    if (element.countdownTimer) {
      clearInterval(element.countdownTimer);
      delete element.countdownTimer;
    }

    // Remove instance marker.
    element.removeAttribute('data-countdown-instance');
  }

  /**
   * Register an instance for tracking.
   *
   * @param {HTMLElement} container
   *   The container element.
   * @param {Object} instance
   *   The countdown instance.
   */
  window.registerCountdownInstance = function (container, instance) {
    if (!activeInstances.has(container)) {
      activeInstances.set(container, []);
    }

    var instances = activeInstances.get(container);
    instances.push(instance);
  };

  /**
   * Clean up before form submissions to prevent recursion.
   */
  document.addEventListener('submit', function (event) {
    var form = event.target;

    // Only clean up for AJAX forms.
    if (form.classList.contains('countdown-settings-form')) {
      var containers = form.querySelectorAll('.countdown-preview-container');

      containers.forEach(function (container) {
        cleanupContainer(container);
      });
    }
  });

})(Drupal, once);

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

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