(function () { let builtInMicrosoftFieldShortcuts = document.querySelectorAll('.cell .control > [id]:not([id$="entityname"])'); builtInMicrosoftFieldShortcuts.forEach(initField); function initField(field) { //-- Shortcuts field.cell = field.closest('.cell'); field.info = field.cell.querySelector('.info, .table-info'); field.info.classList.add('info'); field.label = field.cell.querySelector('.info > label, .table-info > label'); field.validators = field.cell.querySelector('.info > .validators, .table-info > .validators'); field.description = field.cell.querySelector('.description'); //-- Setup (pre-init field validators div if missing) if (!field.validators) { let validatorsDiv = document.createElement('div'); validatorsDiv.classList.add('validators'); field.info.appendChild(validatorsDiv); field.validators = validatorsDiv; } // field.table (requires loaded event, moved to subgrids_preload, keep here for reference) if (field.label == null) { try { field.label = document.createElement('label'); field.label.setAttribute('for', field.id); field.label.classList.add('dummy-label'); field.info.insertAdjacentElement('afterbegin', field.label); const description = field.cell.querySelector('.description, description'); if (description?.innerText && field?.cell?.classList?.contains('textarea')) { field.label.classList.add('remove-bold'); field.label.style = "font-weight: 400!important"; const index = description.innerHTML.indexOf('<'); if (index === -1) { field.label.innerText = description.innerText; description.remove(); } else { field.label.innerText = description.innerText.substring(0, index); description.innerHTML = description.innerHTML.substring(index, description.innerHTML.length); } } } catch (error) { } } // Standardized label ID let targetLabelString = field?.label?.getAttribute('for'); if (field.label && targetLabelString) { field.label.id = (targetLabelString) ? targetLabelString + '_label' : ''; } const reqMessage = { en: { required: '(required)', optional: '' }, fr: { required: '(obligatoire)', optional: '' } }; try { // Create or reuse a span for accessibility text inside the label let statusSpan = field.label.querySelector('.required-status'); if (!statusSpan) { statusSpan = document.createElement('span'); statusSpan.className = 'required-status'; statusSpan.style.marginLeft = '0.5em'; // spacing const dict = reqMessage[LANG] || reqMessage.en; statusSpan.textContent = dict.required; field.label.appendChild(statusSpan); } Object.defineProperty(field.label, 'required', { get() { return this.closest('.info,.table-info')?.classList.contains('required') || false; }, set(isRequired) { this.closest('.info,.table-info')?.classList.toggle('required', isRequired); this?.control?.setAttribute('aria-required', isRequired); }, }); } catch (error) { console.error(error); } if (field.description) { field.description.id = field.id + "_description"; //field.setAttribute("aria-describedby", field.description.id); field.setAttribute("aria-labelledby", field.label.id + ' ' + field.description.id ); } function tieValueToAttribute(el) { const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), 'value'); const originalSetter = descriptor.set; const originalGetter = descriptor.get; Object.defineProperty(el, 'value', { configurable: true, get: function() { return originalGetter.call(this); }, set: function (newValue) { const currentValue = originalGetter.call(this); // dynamically get current value if (newValue !== currentValue) { originalSetter.call(this, newValue); this.setAttribute('value', newValue); // keep attribute in sync this.dispatchEvent(new Event('change')); } } }); } if (field.tagName === 'INPUT' && field.id !== 'gac_stepscompleted_portal') { tieValueToAttribute(field); } field.hide = () =>{ field.cell.classList.add('hide'); }; field.show = () =>{ field.cell.classList.remove('hide'); field.classList.remove('parent-cell-hide'); }; // Usefull for field specfic CSS outside-in targetting. field.cell.setAttribute("data-inner-field-id", field.id); if (DEVMODE) { const span = document.createElement('span'); span.innerText = `${field.id}`; span.classList.add('logical-name'); field.label.insertAdjacentElement('afterend',span); } } /* -- Modals - -- */ let dataPagePath = document.querySelector("html").getAttribute("data-page-path"); if (dataPagePath?.includes("/_portal/modal-form-template-path/")) { document.body.setAttribute("data-modal", "true"); //flag for detecting when operating inside a modal } /* -- Font Awesome Bridge --*/ const FA_CLASS_PAIRS = [ ["fa-pencil-square-o", "fa-pen-to-square"], ["fa-camera", "fa-camera-retro"], ["fa-user", "fa-user-circle"], ]; function replaceClasses(classPairs, root = document, ) { classPairs.forEach(([oldClass, newClass]) => { root.querySelectorAll(`.${oldClass}`).forEach(el => { el.classList.remove(oldClass); el.classList.add(newClass); }); }); } replaceClasses(FA_CLASS_PAIRS); window.initField = initField; })();