mercury_editor-2.0.x-dev/build/js/autosave.js

build/js/autosave.js
(function () {
  'use strict';

  ((Drupal, drupalSettings, $) => {
    let ajaxing = false;
    function setAjaxing(value) {
      document.body.classList.toggle('me-ajaxing', value);
      ajaxing = value;
    }
    $(document).on('ajaxStart', () => setAjaxing(true));
    $(document).on('ajaxComplete', () => setAjaxing(false));

    let interacting = false;
    window.addEventListener('message', (event) => {
      if (event.data.type === 'layoutParagraphsEvent') {
        if (event.data.eventName === 'lpb-component:drag') {
          interacting = true;
        }
        if (event.data.eventName === 'lpb-component:drop') {
          interacting = false;
        }
      }
    });

    /**
     * Serializes a form.
     * @param {HTMLElement} form The form element.
     * @return {string} The serialized form data.
     */
    function serializeForm(form) {
      // JavaScript editors like CKEditor and CodeMirror save changes to text areas
      // when behaviors are detached. So we need to detach behaviors first, then
      // serialize the form.
      Drupal.detachBehaviors(form, drupalSettings, 'serialize');
      // Drupal.attachBehaviors(form, drupalSettings);
      let formData = Object.fromEntries(new FormData(form).entries());
      formData = Object.fromEntries(
        Object.entries(formData).filter(
          ([, value]) => value !== '' && value !== null && value !== undefined,
        ),
      );
      formData = Object.keys(formData)
        .sort()
        .reduce((obj, key) => {
          obj[key] = formData[key];
          return obj;
        }, {});
      // Remove non-essential keys to avoid false positives.
      ['form_build_id', 'form_id', 'form_token', 'tabs'].forEach((key) => {
        delete formData[key];
      });
      return JSON.stringify(formData);
    }

    /**
     * Debounced function to submit form when it changes.
     * @param {Element} form The form.
     * @return {boolean} True if the form has changed.
     */
    function checkFormForChanges(form) {
      if (
        interacting ||
        ajaxing ||
        !drupalSettings.ajaxPreviewPageState ||
        !form.serializedData ||
        form.hasAttribute('data-me-saving') ||
        form.querySelector('input[type="file"][disabled]')
      ) {
        return false;
      }
      const serializedData = serializeForm(form);
      // No changes detected.
      if (form.serializedData === serializedData) {
        return false;
      }
      form.serializedData = serializedData;
      return true;
    }

    // Only one form is autosaved at a time, so we need to keep track of it.
    let autosaveForm = null;

    /**
     * @todo Pause the interval after period of inactivity.
     * @todo Evaluate for performance.
     */
    let autosaveInterval = null;

    /**
     * Start polling for changes in the autosave form.
     * @todo Use a more efficient way to check for changes.
     */
    function startPolling() {
      if (autosaveInterval) {
        return;
      }
      autosaveInterval = setInterval(() => {
        if (!ajaxing && autosaveForm) {
          if (checkFormForChanges(autosaveForm) === true) {
            const saveButton = autosaveForm.querySelector('.me-autosave-btn');
            if (saveButton) {
              saveButton.dispatchEvent(new Event('mousedown'));
            }
          }
        }
      }, 500);
    }

    /**
     * Stop polling for changes in the autosave form.
     */
    function stopPolling() {
      if (autosaveInterval) {
        clearInterval(autosaveInterval);
        autosaveInterval = null;
      }
    }

    /**
     * Set the autosave form to the last autosave button's parent form in the DOM.
     */
    function setAutosaveForm() {
      const autosaveBtns = document.querySelectorAll('form .me-autosave-btn');
      if (autosaveBtns.length > 0) {
        autosaveForm = autosaveBtns[autosaveBtns.length - 1].closest('form');
        if (!autosaveForm.serializedData) {
          autosaveForm.serializedData = serializeForm(autosaveForm);
        }
        autosaveForm.classList.add('me-autosave');
        startPolling();
      } else {
        autosaveForm = null;
        stopPolling();
      }
    }
    /**
     * Debounced function to check validity of inputs on keyup.
     * @todo Re-evaluate necessity, approach, and UX impact.
     */
    // let checkValidityTimeout = null;
    // document.addEventListener('keyup', (event) => {
    //   if (!event.target.validity) return;
    //   clearTimeout(checkValidityTimeout);
    //   checkValidityTimeout = setTimeout(
    //     () => {
    //       if (!event.target.validity.valid) {
    //         event.target.reportValidity();
    //       }
    //     },
    //     event.target.type === 'date' || event.target.type === 'time' ? 1000 : 500,
    //   );
    // });
    /**
     * Re-evaluate the autosave form when a dialog is closed.
     */
    document.addEventListener('dialog:afterclose', () => {
      setTimeout(setAutosaveForm, 100);
    });
    /**
     * Attaches the autosave behavior to forms with the .me-autosave-form class.
     */
    Drupal.behaviors.mercuryEditorAutosave = {
      attach() {
        if (document.querySelectorAll('.me-autosave-form')) {
          setAutosaveForm();
        }
      },
    };
  })(Drupal, drupalSettings, jQuery, once, Drupal.debounce);

})();

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

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