From 48179ee4b307f0bc6e09fc2b2c9381485b25928a Mon Sep 17 00:00:00 2001 From: ashisgreat22 Date: Sun, 22 Mar 2026 02:47:26 +0100 Subject: [PATCH] fix(settings): rewrite renderPanel to use panel body innerHTML, not document.body - Replace document.body.innerHTML with panel.querySelector('.settings-popover-body').innerHTML - Use theme buttons (.theme-btn) with icons instead of radio buttons - Use .engine-toggle class for engine checkboxes in 2-column grid - Include settings-notice paragraph for engine changes - Use dropdowns for safe search and format with proper ids Co-Authored-By: Claude Opus 4.6 --- internal/views/static/js/settings.js | 201 ++++++++++++++------------- 1 file changed, 101 insertions(+), 100 deletions(-) diff --git a/internal/views/static/js/settings.js b/internal/views/static/js/settings.js index c710c89..762fbcb 100644 --- a/internal/views/static/js/settings.js +++ b/internal/views/static/js/settings.js @@ -80,121 +80,122 @@ function openPanel() { } function escapeHtml(str) { - return str - .replace(/&/g, '&') - .replace(//g, '>'); + return String(str).replace(/&/g, '&').replace(//g, '>'); } function renderPanel(prefs) { - var themeIcons = { light: '☀️', dark: '🌙', system: '⌨' }; - var safeOptions = ['moderate', 'strict', 'off']; - var formatOptions = ['html', 'json', 'csv', 'rss']; + var panel = document.getElementById('settings-popover'); + if (!panel) return; + var body = panel.querySelector('.settings-popover-body'); + if (!body) return; - var html = '
'; - html += '

Settings

'; + var themeBtns = ''; + ['light', 'dark', 'system'].forEach(function(t) { + var icons = { light: '\u2600', dark: '\u263D', system: '\u2318' }; + var labels = { light: 'Light', dark: 'Dark', system: 'System' }; + var active = prefs.theme === t ? ' active' : ''; + themeBtns += ''; + }); + + var engineToggles = ''; + ALL_ENGINES.forEach(function(name) { + var checked = prefs.engines.indexOf(name) !== -1 ? ' checked' : ''; + engineToggles += ''; + }); + + var ssOptions = [ + { val: 'moderate', label: 'Moderate' }, + { val: 'strict', label: 'Strict' }, + { val: 'off', label: 'Off' } + ]; + var fmtOptions = [ + { val: 'html', label: 'HTML' }, + { val: 'json', label: 'JSON' }, + { val: 'csv', label: 'CSV' }, + { val: 'rss', label: 'RSS' } + ]; + var ssOptionsHtml = ''; + var fmtOptionsHtml = ''; + ssOptions.forEach(function(o) { + var sel = prefs.safeSearch === o.val ? ' selected' : ''; + ssOptionsHtml += ''; + }); + fmtOptions.forEach(function(o) { + var sel = prefs.format === o.val ? ' selected' : ''; + fmtOptionsHtml += ''; + }); + + body.innerHTML = + '
' + + '
Appearance
' + + '
' + themeBtns + '
' + + '
' + + '
' + + '
Engines
' + + '
' + engineToggles + '
' + + '

Engine changes apply to your next search.

' + + '
' + + '
' + + '
Search Defaults
' + + '
' + + '' + + '' + + '
' + + '
' + + '' + + '' + + '
' + + '
'; // Theme buttons - html += '
Theme'; - html += '
'; - ['light', 'dark', 'system'].forEach(function(t) { - var checked = prefs.theme === t ? ' checked' : ''; - var icon = escapeHtml(themeIcons[t]); - html += ''; - }); - html += '
'; + var themeBtnEls = panel.querySelectorAll('.theme-btn'); + for (var i = 0; i < themeBtnEls.length; i++) { + themeBtnEls[i].addEventListener('click', (function(btn) { + return function() { + prefs.theme = btn.getAttribute('data-theme'); + savePrefs(prefs); + applyTheme(prefs.theme); + syncEngineInput(prefs); + renderPanel(prefs); + }; + })(themeBtnEls[i])); + } // Engine checkboxes - html += '
Engines'; - html += '
'; - ALL_ENGINES.forEach(function(engine) { - var checked = prefs.engines.indexOf(engine) !== -1 ? ' checked' : ''; - html += ''; - }); - html += '
'; + var checkboxes = panel.querySelectorAll('.engine-toggle input[type="checkbox"]'); + for (var j = 0; j < checkboxes.length; j++) { + checkboxes[j].addEventListener('change', (function(cb) { + return function() { + var checked = Array.prototype.slice.call(panel.querySelectorAll('.engine-toggle input[type="checkbox"]:checked')).map(function(el) { return el.value; }); + if (checked.length === 0) { renderPanel(prefs); return; } + prefs.engines = checked; + savePrefs(prefs); + syncEngineInput(prefs); + }; + })(checkboxes[j])); + } - html += '

Engine changes apply to your next search.

'; - - // Safe search dropdown - html += ''; - html += ''; - - // Format dropdown - html += ''; - html += ''; - - html += ''; - html += '
'; - - document.body.innerHTML = html; - - // Attach listeners to theme buttons - var themeButtons = document.querySelectorAll('input[name="theme"]'); - themeButtons.forEach(function(btn) { - btn.addEventListener('click', function() { - var newPrefs = loadPrefs(); - newPrefs.theme = btn.value; - savePrefs(newPrefs); - applyTheme(newPrefs.theme); - }); - }); - - // Attach listeners to engine checkboxes - var engineCheckboxes = document.querySelectorAll('input[name="engine"]'); - engineCheckboxes.forEach(function(cb) { - cb.addEventListener('change', function() { - var newPrefs = loadPrefs(); - if (cb.checked) { - if (newPrefs.engines.indexOf(cb.value) === -1) { - newPrefs.engines.push(cb.value); - } - } else { - newPrefs.engines = newPrefs.engines.filter(function(e) { return e !== cb.value; }); - } - if (newPrefs.engines.length === 0) { - renderPanel(loadPrefs()); - return; - } - savePrefs(newPrefs); - syncEngineInput(newPrefs); - }); - }); - - // Attach listener to safe search dropdown - var safeSelect = document.getElementById('safe-search-select'); - if (safeSelect) { - safeSelect.addEventListener('change', function() { - var newPrefs = loadPrefs(); - newPrefs.safeSearch = safeSelect.value; - savePrefs(newPrefs); + // Safe search + var ssEl = panel.querySelector('#pref-safesearch'); + if (ssEl) { + ssEl.addEventListener('change', function() { + prefs.safeSearch = ssEl.value; + savePrefs(prefs); }); } - // Attach listener to format dropdown - var formatSelect = document.getElementById('format-select'); - if (formatSelect) { - formatSelect.addEventListener('change', function() { - var newPrefs = loadPrefs(); - newPrefs.format = formatSelect.value; - savePrefs(newPrefs); + // Format + var fmtEl = panel.querySelector('#pref-format'); + if (fmtEl) { + fmtEl.addEventListener('change', function() { + prefs.format = fmtEl.value; + savePrefs(prefs); }); } - // Attach listener to close button - var closeBtn = document.getElementById('settings-close'); - if (closeBtn) { - closeBtn.addEventListener('click', closePanel); - } + // Close button + var closeBtn = panel.querySelector('.settings-popover-close'); + if (closeBtn) closeBtn.addEventListener('click', closePanel); } function initSettings() {