File size: 4,995 Bytes
f0f6e5c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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);
        }
    });
}