PageSourceSearch

https://www.bementor.edu.sa/assets/website-designs/BeMentor/js/phone-input.js

js bementor.edu.sa collected 2026-09-28 18:04:29 UTC 4,528 bytes, 126 lines download raw bytes

1/**
2 * Website Phone Input - Vanilla JS Interaction
3 * file: public/assets/js/website/phone-input.js
4 */
5
6(function() {
7    'use strict';
8
9    window.initWebsitePhoneInputs = function() {
10        const components = document.querySelectorAll('.website-phone-input-root');
11
12        components.forEach(root => {
13            if(root.dataset.init === 'true') return;
14            root.dataset.init = 'true';
15
16            const trigger = root.querySelector('.website-phone-country-trigger');
17            const dropdown = root.querySelector('.website-phone-dropdown');
18            const searchInput = root.querySelector('.phone-search-input');
19            const list = root.querySelector('.phone-list');
20            const hiddenIso = root.querySelector('.phone-iso-hidden');
21            
22            // Visual Elements
23            const flagImg = trigger.querySelector('.phone-flag-icon');
24            const dialText = trigger.querySelector('.phone-dial-text');
25
26            // --- Methods ---
27
28            const closeDropdown = () => {
29                trigger.setAttribute('aria-expanded', 'false');
30            };
31
32            const openDropdown = () => {
33                // Close others
34                document.querySelectorAll('.website-phone-country-trigger[aria-expanded="true"]').forEach(t => {
35                    if(t !== trigger) t.setAttribute('aria-expanded', 'false');
36                });
37                
38                trigger.setAttribute('aria-expanded', 'true');
39                dropdown.scrollTop = 0;
40                searchInput.value = '';
41                filterList(''); // reset filter
42                setTimeout(() => searchInput.focus(), 50);
43
44                // Scroll to selected
45                const selected = list.querySelector('.phone-item.selected');
46                if(selected) {
47                    selected.scrollIntoView({ block: 'center' });
48                }
49            };
50
51            const toggleDropdown = (e) => {
52                e.preventDefault();
53                e.stopPropagation();
54                if(trigger.getAttribute('aria-expanded') === 'true') {
55                    closeDropdown();
56                } else {
57                    openDropdown();
58                }
59            };
60
61            const selectItem = (item) => {
62                const iso = item.dataset.iso;
63                const dial = item.dataset.dial;
64                
65                // Update Hidden Input
66                hiddenIso.value = iso;
67                
68                // Update UI
69                dialText.textContent = dial;
70                flagImg.src = `https://flagcdn.com/w20/${iso.toLowerCase()}.png`;
71
72                // Update Selection State
73                list.querySelectorAll('.phone-item').forEach(li => li.classList.remove('selected'));
74                item.classList.add('selected');
75
76                closeDropdown();
77            };
78
79            const filterList = (query) => {
80                const q = query.toLowerCase();
81                const items = list.querySelectorAll('.phone-item');
82                items.forEach(item => {
83                    const text = item.dataset.name.toLowerCase();
84                    const dial = item.dataset.dial.replace('+', '');
85                    if(text.includes(q) || dial.includes(q)) {
86                        item.style.display = 'flex';
87                    } else {
88                        item.style.display = 'none';
89                    }
90                });
91            };
92
93            // --- Event Listeners ---
94            
95            trigger.addEventListener('click', toggleDropdown);
96
97            searchInput.addEventListener('input', (e) => filterList(e.target.value));
98            searchInput.addEventListener('click', (e) => e.stopPropagation());
99
100            list.querySelectorAll('.phone-item').forEach(item => {
101                item.addEventListener('click', (e) => {
102                    e.stopPropagation();
103                    selectItem(item);
104                });
105            });
106
107            // Close on outside click
108            document.addEventListener('click', (e) => {
109                if(!root.contains(e.target)) {
110                    closeDropdown();
111                }
112            });
113
114            // Keyboard Navigation (Basic)
115            root.addEventListener('keydown', (e) => {
116                if(e.key === 'Escape') closeDropdown();
117            });
118        });
119    };
120
121    // Auto Init on Load
122    document.addEventListener('DOMContentLoaded', () => {
123        window.initWebsitePhoneInputs();
124    });
125
126})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.