MediaWiki:Common.js: Difference between revisions
No edit summary |
No edit summary |
||
| Line 228: | Line 228: | ||
/** | /** | ||
* Quick Search | * Quick Search Widgets — Reusable autocomplete for CRT & AV device lookup | ||
* The Main Page wikitext contains the styled | * Each widget is configured via a simple object (container ID, controls ID, | ||
* "Loading search…" | * category, placeholder text). The Main Page wikitext contains the styled | ||
* | * containers with "Loading search…" placeholders; this script replaces them | ||
* with the actual input, button, and dropdown, then wires up event handlers. | |||
*/ | */ | ||
(function () { | (function () { | ||
| Line 239: | Line 239: | ||
if (mw.config.get('wgPageName') !== 'Main_Page') return; | if (mw.config.get('wgPageName') !== 'Main_Page') return; | ||
// ── | // ── Shared config ─────────────────────────────────────────────── | ||
var API_URL = mw.util.wikiScript('api'); | var API_URL = mw.util.wikiScript('api'); | ||
var DEBOUNCE_MS = 250; | var DEBOUNCE_MS = 250; | ||
var MIN_CHARS = 2; | var MIN_CHARS = 2; | ||
| Line 257: | Line 256: | ||
style.id = 'ecrt-qs-styles'; | style.id = 'ecrt-qs-styles'; | ||
style.textContent = [ | style.textContent = [ | ||
/* | /* ── Base (blue) container & label ── */ | ||
'.ecrt-qs-container {', | '.ecrt-qs-container {', | ||
' background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);', | ' background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);', | ||
| Line 271: | Line 270: | ||
' margin-bottom: 0.5rem;', | ' margin-bottom: 0.5rem;', | ||
' font-size: 0.9rem;', | ' font-size: 0.9rem;', | ||
'}', | |||
/* ── Green variant (AV devices) ── */ | |||
'.ecrt-qs-container--av {', | |||
' background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);', | |||
' border-color: #86efac;', | |||
'}', | |||
'.ecrt-qs-container--av .ecrt-qs-label {', | |||
' color: #15803d;', | |||
'}', | |||
'.ecrt-qs-container--av .ecrt-qs-input:focus {', | |||
' border-color: #16a34a;', | |||
' box-shadow: 0 0 0 3px rgba(22,163,74,0.15);', | |||
'}', | |||
'.ecrt-qs-container--av .ecrt-qs-btn {', | |||
' background: #16a34a;', | |||
'}', | |||
'.ecrt-qs-container--av .ecrt-qs-btn:hover {', | |||
' background: #15803d;', | |||
'}', | |||
'.ecrt-qs-container--av .ecrt-qs-btn:active {', | |||
' background: #166534;', | |||
'}', | |||
'.ecrt-qs-container--av .ecrt-qs-item:hover,', | |||
'.ecrt-qs-container--av .ecrt-qs-item.is-active {', | |||
' background: #dcfce7;', | |||
' color: #14532d;', | |||
'}', | '}', | ||
| Line 363: | Line 389: | ||
'}', | '}', | ||
/* Night-mode overrides */ | /* ── Night-mode overrides (base / blue) ── */ | ||
'.skin-theme-clientpref-night .ecrt-qs-container {', | '.skin-theme-clientpref-night .ecrt-qs-container {', | ||
' background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);', | ' background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);', | ||
| Line 399: | Line 425: | ||
' border-top-color: #334155;', | ' border-top-color: #334155;', | ||
'}', | '}', | ||
'.skin-theme-clientpref-night .ecrt-qs-status { color: #64748b; }' | '.skin-theme-clientpref-night .ecrt-qs-status { color: #64748b; }', | ||
/* ── Night-mode overrides (green / AV) ── */ | |||
'.skin-theme-clientpref-night .ecrt-qs-container--av {', | |||
' background: linear-gradient(135deg, #0a1f0f 0%, #14291a 100%);', | |||
' border-color: #1e4d2b;', | |||
'}', | |||
'.skin-theme-clientpref-night .ecrt-qs-container--av .ecrt-qs-label {', | |||
' color: #86efac;', | |||
'}', | |||
'.skin-theme-clientpref-night .ecrt-qs-container--av .ecrt-qs-input:focus {', | |||
' border-color: #4ade80;', | |||
' box-shadow: 0 0 0 3px rgba(74,222,128,0.2);', | |||
'}', | |||
'.skin-theme-clientpref-night .ecrt-qs-container--av .ecrt-qs-btn {', | |||
' background: #15803d;', | |||
'}', | |||
'.skin-theme-clientpref-night .ecrt-qs-container--av .ecrt-qs-btn:hover {', | |||
' background: #16a34a;', | |||
'}', | |||
'.skin-theme-clientpref-night .ecrt-qs-container--av .ecrt-qs-item:hover,', | |||
'.skin-theme-clientpref-night .ecrt-qs-container--av .ecrt-qs-item.is-active {', | |||
' background: #14532d;', | |||
' color: #bbf7d0;', | |||
'}' | |||
].join('\n'); | ].join('\n'); | ||
document.head.appendChild(style); | document.head.appendChild(style); | ||
} | } | ||
// ── | // ── Generic widget initializer ────────────────────────────────── | ||
function | // cfg = { containerId, controlsId, category, placeholder } | ||
var container = document.getElementById( | function initWidget(cfg) { | ||
var wrap = document.getElementById( | var container = document.getElementById(cfg.containerId); | ||
var wrap = document.getElementById(cfg.controlsId); | |||
if (!container || !wrap) return; | if (!container || !wrap) return; | ||
// ── Build interactive controls ────────────────────────────── | // ── Build interactive controls ────────────────────────────── | ||
| Line 419: | Line 468: | ||
input.type = 'text'; | input.type = 'text'; | ||
input.className = 'ecrt-qs-input'; | input.className = 'ecrt-qs-input'; | ||
input.placeholder = | input.placeholder = cfg.placeholder; | ||
input.setAttribute('autocomplete', 'off'); | input.setAttribute('autocomplete', 'off'); | ||
| Line 505: | Line 554: | ||
var url = API_URL + '?action=pfautocomplete&format=json' | var url = API_URL + '?action=pfautocomplete&format=json' | ||
+ '&substr=' + encodeURIComponent(substr) | + '&substr=' + encodeURIComponent(substr) | ||
+ '&category=' + encodeURIComponent( | + '&category=' + encodeURIComponent(cfg.category); | ||
fetch(url) | fetch(url) | ||
| Line 579: | Line 628: | ||
openDropdown(); | openDropdown(); | ||
} | } | ||
}); | |||
} | |||
// ── Init all widgets ──────────────────────────────────────────── | |||
function init() { | |||
injectStyles(); | |||
// CRT Quick Search | |||
initWidget({ | |||
containerId: 'crt-quick-search', | |||
controlsId: 'ecrt-qs-controls-crt', | |||
category: 'CRT models', | |||
placeholder: 'Type a CRT model name (e.g. Sony KV-27S42)' | |||
}); | |||
// AV Device Quick Search | |||
initWidget({ | |||
containerId: 'av-quick-search', | |||
controlsId: 'ecrt-qs-controls-av', | |||
category: 'AV devices', | |||
placeholder: 'Type an AV device name (e.g. JVC SR-V10U)' | |||
}); | }); | ||
} | } | ||
| Line 589: | Line 659: | ||
} | } | ||
})(); | })(); | ||