[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

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

   1  /**
   2   * @copyright   (C) 2021 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   * An object holding all the information of the selected image in media manager
  10   * eg:
  11   * {
  12   *   extension: "png"
  13   *   fileType: "image/png"
  14   *   height: 44
  15   *   path: "local-images:/powered_by.png"
  16   *   thumb: undefined
  17   *   width: 294
  18   * }
  19   */
  20  
  21  
  22  Joomla.selectedMediaFile = {};
  23  const supportedExtensions = Joomla.getOptions('media-picker', {});
  24  
  25  if (!Object.keys(supportedExtensions).length) {
  26    throw new Error('No supported extensions provided');
  27  }
  28  /**
  29   * Event Listener that updates the Joomla.selectedMediaFile
  30   * to the selected file in the media manager
  31   */
  32  
  33  
  34  document.addEventListener('onMediaFileSelected', async e => {
  35    Joomla.selectedMediaFile = e.detail;
  36    const currentModal = Joomla.Modal.getCurrent();
  37    const container = currentModal.querySelector('.modal-body');
  38  
  39    if (!container) {
  40      return;
  41    }
  42  
  43    const optionsEl = container.querySelector('joomla-field-mediamore');
  44  
  45    if (optionsEl) {
  46      optionsEl.parentNode.removeChild(optionsEl);
  47    } // No extra attributes (lazy, alt) for fields
  48  
  49  
  50    if (container.closest('joomla-field-media')) {
  51      return;
  52    }
  53  
  54    const {
  55      images,
  56      audios,
  57      videos,
  58      documents
  59    } = supportedExtensions;
  60  
  61    if (Joomla.selectedMediaFile.path) {
  62      let type;
  63  
  64      if (images.includes(Joomla.selectedMediaFile.extension.toLowerCase())) {
  65        type = 'images';
  66      } else if (audios.includes(Joomla.selectedMediaFile.extension.toLowerCase())) {
  67        type = 'audios';
  68      } else if (videos.includes(Joomla.selectedMediaFile.extension.toLowerCase())) {
  69        type = 'videos';
  70      } else if (documents.includes(Joomla.selectedMediaFile.extension.toLowerCase())) {
  71        type = 'documents';
  72      }
  73  
  74      if (type) {
  75        container.insertAdjacentHTML('afterbegin', `<joomla-field-mediamore
  76    parent-id="$currentModal.id}"
  77    type="$type}"
  78    summary-label="$Joomla.Text._('JFIELD_MEDIA_SUMMARY_LABEL')}"
  79    lazy-label="$Joomla.Text._('JFIELD_MEDIA_LAZY_LABEL')}"
  80    alt-label="$Joomla.Text._('JFIELD_MEDIA_ALT_LABEL')}"
  81    alt-check-label="$Joomla.Text._('JFIELD_MEDIA_ALT_CHECK_LABEL')}"
  82    alt-check-desc-label="$Joomla.Text._('JFIELD_MEDIA_ALT_CHECK_DESC_LABEL')}"
  83    classes-label="$Joomla.Text._('JFIELD_MEDIA_CLASS_LABEL')}"
  84    figure-classes-label="$Joomla.Text._('JFIELD_MEDIA_FIGURE_CLASS_LABEL')}"
  85    figure-caption-label="$Joomla.Text._('JFIELD_MEDIA_FIGURE_CAPTION_LABEL')}"
  86    embed-check-label="$Joomla.Text._('JFIELD_MEDIA_EMBED_CHECK_LABEL')}"
  87    embed-check-desc-label="$Joomla.Text._('JFIELD_MEDIA_EMBED_CHECK_DESC_LABEL')}"
  88    download-check-label="$Joomla.Text._('JFIELD_MEDIA_DOWNLOAD_CHECK_LABEL')}"
  89    download-check-desc-label="$Joomla.Text._('JFIELD_MEDIA_DOWNLOAD_CHECK_DESC_LABEL')}"
  90    title-label="$Joomla.Text._('JFIELD_MEDIA_TITLE_LABEL')}"
  91    width-label="$Joomla.Text._('JFIELD_MEDIA_WIDTH_LABEL')}"
  92    height-label="$Joomla.Text._('JFIELD_MEDIA_HEIGHT_LABEL')}"
  93  ></joomla-field-mediamore>
  94  `);
  95      }
  96    }
  97  });
  98  /**
  99   * Method to check if passed param is HTMLElement
 100   *
 101   * @param o {string|HTMLElement}  Element to be checked
 102   *
 103   * @returns {boolean}
 104   */
 105  
 106  const isElement = o => typeof HTMLElement === 'object' ? o instanceof HTMLElement : o && typeof o === 'object' && o.nodeType === 1 && typeof o.nodeName === 'string';
 107  /**
 108   * Method to return the image size
 109   *
 110   * @param url {string}
 111   *
 112   * @returns {bool}
 113   */
 114  
 115  
 116  const getImageSize = url => new Promise((resolve, reject) => {
 117    const img = new Image();
 118    img.src = url;
 119  
 120    img.onload = () => {
 121      Joomla.selectedMediaFile.width = img.width;
 122      Joomla.selectedMediaFile.height = img.height;
 123      resolve(true);
 124    };
 125  
 126    img.onerror = () => {
 127      // eslint-disable-next-line prefer-promise-reject-errors
 128      reject(false);
 129    };
 130  });
 131  
 132  const insertAsImage = async (media, editor, fieldClass) => {
 133    if (media.url) {
 134      const {
 135        rootFull
 136      } = Joomla.getOptions('system.paths');
 137      const parts = media.url.split(rootFull);
 138  
 139      if (parts.length > 1) {
 140        // eslint-disable-next-line prefer-destructuring
 141        Joomla.selectedMediaFile.url = parts[1];
 142  
 143        if (media.thumb_path) {
 144          Joomla.selectedMediaFile.thumb = media.thumb_path;
 145        } else {
 146          Joomla.selectedMediaFile.thumb = false;
 147        }
 148      } else if (media.thumb_path) {
 149        Joomla.selectedMediaFile.url = media.url;
 150        Joomla.selectedMediaFile.thumb = media.thumb_path;
 151      }
 152    } else {
 153      Joomla.selectedMediaFile.url = false;
 154    }
 155  
 156    if (Joomla.selectedMediaFile.url) {
 157      let attribs;
 158      let isLazy = '';
 159      let alt = '';
 160      let appendAlt = '';
 161      let classes = '';
 162      let figClasses = '';
 163      let figCaption = '';
 164      let imageElement = '';
 165  
 166      if (!isElement(editor)) {
 167        const currentModal = fieldClass.closest('.modal-content');
 168        attribs = currentModal.querySelector('joomla-field-mediamore');
 169  
 170        if (attribs) {
 171          if (attribs.getAttribute('alt-check') === 'true') {
 172            appendAlt = ' alt=""';
 173          }
 174  
 175          alt = attribs.getAttribute('alt-value') ? ` alt="$attribs.getAttribute('alt-value')}"` : appendAlt;
 176          classes = attribs.getAttribute('img-classes') ? ` class="$attribs.getAttribute('img-classes')}"` : '';
 177          figClasses = attribs.getAttribute('fig-classes') ? ` class="image $attribs.getAttribute('fig-classes')}"` : ' class="image"';
 178          figCaption = attribs.getAttribute('fig-caption') ? `$attribs.getAttribute('fig-caption')}` : '';
 179  
 180          if (attribs.getAttribute('is-lazy') === 'true') {
 181            isLazy = ` loading="lazy" width="$Joomla.selectedMediaFile.width}" height="$Joomla.selectedMediaFile.height}"`;
 182  
 183            if (Joomla.selectedMediaFile.width === 0 || Joomla.selectedMediaFile.height === 0) {
 184              try {
 185                await getImageSize(Joomla.selectedMediaFile.url);
 186                isLazy = ` loading="lazy" width="$Joomla.selectedMediaFile.width}" height="$Joomla.selectedMediaFile.height}"`;
 187              } catch (err) {
 188                isLazy = '';
 189              }
 190            }
 191          }
 192        }
 193  
 194        if (figCaption) {
 195          imageElement = `<figure$figClasses}><img src="$Joomla.selectedMediaFile.url}"$classes}$isLazy}$alt} data-path="$Joomla.selectedMediaFile.path}"/><figcaption>$figCaption}</figcaption></figure>`;
 196        } else {
 197          imageElement = `<img src="$Joomla.selectedMediaFile.url}"$classes}$isLazy}$alt} data-path="$Joomla.selectedMediaFile.path}"/>`;
 198        }
 199  
 200        if (attribs) {
 201          attribs.parentNode.removeChild(attribs);
 202        }
 203  
 204        Joomla.editors.instances[editor].replaceSelection(imageElement);
 205      } else {
 206        if (Joomla.selectedMediaFile.width === 0 || Joomla.selectedMediaFile.height === 0) {
 207          try {
 208            await getImageSize(Joomla.selectedMediaFile.url); // eslint-disable-next-line no-empty
 209          } catch (err) {
 210            Joomla.selectedMediaFile.height = 0;
 211            Joomla.selectedMediaFile.width = 0;
 212          }
 213        }
 214  
 215        fieldClass.markValid();
 216        fieldClass.setValue(`$Joomla.selectedMediaFile.url}#joomlaImage://${media.path.replace(':', '')}?width=${Joomla.selectedMediaFile.width}&height=${Joomla.selectedMediaFile.height}`);
 217      }
 218    }
 219  };
 220  
 221  const insertAsOther = (media, editor, fieldClass, type) => {
 222    if (media.url) {
 223      const {
 224        rootFull
 225      } = Joomla.getOptions('system.paths');
 226      const parts = media.url.split(rootFull);
 227  
 228      if (parts.length > 1) {
 229        // eslint-disable-next-line prefer-destructuring
 230        Joomla.selectedMediaFile.url = parts[1];
 231      } else {
 232        Joomla.selectedMediaFile.url = media.url;
 233      }
 234    } else {
 235      Joomla.selectedMediaFile.url = false;
 236    }
 237  
 238    let attribs;
 239  
 240    if (Joomla.selectedMediaFile.url) {
 241      // Available Only inside an editor
 242      if (!isElement(editor)) {
 243        let outputText;
 244        const currentModal = fieldClass.closest('.modal-content');
 245        attribs = currentModal.querySelector('joomla-field-mediamore');
 246  
 247        if (attribs) {
 248          const embedable = attribs.getAttribute('embed-it');
 249  
 250          if (embedable && embedable === 'true') {
 251            if (type === 'audios') {
 252              outputText = `<audio controls src="$Joomla.selectedMediaFile.url}"></audio>`;
 253            }
 254  
 255            if (type === 'documents') {
 256              // @todo use ${Joomla.selectedMediaFile.filetype} in type
 257              const title = attribs.getAttribute('title');
 258              outputText = `<object type="application/$Joomla.selectedMediaFile.extension}" data="$Joomla.selectedMediaFile.url}" $title ? `title="$title}"` : ''} width="$attribs.getAttribute('width')}" height="$attribs.getAttribute('height')}">
 259    $Joomla.Text._('JFIELD_MEDIA_UNSUPPORTED').replace('{tag}', `<a download href="$Joomla.selectedMediaFile.url}">`).replace(/{extension}/g, Joomla.selectedMediaFile.extension)}
 260  </object>`;
 261            }
 262  
 263            if (type === 'videos') {
 264              outputText = `<video controls width="$attribs.getAttribute('width')}" height="$attribs.getAttribute('height')}">
 265    <source src="$Joomla.selectedMediaFile.url}" type="$Joomla.selectedMediaFile.fileType}">
 266  </video>`;
 267            }
 268          } else if (Joomla.editors.instances[editor].getSelection() !== '') {
 269            outputText = `<a download href="$Joomla.selectedMediaFile.url}">$Joomla.editors.instances[editor].getSelection()}</a>`;
 270          } else {
 271            const name = /([\w-]+)\./.exec(Joomla.selectedMediaFile.url);
 272            outputText = `<a download href="$Joomla.selectedMediaFile.url}">$Joomla.Text._('JFIELD_MEDIA_DOWNLOAD_FILE').replace('{file}', name[1])}</a>`;
 273          }
 274        }
 275  
 276        if (attribs) {
 277          attribs.parentNode.removeChild(attribs);
 278        }
 279  
 280        Joomla.editors.instances[editor].replaceSelection(outputText);
 281      } else {
 282        fieldClass.markValid();
 283        fieldClass.givenType = type;
 284        fieldClass.setValue(Joomla.selectedMediaFile.url);
 285      }
 286    }
 287  };
 288  /**
 289   * Method to append the image in an editor or a field
 290   *
 291   * @param {{}} resp
 292   * @param {string|HTMLElement} editor
 293   * @param {string} fieldClass
 294   */
 295  
 296  
 297  const execTransform = async (resp, editor, fieldClass) => {
 298    if (resp.success === true) {
 299      const media = resp.data[0];
 300      const {
 301        images,
 302        audios,
 303        videos,
 304        documents
 305      } = supportedExtensions;
 306  
 307      if (Joomla.selectedMediaFile.extension && images.includes(media.extension.toLowerCase())) {
 308        return insertAsImage(media, editor, fieldClass);
 309      }
 310  
 311      if (Joomla.selectedMediaFile.extension && audios.includes(media.extension.toLowerCase())) {
 312        return insertAsOther(media, editor, fieldClass, 'audios');
 313      }
 314  
 315      if (Joomla.selectedMediaFile.extension && documents.includes(media.extension.toLowerCase())) {
 316        return insertAsOther(media, editor, fieldClass, 'documents');
 317      }
 318  
 319      if (Joomla.selectedMediaFile.extension && videos.includes(media.extension.toLowerCase())) {
 320        return insertAsOther(media, editor, fieldClass, 'videos');
 321      }
 322  
 323      return '';
 324    }
 325  
 326    return '';
 327  };
 328  /**
 329   * Method that resolves the real url for the selected media file
 330   *
 331   * @param data        {object}         The data for the detail
 332   * @param editor      {string|object}  The data for the detail
 333   * @param fieldClass  {HTMLElement}    The fieldClass for the detail
 334   *
 335   * @returns {void}
 336   */
 337  
 338  
 339  Joomla.getMedia = (data, editor, fieldClass) => new Promise((resolve, reject) => {
 340    if (!data || typeof data === 'object' && (!data.path || data.path === '')) {
 341      Joomla.selectedMediaFile = {};
 342      resolve({
 343        resp: {
 344          success: false
 345        }
 346      });
 347      return;
 348    }
 349  
 350    const url = `$Joomla.getOptions('system.paths').baseFull}index.php?option=com_media&task=api.files&url=true&path=$data.path}&mediatypes=0,1,2,3&$Joomla.getOptions('csrf.token')}=1&format=json`;
 351    fetch(url, {
 352      method: 'GET',
 353      headers: {
 354        'Content-Type': 'application/json'
 355      }
 356    }).then(response => response.json()).then(async response => resolve(await execTransform(response, editor, fieldClass))).catch(error => reject(error));
 357  }); // For B/C purposes
 358  
 359  
 360  Joomla.getImage = Joomla.getMedia;
 361  /**
 362   * A simple Custom Element for adding alt text and controlling
 363   * the lazy loading on a selected image
 364   *
 365   * Will be rendered only for editor content images
 366   * Attributes:
 367   * - parent-id: the id of the parent media field {string}
 368   * - lazy-label: The text for the checkbox label {string}
 369   * - alt-label: The text for the alt label {string}
 370   * - is-lazy: The value for the lazyloading (calculated, defaults to 'true') {string}
 371   * - alt-value: The value for the alt text (calculated, defaults to '') {string}
 372   */
 373  
 374  class JoomlaFieldMediaOptions extends HTMLElement {
 375    get type() {
 376      return this.getAttribute('type');
 377    }
 378  
 379    get parentId() {
 380      return this.getAttribute('parent-id');
 381    }
 382  
 383    get lazytext() {
 384      return this.getAttribute('lazy-label');
 385    }
 386  
 387    get alttext() {
 388      return this.getAttribute('alt-label');
 389    }
 390  
 391    get altchecktext() {
 392      return this.getAttribute('alt-check-label');
 393    }
 394  
 395    get altcheckdesctext() {
 396      return this.getAttribute('alt-check-desc-label');
 397    }
 398  
 399    get embedchecktext() {
 400      return this.getAttribute('embed-check-label');
 401    }
 402  
 403    get embedcheckdesctext() {
 404      return this.getAttribute('embed-check-desc-label');
 405    }
 406  
 407    get downloadchecktext() {
 408      return this.getAttribute('download-check-label');
 409    }
 410  
 411    get downloadcheckdesctext() {
 412      return this.getAttribute('download-check-desc-label');
 413    }
 414  
 415    get classestext() {
 416      return this.getAttribute('classes-label');
 417    }
 418  
 419    get figclassestext() {
 420      return this.getAttribute('figure-classes-label');
 421    }
 422  
 423    get figcaptiontext() {
 424      return this.getAttribute('figure-caption-label');
 425    }
 426  
 427    get summarytext() {
 428      return this.getAttribute('summary-label');
 429    }
 430  
 431    get widthtext() {
 432      return this.getAttribute('width-label');
 433    }
 434  
 435    get heighttext() {
 436      return this.getAttribute('height-label');
 437    }
 438  
 439    get titletext() {
 440      return this.getAttribute('title-label');
 441    }
 442  
 443    connectedCallback() {
 444      if (this.type === 'images') {
 445        this.innerHTML = `<details open>
 446  <summary>$this.summarytext}</summary>
 447  <div class="">
 448    <div class="form-group">
 449      <div class="input-group">
 450        <label class="input-group-text" for="$this.parentId}-alt">$this.alttext}</label>
 451        <input class="form-control" type="text" id="$this.parentId}-alt" data-is="alt-value" />
 452      </div>
 453    </div>
 454    <div class="form-group">
 455      <div class="form-check">
 456        <input class="form-check-input" type="checkbox" id="$this.parentId}-alt-check">
 457        <label class="form-check-label" for="$this.parentId}-alt-check">$this.altchecktext}</label>
 458        <div><small class="form-text">$this.altcheckdesctext}</small></div>
 459      </div>
 460    </div>
 461    <div class="form-group">
 462      <div class="form-check">
 463        <input class="form-check-input" type="checkbox" id="$this.parentId}-lazy" checked>
 464        <label class="form-check-label" for="$this.parentId}-lazy">$this.lazytext}</label>
 465      </div>
 466    </div>
 467    <div class="form-group">
 468      <div class="input-group">
 469        <label class="input-group-text" for="$this.parentId}-classes">$this.classestext}</label>
 470        <input class="form-control" type="text" id="$this.parentId}-classes" data-is="img-classes"/>
 471      </div>
 472    </div>
 473    <div class="form-group">
 474      <div class="input-group">
 475        <label class="input-group-text" for="$this.parentId}-figclasses">$this.figclassestext}</label>
 476        <input class="form-control" type="text" id="$this.parentId}-figclasses" data-is="fig-classes"/>
 477      </div>
 478    </div>
 479    <div class="form-group">
 480      <div class="input-group">
 481        <label class="input-group-text" for="$this.parentId}-figcaption">$this.figcaptiontext}</label>
 482        <input class="form-control" type="text" id="$this.parentId}-figcaption" data-is="fig-caption"/>
 483      </div>
 484    </div>
 485  </div>
 486  </details>`;
 487        this.lazyInputFn = this.lazyInputFn.bind(this);
 488        this.altCheckFn = this.altCheckFn.bind(this);
 489        this.inputFn = this.inputFn.bind(this); // Add event listeners
 490  
 491        this.lazyInput = this.querySelector(`#$this.parentId}-lazy`);
 492        this.lazyInput.addEventListener('change', this.lazyInputFn);
 493        this.altCheck = this.querySelector(`#$this.parentId}-alt-check`);
 494        this.altCheck.addEventListener('input', this.altCheckFn);
 495        [].slice.call(this.querySelectorAll('input[type="text"]')).map(el => {
 496          el.addEventListener('input', this.inputFn);
 497          const {
 498            is
 499          } = el.dataset;
 500  
 501          if (is) {
 502            this.setAttribute(is, el.value.replace(/"/g, '&quot;'));
 503          }
 504  
 505          return el;
 506        }); // Set initial values
 507  
 508        this.setAttribute('is-lazy', !!this.lazyInput.checked);
 509        this.setAttribute('alt-check', false);
 510      } else if (['audios', 'videos', 'documents'].includes(this.type)) {
 511        this.innerHTML = `<details open>
 512  <summary>$this.summarytext}</summary>
 513  <div class="">
 514    <div class="form-group">
 515      <div class="form-check">
 516        <input class="form-check-input radio" type="radio" name="flexRadioDefault" id="$this.parentId}-embed-check-2" value="0" checked>
 517        <label class="form-check-label" for="$this.parentId}-embed-check-2">
 518          $this.downloadchecktext}
 519          <div><small class="form-text">$this.downloadcheckdesctext}</small></div>
 520        </label>
 521      </div>
 522      <div class="form-check">
 523        <input class="form-check-input radio" type="radio" name="flexRadioDefault" id="$this.parentId}-embed-check-1" value="1">
 524        <label class="form-check-label" for="$this.parentId}-embed-check-1">
 525          $this.embedchecktext}
 526          <div><small class="form-text">$this.embedcheckdesctext}</small></div>
 527        </label>
 528      </div>
 529    </div>
 530    <div class="toggable-parts" style="display: none">
 531      <div style="display: $this.type === 'audios' ? 'none' : 'block'}">
 532        <div class="form-group">
 533          <div class="input-group">
 534            <label class="input-group-text" for="$this.parentId}-width">$this.widthtext}</label>
 535            <input class="form-control" type="text" id="$this.parentId}-width" value="800" data-is="width"/>
 536          </div>
 537        </div>
 538        <div class="form-group">
 539          <div class="input-group">
 540            <label class="input-group-text" for="$this.parentId}-height">$this.heighttext}</label>
 541            <input class="form-control" type="text" id="$this.parentId}-height" value="600" data-is="height"/>
 542          </div>
 543        </div>
 544        <div style="display: $this.type === 'document' ? 'block' : 'none'}">
 545          <div class="form-group">
 546            <div class="input-group">
 547              <label class="input-group-text" for="$this.parentId}-title">$this.titletext}</label>
 548              <input class="form-control" type="text" id="$this.parentId}-title" value="" data-is="title"/>
 549            </div>
 550          </div>
 551      </div>
 552    </div>
 553  </div>
 554  </details>`;
 555        this.embedInputFn = this.embedInputFn.bind(this);
 556        this.inputFn = this.inputFn.bind(this);
 557        [].slice.call(this.querySelectorAll('.form-check-input.radio')).map(el => el.addEventListener('input', this.embedInputFn));
 558        this.setAttribute('embed-it', false);
 559        [].slice.call(this.querySelectorAll('input[type="text"]')).map(el => {
 560          el.addEventListener('input', this.inputFn);
 561          const {
 562            is
 563          } = el.dataset;
 564  
 565          if (is) {
 566            this.setAttribute(is, el.value.replace(/"/g, '&quot;'));
 567          }
 568  
 569          return el;
 570        });
 571      }
 572    }
 573  
 574    disconnectedCallback() {
 575      if (this.type === 'image') {
 576        this.lazyInput.removeEventListener('input', this.lazyInputFn);
 577        this.altInput.removeEventListener('input', this.inputFn);
 578        this.altCheck.removeEventListener('input', this.altCheckFn);
 579      }
 580  
 581      if (['audio', 'video', 'document'].includes(this.type)) {
 582        [].slice.call(this.querySelectorAll('.form-check-input.radio')).map(el => el.removeEventListener('input', this.embedInputFn));
 583        [].slice.call(this.querySelectorAll('input[type="text"]')).map(el => el.removeEventListener('input', this.embedInputFn));
 584      }
 585  
 586      this.innerHTML = '';
 587    }
 588  
 589    lazyInputFn(e) {
 590      this.setAttribute('is-lazy', !!e.target.checked);
 591    }
 592  
 593    altCheckFn(e) {
 594      this.setAttribute('alt-check', !!e.target.checked);
 595    }
 596  
 597    inputFn(e) {
 598      const {
 599        is
 600      } = e.target.dataset;
 601  
 602      if (is) {
 603        this.setAttribute(is, e.target.value.replace(/"/g, '&quot;'));
 604      }
 605    }
 606  
 607    embedInputFn(e) {
 608      const {
 609        value
 610      } = e.target;
 611      this.setAttribute('embed-it', value !== '0');
 612      const toggable = this.querySelector('.toggable-parts');
 613  
 614      if (toggable) {
 615        if (toggable.style.display !== 'block') {
 616          toggable.style.display = 'block';
 617        } else {
 618          toggable.style.display = 'none';
 619        }
 620      }
 621    }
 622  
 623  }
 624  
 625  customElements.define('joomla-field-mediamore', JoomlaFieldMediaOptions);


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