MediaWiki:Common.js: Difference between revisions
Appearance
DawahAgent (talk | contribs) Wiki UI polish owner-approved preview packet |
DawahAgent (talk | contribs) wiki UI footer/panel/Main Page hotfix (owner approved 2026-06-18) |
||
| Line 213: | Line 213: | ||
var places = document.getElementById('footer-places'); | var places = document.getElementById('footer-places'); | ||
if (!places || places.getAttribute('data-dw-polished') === '1') { return; } | if (!places || places.getAttribute('data-dw-polished') === '1') { return; } | ||
var info = document.getElementById('footer-info'); | |||
var isAr = (document.documentElement.lang || '').toLowerCase().indexOf('ar') === 0 || document.documentElement.dir === 'rtl'; | var isAr = (document.documentElement.lang || '').toLowerCase().indexOf('ar') === 0 || document.documentElement.dir === 'rtl'; | ||
var links = isAr ? [ | var links = isAr ? [ | ||
| Line 235: | Line 236: | ||
places.appendChild(li); | places.appendChild(li); | ||
}); | }); | ||
if (info) { | |||
info.textContent = ''; | |||
var copy = document.createElement('li'); | |||
copy.id = 'footer-info-copyright'; | |||
copy.textContent = isAr ? '© 2026 Dawah.Wiki. جميع الحقوق محفوظة.' : '© 2026 Dawah.Wiki. All rights reserved.'; | |||
info.appendChild(copy); | |||
} | |||
} | } | ||
ready(footerLinks); | ready(footerLinks); | ||
Revision as of 13:24, 18 June 2026
/* URETHANE DESIGN — generic theme engine (app-agnostic).
Pair with 02-tokens.css. Include synchronously in <head>.
Sets on <html>: data-du-mode (light|dark, auto-resolved),
data-du-glass (faithful|modern|flat), inline --du-h (accent hue) and --du-c (accent chroma).
Prefs: localStorage 'dawahUrethane' + mirrored to a .dawah.wiki cookie
so the choice follows users across subdomains. Defaults (owner-mandated):
mode 'auto', glass 'faithful' (the 2006 look), accent '#2e8fc7' (blue).
Optional: set window.DU_MOUNT = 'css selector' before this script to pick
where the "Theme" switcher button mounts (default: fixed bottom corner).
*/
(function () {
'use strict';
var KEY = 'dawahUrethane';
var DEFAULTS = { mode: 'auto', glass: 'faithful', accent: '#2e8fc7', t: 0 };
var PRESETS = [
['#2e8fc7', 'Urethane blue'], ['#29a395', 'Madinah teal'],
['#2ea05b', 'Palm green'], ['#d4912a', 'Desert amber'],
['#7a5cc7', 'Violet'], ['#cc3d77', 'Rose']
];
function valid(p) {
p = p || {};
return {
mode: ['auto', 'light', 'dark'].indexOf(p.mode) >= 0 ? p.mode : DEFAULTS.mode,
glass: ['faithful', 'modern', 'flat'].indexOf(p.glass) >= 0 ? p.glass : DEFAULTS.glass,
accent: /^#[0-9a-fA-F]{6}$/.test(p.accent || '') ? p.accent : DEFAULTS.accent,
t: typeof p.t === 'number' ? p.t : 0
};
}
function readLocal() { try { return JSON.parse(localStorage.getItem(KEY) || 'null'); } catch (e) { return null; } }
function readCookie() {
var m = document.cookie.match(new RegExp('(?:^|; )' + KEY + '=([^;]*)'));
if (!m) { return null; }
try { return JSON.parse(decodeURIComponent(m[1])); } catch (e) { return null; }
}
function load() {
var a = readLocal(), b = readCookie();
var p = (b && (!a || (b.t || 0) > (a.t || 0))) ? b : a; /* newer wins */
return valid(p);
}
function save(p) {
p.t = Date.now();
var s = JSON.stringify(p);
try { localStorage.setItem(KEY, s); } catch (e) { /* private mode */ }
try {
document.cookie = KEY + '=' + encodeURIComponent(s) +
'; domain=.dawah.wiki; path=/; max-age=31536000; SameSite=Lax; Secure';
} catch (e) { /* file:// etc. */ }
}
function hexToHue(hex) {
var r = parseInt(hex.substr(1, 2), 16) / 255,
g = parseInt(hex.substr(3, 2), 16) / 255,
b = parseInt(hex.substr(5, 2), 16) / 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b), d = max - min, h = 0;
if (d === 0) { return 205; } /* achromatic: keep blue chrome */
if (max === r) { h = ((g - b) / d) % 6; }
else if (max === g) { h = (b - r) / d + 2; }
else { h = (r - g) / d + 4; }
return (Math.round(h * 60) + 360) % 360;
}
function hexToChroma(hex) {
var r = parseInt(hex.substr(1, 2), 16) / 255,
g = parseInt(hex.substr(3, 2), 16) / 255,
b = parseInt(hex.substr(5, 2), 16) / 255;
var d = Math.max(r, g, b) - Math.min(r, g, b);
var base = 153 / 255; /* #2e8fc7, the default Urethane blue */
return Math.max(0, Math.min(1.25, d / base));
}
var mq = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
function apply() {
var p = load();
var mode = p.mode === 'auto' ? (mq && mq.matches ? 'dark' : 'light') : p.mode;
var de = document.documentElement;
de.setAttribute('data-du-mode', mode);
de.setAttribute('data-du-glass', p.glass);
de.style.setProperty('--du-h', String(hexToHue(p.accent)));
de.style.setProperty('--du-c', String(hexToChroma(p.accent)));
}
apply();
if (mq) {
var onChange = function () { if (load().mode === 'auto') { apply(); } };
if (mq.addEventListener) { mq.addEventListener('change', onChange); }
else if (mq.addListener) { mq.addListener(onChange); }
}
/* ---------------- switcher UI ---------------- */
function el(tag, cls, text) {
var e = document.createElement(tag);
if (cls) { e.className = cls; }
if (text) { e.textContent = text; }
return e;
}
function buildPanel(anchor) {
var p = load();
var panel = el('div'); panel.id = 'du-panel';
panel.setAttribute('role', 'dialog');
panel.setAttribute('aria-label', 'Theme options');
panel.style.cssText = 'position:absolute;z-index:9999;inset-inline-end:0;bottom:calc(100% + 8px);width:248px;background:var(--du-panel);border:1px solid var(--du-edge);border-radius:10px;box-shadow:var(--du-psh),0 6px 22px rgb(0 0 0 / .25);padding:12px;color:var(--du-text);font-size:12px;text-align:start';
function section(title) {
var h = el('h4', null, title);
h.style.cssText = 'margin:0 0 4px;font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--du-muted)';
panel.appendChild(h);
var row = el('div'); row.style.cssText = 'display:flex;gap:5px;flex-wrap:wrap;margin-bottom:10px';
panel.appendChild(row); return row;
}
function styleOpt(o, on) {
o.style.cssText = 'flex:1;text-align:center;padding:5px 8px;border:1px solid var(--du-edge);border-radius:7px;cursor:pointer;white-space:nowrap;' +
(on ? 'background:var(--du-prim);color:#fff;text-shadow:0 1px rgb(0 0 0 / .3)'
: 'background:var(--du-face);box-shadow:var(--du-bev);color:var(--du-text);text-shadow:var(--du-tsh)');
}
function opts(row, items, key, current) {
items.forEach(function (it) {
var o = el('span', null, it[1]);
o.setAttribute('role', 'button'); o.tabIndex = 0;
styleOpt(o, current === it[0]);
var act = function () {
var np = load(); np[key] = it[0]; save(np); apply();
Array.prototype.forEach.call(row.children, function (c, i) { styleOpt(c, items[i][0] === it[0]); });
};
o.addEventListener('click', act);
o.addEventListener('keydown', function (ev) { if (ev.key === 'Enter' || ev.key === ' ') { ev.preventDefault(); act(); } });
row.appendChild(o);
});
}
opts(section('Mode'), [['auto', 'Auto'], ['light', 'Light'], ['dark', 'Dark']], 'mode', p.mode);
opts(section('Glass'), [['faithful', '2006'], ['modern', 'Modern'], ['flat', 'Flat']], 'glass', p.glass);
var crow = section('Accent');
function ring(s, on) { s.style.outline = on ? '2px solid var(--du-link)' : 'none'; s.style.outlineOffset = '2px'; }
var swatches = [];
PRESETS.forEach(function (pr) {
var s = el('button'); s.type = 'button'; s.title = pr[1];
s.setAttribute('aria-label', pr[1]);
s.style.cssText = 'width:24px;height:24px;border-radius:50%;border:1px solid var(--du-edge);cursor:pointer;padding:0;box-shadow:inset 0 1px rgb(255 255 255 / .55);background:' + pr[0];
ring(s, p.accent.toLowerCase() === pr[0]);
s.addEventListener('click', function () {
var np = load(); np.accent = pr[0]; save(np); apply();
swatches.forEach(function (x) { ring(x, x === s); });
picker.value = pr[0];
});
swatches.push(s); crow.appendChild(s);
});
var picker = document.createElement('input');
picker.type = 'color'; picker.value = p.accent; picker.title = 'Custom color';
picker.setAttribute('aria-label', 'Custom accent color');
picker.style.cssText = 'width:34px;height:26px;padding:0;border:1px solid var(--du-edge);border-radius:6px;background:var(--du-panel);cursor:pointer';
picker.addEventListener('input', function () {
var np = load(); np.accent = picker.value; save(np); apply();
swatches.forEach(function (x) { ring(x, false); });
});
crow.appendChild(picker);
var note = el('p', null, 'Applies across dawah.wiki in this browser.');
note.style.cssText = 'color:var(--du-muted);font-size:11px;margin:2px 0 0';
panel.appendChild(note);
anchor.appendChild(panel);
return panel;
}
function buildFab() {
var mount = window.DU_MOUNT ? document.querySelector(window.DU_MOUNT) : null;
var li = el(mount ? 'span' : 'div');
li.style.position = 'relative';
if (mount) { mount.appendChild(li); }
else {
li.style.cssText += ';position:fixed;bottom:14px;inset-inline-end:14px;z-index:9998';
document.body.appendChild(li);
}
var fab = el('a', null, 'Theme'); fab.id = 'du-fab'; fab.href = '#';
fab.setAttribute('role', 'button');
fab.setAttribute('aria-haspopup', 'dialog');
fab.title = 'Theme options';
fab.style.cssText = 'display:inline-flex;align-items:center;gap:6px;cursor:pointer;user-select:none;padding:6px 12px;border:1px solid var(--du-edge);border-radius:7px;background:var(--du-face);box-shadow:var(--du-bev);color:var(--du-text);text-shadow:var(--du-tsh);text-decoration:none;font-size:12.5px';
var dot = el('span'); dot.setAttribute('aria-hidden', 'true');
dot.style.cssText = 'width:12px;height:12px;border-radius:50%;background:hsl(var(--du-h) calc(70% * var(--du-c)) 50%);box-shadow:inset 0 1px rgb(255 255 255 / .6)';
fab.insertBefore(dot, fab.firstChild);
li.appendChild(fab);
var panel = null;
fab.addEventListener('click', function (ev) {
ev.preventDefault();
if (panel) { panel.parentNode.removeChild(panel); panel = null; return; }
panel = buildPanel(li);
});
document.addEventListener('click', function (ev) {
if (panel && !li.contains(ev.target)) { panel.parentNode.removeChild(panel); panel = null; }
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', buildFab);
} else {
buildFab();
}
})();
/* MediaWiki footer polish: replace stock wiki footer links with site-wide public links. */
(function () {
'use strict';
function ready(fn) {
if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', fn); }
else { fn(); }
}
function footerLinks() {
var places = document.getElementById('footer-places');
if (!places || places.getAttribute('data-dw-polished') === '1') { return; }
var info = document.getElementById('footer-info');
var isAr = (document.documentElement.lang || '').toLowerCase().indexOf('ar') === 0 || document.documentElement.dir === 'rtl';
var links = isAr ? [
['عن', 'https://dawah.wiki/about'],
['الإرشادات', 'https://dawah.wiki/guidelines'],
['الخصوصية', 'https://dawah.wiki/privacy'],
['اتصل بنا', 'https://dawah.wiki/contact']
] : [
['About', 'https://dawah.wiki/about'],
['Guidelines', 'https://dawah.wiki/guidelines'],
['Privacy', 'https://dawah.wiki/privacy'],
['Contact', 'https://dawah.wiki/contact']
];
places.setAttribute('data-dw-polished', '1');
places.textContent = '';
links.forEach(function (item) {
var li = document.createElement('li');
var a = document.createElement('a');
a.href = item[1];
a.textContent = item[0];
li.appendChild(a);
places.appendChild(li);
});
if (info) {
info.textContent = '';
var copy = document.createElement('li');
copy.id = 'footer-info-copyright';
copy.textContent = isAr ? '© 2026 Dawah.Wiki. جميع الحقوق محفوظة.' : '© 2026 Dawah.Wiki. All rights reserved.';
info.appendChild(copy);
}
}
ready(footerLinks);
}());
/* IMPLEMENTAUDIT wiki-ui-polish 2026-06-18: canonical wiki platform nav. */
(function () {
'use strict';
window.DU_MOUNT = '#du-theme-slot';
function ready(fn) {
if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', fn); }
else { fn(); }
}
function icon(name) {
var paths = {
home: '<path d="M3 10.5 12 3l9 7.5"/><path d="M5 9.5V21h5v-6h4v6h5V9.5"/>',
wiki: '<path d="M5 5h14v14H5z"/><path d="M8 9h8M8 13h8"/>',
forum: '<path d="M4 6h16v10H8l-4 4z"/>',
markdown: '<path d="M3 7h18v10H3z"/><path d="M7 14V10l2 2 2-2v4M15 10v4M13 12l2 2 2-2"/>',
gallery: '<path d="M4 5h16v14H4z"/><path d="m7 16 3-4 3 3 2-2 2 3"/><circle cx="9" cy="9" r="1.5"/>',
qamus: '<path d="M7 4h9a3 3 0 0 1 3 3v13H8a3 3 0 0 1-3-3V6a2 2 0 0 1 2-2z"/><path d="M8 4v13a3 3 0 0 0 3 3"/>'
};
return '<span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24">' + (paths[name] || '') + '</svg></span>';
}
function makeLink(item, currentHost) {
var a = document.createElement('a');
a.href = item.href;
a.innerHTML = icon(item.icon) + '<span>' + item.label + '</span>';
if (item.current || currentHost === item.host) { a.setAttribute('aria-current', 'page'); }
return a;
}
function loginHref() {
var login = document.querySelector('#pt-login-2 a, #pt-login a, a[href*="Special:UserLogin"]');
return login ? login.href : 'https://forum.dawah.wiki/ucp.php?mode=login';
}
function moveThemeFab() {
var slot = document.getElementById('du-theme-slot');
var fab = document.getElementById('du-fab');
if (!slot || !fab) { return; }
var wrap = fab.parentElement;
if (wrap && wrap.parentElement !== slot) {
wrap.style.position = 'relative';
wrap.style.insetInlineEnd = '';
wrap.style.bottom = '';
wrap.style.zIndex = '';
slot.appendChild(wrap);
}
}
function wireThemeDismissal() {
if (wireThemeDismissal.done) { return; }
wireThemeDismissal.done = true;
document.addEventListener('keydown', function (ev) {
if (ev.key !== 'Escape' || !document.getElementById('du-panel')) { return; }
ev.preventDefault();
document.body.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
var fab = document.getElementById('du-fab');
if (fab) { fab.focus(); }
});
}
function ensureWikiNav() {
if (document.querySelector('.duglobal[data-dw-wiki-nav="1"]')) { moveThemeFab(); return; }
var header = document.querySelector('.vector-header-container');
if (!header || !document.body.classList.contains('skin-vector')) { return; }
var host = location.hostname;
var isAr = host.indexOf('ar.') === 0 || document.documentElement.dir === 'rtl';
var nav = document.createElement('header');
nav.className = 'du-chrome duglobal';
nav.setAttribute('role', 'banner');
nav.setAttribute('data-dw-wiki-nav', '1');
var inner = document.createElement('div');
inner.className = 'duglobal-in';
var brand = document.createElement('a');
brand.className = 'brand';
brand.href = 'https://dawah.wiki/';
brand.innerHTML = '<img class="crest" src="/resources/assets/dawahwiki-logo-135.png" alt=""><span class="wm">Dawah.Wiki</span>';
var tabs = document.createElement('nav');
tabs.className = 'switch';
tabs.setAttribute('aria-label', 'Platform');
[
{label:'Home', href:'https://dawah.wiki/', icon:'home', host:'dawah.wiki'},
{label:'Wiki', href:isAr ? 'https://ar.dawah.wiki/' : 'https://en.dawah.wiki/', icon:'wiki', current:true},
{label:'Forum', href:'https://forum.dawah.wiki/', icon:'forum'},
{label:'Markdown', href:'https://md.dawah.wiki/', icon:'markdown'},
{label:'Gallery', href:'https://gallery.dawah.wiki/', icon:'gallery'},
{label:'Qamus', href:'https://qamus.dawah.wiki/', icon:'qamus'}
].forEach(function (item) { tabs.appendChild(makeLink(item, host)); });
var right = document.createElement('div');
right.className = 'gright';
var lang = document.createElement('span');
lang.className = 'langtog';
lang.setAttribute('aria-label', 'Language');
lang.innerHTML = '<a href="https://en.dawah.wiki/"' + (!isAr ? ' aria-current="true"' : '') + '>EN</a><a href="https://ar.dawah.wiki/"' + (isAr ? ' aria-current="true"' : '') + ' lang="ar" dir="rtl">ع</a>';
var theme = document.createElement('span');
theme.id = 'du-theme-slot';
var who = document.createElement('span');
who.className = 'who';
var auth = document.createElement('a');
auth.className = 'du-login';
auth.href = loginHref();
auth.textContent = isAr ? 'دخول / تسجيل' : 'Login / Register';
who.appendChild(auth);
right.appendChild(lang);
right.appendChild(theme);
right.appendChild(who);
inner.appendChild(brand);
inner.appendChild(tabs);
inner.appendChild(right);
nav.appendChild(inner);
header.parentNode.insertBefore(nav, header);
moveThemeFab();
wireThemeDismissal();
setTimeout(moveThemeFab, 0);
setTimeout(moveThemeFab, 250);
}
ready(ensureWikiNav);
})();
/* /IMPLEMENTAUDIT wiki-ui-polish 2026-06-18 */