diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java index 50f3a643d5..5cb5747a56 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java @@ -17,17 +17,7 @@ import java.io.IOException; import java.math.BigDecimal; -import java.util.AbstractMap; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -68,9 +58,12 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.node.ArrayNode; public class AbstractFormComponentImpl extends AbstractComponentImpl implements FormComponent { @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_DATAREF) @@ -289,6 +282,10 @@ protected boolean getEditMode() { if (rulesProperties.size() > 0) { properties.put(CUSTOM_RULE_PROPERTY_WRAPPER, rulesProperties); } + List disabledScripts = getDisabledXFAScripts(); + if (disabledScripts.size() > 0) { + properties.put("fd:disabledXfaScripts", disabledScripts); + } return properties; } @@ -541,4 +538,24 @@ public Map getDorProperties() { return customDorProperties; } + private List getDisabledXFAScripts() { + Set disabledScripts = new HashSet<>(); + String xfaScripts = resource.getValueMap().get("fd:xfaScripts", ""); + if (StringUtils.isNotEmpty(xfaScripts)) { + // read string xfaScripts to jsonNode + ObjectMapper mapper = new ObjectMapper(); + try { + ArrayNode node = (ArrayNode) mapper.readTree(xfaScripts); + // iterate through the array node and add the elements which have disabled property set to true + for (JsonNode jsonNode : node) { + if (jsonNode.has("disabled") && jsonNode.get("disabled").asBoolean()) { + disabledScripts.add(jsonNode.get("activity").asText()); + } + } + } catch (IOException e) { + logger.error("Error while parsing xfaScripts {} {}", e, resource.getPath()); + } + } + return new ArrayList<>(disabledScripts); + } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java index b43f30b643..1b7fb8537f 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java @@ -107,7 +107,11 @@ public String[] getEnumNames() { String[] enumName = map.values().toArray(new String[0]); return Arrays.stream(enumName) .map(p -> { - return this.translate(ReservedProperties.PN_ENUM_NAMES, p); + String value = this.translate(ReservedProperties.PN_ENUM_NAMES, p); + if (value == null) { + value = ""; + } + return value; }) .toArray(String[]::new); } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/base/v1/base/_cq_editConfig.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/base/v1/base/_cq_editConfig.xml index fc6d62c32d..5a4a7100a8 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/base/v1/base/_cq_editConfig.xml +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/base/v1/base/_cq_editConfig.xml @@ -23,6 +23,12 @@ handler="CQ.FormsCoreComponents.editorhooks.viewQualifiedName" icon="viewSOMExpression" text="View Qualified Name"/> + + 0){ schemaRef = schemaRef[0].value; configuredFormModel = schemaRef; @@ -138,6 +154,8 @@ $(SCHEMA_DROPDOWN_SELECTOR).val(schemaRef); } else if (schemaType == FORM_DATA_MODEL) { $(FDM_DROPDOWN_SELECTOR).val(schemaRef); + } else if (schemaType == FORM_TEMPLATE) { + $(FORM_TEMPLATE_DROPDOWN_SELECTOR).val(schemaRef); } } }; @@ -172,6 +190,21 @@ } }; + function formTemplateSelectorOnChanged(dialog) { + var selectedSchema = dialog.find(FORM_TEMPLATE_DROPDOWN_SELECTOR); + if(selectedSchema.length > 0) { + selectedSchema = selectedSchema[0].value; + setElementValue(dialog, SCHEMA_REF, selectedSchema); + setElementValue(dialog, DAM_SCHEMA_REF, selectedSchema); + isSchemaChanged = true; + if (configuredFormModel) { + confirmFormModelChange(selectedSchema, $(FORM_TEMPLATE_DROPDOWN_SELECTOR)); + } else { + toBeConfiguredFormModel = selectedSchema; + } + } + }; + function setElementValue(dialog, elementRef, value){ var element = dialog.find(elementRef); if(element.length > 0){ @@ -205,13 +238,20 @@ function hideContainersExcept(selectedSchemaType) { if (selectedSchemaType == JSON_SCHEMA) { $(FDM_CONTAINER).hide(); + $(FORM_TEMPLATE_CONTAINER).hide(); $(SCHEMA_CONTAINER).show(); } else if (selectedSchemaType == FORM_DATA_MODEL) { $(SCHEMA_CONTAINER).hide(); + $(FORM_TEMPLATE_CONTAINER).hide(); $(FDM_CONTAINER).show(); - } else if (selectedSchemaType == 'none') { + } else if (selectedSchemaType == FORM_TEMPLATE) { $(FDM_CONTAINER).hide(); $(SCHEMA_CONTAINER).hide(); + $(FORM_TEMPLATE_CONTAINER).show(); + } else if (selectedSchemaType == NONE) { + $(FDM_CONTAINER).hide(); + $(SCHEMA_CONTAINER).hide(); + $(FORM_TEMPLATE_CONTAINER).hide(); } }; @@ -238,7 +278,8 @@ function initialiseDataModel(dialog) { var formModelSelector = dialog.find(FORM_MODEL_SELECTOR)[0], schemaSelector = dialog.find(SCHEMA_DROPDOWN_SELECTOR)[0], - fdmSelector = dialog.find(FDM_DROPDOWN_SELECTOR)[0]; + fdmSelector = dialog.find(FDM_DROPDOWN_SELECTOR)[0], + formTemplateSelector = dialog.find(FORM_TEMPLATE_DROPDOWN_SELECTOR)[0]; if (formModelSelector) { formModelSelector.on("change", function() { selectFormModelOnChanged(dialog); @@ -254,6 +295,11 @@ fdmSelectorOnChanged(dialog); }); }; + if(formTemplateSelector) { + formTemplateSelector.on("change", function() { + formTemplateSelectorOnChanged(dialog); + }); + } selectFormModelOnLoad(dialog); } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/container/v2/container/_cq_dialog/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/container/v2/container/_cq_dialog/.content.xml index 119e49ce73..961f32d22d 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/container/v2/container/_cq_dialog/.content.xml +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/container/v2/container/_cq_dialog/.content.xml @@ -120,6 +120,10 @@ jcr:primaryType="nt:unstructured" text="Form Data Model" value="formdatamodel"/> + + + + + + + + 0; + } catch(e) { + console.error('Error parsing xfaScripts', e, json['fd:xfaScripts']); + } + } + } + return false + } + + window.CQ.FormsCoreComponents.editorhooks.viewXfaScripts = function (editable) { + fetch(Granite.HTTP.externalize(editable.path + ".json")).then(async function (resp) { + const json = await resp.json(); + // Assuming `resp` contains the JSON string with `fd:xfaScripts` + var xfaScripts = JSON.parse(json['fd:xfaScripts']); + var dialogContent = document.createElement('div'); + + // Create a Coral Table + var table = document.createElement('coral-table'); + + // Create the header + var thead = document.createElement('coral-table-head'); + var headerRow = document.createElement('coral-table-row'); + + var eventNameHeader = document.createElement('coral-table-headercell'); + eventNameHeader.textContent = 'Event Name'; + var eventContentHeader = document.createElement('coral-table-headercell'); + eventContentHeader.textContent = 'Event Content'; + var disableHeader = document.createElement('coral-table-headercell'); + disableHeader.textContent = 'Disable'; + + headerRow.appendChild(eventNameHeader); + headerRow.appendChild(eventContentHeader); + headerRow.appendChild(disableHeader); + thead.appendChild(headerRow); + table.appendChild(thead); + + // Populate the table with data from xfaScripts + var tbody = document.createElement('coral-table-body'); + xfaScripts.forEach(function(script) { + var row = document.createElement('coral-table-row'); + + var nameCell = document.createElement('coral-table-cell'); + nameCell.textContent = script.runAt === "server" ? `${script.activity}(server)` : script.activity; + var contentCell = document.createElement('coral-table-cell'); + contentCell.innerHTML = script.value.replaceAll("\n", "
"); + + var checkboxCell = document.createElement('coral-table-cell'); + var checkbox = new Coral.Checkbox(); + checkbox.name = 'disableCheckbox'; + checkbox.on('change', function() { + script.disabled = this.checked; + }); + checkboxCell.appendChild(checkbox); + checkbox.checked = !!script.disabled; + if (script.runAt === "server") { + checkbox.disabled = true; + } + row.appendChild(nameCell); + row.appendChild(contentCell); + row.appendChild(checkboxCell); + + tbody.appendChild(row); + }); + table.appendChild(tbody); + + dialogContent.appendChild(table); + + // Create the dialog + var dialog = new Coral.Dialog().set({ + id: 'xfaScriptsDialog', + header: { + innerHTML: 'XFA Scripts' + }, + content: { + innerHTML: '' + }, + footer: {}, + closable: "on" + }); + + // Add the table to the dialog content + //dialog.content.appendChild(dialogContent); + + var okButton = new Coral.Button(); + okButton.label.textContent = 'OK'; + okButton.variant = Coral.Button.variant.PRIMARY; + okButton.addEventListener('click', function() { + // Prepare the modified xfaScripts for POST request + var modifiedXfaScripts = JSON.stringify({ 'fd:xfaScripts': JSON.stringify(xfaScripts) }); + $.ajax({ + url: editable.path, + type: 'POST', + data: { + "_charset_" : "UTF-8", + ':operation': 'import', + ':contentType': 'json', + ':content': modifiedXfaScripts, + ':replaceProperties': true + }, + success: function(response) { + console.log('Successfully posted the data'); + dialog.remove(); + }, + error: function(xhr, status, error) { + console.error('Error posting the data', error); + dialog.remove(); + } + }); + }); + dialog.footer.appendChild(okButton); + +// Append and show the dialog + document.body.appendChild(dialog); + + // add a listener on dialog show event + dialog.on('coral-overlay:open', function() { + dialog.content.appendChild(dialogContent); + }); + dialog.show(); + + }) + return true; + }; + +})(window, Granite.author, Coral); diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerview.js index 86f65a2ab5..c4df1c1302 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerview.js @@ -99,10 +99,12 @@ this.widgetObject.setDisplayValue(this._model.value); this.widgetObject.setCalendarWidgetValue(this._model.value); this.setInactive(); + this.triggerExit(); }, this.getWidget()); this.widgetObject.addEventListener('focus', (e) => { this.widgetObject.setValue(e.target.value); this.setActive(); + this.triggerEnter(); }, this.getWidget()); this.widgetObject.addEventListener('input', (e) => { if( e.target.value === '') { @@ -117,9 +119,11 @@ this.widget.addEventListener('blur', (e) => { this.setModelValue(e.target.value); this.setInactive(); + this.triggerExit(); }); this.widget.addEventListener('focus', (e) => { this.setActive(); + this.triggerEnter(); }); } } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/dropdown/v1/dropdown/clientlibs/site/js/dropdownview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/dropdown/v1/dropdown/clientlibs/site/js/dropdownview.js index 3deb8ba4a1..fc211ab282 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/dropdown/v1/dropdown/clientlibs/site/js/dropdownview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/dropdown/v1/dropdown/clientlibs/site/js/dropdownview.js @@ -208,9 +208,11 @@ }); this.widget.addEventListener('focus', (e) => { this.setActive(); + this.triggerEnter(); }); this.widget.addEventListener('blur', (e) => { this.setInactive(); + this.triggerExit(); }); } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/emailinput/v1/emailinput/clientlibs/site/js/emailinputview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/emailinput/v1/emailinput/clientlibs/site/js/emailinputview.js index 41662f809c..b8974c5c7c 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/emailinput/v1/emailinput/clientlibs/site/js/emailinputview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/emailinput/v1/emailinput/clientlibs/site/js/emailinputview.js @@ -74,10 +74,12 @@ this.setModelValue(e.target.value); this.setWidgetValueToDisplayValue(); this.setInactive(); + this.triggerExit(); }); this.widget.addEventListener('focus', (e) => { this.setActive(); this.setWidgetValueToModelValue(); + this.triggerEnter(); }); } } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/site/js/numberinputview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/site/js/numberinputview.js index 8d737e0a0c..a81994501f 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/site/js/numberinputview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/site/js/numberinputview.js @@ -100,12 +100,14 @@ this.setModelValue(e.target.value); if(this.element) { this.setInactive(); + this.triggerExit(); } }); } this.getWidget().addEventListener('focus', (e) => { if (this.element) { this.setActive(); + this.triggerEnter(); } }); } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/panelcontainer/v1/panelcontainer/_cq_editConfig.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/panelcontainer/v1/panelcontainer/_cq_editConfig.xml index b9cf9ad1bb..428607e492 100755 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/panelcontainer/v1/panelcontainer/_cq_editConfig.xml +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/panelcontainer/v1/panelcontainer/_cq_editConfig.xml @@ -25,5 +25,11 @@ handler="CQ.FormsCoreComponents.editorhooks.viewQualifiedName" icon="viewSOMExpression" text="View Qualified Name"/> + diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/telephoneinput/v1/telephoneinput/clientlibs/site/js/telephoneinputview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/telephoneinput/v1/telephoneinput/clientlibs/site/js/telephoneinputview.js index 7fe8a2d048..ea43ca183f 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/telephoneinput/v1/telephoneinput/clientlibs/site/js/telephoneinputview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/telephoneinput/v1/telephoneinput/clientlibs/site/js/telephoneinputview.js @@ -74,10 +74,12 @@ this.setModelValue(e.target.value); this.setWidgetValueToDisplayValue(); this.setInactive(); + this.triggerExit(); }); this.widget.addEventListener('focus', (e) => { this.setActive(); this.setWidgetValueToModelValue(); + this.triggerEnter(); }); } } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/textinput/v1/textinput/clientlibs/site/js/textinputview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/textinput/v1/textinput/clientlibs/site/js/textinputview.js index e2119a07df..2c075f12c1 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/textinput/v1/textinput/clientlibs/site/js/textinputview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/textinput/v1/textinput/clientlibs/site/js/textinputview.js @@ -74,10 +74,12 @@ this.setModelValue(e.target.value); this.setWidgetValueToDisplayValue(); this.setInactive(); + this.triggerExit(); }); this.widget.addEventListener('focus', (e) => { this.setActive(); this.setWidgetValueToModelValue(); + this.triggerEnter(); }); } } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/page/v1/page/customfooterlibs.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/page/v1/page/customfooterlibs.html index 268a57ac5c..c1152c89c8 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/page/v1/page/customfooterlibs.html +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/page/v1/page/customfooterlibs.html @@ -19,6 +19,7 @@ + diff --git a/ui.frontend/package.json b/ui.frontend/package.json index 3ed09dfea5..87f262aacc 100644 --- a/ui.frontend/package.json +++ b/ui.frontend/package.json @@ -23,7 +23,7 @@ "webpack-merge": "^5.8.0" }, "dependencies": { - "@aemforms/af-core": "^0.22.104", + "@aemforms/af-core-xfa": "^0.1.2", "@aemforms/af-formatters": "^0.22.104", "@aemforms/af-custom-functions": "1.0.10" } diff --git a/ui.frontend/src/handleXfa.js b/ui.frontend/src/handleXfa.js new file mode 100644 index 0000000000..f1a6468b58 --- /dev/null +++ b/ui.frontend/src/handleXfa.js @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright 2024 Adobe + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +export function loadXfa(formdom, renderContext) { + if (window.xfalib) { + formBridge.registerConfig("disabledServerScripts", ["initialize", "$formready", "$layoutready"]) + const xfaJson = JSON.parse(JSON.parse(JSON.stringify(formdom))); + xfalib.runtime.renderContext = JSON.parse(JSON.parse(JSON.stringify(renderContext))); + xfalib.script.XfaModelRegistry.prototype.createModel(xfaJson); + //initialize Acrobat specific scripts + new xfalib.acrobat.Acrobat(); + return function (model) { + model._syncXfaProps(); + xfalib.runtime.xfa.form._initialize(true); + $(window).trigger("XfaInitialized"); + } + } +} diff --git a/ui.frontend/src/utils.js b/ui.frontend/src/utils.js index b201ae4eee..8333740e20 100644 --- a/ui.frontend/src/utils.js +++ b/ui.frontend/src/utils.js @@ -17,7 +17,8 @@ import {Constants} from "./constants.js"; import HTTPAPILayer from "./HTTPAPILayer.js"; import {customFunctions} from "./customFunctions.js"; -import {FunctionRuntime} from '@aemforms/af-core' +import {FunctionRuntime} from '@aemforms/af-core'; +import {loadXfa} from "./handleXfa"; /** * @module FormView @@ -307,7 +308,18 @@ class Utils { if (_path == null) { console.error(`data-${Constants.NS}-${formContainerClass}-path attribute is not present in the HTML element. Form cannot be initialized` ) } else { - const _formJson = await HTTPAPILayer.getFormDefinition(_path, _pageLang); + const loader = elements[i].parentElement?.querySelector('[data-cmp-adaptiveform-container-loader]'); + let _formJson, callback; + if (loader) { + const id = loader.getAttribute('data-cmp-adaptiveform-container-loader'); + const response = await fetch(`/adobe/forms/af/${id}`) + _formJson = (await response.json()).afModelDefinition; + _formJson.id = id; + //window.formJson = _formJson + callback = loadXfa(_formJson.formdom, _formJson.xfaRenderContext); + } else { + _formJson = await HTTPAPILayer.getFormDefinition(_path, _pageLang); + } console.debug("fetched model json", _formJson); await this.registerCustomFunctions(_formJson.id); await this.registerCustomFunctionsByUrl(customFunctionUrl); @@ -318,6 +330,14 @@ class Utils { // only execute when fd:formDataEnabled is present and set to true _prefillData = await HTTPAPILayer.getPrefillData(_formJson.id, params) || {}; _prefillData = Utils.stripIfWrapped(_prefillData); + if(window.formBridge){ + window.formBridge.restoreFormState({ + formState : {xfaDom: _prefillData.data.xfaDom, xfaRenderContext: _prefillData.data.xfaRenderContext}, + context : this, + error : function() {}, + success : function () {} + }); + } } const formContainer = await createFormContainer({ _formJson, @@ -325,6 +345,9 @@ class Utils { _path, _element: elements[i] }); + if (typeof callback === 'function') { + callback(formContainer.getModel()); + } Utils.initializeAllFields(formContainer); const event = new CustomEvent(Constants.FORM_CONTAINER_INITIALISED, { "detail": formContainer }); document.dispatchEvent(event); diff --git a/ui.frontend/src/view/FormCheckBox.js b/ui.frontend/src/view/FormCheckBox.js index 6c47438cd4..9eee73e711 100644 --- a/ui.frontend/src/view/FormCheckBox.js +++ b/ui.frontend/src/view/FormCheckBox.js @@ -46,7 +46,14 @@ class FormCheckBox extends FormFieldBase { const value = this.widget.checked ? this._onValue : this._offValue; this._model.dispatch(new FormView.Actions.UIChange({'value': value})); }) - + this.widget.addEventListener('focus', (e) => { + this.setActive(); + this.triggerEnter(); + }); + this.widget.addEventListener('blur', (e) => { + this.setInactive(); + this.triggerExit(); + }); } } diff --git a/ui.frontend/src/view/FormField.js b/ui.frontend/src/view/FormField.js index 271d5451d9..b0a80abae9 100644 --- a/ui.frontend/src/view/FormField.js +++ b/ui.frontend/src/view/FormField.js @@ -101,6 +101,14 @@ class FormField { return this.element.getAttribute(Constants.DATA_ATTRIBUTE_ACTIVE) === 'true'; } + triggerExit() { + this._model.dispatch(new FormView.Actions.CustomEvent('xfaexit')); + } + + triggerEnter() { + this._model.dispatch(new FormView.Actions.CustomEvent('xfaenter')); + } + /** * Returns the form container path of the form field. * @returns {string} The form container path.