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 += '
';
+ 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 += '
';
+ 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() {