mercury_editor-2.0.x-dev/build/js/edit-screen.js

build/js/edit-screen.js
(function () {
  'use strict';

  ((Drupal, drupalSettings, $, once) => {
    // Catch all Ajax errors and send to home page.
    // @todo Consider a more elegant / graceful way to handle errors.
    $(document).ajaxError((event, xhr) => {
      if (xhr.status >= 400) {
        // eslint-disable-next-line no-alert
        alert(Drupal.t('Something went wrong. Please try again.'));
        window.location.href = `${window.location.origin}${window.location.pathname}?_ts=${Date.now()}`;
      }
    });

    // The width of the sidebar.
    let sidebarWidth;
    // The state of the sidebar.
    let sidebarState = 'open';

    /**
     * Open the sidebar.
     */
    function openSidebar() {
      if (sidebarState === 'open') {
        return;
      }
      sidebarState = 'open';
      // When re-opening the sidebar, set the width to the default width.
      sidebarWidth = localStorage.getItem('mercury-dialog-dock-default-width');
      if (sidebarWidth) {
        document.documentElement.style.setProperty(
          '--me-dialog-dock-right-width',
          `${sidebarWidth}px`,
        );
      }
    }

    /**
     * Close the sidebar.
     */
    function closeSidebar() {
      if (sidebarState === 'closed') {
        return;
      }
      sidebarState = 'closed';
      // When closing the sidebar, set the width to 10px.
      document.documentElement.style.setProperty(
        '--me-dialog-dock-right-width',
        '10px',
      );
      localStorage.setItem('mercury-dialog-dock-collapsed', 'true');
    }

    window.addEventListener('message', (event) => {
      if (event.data.type === 'openSidebar') {
        openSidebar();
      }
    });

    /**
     * Set the size of the preview iframe.
     * @param {String} w The width of the preview iframe.
     * @param {String} h The height of the preview iframe.
     */
    function setPreviewViewportSize(w, h) {
      const iframe = document.querySelector('#me-preview');
      if (w) {
        iframe.style.width = w;
      } else {
        iframe.style.removeProperty('width');
      }
      if (h) {
        iframe.style.height = h;
      } else {
        iframe.style.removeProperty('height');
      }
    }

    /**
     * Save the content.
     * @param {Event} event The click event.
     */
    function save() {
      const saveBtn = document.querySelector(
        '[data-drupal-selector="edit-submit"]:not([disabled])',
      );
      if (saveBtn) {
        const inputs =
          saveBtn.closest('form').querySelectorAll('input, textarea, select') ||
          [];
        // Checks visible form inputs for validity errors.
        const invalid = Array.from(inputs).filter(
          (input) =>
            !!(
              input.offsetWidth ||
              input.offsetHeight ||
              input.getClientRects().length
            ) && !input.validity.valid,
        );
        if (invalid.length) {
          invalid[0].focus();
          invalid[0].reportValidity();
        } else {
          saveBtn.dispatchEvent(new Event('mousedown'));
        }
      }
    }

    /**
     * Perform an undo or redo action.
     * @param {String} which Either 'undo' or 'redo'.
     */
    function undoRedo(which) {
      const match = window.location.pathname.match(
        /^\/mercury-editor\/([0-9a-fA-F-]+)/,
      );
      const id = match ? match[1] : null;
      Drupal.ajax({
        url: `/mercury-editor/${id}/${which}`,
        submit: {},
        success: () => Drupal.ajax({ url: `/mercury-editor/${id}` }).execute(),
      }).execute();
    }

    /**
     * Initialize the toolbar.
     */
    function initToolbar() {
      const previewIframeWrapper = document.querySelector('#me-iframe-wrapper');
      function mobileViewport() {
        const presetsSelect = document.querySelector('.me-mobile-presets');
        if (presetsSelect) {
          const preset =
            presetsSelect.options[presetsSelect.selectedIndex ?? 0].value;
          const presetValues = preset.split('x');
          setPreviewViewportSize(
            `${presetValues[0]}px`,
            `${Math.min(
            presetValues[1],
            window.innerHeight -
              document.getElementById('me-toolbar').offsetHeight -
              20,
          )}px`,
          );
        } else {
          setPreviewViewportSize(
            '390px',
            `${Math.min(
            '844',
            window.innerHeight -
              document.getElementById('me-toolbar').offsetHeight -
              20,
          )}px`,
          );
        }
      }
      const presetsSelect = document.querySelector('.me-mobile-presets');
      if (presetsSelect) {
        presetsSelect.addEventListener('change', mobileViewport);
      }
      document
        .querySelector('#me-mobile-toggle-btn')
        .addEventListener('click', (e) => {
          if (presetsSelect) {
            presetsSelect.style.display = 'block';
          }
          previewIframeWrapper.classList.add('is-device-preview');
          document
            .querySelector('#me-desktop-toggle-btn')
            .classList.remove('active');
          e.currentTarget.classList.add('active');
          mobileViewport();
          window.addEventListener('resize', mobileViewport);
          e.preventDefault();
          e.stopPropagation();
          return false;
        });
      document
        .querySelector('#me-desktop-toggle-btn')
        .addEventListener('click', (e) => {
          if (presetsSelect) {
            presetsSelect.style.display = 'none';
          }
          previewIframeWrapper.classList.remove('is-device-preview');
          document
            .querySelector('#me-mobile-toggle-btn')
            .classList.remove('active');
          e.currentTarget.classList.add('active');
          window.removeEventListener('resize', mobileViewport);
          setPreviewViewportSize('100cqw', '100cqw');
          e.preventDefault();
          e.stopPropagation();
          return false;
        });
      document.querySelector('#me-undo').addEventListener('click', () => {
        document.querySelector('.lpb-dialog')?.close();
      });
      document.querySelector('#me-redo').addEventListener('click', () => {
        document.querySelector('.lpb-dialog')?.close();
      });

      document
        .querySelector('#me-undo')
        .addEventListener('click', () => undoRedo('undo'));

      document
        .querySelector('#me-redo')
        .addEventListener('click', () => undoRedo('redo'));

      document.addEventListener('mercuryEditorUpdateState', (event) => {
        const { stateIndex, stateCount } = event.detail;
        const undoBtn = document.querySelector('#me-undo');
        const redoBtn = document.querySelector('#me-redo');
        if (stateIndex === 0) {
          undoBtn.classList.add('disabled');
        } else {
          undoBtn.classList.remove('disabled');
        }
        if (stateCount === 0 || stateIndex === stateCount - 1) {
          redoBtn.classList.add('disabled');
        } else {
          redoBtn.classList.remove('disabled');
        }
      });

      const saveBtn = document.querySelector(
        '[data-drupal-selector="edit-submit"]:not([disabled])',
      );
      if (saveBtn) {
        document.querySelector('#me-save-btn').addEventListener('click', save);
      } else {
        document.querySelector('#me-save-btn').remove();
      }

      // Store the default width of the dock.
      if (
        drupalSettings.mercuryEditor &&
        drupalSettings.mercuryEditor.defaultWidth
      ) {
        localStorage.setItem(
          'mercury-dialog-dock-default-width',
          drupalSettings.mercuryEditor.defaultWidth,
        );
      }

      const isTrayCollapsed =
        localStorage.getItem('mercury-dialog-dock-collapsed') === 'true';
      sidebarState = isTrayCollapsed ? 'closed' : 'open';

      const sidebarToggle = document.querySelector('#me-sidebar-toggle-btn');
      sidebarToggle.addEventListener('click', (e) => {
        if (sidebarState === 'open') {
          closeSidebar();
        } else {
          openSidebar();
        }
        e.preventDefault();
        e.stopPropagation();
        return false;
      });

      // Listen for dock resize events.
      document.addEventListener('mercury:dockResize', (e) => {
        // The width of the resize event.
        const { width } = e.detail;
        const contentElements = e.target.shadowRoot.querySelectorAll(
          'header, main, footer',
        );
        // If width is greater than 10, the dock is open.
        if (width > 10) {
          sidebarState = 'open';
          contentElements.forEach((el) => {
            el.style.display = '';
          });
          sidebarToggle.classList.remove('me-button--sidebar-expand');
          sidebarToggle.classList.add('me-button--sidebar-collapse');
          sidebarToggle.innerHTML = `<span>${Drupal.t('Hide sidebar')}</span>`;
          sidebarToggle.setAttribute('title', Drupal.t('Hide sidebar'));
          localStorage.removeItem('mercury-dialog-dock-collapsed');
        } else {
          sidebarState = 'closed';
          sidebarToggle.classList.remove('me-button--sidebar-collapse');
          sidebarToggle.classList.add('me-button--sidebar-expand');
          sidebarToggle.innerHTML = `<span>${Drupal.t('Show sidebar')}</span>`;
          sidebarToggle.setAttribute('title', Drupal.t('Show sidebar'));
          localStorage.setItem('mercury-dialog-dock-collapsed', 'true');
          contentElements.forEach((el) => {
            el.style.display = 'none';
          });
        }
        localStorage.setItem('mercury-dialog-dock-width', width);
      });
    }
    /**
     * Toggles mouse pointer events on the preview iFrame.
     *
     * When dragging the dialog border, the iFrame intercepts mouse events and
     * prematurely stops the drag behavior. Toggling pointer events prevents
     * this behavior.
     *
     * @param {Event} e
     *   The mouseup or mousedown event
     */
    function iFramePointerEventsToggle(e) {
      const iframe = document.querySelector('#me-preview');
      if (iframe) {
        iframe.style.pointerEvents = e.type === 'mouseup' ? 'auto' : 'none';
      }
    }

    /**
     * Attaches the behavior to the edit screen.
     */
    Drupal.behaviors.mercuryEditorEditScreen = {
      attach(context) {
        // After saving the host ME entity, check if a component form is open and
        // if so, re-focus the component to reload its data and form, preventing
        // stale form data issues.
        if (context?.classList?.contains('me-entity-form')) {
          const uuid = document.querySelector('[name="uuid"]')?.value;
          if (uuid) {
            const iframe = document.querySelector('#me-preview');
            if (iframe && iframe.contentWindow) {
              iframe.contentWindow.postMessage({
                type: 'componentSelected',
                settings: { uuid },
              });
            }
          }
        }
        // Move focus to the first input with error, if any.
        const firstError = once(
          'me-first-error',
          '.js-form-item.error',
          context,
        )[0];
        if (firstError) {
          firstError.focus();
          firstError.scrollIntoView({
            behavior: 'smooth',
          });
        }
        // Initialize the toolbar.
        if (once('me-toolbar', '#me-toolbar', context).length) {
          initToolbar();
        }
        // Open the edit tray dialog.
        if (once('me-edit-tray', '#me-edit-screen', context).length) {
          // Opens the dialog and attaches event listeners.
          const mercuryDialogElement = context.querySelector('#me-edit-screen');
          if (mercuryDialogElement) {
            const mercuryDialog = Drupal.mercuryDialog(mercuryDialogElement);
            mercuryDialog.show();
            // Attaches a custom beforeSerialize() method to Drupal.Ajax.
            // This method adds the ajaxPreviewPageState to the ajax request.
            if (
              typeof Drupal.Ajax !== 'undefined' &&
              typeof Drupal.Ajax.prototype.beforeSerializeMercuryEditor ===
                'undefined'
            ) {
              Drupal.Ajax.prototype.beforeSerializeMercuryEditor =
                Drupal.Ajax.prototype.beforeSerialize;
              Drupal.Ajax.prototype.beforeSerialize = function beforeSerialize(
                element,
                options,
              ) {
                this.beforeSerializeMercuryEditor(element, options);
                const pageState = drupalSettings.ajaxPreviewPageState || {};
                options.data['ajax_preview_page_state[theme]'] = pageState.theme;
                options.data['ajax_preview_page_state[theme_token]'] =
                  pageState.theme_token;
                options.data['ajax_preview_page_state[libraries]'] =
                  pageState.libraries;
              };
            }
            // Remove min-width from the dialog.
            // @todo Refactor once dialog min-width is addressed.
            // var style = document.createElement( 'style' )
            // style.innerHTML = 'dialog { min-width: 0 !important; }'
            // mercuryDialogElement.shadowRoot.appendChild( style );
            // @todo Refactor if we have drag events from dialog.
            document.addEventListener('mousedown', iFramePointerEventsToggle);
            document.addEventListener('mouseup', iFramePointerEventsToggle);
          }
        }
        // Set the iframe URL once other js files have loaded.
        if (once('me-preview-iframe', '#me-preview', context).length) {
          const iframe = document.querySelector('#me-preview');
          iframe.src = iframe.getAttribute('data-src');
        }
      },
    };
    /**
     * Ajax command to show save success feedback.
     */
    Drupal.AjaxCommands.prototype.mercuryEditorSaveSuccess = () => {
      const btn = document.querySelector('#me-save-btn');
      btn.classList.add('me-button--saved');
      btn.innerHTML = `${Drupal.t('Saved!')}`;
      setTimeout(() => {
        btn.classList.remove('me-button--saved');
        btn.innerHTML = `${Drupal.t('Save changes')}`;
      }, 2000);
      // Create a div element.
      const message = document.createElement('div');
      message.className = 'me-toolbar__save-status';
      // Use the current time.
      const now = new Date();
      const time = now.toLocaleTimeString([], {
        hour: '2-digit',
        minute: '2-digit',
      });
      message.innerHTML = Drupal.t('Changes saved at @time.', { '@time': time });
      // Remove any existing messages.
      document
        .querySelectorAll('.me-toolbar__save-status')
        .forEach((el) => el.remove());
      // Prepend the message to the "me-toolbar__edit-controls" element.
      document.querySelector('.me-toolbar__edit-controls').prepend(message);
      // Fade out and remove the message after 3 seconds.
      setTimeout(() => {
        message.style.opacity = '0';
        setTimeout(() => {
          message.remove();
        }, 1000);
      }, 3000);
    };
  })(Drupal, drupalSettings, jQuery, once, Drupal.debounce);

})();

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

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