// Shared "Border" card (models.Widget.border_style/border_thickness/ // border_color_index, _widget_border_fields.html) -- present on every // widget type's dialog regardless of widget_type, so this is one shared // init function each widget_dialog_.js's initDialog() calls, // rather than 8 copies of the same slider/swatch/save wiring. Not a // page-load script by itself -- frame_layout.js loads it unconditionally // (like every other widget_dialog_*.js) since which dialog is open, and // therefore which initDialog() calls initBorderFields(), varies. function initBorderFields() { const styleSelect = document.getElementById('border_style'); if (!styleSelect) return; // dialog fragment didn't render the border card -- shouldn't happen const thickness = document.getElementById('border_thickness'); const thicknessValue = document.getElementById('border_thickness_value'); thickness.addEventListener('input', (e) => { thicknessValue.textContent = `${e.target.value}px`; }); const colorIndexInput = document.getElementById('border_color_index'); document.querySelectorAll('#border-color-picker .color-swatch').forEach((btn) => { btn.addEventListener('click', () => { document.querySelectorAll('#border-color-picker .color-swatch').forEach((el) => el.classList.remove('selected')); btn.classList.add('selected'); colorIndexInput.value = btn.dataset.index; }); }); document.getElementById('border-config-form').addEventListener('submit', async (e) => { e.preventDefault(); const body = JSON.stringify({ border_style: styleSelect.value, border_thickness: Number(thickness.value), border_color_index: Number(colorIndexInput.value), }); try { const resp = await fetch(`${window.FRAME_API}/border`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body, }); if (!resp.ok) throw new Error(await apiError(resp)); showStatus(true, 'Border saved.'); } catch (err) { showStatus(false, err.message); } }); }