iframe_consent-1.0.x-dev/js/iframe-consent.js

js/iframe-consent.js
/**
 * @file
 * Do not load iframes until user accept cookies.
 */

/**
 * Manage iframe load according given consent groups.
 *
 * @param {array} consentGroups
 *   Consent groups list.
 *
 * @constructor
 */
function IframeConsent(consentGroups) {
  this.consentGroups = consentGroups;
  this.manageCookiesCallback = null;
  this.acceptedCategories = [];
  this.placeholderWrapperClass = 'iframe-consent-placeholder-wrapper';
  this.placeholderWrapperSelector = '.iframe-consent-placeholder-wrapper';
  this.consentListWrapperSelector =
    '.iframe-consent-placeholder__required-consents';
  this.manageButtonSelector = '.iframe-consent-placeholder-button--manage';
  this.acceptButtonSelector = '.iframe-consent-placeholder-button--accept';
  this.initializedClass = 'iframe-consent--initialized';
  this.initializedSelector = '.iframe-consent--initialized';
}

/**
 * Callback that allow third parties set the consent banner.
 *
 * @param {function} callback
 *   Callback that show the consent banner.
 */
IframeConsent.prototype.setManageCookiesCallback = function (callback) {
  this.manageCookiesCallback = callback;
};

/**
 * Update the accepted categories.
 *
 * @param {array} categories
 *   Array of accepted categories.
 */
IframeConsent.prototype.setAcceptedCategories = function (categories) {
  this.acceptedCategories = categories;
  this.processAllIframes();
};

/**
 * Check if given categories are accepted.
 *
 * @param {array} requiredCategories
 *   The categories array to be checked.
 */
IframeConsent.prototype.checkIfCategoriesAreAccepted = function (
  requiredCategories,
) {
  if (requiredCategories.length === 0) {
    return true;
  }

  let requiredCategoriesArray = requiredCategories.split(',');

  requiredCategoriesArray = requiredCategoriesArray.filter((category) => {
    return this.acceptedCategories.indexOf(category) === -1;
  });

  return requiredCategoriesArray.length === 0;
};

/**
 * Open consent banner on preferences button is clicked.
 */
IframeConsent.prototype.onManageConsentClick = function (event) {
  if (this.manageCookiesCallback !== null) {
    this.manageCookiesCallback();
  }
};

/**
 * Action when accept button is clicked.
 *
 * @param event
 *   Event object.
 */
IframeConsent.prototype.onAcceptClick = function (event) {
  const placeholderWrapper = event.target.closest(
    this.placeholderWrapperSelector,
  );
  const iframe = placeholderWrapper.parentNode.querySelector(
    this.initializedSelector,
  );

  this.disableIframeConsent(iframe);
};

/**
 * Process all iframes.
 */
IframeConsent.prototype.processAllIframes = function () {
  const iframes = document.querySelectorAll('iframe.iframe-consent');

  iframes.forEach((iframe) => {
    this.processIframe(iframe);
  });
};

/**
 * Process iframe.
 *
 * @param {object} iframe
 *   Element that contains the iframe.
 */
IframeConsent.prototype.processIframe = function (iframe) {
  const iframeStatus = iframe.getAttribute('data-iframe-consent-status') ?? '';

  if (iframeStatus === 'allowed') {
    return;
  }

  const requiredConsents = iframe.getAttribute('data-required-consents') ?? '';

  if (this.checkIfCategoriesAreAccepted(requiredConsents)) {
    if (iframeStatus === 'processed') {
      this.disableIframeConsent(iframe);
    } else {
      this.restoreIframeSrc(iframe);
    }
    iframe.setAttribute('data-iframe-consent-status', 'allowed');
  } else if (iframeStatus !== 'processed') {
    this.enableIframeConsent(iframe);
    iframe.setAttribute('data-iframe-consent-status', 'processed');
  }
};

/**
 * Restore the iframe src.
 *
 * @param {object} iframe
 *   Iframe object.
 */
IframeConsent.prototype.restoreIframeSrc = function (iframe) {
  const src = iframe.getAttribute('data-src');
  iframe.setAttribute('src', src);
  iframe.removeAttribute('data-src');
};

/**
 * Set the iframe/container to his initial state.
 *
 * @param {object} iframe
 *    Iframe element.
 */
IframeConsent.prototype.disableIframeConsent = function (iframe) {
  const iframeParent = iframe.parentNode;

  iframeParent.querySelector(this.placeholderWrapperSelector).remove();
  this.restoreIframeSrc(iframe);

  iframe.setAttribute('data-iframe-consent-status', 'allowed');
  iframe.classList.remove(this.initializedClass);
};

/**
 * Enable the Iframe consent on the given iframe.
 *
 * @param {object} iframe
 *   Iframe element.
 */
IframeConsent.prototype.enableIframeConsent = function (iframe) {
  const template =
    iframe.getAttribute('data-placeholder-template') ?? 'default';
  const hash = iframe.getAttribute('data-hash') ?? Math.random(10);
  const iframeParent = iframe.parentNode;
  const placeholderWrapper = document.createElement('div');
  placeholderWrapper.classList.add(this.placeholderWrapperClass);
  placeholderWrapper.id = `iframe-consent-placeholder--${hash}`;
  iframeParent.insertBefore(placeholderWrapper, iframe);

  Drupal.ajax({
    url: Drupal.url(`/ajax/iframe-consent/placeholder/${template}/${hash}`),
  }).execute();

  const observer = new MutationObserver((mutationsList) => {
    mutationsList.forEach((mutation) => {
      if (mutation.addedNodes.length > 0) {
        // Add buttons actions.
        const manageButton = placeholderWrapper.querySelector(this.manageButtonSelector);
        if (manageButton) {
          manageButton.addEventListener('click', this.onManageConsentClick.bind(this));
        }

        const acceptButton = placeholderWrapper.querySelector(this.acceptButtonSelector);
        if (acceptButton) {
          acceptButton.addEventListener('click', this.onAcceptClick.bind(this));
        }

        // Add required consents text.
        const requiredConsents = iframe.getAttribute('data-required-consents');
        const requiredConsentsArray = requiredConsents.split(',');
        const requiredConsentsWrapper = placeholderWrapper.querySelector(
          this.consentListWrapperSelector,
        );

        const consentItem = document.createElement('span');
        let count = 0;
        requiredConsentsArray.forEach((consent) => {
          const consentLabel = this.consentGroups[consent];

          if (consentLabel) {
            if (count > 0) {
              consentItem.innerText += ', ';
            }
            consentItem.innerText += consentLabel;
            count++;
          }
        });

        if (count > 0) {
          requiredConsentsWrapper.appendChild(consentItem);
        }

        iframe.classList.add(this.initializedClass);
        observer.disconnect();
      }
    });
  });

  observer.observe(placeholderWrapper, { childList: true });
};

/**
 * Initialize Iframe consent.
 */
(function (Drupal, drupalSettings, once) {
  if (typeof drupalSettings.iframeConsent === 'object') {
    Drupal.iframeConsent = new IframeConsent(
      drupalSettings.iframeConsent.consentGroups,
    );
  }

  Drupal.behaviors.iframeConsent = {
    attach(context) {
      once('iframe-consent', 'iframe.iframe-consent', context).forEach(
        (iframe) => {
          Drupal.iframeConsent.processIframe(iframe);
        },
      );
    },
  };
})(Drupal, drupalSettings, once);

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

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