Spaces:
Running
Running
| handledSelectElementsConvergence = new WeakSet(); | |
| overwriteDefaultSelectConvergence = (input = null) => { | |
| let activeSelectElement = null; | |
| // Handle iframe input element | |
| let rootElement = input ? input : document.documentElement; | |
| function createCustomSelectElement() { | |
| // Create the custom select container | |
| const customSelect = document.createElement('div'); | |
| customSelect.id = 'convergence-custom-select-element-X2EmudtLRN'; | |
| customSelect.style.position = 'absolute' | |
| customSelect.style.zIndex = 2147483647 - 1; | |
| customSelect.style.display = 'none'; | |
| document.body.appendChild(customSelect); | |
| // Create the select options list | |
| const optionsList = document.createElement('div'); | |
| optionsList.style.border = '1px solid #ccc'; | |
| optionsList.style.backgroundColor = '#fff'; | |
| optionsList.style.color = 'black'; | |
| customSelect.appendChild(optionsList); | |
| return customSelect; | |
| } | |
| function showCustomSelect(select) { | |
| activeSelectElement = select; | |
| // Clear previous options | |
| const customSelect = rootElement.querySelector('#convergence-custom-select-element-X2EmudtLRN'); | |
| let optionsList = customSelect.firstChild; | |
| optionsList.innerHTML = ''; | |
| // Populate with new options | |
| Array.from(select.options).forEach(option => { | |
| const customOption = document.createElement('div'); | |
| customOption.className = 'custom-option'; | |
| customOption.style.padding = '8px'; | |
| customOption.style.cursor = 'pointer'; | |
| customOption.textContent = option.text; | |
| customOption.dataset.value = option.value; | |
| optionsList.appendChild(customOption); | |
| customOption.addEventListener('mouseenter', function () { | |
| customOption.style.backgroundColor = '#f0f0f0'; | |
| }); | |
| customOption.addEventListener('mouseleave', function () { | |
| customOption.style.backgroundColor = ''; | |
| }); | |
| customOption.addEventListener('mousedown', (e) => { | |
| e.stopPropagation(); | |
| select.value = customOption.dataset.value; | |
| customSelect.style.display = 'none'; | |
| activeSelectElement = null; | |
| // ensure we trigger all potential event listeners | |
| select.dispatchEvent(new InputEvent('focus', { bubbles: true, cancelable: true })); | |
| select.dispatchEvent(new InputEvent('input', { bubbles: true, cancelable: true })); | |
| select.dispatchEvent(new InputEvent('change', { bubbles: true, cancelable: true })); | |
| select.dispatchEvent(new InputEvent('blur', { bubbles: true, cancelable: true })); | |
| }); | |
| }); | |
| // Position and show the custom select | |
| const selectRect = select.getBoundingClientRect(); | |
| customSelect.style.top = `${selectRect.bottom + window.scrollY}px`; | |
| customSelect.style.left = `${selectRect.left + window.scrollX}px`; | |
| customSelect.style.width = `${selectRect.width}px`; | |
| customSelect.style.display = 'block'; | |
| select.focus(); | |
| select.addEventListener('blur', function (e) { | |
| customSelect.style.display = 'none'; | |
| activeSelectElement = null; | |
| }); | |
| select.addEventListener('change', function (e) { | |
| customSelect.style.display = 'none'; | |
| activeSelectElement = null; | |
| }); | |
| } | |
| // Ensure we have a custom select element | |
| let customSelect = rootElement.querySelector(`#convergence-custom-select-element-X2EmudtLRN`); | |
| if (!customSelect) { | |
| customSelect = createCustomSelectElement(); | |
| } | |
| // Find selects in shadow DOMs | |
| function findSelectInShadowRoot(element) { | |
| if (element.shadowRoot) { | |
| return element.shadowRoot.querySelectorAll('select'); | |
| } | |
| return []; | |
| } | |
| let shadowSelects = []; | |
| rootElement.querySelectorAll('*').forEach(el => { | |
| shadowSelects.push(...findSelectInShadowRoot(el)); | |
| }); | |
| // Find selects in the regular (light) DOM | |
| const lightSelects = Array.from(rootElement.querySelectorAll('select')); | |
| // Add event listeners to all select elements | |
| const allSelects = [...lightSelects, ...shadowSelects]; | |
| allSelects.forEach(select => { | |
| if (select.hasAttribute('multiple')) { | |
| // skip special multiple elements as our POI code already handles them | |
| return; | |
| } | |
| if (!handledSelectElementsConvergence.has(select)) { | |
| select.addEventListener('mousedown', (e) => { | |
| // only use custom select when the default behaviour is being used | |
| if (!e.defaultPrevented) { | |
| showCustomSelect(select); | |
| e.preventDefault(); | |
| } | |
| }); | |
| handledSelectElementsConvergence.add(select); | |
| } | |
| }); | |
| } | |