From 9530e2385beb6a3954f545be5bc69d92d3ca7952 Mon Sep 17 00:00:00 2001 From: Aleksandra Bozek Date: Mon, 20 Apr 2026 13:48:03 +0200 Subject: [PATCH] IBX-11005: Added alternative text validation in image assets --- .../public/js/scripts/fieldType/ezimage.js | 3 +- .../js/scripts/fieldType/ezimageasset.js | 50 ++++++++++++++++++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/bundle/Resources/public/js/scripts/fieldType/ezimage.js b/src/bundle/Resources/public/js/scripts/fieldType/ezimage.js index b6ad45f904..c38e477b9d 100644 --- a/src/bundle/Resources/public/js/scripts/fieldType/ezimage.js +++ b/src/bundle/Resources/public/js/scripts/fieldType/ezimage.js @@ -92,9 +92,8 @@ const dataContainer = this.fieldContainer.querySelector('.ibexa-field-edit__data'); const isFileFieldEmpty = fileField.files && !fileField.files.length && dataContainer && !dataContainer.hasAttribute('hidden'); const { isRequired } = event.target.dataset; - const alreadyIsError = this.fieldContainer.classList.contains(this.classInvalid); const isEmpty = !event.target.value; - const isError = alreadyIsError || (isEmpty && isRequired && !isFileFieldEmpty); + const isError = isEmpty && isRequired && !isFileFieldEmpty; const label = event.target.closest(SELECTOR_ALT_WRAPPER).querySelector('.ibexa-data-source__label').innerText; const result = { isError }; diff --git a/src/bundle/Resources/public/js/scripts/fieldType/ezimageasset.js b/src/bundle/Resources/public/js/scripts/fieldType/ezimageasset.js index 769d171580..94a039be08 100644 --- a/src/bundle/Resources/public/js/scripts/fieldType/ezimageasset.js +++ b/src/bundle/Resources/public/js/scripts/fieldType/ezimageasset.js @@ -2,6 +2,9 @@ const SELECTOR_FIELD = '.ibexa-field-edit--ezimageasset'; const SELECTOR_INPUT_FILE = 'input[type="file"]'; const SELECTOR_INPUT_DESTINATION_CONTENT_ID = '.ibexa-data-source__destination-content-id'; + const SELECTOR_ALT_WRAPPER = '.ibexa-field-edit-preview__image-alt'; + const SELECTOR_INPUT_ALT = '.ibexa-field-edit-preview__image-alt .ibexa-data-source__input'; + const EVENT_CANCEL_ERROR = 'ibexa-cancel-errors'; const token = doc.querySelector('meta[name="CSRF-Token"]').content; const { showErrorNotification } = ibexa.helpers.notification; const { showSuccessNotification } = ibexa.helpers.notification; @@ -158,6 +161,7 @@ this.inputDestinationContentId.value = destinationContentId; this.inputField.value = ''; + previewAlt.dispatchEvent(new CustomEvent(EVENT_CANCEL_ERROR)); this.showPreview(); } @@ -227,7 +231,7 @@ super.resetInputField(); this.inputDestinationContentId.value = ''; - this.fieldContainer.querySelector('.ibexa-field-edit-preview__image-alt .ibexa-data-source__input').value = ''; + this.fieldContainer.querySelector(SELECTOR_INPUT_ALT).value = ''; } /** @@ -244,8 +248,35 @@ } } + class EzImageAssetFieldValidator extends ibexa.BaseFileFieldValidator { + /** + * Validates the alternative text input + * + * @method validateAltInput + * @param {Event} event + * @returns {Object} + * @memberof EzImageAssetFieldValidator + */ + validateAltInput(event) { + const fileField = this.fieldContainer.querySelector(SELECTOR_INPUT_FILE); + const dataContainer = this.fieldContainer.querySelector('.ibexa-field-edit__data'); + const isFileFieldEmpty = fileField.files && !fileField.files.length && dataContainer && !dataContainer.hasAttribute('hidden'); + const isRequired = this.fieldContainer.classList.contains('ibexa-field-edit--required'); + const isEmpty = !event.target.value.trim(); + const isError = isEmpty && isRequired && !isFileFieldEmpty; + const label = event.target.closest(SELECTOR_ALT_WRAPPER).querySelector('.ibexa-data-source__label').innerText; + const result = { isError }; + + if (isEmpty) { + result.errorMessage = ibexa.errors.emptyField.replace('{fieldName}', label); + } + + return result; + } + } + doc.querySelectorAll(SELECTOR_FIELD).forEach((fieldContainer) => { - const validator = new ibexa.BaseFileFieldValidator({ + const validator = new EzImageAssetFieldValidator({ classInvalid: 'is-invalid', fieldContainer, eventsMap: [ @@ -272,6 +303,21 @@ errorNodeSelectors: ['.ibexa-form-error'], invalidStateSelectors: ['.ibexa-field-edit__label'], }, + { + selector: SELECTOR_INPUT_ALT, + eventName: 'blur', + callback: 'validateAltInput', + invalidStateSelectors: ['.ibexa-data-source__field--alternativeText'], + errorNodeSelectors: [`${SELECTOR_ALT_WRAPPER} .ibexa-form-error`], + }, + { + isValueValidator: false, + selector: SELECTOR_INPUT_ALT, + eventName: EVENT_CANCEL_ERROR, + callback: 'cancelErrors', + invalidStateSelectors: ['.ibexa-data-source__field--alternativeText'], + errorNodeSelectors: [`${SELECTOR_ALT_WRAPPER} .ibexa-form-error`], + }, ], });