MediaWiki:Citizen.js
MediaWiki interface page
More actions
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/**
* Dashboard Quick-Jump (v5 - ES5 Compatible)
* Listens for typing on the Dashboard page and jumps to matching cards.
* Replaced modern syntax to appease the MediaWiki ResourceLoader gods.
*/
$(function() {
try {
// 1. EDIT MODE GUARD (URL Check)
// Check if we are trying to edit.
var search = window.location.search;
if (search.indexOf('veaction') !== -1) return;
if (search.indexOf('action=edit') !== -1) return;
if (search.indexOf('action=submit') !== -1) return;
// 2. CONTEXT GUARD
// If there are no dashboard cards, exit.
var cards = document.querySelectorAll('.dashboard-card');
if (cards.length === 0) return;
var CONFIG = {
selectorCard: '.dashboard-card',
selectorLabel: '.dashboard-label',
selectorDesc: '.dashboard-desc',
selectorLink: 'a',
classActive: 'dashboard-jump-active',
timeout: 1500
};
var searchBuffer = '';
var clearTimer = null;
document.addEventListener('keydown', function(e) {
// 3. EDIT INTERFACE GUARD (Dynamic)
// Check for active editor classes or elements
if (document.documentElement.classList.contains('ve-active') ||
document.querySelector('.ve-ui-surface') ||
document.querySelector('.wikiEditor-ui')) {
return;
}
// 4. INPUT GUARD
// Don't intercept typing in search bars or inputs
var target = e.target;
var tagName = target.tagName;
if (tagName === 'INPUT' ||
tagName === 'TEXTAREA' ||
tagName === 'SELECT' ||
target.isContentEditable) {
return;
}
// 5. MODIFIER GUARD
if (e.ctrlKey || e.altKey || e.metaKey) return;
// --- Logic ---
if (e.key === 'Escape') {
resetSearch();
return;
}
if (e.key === 'Enter') {
var active = document.querySelector('.' + CONFIG.classActive + ' ' + CONFIG.selectorLink);
if (active) {
e.preventDefault();
e.stopPropagation();
active.click();
}
return;
}
if (e.key === 'Backspace') {
searchBuffer = searchBuffer.slice(0, -1);
if (searchBuffer.length === 0) resetSearch();
else updateSelection();
return;
}
// Capture single char keys (letters/numbers)
if (e.key.length === 1) {
searchBuffer += e.key;
updateSelection();
clearTimeout(clearTimer);
clearTimer = setTimeout(resetSearch, CONFIG.timeout);
}
});
function updateSelection() {
// Clear previous highlights
var actives = document.querySelectorAll('.' + CONFIG.classActive);
for (var i = 0; i < actives.length; i++) {
actives[i].classList.remove(CONFIG.classActive);
}
if (!searchBuffer) return;
// Escape special regex chars
var safeBuffer = searchBuffer.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
var regex = new RegExp('^' + safeBuffer, 'i');
for (var j = 0; j < cards.length; j++) {
var card = cards[j];
var labelEl = card.querySelector(CONFIG.selectorLabel);
var descEl = card.querySelector(CONFIG.selectorDesc);
// Old school null checks (No optional chaining ?.)
var label = labelEl ? labelEl.innerText.trim() : '';
var desc = descEl ? descEl.innerText.trim() : '';
// Priority 1: Label match
if (label && regex.test(label)) {
activateCard(card);
return;
}
// Priority 2: Description match
if (desc && regex.test(desc)) {
activateCard(card);
return;
}
}
}
function activateCard(card) {
card.classList.add(CONFIG.classActive);
card.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
function resetSearch() {
searchBuffer = '';
var actives = document.querySelectorAll('.' + CONFIG.classActive);
for (var i = 0; i < actives.length; i++) {
actives[i].classList.remove(CONFIG.classActive);
}
}
} catch (err) {
console.error('Hallyu Dashboard Script Error:', err);
}
});