/** * AKSRT universal icon picker — shared admin modal for FA5, the built-in * SVG sprite and inline custom SVG values ("fa fas fa-x" / "zibsvg-key" / * "customsvg-"). * * Any admin screen: call aksrt_icon_picker_assets() (PHP) and render fields * via aksrt_icon_picker_field(); interaction is fully delegated, so lazy * loaded widget forms and repeater rows work without re-init. */ (function ($) { 'use strict'; const config = window.aksrtIconPicker || {}; const i18n = config.i18n || {}; const state = { loaded: false, loading: false, activeTab: 'fas', tabs: [], grids: {}, sessionCustom: [], $target: null, }; function modal() { return $('#aksrt-modal-icon'); } function setBusy(busy) { modal().find('.aksrt-icon-modal__loading').each((_i, el) => { el.hidden = !busy; }); } /* Custom SVG cleanup — strip authoring leftovers, keep pure vector markup. */ function cleanSvg(raw) { const text = String(raw || '').trim(); if (!text) return ''; let doc; try { doc = new window.DOMParser().parseFromString(text, 'image/svg+xml'); } catch (e) { return ''; } if (doc.querySelector('parsererror')) return ''; const svg = doc.querySelector('svg'); if (!svg || svg.querySelector('script, foreignObject, animate')) return ''; ['class', 'id', 'style', 't', 'version', 'p-id'].forEach((attr) => svg.removeAttribute(attr)); Array.prototype.slice.call(svg.attributes).forEach((attr) => { if (attr.name.indexOf('data-') === 0) svg.removeAttribute(attr.name); }); const keep = new window.XMLSerializer().serializeToString(svg); return /"']/g, (ch) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', }[ch])); } function previewMarkup(value) { value = String(value || '').trim(); if (!value) return ''; if (value.indexOf('customsvg-') === 0) return cleanSvg(value.slice(10)); if (value.indexOf('zibsvg-') === 0) { const key = value.slice(7).replace(/[^a-zA-Z0-9_-]/g, ''); return key ? `` : ''; } const el = document.createElement('i'); el.className = !/\bfa\b/.test(value) && value.indexOf('fa-') !== -1 ? `fa ${value}` : value; el.setAttribute('aria-hidden', 'true'); return el.outerHTML; } function seedSessionCustom() { $('input.aksrt-icon-picker__value').each(function () { const value = String(this.value || '').trim(); if (value.indexOf('customsvg-') !== 0) return; const svg = value.slice(10); if (svg && state.sessionCustom.indexOf(svg) === -1) state.sessionCustom.push(svg); }); } function itemButton(value, name, innerHtml) { return $(''); (group.icons || []).forEach((name) => { if (group.type === 'fa') { const value = `fa ${group.id} fa-${name}`; $grid.append(itemButton(value, name, ``)); } else if (group.type === 'svg') { const value = `zibsvg-${name}`; const key = escapeText(name).replace(/[^a-zA-Z0-9_-]/g, ''); $grid.append(itemButton(value, name, ``)); } }); $wrap.append($grid); state.grids[group.id] = $grid; const $tab = $('