[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/system/js/fields/ -> joomla-field-media.js (source)

   1  /**
   2   * @copyright  (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
   3   * @license    GNU General Public License version 2 or later; see LICENSE.txt
   4   */
   5  if (!Joomla) {
   6    throw new Error('Joomla API is not properly initiated');
   7  }
   8  /**
   9   * Extract the extensions
  10   *
  11   * @param {*} path
  12   * @returns {string}
  13   */
  14  
  15  
  16  const getExtension = path => {
  17    const parts = path.split(/[#]/);
  18  
  19    if (parts.length > 1) {
  20      return parts[1].split(/[?]/)[0].split('.').pop().trim();
  21    }
  22  
  23    return path.split(/[#?]/)[0].split('.').pop().trim();
  24  };
  25  
  26  class JoomlaFieldMedia extends HTMLElement {
  27    constructor() {
  28      super();
  29      this.onSelected = this.onSelected.bind(this);
  30      this.show = this.show.bind(this);
  31      this.clearValue = this.clearValue.bind(this);
  32      this.modalClose = this.modalClose.bind(this);
  33      this.setValue = this.setValue.bind(this);
  34      this.updatePreview = this.updatePreview.bind(this);
  35      this.validateValue = this.validateValue.bind(this);
  36      this.markValid = this.markValid.bind(this);
  37      this.markInvalid = this.markInvalid.bind(this);
  38    }
  39  
  40    static get observedAttributes() {
  41      return ['type', 'base-path', 'root-folder', 'url', 'modal-container', 'modal-width', 'modal-height', 'input', 'button-select', 'button-clear', 'button-save-selected', 'preview', 'preview-width', 'preview-height'];
  42    }
  43  
  44    get type() {
  45      return this.getAttribute('type');
  46    }
  47  
  48    set type(value) {
  49      this.setAttribute('type', value);
  50    }
  51  
  52    get basePath() {
  53      return this.getAttribute('base-path');
  54    }
  55  
  56    set basePath(value) {
  57      this.setAttribute('base-path', value);
  58    }
  59  
  60    get rootFolder() {
  61      return this.getAttribute('root-folder');
  62    }
  63  
  64    set rootFolder(value) {
  65      this.setAttribute('root-folder', value);
  66    }
  67  
  68    get url() {
  69      return this.getAttribute('url');
  70    }
  71  
  72    set url(value) {
  73      this.setAttribute('url', value);
  74    }
  75  
  76    get modalContainer() {
  77      return this.getAttribute('modal-container');
  78    }
  79  
  80    set modalContainer(value) {
  81      this.setAttribute('modal-container', value);
  82    }
  83  
  84    get input() {
  85      return this.getAttribute('input');
  86    }
  87  
  88    set input(value) {
  89      this.setAttribute('input', value);
  90    }
  91  
  92    get buttonSelect() {
  93      return this.getAttribute('button-select');
  94    }
  95  
  96    set buttonSelect(value) {
  97      this.setAttribute('button-select', value);
  98    }
  99  
 100    get buttonClear() {
 101      return this.getAttribute('button-clear');
 102    }
 103  
 104    set buttonClear(value) {
 105      this.setAttribute('button-clear', value);
 106    }
 107  
 108    get buttonSaveSelected() {
 109      return this.getAttribute('button-save-selected');
 110    }
 111  
 112    set buttonSaveSelected(value) {
 113      this.setAttribute('button-save-selected', value);
 114    }
 115  
 116    get modalWidth() {
 117      return parseInt(this.getAttribute('modal-width'), 10);
 118    }
 119  
 120    set modalWidth(value) {
 121      this.setAttribute('modal-width', value);
 122    }
 123  
 124    get modalHeight() {
 125      return parseInt(this.getAttribute('modal-height'), 10);
 126    }
 127  
 128    set modalHeight(value) {
 129      this.setAttribute('modal-height', value);
 130    }
 131  
 132    get previewWidth() {
 133      return parseInt(this.getAttribute('preview-width'), 10);
 134    }
 135  
 136    set previewWidth(value) {
 137      this.setAttribute('preview-width', value);
 138    }
 139  
 140    get previewHeight() {
 141      return parseInt(this.getAttribute('preview-height'), 10);
 142    }
 143  
 144    set previewHeight(value) {
 145      this.setAttribute('preview-height', value);
 146    }
 147  
 148    get preview() {
 149      return this.getAttribute('preview');
 150    }
 151  
 152    set preview(value) {
 153      this.setAttribute('preview', value);
 154    }
 155  
 156    get previewContainer() {
 157      return this.getAttribute('preview-container');
 158    } // attributeChangedCallback(attr, oldValue, newValue) {}
 159  
 160  
 161    connectedCallback() {
 162      this.button = this.querySelector(this.buttonSelect);
 163      this.inputElement = this.querySelector(this.input);
 164      this.buttonClearEl = this.querySelector(this.buttonClear);
 165      this.modalElement = this.querySelector('.joomla-modal');
 166      this.buttonSaveSelectedElement = this.querySelector(this.buttonSaveSelected);
 167      this.previewElement = this.querySelector('.field-media-preview');
 168  
 169      if (!this.button || !this.inputElement || !this.buttonClearEl || !this.modalElement || !this.buttonSaveSelectedElement) {
 170        throw new Error('Misconfiguaration...');
 171      }
 172  
 173      this.button.addEventListener('click', this.show); // Bootstrap modal init
 174  
 175      if (this.modalElement && window.bootstrap && window.bootstrap.Modal && !window.bootstrap.Modal.getInstance(this.modalElement)) {
 176        Joomla.initialiseModal(this.modalElement, {
 177          isJoomla: true
 178        });
 179      }
 180  
 181      if (this.buttonClearEl) {
 182        this.buttonClearEl.addEventListener('click', this.clearValue);
 183      }
 184  
 185      this.supportedExtensions = Joomla.getOptions('media-picker', {});
 186  
 187      if (!Object.keys(this.supportedExtensions).length) {
 188        throw new Error('Joomla API is not properly initiated');
 189      }
 190  
 191      this.updatePreview();
 192      this.inputElement.removeAttribute('readonly');
 193      this.inputElement.addEventListener('change', this.validateValue);
 194    }
 195  
 196    disconnectedCallback() {
 197      if (this.button) {
 198        this.button.removeEventListener('click', this.show);
 199      }
 200  
 201      if (this.buttonClearEl) {
 202        this.buttonClearEl.removeEventListener('click', this.clearValue);
 203      }
 204  
 205      if (this.inputElement) {
 206        this.inputElement.removeEventListener('change', this.validateValue);
 207      }
 208    }
 209  
 210    onSelected(event) {
 211      event.preventDefault();
 212      event.stopPropagation();
 213      this.modalClose();
 214      return false;
 215    }
 216  
 217    show() {
 218      this.modalElement.open();
 219      Joomla.selectedMediaFile = {};
 220      this.buttonSaveSelectedElement.addEventListener('click', this.onSelected);
 221    }
 222  
 223    async modalClose() {
 224      try {
 225        await Joomla.getMedia(Joomla.selectedMediaFile, this.inputElement, this);
 226      } catch (err) {
 227        Joomla.renderMessages({
 228          error: [Joomla.Text._('JLIB_APPLICATION_ERROR_SERVER')]
 229        });
 230      }
 231  
 232      Joomla.selectedMediaFile = {};
 233      Joomla.Modal.getCurrent().close();
 234    }
 235  
 236    setValue(value) {
 237      this.inputElement.value = value;
 238      this.validatedUrl = value;
 239      this.updatePreview(); // trigger change event both on the input and on the custom element
 240  
 241      this.inputElement.dispatchEvent(new Event('change'));
 242      this.dispatchEvent(new CustomEvent('change', {
 243        detail: {
 244          value
 245        },
 246        bubbles: true
 247      }));
 248    }
 249  
 250    validateValue(event) {
 251      let {
 252        value
 253      } = event.target;
 254      if (this.validatedUrl === value || value === '') return;
 255  
 256      if (/^(http(s)?:\/\/).+$/.test(value)) {
 257        try {
 258          fetch(value).then(response => {
 259            if (response.status === 200) {
 260              this.validatedUrl = value;
 261              this.markValid();
 262            } else {
 263              this.validatedUrl = value;
 264              this.markInvalid();
 265            }
 266          });
 267        } catch (err) {
 268          this.validatedUrl = value;
 269          this.markInvalid();
 270        }
 271      } else {
 272        if (/^\//.test(value)) {
 273          value = value.substring(1);
 274        }
 275  
 276        const hashedUrl = value.split('#');
 277        const urlParts = hashedUrl[0].split('/');
 278        const rest = urlParts.slice(1);
 279        fetch(`$Joomla.getOptions('system.paths').rootFull}/$value}`).then(response => response.blob()).then(blob => {
 280          if (blob.type.includes('image')) {
 281            const img = new Image();
 282            img.src = URL.createObjectURL(blob);
 283  
 284            img.onload = () => {
 285              this.inputElement.value = `$urlParts[0]}/$rest.join('/')}#joomlaImage://local-${urlParts[0]}/${rest.join('/')}?width=${img.width}&height=${img.height}`;
 286              this.validatedUrl = `$urlParts[0]}/$rest.join('/')}#joomlaImage://local-${urlParts[0]}/${rest.join('/')}?width=${img.width}&height=${img.height}`;
 287              this.markValid();
 288            };
 289          } else if (blob.type.includes('audio')) {
 290            this.inputElement.value = value;
 291            this.validatedUrl = value;
 292            this.markValid();
 293          } else if (blob.type.includes('video')) {
 294            this.inputElement.value = value;
 295            this.validatedUrl = value;
 296            this.markValid();
 297          } else if (blob.type.includes('application/pdf')) {
 298            this.inputElement.value = value;
 299            this.validatedUrl = value;
 300            this.markValid();
 301          } else {
 302            this.validatedUrl = value;
 303            this.markInvalid();
 304          }
 305        }).catch(() => {
 306          this.setValue(value);
 307          this.validatedUrl = value;
 308          this.markInvalid();
 309        });
 310      }
 311    }
 312  
 313    markValid() {
 314      this.inputElement.removeAttribute('required');
 315      this.inputElement.removeAttribute('pattern');
 316  
 317      if (document.formvalidator) {
 318        document.formvalidator.validate(this.inputElement);
 319      }
 320    }
 321  
 322    markInvalid() {
 323      this.inputElement.setAttribute('required', '');
 324      this.inputElement.setAttribute('pattern', '/^(http://INVALID/).+$/');
 325  
 326      if (document.formvalidator) {
 327        document.formvalidator.validate(this.inputElement);
 328      }
 329    }
 330  
 331    clearValue() {
 332      this.setValue('');
 333      this.validatedUrl = '';
 334      this.inputElement.removeAttribute('required');
 335      this.inputElement.removeAttribute('pattern');
 336  
 337      if (document.formvalidator) {
 338        document.formvalidator.validate(this.inputElement);
 339      }
 340    }
 341  
 342    updatePreview() {
 343      if (['true', 'static'].indexOf(this.preview) === -1 || this.preview === 'false' || !this.previewElement) {
 344        return;
 345      } // Reset preview
 346  
 347  
 348      if (this.preview) {
 349        const {
 350          value
 351        } = this.inputElement;
 352        const {
 353          supportedExtensions
 354        } = this;
 355  
 356        if (!value) {
 357          this.buttonClearEl.style.display = 'none';
 358          this.previewElement.innerHTML = Joomla.sanitizeHtml('<span class="field-media-preview-icon"></span>');
 359        } else {
 360          let type;
 361          this.buttonClearEl.style.display = '';
 362          this.previewElement.innerHTML = '';
 363          const ext = getExtension(value);
 364          if (supportedExtensions.images.includes(ext)) type = 'images';
 365          if (supportedExtensions.audios.includes(ext)) type = 'audios';
 366          if (supportedExtensions.videos.includes(ext)) type = 'videos';
 367          if (supportedExtensions.documents.includes(ext)) type = 'documents';
 368          let previewElement;
 369          const mediaType = {
 370            images: () => {
 371              if (supportedExtensions.images.includes(ext)) {
 372                previewElement = new Image();
 373                previewElement.src = /http/.test(value) ? value : Joomla.getOptions('system.paths').rootFull + value;
 374                previewElement.setAttribute('alt', '');
 375              }
 376            },
 377            audios: () => {
 378              if (supportedExtensions.audios.includes(ext)) {
 379                previewElement = document.createElement('audio');
 380                previewElement.src = /http/.test(value) ? value : Joomla.getOptions('system.paths').rootFull + value;
 381                previewElement.setAttribute('controls', '');
 382              }
 383            },
 384            videos: () => {
 385              if (supportedExtensions.videos.includes(ext)) {
 386                previewElement = document.createElement('video');
 387                const previewElementSource = document.createElement('source');
 388                previewElementSource.src = /http/.test(value) ? value : Joomla.getOptions('system.paths').rootFull + value;
 389                previewElementSource.type = `video/$ext}`;
 390                previewElement.setAttribute('controls', '');
 391                previewElement.setAttribute('width', this.previewWidth);
 392                previewElement.setAttribute('height', this.previewHeight);
 393                previewElement.appendChild(previewElementSource);
 394              }
 395            },
 396            documents: () => {
 397              if (supportedExtensions.documents.includes(ext)) {
 398                previewElement = document.createElement('object');
 399                previewElement.data = /http/.test(value) ? value : Joomla.getOptions('system.paths').rootFull + value;
 400                previewElement.type = `application/$ext}`;
 401                previewElement.setAttribute('width', this.previewWidth);
 402                previewElement.setAttribute('height', this.previewHeight);
 403              }
 404            }
 405          }; // @todo more checks
 406  
 407          if (this.givenType && ['images', 'audios', 'videos', 'documents'].includes(this.givenType)) {
 408            mediaType[this.givenType]();
 409          } else if (type && ['images', 'audios', 'videos', 'documents'].includes(type)) {
 410            mediaType[type]();
 411          } else {
 412            return;
 413          }
 414  
 415          this.previewElement.style.width = this.previewWidth;
 416          this.previewElement.appendChild(previewElement);
 417        }
 418      }
 419    }
 420  
 421  }
 422  
 423  customElements.define('joomla-field-media', JoomlaFieldMedia);


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer