insert-8.x-2.x-dev/js/Rotator.js

js/Rotator.js
(function(Drupal) {
  'use strict';

  /**
   * The Rotator contains the functionality for rotating images, triggering the
   * stored image to be rotated and updating the image references already
   * inserted into textareas and editors.
   */
  Drupal.insert.Rotator = class {

    /**
     * @type {HTMLElement}
     */
    #element;

    /**
     * @type {HTMLElement}
     */
    #templates;

    /**
     * @param {HTMLElement} element
     * @param {HTMLElement} templates
     */
    constructor(element, templates) {
      this.#element = element;
      this.#templates = templates;

      this.#element.querySelectorAll('.insert-rotate-controls a')?.forEach(
        a => {
          a.addEventListener('click', async event => {
            event.preventDefault();

            const response = await fetch(a.getAttribute('href'));
            const data = await response.json();

            console.log(data);

            document.querySelector('input[name="changed"]').value
              = data.revision;

            this.#updateImageRotation(data.data);
          });
        }
      );
    }

    /**
     * Updates the preview image, the insert templates as well as any images
     * derivatives already placed.
     *
     * @param {{[key: string]: string}} styleInfo
     */
    #updateImageRotation(styleInfo) {
      const updatedStyleInfo = {};

      Object.entries(styleInfo).forEach(([styleName, url]) => {
        updatedStyleInfo[styleName] = url + (url.indexOf('?') === -1 ? '?' : '&');
        updatedStyleInfo[styleName] += 'insert-refresh=' + Date.now();
      });

      this.#updatePreviewImage(styleInfo);
      this.#updateTemplates(styleInfo);
      this.#updateInsertedImages(styleInfo);
    }

    /**
     * @param {{[key: string]: string}} styleInfo
     */
    #updatePreviewImage(styleInfo) {
      const previewImg = this.#element.closest('.image-widget')
        .querySelector('.image-preview__img-wrapper img');

      if (!previewImg) {
        return;
      }

      for (const cssClass of previewImg.classList) {
        const styleClass = cssClass.match('^image-style-(.+)');

        if (styleClass !== null && typeof styleInfo[styleClass[1]] !== 'undefined') {
          previewImg.setAttribute('src', styleInfo[styleClass[1]])
          previewImg.removeAttribute('width')
          previewImg.removeAttribute('height');

          break;
        }
      }
    }

    /**
     * @param {{[key: string]: string}} styleInfo
     */
    #updateTemplates(styleInfo) {
      Object.entries(styleInfo).forEach(([styleName, url]) => {
        this.#templates
          .querySelectorAll(`.insert-template[name*="[${styleName}]"]`)
          .forEach(templateElement => {
            let template = templateElement.value;

            const widthMatches = template.match(/width[ ]*=[ ]*"(\d*)"/i);
            const heightMatches = template.match(/height[ ]*=[ ]*"(\d*)"/i);

            if (heightMatches && heightMatches.length === 2) {
              template = template.replace(
                /(width[ ]*=[ ]*")(\d*)"/i,
                `width="${heightMatches[1]}"`
              );
            }

            if (widthMatches && widthMatches.length === 2) {
              template = template.replace(
                /(height[ ]*=[ ]*")(\d*)"/i,
                `height="${widthMatches[1]}"`
              );
            }

            templateElement.value = template.replace(/src="[^"]+"/, `src="${url}"`);
          });
      });
    }

    /**
     * @param {{[key: string]: string}} styleInfo
     */
    #updateInsertedImages(styleInfo) {
      Object.values(styleInfo).forEach(url => {
        const updatedImageCleanUrl = url.split('?')[0];

        Drupal.insert.FocusManager.textareas.forEach(textarea => {
          this.#updateTextarea(textarea, url, updatedImageCleanUrl);
        });

        Drupal.insert.FocusManager.editors.forEach(editor => {
          this.#updateEditor(editor, url, updatedImageCleanUrl);
        });
      });
    }

    /**
     * @param {HTMLTextAreaElement} textarea
     * @param {string} url
     * @param {string} updatedImageCleanUrl
     */
    #updateTextarea(textarea, url, updatedImageCleanUrl) {
      let textareaString = textarea.value;
      const temp = document.createElement('div');
      temp.innerHTML = textarea.value;

      temp.querySelectorAll('img').forEach((img, index) => {
        const imgCleanUrl = img.getAttribute('src').split('?')[0];

        if (imgCleanUrl === updatedImageCleanUrl) {
          const width = img.getAttribute('width');
          const height = img.getAttribute('height');

          if (width) {
            img.setAttribute('height', width);
          } else {
            img.removeAttribute('height');
          }
          if (height) {
            img.setAttribute('width', height);
          } else {
            img.removeAttribute('width');
          }

          img.setAttribute('src', url);

          let i = 0;

          textareaString = textareaString.replace(
            /<img[^>]*>/g,
            match => {
              if (i++ !== index) {
                return match;
              }

              const temp = document.createElement('div');
              temp.appendChild(img);
              return temp.innerHTML;
            }
          );
        }

        textarea.value = textareaString;
      });
    }

    /**
     * @param {ckeditor.Editor} editor
     * @param {string} url
     * @param {string} updatedImageCleanUrl
     */
    #updateEditor(editor, url, updatedImageCleanUrl) {

      editor.model.change(writer => {
        this.#updateEditorModel(
          writer.model.document.getRoot(),
          url,
          updatedImageCleanUrl
        );

        this.#updateEditorView(
          editor.editing.view.getDomRoot(),
          url,
          updatedImageCleanUrl
        );
      });
    }

    /**
     * @param {ckeditor.Element} root
     * @param {string} url
     * @param {string} updatedImageCleanUrl
     */
    #updateEditorModel(root, url, updatedImageCleanUrl) {
      const elements = Drupal.insert.Manager.findDescendants(
        root,
        element => {
          return element.getAttribute('htmlImgAttributes')?.attributes.src
            .split('?')[0] === updatedImageCleanUrl;
        }
      );

      elements.forEach(element => {
        const imgAttributes = element.getAttribute('htmlImgAttributes');
        const width = imgAttributes.attributes.width;
        const height = imgAttributes.attributes.height;

        if (width) {
          imgAttributes.attributes.height = width;
        }

        if (height) {
          imgAttributes.attributes.width = height;
        }

        imgAttributes.attributes.src = url;
        imgAttributes.src = url;

        element._setAttribute('htmlImgAttributes', imgAttributes);
      });
    }

    /**
     * @param {HTMLElement} root
     * @param {string} url
     * @param {string} updatedImageCleanUrl
     */
    #updateEditorView(root, url, updatedImageCleanUrl) {
      root.querySelectorAll('img').forEach(img => {
        if (img.getAttribute('src')?.split('?')[0] !== updatedImageCleanUrl) {
          return;
        }

        const width = img.getAttribute('width');
        const height = img.getAttribute('height');

        img.setAttribute('width', height);
        img.setAttribute('height', width);

        img.setAttribute('src', url);

        if (img.style.aspectRatio) {
          img.style.aspectRatio = `${height}/${width}`;
        }
      });
    }
  }

})(Drupal);

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

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