cloudinary-8.x-1.x-dev/modules/cloudinary_media_library_widget/js/cloudinary_media_library.form.js

modules/cloudinary_media_library_widget/js/cloudinary_media_library.form.js
(function ($, Drupal, once, drupalSettings, cloudinary) {

  'use strict';

  /**
   * Defines a behaviour to handle custom cloudinary form element.
   */
  Drupal.behaviors.cloudinaryMediaLibraryFormElement = {
    attach: function (context) {
      const self = this;
      const settings = drupalSettings.cloudinary_media_library || false;

      if (!settings) {
        console.error('No settings available for cloudinary elements.');
        return;
      }

      const widgetSettings = settings.base;
      const elementsWidgetSettings = settings.elements;

      once('cloudinaryMediaLibrary', $(context).find('input.form-cloudinary')).forEach(function (input) {
        const $input = $(input);
        const elementSettings = elementsWidgetSettings[$input.closest('fieldset').attr('id')];
        const hasPreview = $input.hasClass('has-preview');
        const multiple = elementSettings.multiple;

        // Build preview based on default value.
        if ($input.val().length && hasPreview) {
          const preview = multiple
          ? self.buildMultiplePreviewByInput(input)
          : self.buildPreviewImageByInput(input);

          $input.before(preview);
        }

        // Build open media button.
        $input.after('<div class="js-cloudinary-button-wrapper"><button class="button cloudinary-media-library-button">' + Drupal.t('Open media library', {}, { context: 'Cloudinary media' }), + '</button></div>');
        $input.parent().find('.cloudinary-media-library-button').on('click', function (e) {
          e.preventDefault();

          // Display loading spinner.
          $input.after($(Drupal.theme('ajaxProgressThrobber')));

          const options = {
            cloud_name: widgetSettings.cloud_name,
            api_key: widgetSettings.api_key,
            use_saml: widgetSettings.use_saml || false,
            multiple: multiple,
            max_files: elementSettings.max_files,
            button_caption: Drupal.t('Open media library', {}, { context: 'Cloudinary media' }),
            button_class: 'button cloudinary-media-library-button',
            insert_caption: Drupal.t('Insert', {}, { context: 'Cloudinary media' }),
            folder: {
              resource_type: $input.data('resource-type'),
            }
          };

          if (widgetSettings.starting_folder) {
            options.folder.path = widgetSettings.starting_folder;
          }

          // Better support of files including PDF files.
          if ($input.data('resource-type') === 'raw') {
            delete options.folder;
            options.search = {
              expression: 'resource_type:raw OR format=pdf'
            };
          }

          const handlers = {
            insertHandler: function (data) {
              if (!this.input) {
                console.error('Cloudinary input element not found.');
                return;
              }

              const $input = $(this.input);

              // Trigger add asset button automatically once the input was populated.
              $input.on('change', function () {
                $(this).closest('.js-form-cloudinary-container')
                  .find('.add-asset-button')
                  .trigger('mousedown');
              });

              // Collect multiple value from all the assets.
              const values = [];

              data.assets.forEach(function (asset) {
                const context = asset.context || {};
                const metadata = context.custom || {};
                const transformation = [];

                if (typeof asset.derived !== 'undefined') {
                  for (let i = 0; i < asset.derived.length; i++) {
                    transformation.push(asset.derived[i].raw_transformation);
                  }
                }

                const titleAttribute = widgetSettings.default_title_attribute;
                const descriptionAttribute = widgetSettings.default_description_attribute;
                let title = '';
                let description = '';

                if (titleAttribute === 'context.custom.caption') {
                  title = metadata.caption || '';
                }
                else {
                  title = asset.metadata[titleAttribute] || '';
                }

                if (descriptionAttribute === 'context.custom.alt') {
                  description = metadata.alt || '';
                }
                else {
                  description = asset.metadata[descriptionAttribute] || '';
                }

                const value = [
                  'cloudinary',
                  asset.resource_type,
                  asset.type,
                  asset.public_id,
                  transformation.join('/')
                ].filter(value => value.length).join(':');

                values.push({
                  value: value,
                  alt: description,
                  title: title
                });

                // Nothing to do more for multiple items.
                if (multiple) {
                  return;
                }

                $input.val(value);

                const $wrapper = $input.closest('.form-item').parent();

                if ($wrapper.find('.form-asset-item--alt').length) {
                  $wrapper.find('.form-asset-item--alt').val(description);
                }

                if ($wrapper.find('.form-asset-item--title').length) {
                  $wrapper.find('.form-asset-item--title').val(title);
                }

                if (hasPreview) {
                  const previewImage = self.buildPreviewImageByAsset(asset);
                  const $oldPreview = $input.parent().find('.cloudinary-preview');

                  if ($oldPreview.length) {
                    $oldPreview.remove();
                  }

                  $input.before('<div class="cloudinary-preview">' + previewImage + '</div>');
                }

                $input.trigger('change');
              });

              // Store multiple values as a json string.
              if (multiple) {
                $input.val(JSON.stringify(values));

                if (hasPreview) {
                  const preview = self.buildPreviewWithMultipleAssets(data.assets);

                  const $oldPreview = $input.parent().find('.cloudinary-preview');

                  if ($oldPreview.length) {
                    $oldPreview.remove();
                  }

                  $input.before(preview);
                }

                $input.trigger('change');
              }
            },
            showHandler: function () {
              const input = this.input;

              if (!input) {
                console.error('Cloudinary input element not found.');
                return;
              }

              // Delete ajax progress spinner.
              const spinner = input.parentElement.querySelector('.ajax-progress');

              if (spinner) {
                spinner.remove();
              }
            }
          };

          const element = cloudinary.openMediaLibrary(options, handlers);
          element.input = $(this).closest('.js-form-item').find('input')[0];
        });
      });
    },
    buildPreviewImageByInput: function (input) {
      const imageUrl = input.dataset.previewImage;

      if (typeof imageUrl === 'undefined') {
        return '';
      }

      return '<div class="cloudinary-preview"><img loading="lazy" width="200" alt="Preview image" src="' + imageUrl + '"></div>';
    },
    buildMultiplePreviewByInput: function (input) {
      const assets = [];
      const values = JSON.parse(input.value);
      const preview = JSON.parse(input.dataset.preview);

      for (let i = 0; i < values.length; i++) {
        const value = values[i];
        const asset = {
          public_id: value.public_id,
          previewImageUrl: preview[i] || null,
          context: {
            custom: {
              caption: value.title || null,
              alt: value.alt || null
            }
          },
        };

        assets.push(asset);
      }

      return this.buildPreviewWithMultipleAssets(assets);
    },
    buildPreviewWithMultipleAssets: function (assets) {
      let output = '';

      for (let i = 0; i < assets.length; i++) {
        const asset = assets[i];
        const context = asset.context || {};
        const metadata = context.custom || {};
        const imageAlt = metadata.alt || 'Preview image';
        const imageTag = typeof asset.previewImageUrl !== 'undefined'
          ? asset.previewImageUrl ? '<img loading="lazy" width="100" alt="' + imageAlt + '" src="' + asset.previewImageUrl + '">' : ''
          : this.buildPreviewImageByAsset(asset, 100);

        output += '<div>' + imageTag + '<div>';

        if (metadata.caption) {
          output += '<p>' + metadata.caption + '</p>';
        }

        if (metadata.alt) {
          output += '<p>' + metadata.alt + '</p>';
        }

        output += '<p><strong>' + asset.public_id + '</strong></p>';
        output += '</div></div>';
      }

      return '<div class="cloudinary-preview">' + output + '</div>'
    },
    buildPreviewImageByAsset: function (asset, width) {
      // No preview images available for raw files.
      if (asset.resource_type === 'raw') {
        return '';
      }

      let imageUrl = asset.secure_url;
      let alt = asset.public_id;

      if (asset.context && asset.context.custom && asset.context.custom.alt) {
        alt = asset.context.custom.alt;
      }

      // Get thumbnail from video or PDF.
      if (asset.resource_type === 'video' || (asset.resource_type === 'image' && asset.format === 'pdf')) {
        imageUrl = imageUrl.replace('.' + asset.format, '.jpeg');
      }

      // Crop image by 400px to improve performance.
      const splitter = '/' + asset.resource_type + '/' + asset.type;
      const urlParts = imageUrl.split(splitter);
      width = width || 200;
      const rawTransformation = ['c_fill,w_' + width * 2];

      if (typeof asset.derived !== 'undefined') {
        for (let i = 0; i < asset.derived.length; i++) {
          rawTransformation.push(asset.derived[i].raw_transformation);
        }
      }

      imageUrl = urlParts[0] + splitter + '/' + rawTransformation.join('/') + urlParts[1];

      return '<img loading="lazy" width="' + width + '" alt="' + alt + '" src="' + imageUrl + '">';
    }
  };

})(jQuery, Drupal, once, drupalSettings, cloudinary);

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

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