1/* 2 Searchable Select (Vanilla JS) 3 - Seçim kutusunun üstüne bir arama input'u ekler 4 - Yazdıkça seçenekleri filtreleyip SELECT içeriÄini yeniden oluÅturur 5 - loadQuarters gibi dinamik doldurmalarda otomatik senkron kalması için MutationObserver kullanır 6 - Global API: window.makeSelectSearchable(selectOrSelector, { placeholder?: string }) 7*/ 8(function(){ 9 function toArray(nodeList){ return Array.prototype.slice.call(nodeList || []); } 10 11 function captureOptions(select){ 12 const opts = []; 13 toArray(select.options).forEach(function(o, idx){ 14 // İlk seçenek (placeholder) hariç tut, ama metnini ve deÄerini koru 15 if (idx === 0) return; 16 opts.push({ 17 value: o.value, 18 text: o.textContent || '', 19 disabled: !!o.disabled, 20 dataset: Object.assign({}, o.dataset), 21 }); 22 }); 23 return opts; 24 } 25 26 function rebuildSelect(select, originalOptions, filterText){ 27 const placeholderOption = select.options[0] ? select.options[0].outerHTML : '<option value="">Seçiniz</option>'; 28 const q = (filterText || '').trim().toLowerCase(); 29 var html = placeholderOption; 30 originalOptions.forEach(function(opt){ 31 if (!q || (opt.text || '').toLowerCase().indexOf(q) !== -1) { 32 var attrs = ''; 33 if (opt.disabled) attrs += ' disabled'; 34 // dataset attribute'ları geri yaz 35 if (opt.dataset) { 36 Object.keys(opt.dataset).forEach(function(k){ 37 attrs += ' data-' + k.replace(/[A-Z]/g, function(m){ return '-' + m.toLowerCase(); }) + '="' + String(opt.dataset[k]).replace(/"/g, '"') + '"'; 38 }); 39 } 40 html += '<option value="' + String(opt.value).replace(/"/g, '"') + '"' + attrs + '>' + (opt.text || '') + '</option>'; 41 } 42 }); 43 const prevValue = select.value; 44 select.innerHTML = html; 45 // Filtre sonrası eski deÄer hâlâ görünürse koru, deÄilse placeholder'a dön 46 const exists = toArray(select.options).some(function(o){ return o.value === prevValue; }); 47 select.value = exists ? prevValue : ''; 48 // change event tetikleme yok; kullanıcı seçerse tetiklenecek 49 } 50 51 function ensureContainer(select){ 52 if (select.__searchableContainer) return select.__searchableContainer; 53 var wrapper = document.createElement('div'); 54 wrapper.className = 'pp-searchable-select'; 55 wrapper.style.display = 'flex'; 56 wrapper.style.flexDirection = 'column'; 57 wrapper.style.gap = '6px'; 58 // SELECT'in önüne yerleÅtir 59 select.parentNode.insertBefore(wrapper, select); 60 wrapper.appendChild(select); 61 select.__searchableContainer = wrapper; 62 return wrapper; 63 } 64 65 function createSearchBox(select, placeholder){ 66 if (select.__searchInput) return select.__searchInput; 67 var input = document.createElement('input'); 68 input.type = 'text'; 69 input.className = 'pp-select-search-input'; 70 input.placeholder = placeholder || 'Ara...'; 71 input.autocomplete = 'off'; 72 input.style.padding = '8px 10px'; 73 input.style.border = '1px solid #d1d5db'; 74 input.style.borderRadius = '6px'; 75 input.style.fontSize = '14px'; 76 input.style.outline = 'none'; 77 input.addEventListener('focus', function(){ input.style.borderColor = '#3498db'; }); 78 input.addEventListener('blur', function(){ input.style.borderColor = '#d1d5db'; }); 79 select.__searchInput = input; 80 return input; 81 } 82 83 function makeSelectSearchable(selectOrSelector, opts){ 84 var select = typeof selectOrSelector === 'string' ? document.querySelector(selectOrSelector) : selectOrSelector; 85 if (!select || select.tagName !== 'SELECT') return; 86 87 var placeholder = (opts && opts.placeholder) || 'Mahalle ara...'; 88 89 var container = ensureContainer(select); 90 var searchBox = createSearchBox(select, placeholder); 91 // Input'u SELECT'in üstüne koy 92 if (searchBox.parentNode !== container) container.insertBefore(searchBox, select); 93 94 // Orijinal seçenekleri tut 95 var originalOptions = captureOptions(select); 96 97 // Dinamik doldurmalarda (loadQuarters) orijinali tazelemek için gözlemci 98 if (!select.__searchMutationObserver) { 99 var mo = new MutationObserver(function(mutations){ 100 var needRefresh = mutations.some(function(m){ return m.type === 'childList'; }); 101 if (needRefresh) { 102 originalOptions = captureOptions(select); 103 // Aktif arama metni varsa, yeniden uygula 104 rebuildSelect(select, originalOptions, searchBox.value || ''); 105 } 106 }); 107 mo.observe(select, { childList: true });
108 select.__searchMutationObserver = mo; 109 } 110 111 // Arama davranıÅı 112 var debounceTimer = null; 113 searchBox.addEventListener('input', function(){ 114 if (debounceTimer) clearTimeout(debounceTimer); 115 debounceTimer = setTimeout(function(){ 116 rebuildSelect(select, originalOptions, searchBox.value || ''); 117 }, 60); 118 }); 119 120 // İlk kurulumda mevcut metin boÅsa tümünü göster 121 rebuildSelect(select, originalOptions, ''); 122 } 123 124 // Global export 125 window.makeSelectSearchable = makeSelectSearchable; 126})(); 127 128
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.