// public/js/icon-picker.js (function () { let ALL_ICONS = []; let _targetInput = null; // ── Init: inject modal + fetch icons ────────────────────────────────────── function init() { _injectModal(); _fetchIcons(); _bindSearch(); } function _injectModal() { if (document.getElementById('iconPickerModal')) return; // tránh inject 2 lần document.body.insertAdjacentHTML('beforeend', ` `); } async function _fetchIcons() { try { const res = await fetch('/js/fa-icons.json'); if (!res.ok) throw new Error('HTTP ' + res.status); const json = await res.json(); ALL_ICONS = Object.entries(json).flatMap(([name, meta]) => (meta.styles || []) .filter(s => ['solid', 'regular', 'brands'].includes(s)) .map(style => ({ value: `fa-${style} fa-${name}`, label: meta.label || name, })) ); console.log('[IconPicker] loaded:', ALL_ICONS.length, 'icons'); } catch (err) { console.error('[IconPicker] fetch failed:', err); } } function _bindSearch() { document.addEventListener('input', function (e) { if (e.target.id !== 'iconSearchInput') return; const q = e.target.value.toLowerCase().trim(); const filtered = q ? ALL_ICONS.filter(i => i.label.toLowerCase().includes(q) || i.value.includes(q)) : ALL_ICONS; console.log('[IconPicker] search:', q, '→', filtered.length); _renderGrid(filtered); }); } // ── Public: open picker ─────────────────────────────────────────────────── function open(inputEl) { _targetInput = inputEl; document.getElementById('iconSearchInput').value = ''; if (!ALL_ICONS.length) { _setStatus('Loading icons...'); _renderGrid([]); } else { _setStatus(''); _renderGrid(ALL_ICONS); } new bootstrap.Modal(document.getElementById('iconPickerModal')).show(); } function _renderGrid(icons) { const grid = document.getElementById('iconGrid'); if (!icons.length) { grid.innerHTML = '

No icons found.

'; return; } _setStatus(`Showing ${Math.min(icons.length, 200)} / ${icons.length}`); grid.innerHTML = icons.slice(0, 200).map(icon => ` `).join(''); } function pick(value) { if (!_targetInput) return; _targetInput.value = value; // Update preview nếu có const previewCell = _targetInput.closest('.input-group')?.querySelector('.icon-preview-cell'); if (previewCell) previewCell.innerHTML = ``; bootstrap.Modal.getInstance(document.getElementById('iconPickerModal')).hide(); console.log('[IconPicker] picked:', value); } function _setStatus(msg) { const el = document.getElementById('iconPickerStatus'); if (el) el.textContent = msg; } function _esc(val) { return String(val || '').replace(/"/g, '"').replace(//g, '>'); } // ── Expose global ───────────────────────────────────────────────────────── window.IconPicker = { init, open, pick }; window.IconPicker.pick = pick; window.IconPickerPick = pick; })();