diff --git a/build/media_source/system/js/fields/joomla-field-media.w-c.es6.js b/build/media_source/system/js/fields/joomla-field-media.w-c.es6.js index d0a5531500887..56e9e9a2a5466 100644 --- a/build/media_source/system/js/fields/joomla-field-media.w-c.es6.js +++ b/build/media_source/system/js/fields/joomla-field-media.w-c.es6.js @@ -30,6 +30,9 @@ class JoomlaFieldMedia extends HTMLElement { this.modalClose = this.modalClose.bind(this); this.setValue = this.setValue.bind(this); this.updatePreview = this.updatePreview.bind(this); + this.validateValue = this.validateValue.bind(this); + this.markValid = this.markValid.bind(this); + this.markInvalid = this.markInvalid.bind(this); } static get observedAttributes() { @@ -130,6 +133,8 @@ class JoomlaFieldMedia extends HTMLElement { } this.updatePreview(); + this.inputElement.removeAttribute('readonly'); + this.inputElement.addEventListener('change', this.validateValue); } disconnectedCallback() { @@ -139,6 +144,9 @@ class JoomlaFieldMedia extends HTMLElement { if (this.buttonClearEl) { this.buttonClearEl.removeEventListener('click', this.clearValue); } + if (this.inputElement) { + this.inputElement.removeEventListener('change', this.validateValue); + } } onSelected(event) { @@ -172,6 +180,7 @@ class JoomlaFieldMedia extends HTMLElement { setValue(value) { this.inputElement.value = value; + this.validatedUrl = value; this.updatePreview(); // trigger change event both on the input and on the custom element @@ -182,8 +191,94 @@ class JoomlaFieldMedia extends HTMLElement { })); } + validateValue(event) { + let { value } = event.target; + if (this.validatedUrl === value || value === '') return; + + if (/^(http(s)?:\/\/).+$/.test(value)) { + try { + fetch(value).then((response) => { + if (response.status === 200) { + this.validatedUrl = value; + this.markValid(); + } else { + this.validatedUrl = value; + this.markInvalid(); + } + }); + } catch (err) { + this.validatedUrl = value; + this.markInvalid(); + } + } else { + if (/^\//.test(value)) { + value = value.substring(1); + } + + const hashedUrl = value.split('#'); + const urlParts = hashedUrl[0].split('/'); + const rest = urlParts.slice(1); + fetch(`${Joomla.getOptions('system.paths').rootFull}/${value}`) + .then((response) => response.blob()) + .then((blob) => { + if (blob.type.includes('image')) { + const img = new Image(); + img.src = URL.createObjectURL(blob); + + img.onload = () => { + this.inputElement.value = `${urlParts[0]}/${rest.join('/')}#joomlaImage://local-${urlParts[0]}/${rest.join('/')}?width=${img.width}&height=${img.height}`; + this.validatedUrl = `${urlParts[0]}/${rest.join('/')}#joomlaImage://local-${urlParts[0]}/${rest.join('/')}?width=${img.width}&height=${img.height}`; + this.markValid(); + }; + } else if (blob.type.includes('audio')) { + this.inputElement.value = value; + this.validatedUrl = value; + this.markValid(); + } else if (blob.type.includes('video')) { + this.inputElement.value = value; + this.validatedUrl = value; + this.markValid(); + } else if (blob.type.includes('application/pdf')) { + this.inputElement.value = value; + this.validatedUrl = value; + this.markValid(); + } else { + this.validatedUrl = value; + this.markInvalid(); + } + }) + .catch(() => { + this.setValue(value); + this.validatedUrl = value; + this.markInvalid(); + }); + } + } + + markValid() { + this.inputElement.removeAttribute('required'); + this.inputElement.removeAttribute('pattern'); + if (document.formvalidator) { + document.formvalidator.validate(this.inputElement); + } + } + + markInvalid() { + this.inputElement.setAttribute('required', ''); + this.inputElement.setAttribute('pattern', '/^(http://INVALID/).+$/'); + if (document.formvalidator) { + document.formvalidator.validate(this.inputElement); + } + } + clearValue() { this.setValue(''); + this.validatedUrl = ''; + this.inputElement.removeAttribute('required'); + this.inputElement.removeAttribute('pattern'); + if (document.formvalidator) { + document.formvalidator.validate(this.inputElement); + } } updatePreview() { diff --git a/build/media_source/system/js/fields/joomla-media-select.w-c.es6.js b/build/media_source/system/js/fields/joomla-media-select.w-c.es6.js index f50ef67639081..98030b59f45ed 100644 --- a/build/media_source/system/js/fields/joomla-media-select.w-c.es6.js +++ b/build/media_source/system/js/fields/joomla-media-select.w-c.es6.js @@ -197,8 +197,8 @@ const insertAsImage = async (media, editor, fieldClass) => { Joomla.selectedMediaFile.width = 0; } } - editor.value = `${Joomla.selectedMediaFile.url}#joomlaImage://${media.path.replace(':', '')}?width=${Joomla.selectedMediaFile.width}&height=${Joomla.selectedMediaFile.height}`; - fieldClass.updatePreview(); + fieldClass.markValid(); + fieldClass.setValue(`${Joomla.selectedMediaFile.url}#joomlaImage://${media.path.replace(':', '')}?width=${Joomla.selectedMediaFile.width}&height=${Joomla.selectedMediaFile.height}`); } } }; @@ -256,9 +256,9 @@ const insertAsOther = (media, editor, fieldClass, type) => { Joomla.editors.instances[editor].replaceSelection(outputText); } else { - editor.value = Joomla.selectedMediaFile.url; + fieldClass.markValid(); fieldClass.givenType = type; - fieldClass.updatePreview(); + fieldClass.setValue(Joomla.selectedMediaFile.url); } } }; diff --git a/layouts/joomla/form/field/media.php b/layouts/joomla/form/field/media.php index 13ce9086951c4..57fa34bde02c5 100644 --- a/layouts/joomla/form/field/media.php +++ b/layouts/joomla/form/field/media.php @@ -196,7 +196,7 @@
- > + >