component_library-1.0.x-dev/js/override_mode.js

js/override_mode.js
(function ($, Drupal, once) {

  Drupal.behaviors.OverrideUiBehaviour = {
    overrideMode: false,
    overrideTrayOpen: false,
    attach: function (context, settings) {
      // Set a data attribute on each template element based on its paired HTML comment.
      Drupal.behaviors.OverrideUiBehaviour.processHtmlComments(context);

      // Close the off canvas dialog when clicking on the toolbar button and the
      // dialog is already open.
      once('OverrideUiToolbarBtn', '#enable-override-mode', context).forEach(function (toggleButton) {
        toggleButton.addEventListener(
          'click',
          function (event) {
            if (!Drupal.behaviors.OverrideUiBehaviour.overrideTrayOpen) {
              const drupalAjaxDialog = Drupal.ajax({
                url: settings.path.baseUrl + settings.path.pathPrefix + 'override-mode',
                dialogType: 'dialog',
                dialogRenderer: 'off_canvas',
                dialog: { width: 300 },
              });
              drupalAjaxDialog.execute();
              Drupal.behaviors.OverrideUiBehaviour.overrideTrayOpen = true;
            } else {
              $(toggleButton).off();
              $closeButton = $('.ui-front').find('.ui-dialog-titlebar-close').click();
              Drupal.behaviors.OverrideUiBehaviour.overrideTrayOpen = false;
            }
            event.preventDefault();
            return false;
          },
        );

      });

      // Build the Override Mode tray list of buttons.
      once('OverrideUiBehaviour', '#override-mode-tray', context).forEach(function (buttonContainer) {

        // Flag that Override Mode is enabled.
        Drupal.behaviors.OverrideUiBehaviour.overrideMode = true;

        const overridableTemplates = document.querySelectorAll('[data-override-mode]:not(#override-mode-tray)');
        const list = document.createElement('ul');

        overridableTemplates.forEach(function (overridableTemplate) {
          if (typeof drupalSettings.overrides[overridableTemplate.dataset.overrideMode] !== 'undefined') {
            let settings = drupalSettings.overrides[overridableTemplate.dataset.overrideMode];

            // Add a button to override this template.
            let button = document.createElement('li');
            button.classList.add('override-button');
            button.setAttribute('data-override-mode', settings.uuid);
            button.innerHTML = settings.theme_suggestion;
            list.appendChild(button);
            button.onmouseover = button.onmouseout = Drupal.behaviors.OverrideUiBehaviour.buttonHover;
            button.onclick = overridableTemplate.onclick = Drupal.behaviors.OverrideUiBehaviour.openDialog;
          }
        });
        buttonContainer.appendChild(list);
      });

      // CodeMirror tracks form submissions to update textareas, but this does
      // not work on ajax requests. So we save data manually.
      once('SaveCodeMirror', '.CodeMirror').forEach(function (editor) {
        editor.CodeMirror.on('blur', function (codeMirror) {
          codeMirror.save();
        });
      });

      // Flag that Override Mode has been disabled.
      $(window).on('dialog:afterclose', function (e, dialog, $element) {
        if ($('#override-mode-tray', $element).length > 0) {
          Drupal.behaviors.OverrideUiBehaviour.overrideMode = false;
          Drupal.behaviors.OverrideUiBehaviour.overrideTrayOpen = false;
          document.getElementsByTagName('html')[0].classList.remove('override-mode')
        }
      });
    },
    processHtmlComments: function (context) {
      // Don't override the component override form. It's confusing.
      if (
        (context.classList && context.classList.length > 0 && context.classList.contains('component-override-form')) ||
        (context.id === 'dynamic-elements-container') ||
        (context.id === 'libraries-wrapper') ||
        (context.id === 'override-preview-context')
      ) {
        return;
      }
      const iterator = document.createNodeIterator(context, NodeFilter.SHOW_COMMENT, function () { return NodeFilter.FILTER_ACCEPT; });
      // Loop through nodes to find Override Mode comments.
      let overrideHtmlComment;
      while (overrideHtmlComment = iterator.nextNode()) {
        if (overrideHtmlComment.nodeValue.includes('OVERRIDE MODE BEGIN')) {
          // Determine if we can simply add an attribute to the nextElementSibling.
          let uuid = overrideHtmlComment.nodeValue.match(/uuid\[([^\]]*)\]/)[1]
          let parent = overrideHtmlComment.parentElement;
          let siblings = parent.childNodes;
          let overrideBeginHtmlCommentIndex = Array.from(siblings).indexOf(overrideHtmlComment);
          let overrideEndHtmlCommentIndex = null;
          for (let i = overrideBeginHtmlCommentIndex; i < siblings.length; i++) {
            if (
              typeof siblings[i].data !== 'undefined' &&
              siblings[i].data.includes('OVERRIDE MODE END') &&
              siblings[i].data.includes(uuid)
            ) {
              overrideEndHtmlCommentIndex = i;
            }
          }
          let templateElement = null;
          // The template contents could be a string or a set of nodes which we
          // can't attach an attribute to. If we see the same element between
          // the override HTML comments that means the template was wrapped in a
          // tag and we can add an attribute to it.
          if (siblings[overrideBeginHtmlCommentIndex].nextElementSibling === siblings[overrideEndHtmlCommentIndex].previousElementSibling) {
            templateElement = overrideHtmlComment.nextElementSibling;
          } else {
            // Add a wrapper around the templated pieces.
            let siblingsArray = Array.from(siblings);
            let templatePieces = siblingsArray.slice(overrideBeginHtmlCommentIndex + 1, overrideEndHtmlCommentIndex);
            templateElement = document.createElement('override_mode');
            templatePieces.forEach(element => templateElement.appendChild(element));
            overrideHtmlComment.after(templateElement);
          }

          if (templateElement && !templateElement.hasAttribute('data-override-mode')) {
            // Set a binding attribute on the paired template element.
            templateElement.setAttribute('data-override-mode', uuid);
            templateElement.onmouseover = templateElement.onmouseout = Drupal.behaviors.OverrideUiBehaviour.domElementHover;
          }
        }
      }
    },
    buttonHover: function (e) {
      let pairedElement = document.querySelector('[data-override-mode="' + this.dataset.overrideMode + '"]:not(#override-mode-tray)')
      if (e.type === 'mouseover') {
        this.classList.add('override-mode-highlight');
        pairedElement.classList.add('override-mode-highlight');
      }
      if (e.type === 'mouseout') {
        pairedElement.classList.remove('override-mode-highlight');
        this.classList.remove('override-mode-highlight');
      }
    },
    domElementHover: function (e) {
      e.stopPropagation();
      if (!Drupal.behaviors.OverrideUiBehaviour.overrideMode) {
        return;
      }
      let element = e.target;

      let pairedButton = document.querySelector('[data-override-mode="' + this.dataset.overrideMode + '"].override-button');

      if (e.type === 'mouseover') {
        element.classList.add('override-mode-highlight');
        pairedButton.classList.add('override-mode-highlight');
      }
      if (e.type === 'mouseout') {
        element.classList.remove('override-mode-highlight');
        pairedButton.classList.remove('override-mode-highlight');
      }
    },
    openDialog: function (e) {
      e.stopPropagation();
      if (!Drupal.behaviors.OverrideUiBehaviour.overrideMode) {
        return;
      }
      e.preventDefault();

      let settings = drupalSettings.overrides[this.dataset.overrideMode];
      let ajaxConfig = {
        url: settings.url + '&destination=' + window.location.pathname,
        dialogType: 'modal',
        dialog: { width: '90%' },
        type: 'POST',
        dataType: 'text',
        progress: {
          type: 'fullscreen',
          message: Drupal.t('Please wait...')
        },
      };
      let variables = document.querySelector('script[data-uuid="' + settings.uuid + '"]');
      if (variables !== null && typeof variables.textContent !== 'undefined') {
        ajaxConfig.submit = {variables: variables.textContent};
      }
      let ajax = Drupal.ajax(ajaxConfig);
      ajax.execute();
    },
  };
})(jQuery, Drupal, once);

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

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