MediaWiki:Common.js: Difference between revisions
Jump to navigation
Jump to search
No edit summary Tag: Reverted |
No edit summary Tag: Reverted |
||
| Line 1: | Line 1: | ||
mw.loader.using([' | /* Any JavaScript here will be loaded for all users on every page load. */ | ||
/* ----------------------------------------- | |||
jQuery UI tabs (safe) – won't break page | |||
------------------------------------------*/ | |||
mw.loader.using(['jquery.ui']).then(function () { | |||
try { | |||
} | if ($("[class^=portal_vtab]").length) { | ||
$("[class^=portal_vtab]").tabs().addClass("ui-tabs-vertical ui-helper-clearfix"); | |||
$("[class^=portal_vtab] li").removeClass("ui-corner-top").addClass("ui-corner-left"); | |||
} | |||
var $tabs = $("#portal_slider"); | |||
if ($tabs.length) { | |||
$tabs.tabs({ fx: { opacity: 'toggle', duration: 100 } }); | |||
function selectTab(idx) { | |||
idx = parseInt(idx, 10) || 0; | |||
$tabs.tabs("option", "active", idx); | |||
} | |||
$("[class*=portal_sliderlink]").on('click', function (e) { | |||
e.preventDefault(); | |||
/ | var m = this.className.match(/portal_sliderlink-(\d+)/); | ||
if (m) selectTab(m[1]); | |||
}); | |||
$('#portal_next').on('click', function (e) { | |||
e.preventDefault(); | |||
var active = $tabs.tabs("option", "active"); | |||
var total = $tabs.find("> ul > li").length || 1; | |||
selectTab((active + 1) % total); | |||
}); | |||
$('#portal_prev').on('click', function (e) { | |||
e.preventDefault(); | |||
var active = $tabs.tabs("option", "active"); | |||
var total = $tabs.find("> ul > li").length || 1; | |||
selectTab((active - 1 + total) % total); | |||
}); | |||
} | |||
} catch (err) { | |||
console.warn('[tabs] disabled due to error:', err); | |||
} | |||
} | |||
}); | }); | ||
/* lockdown | /* ----------------------------------------- | ||
ReferencePopups lockdown + upload tweak | |||
------------------------------------------*/ | |||
((window.dev = window.dev || {}).ReferencePopups = dev.ReferencePopups || {}).lockdown = true; | ((window.dev = window.dev || {}).ReferencePopups = dev.ReferencePopups || {}).lockdown = true; | ||
mw.config.set('UMFBypassLicenseCheck', true); | mw.config.set('UMFBypassLicenseCheck', true); | ||
/* Hide Admin toolbox for non-admins */ | /* ----------------------------------------- | ||
Hide Admin toolbox for non-admins | |||
------------------------------------------*/ | |||
mw.loader.using('mediawiki.util').then(function () { | mw.loader.using('mediawiki.util').then(function () { | ||
var g = mw.config.get('wgUserGroups') || []; | try { | ||
var g = mw.config.get('wgUserGroups') || []; | |||
var isAdmin = g.indexOf('sysop') !== -1 || g.indexOf('interface-admin') !== -1; | |||
if (!isAdmin) { | |||
document.querySelectorAll('.only-sysop').forEach(function (el) { el.style.display = 'none'; }); | |||
} | |||
} catch (e) { | |||
console.warn('[only-sysop] hide failed:', e); | |||
} | |||
}); | }); | ||
/* ============================ | /* ========================================================== | ||
RANDOM PAGE TEASER | RANDOM PAGE TEASER – robust, pageid-based, no extensions | ||
============================ */ | Renders into <div id="random-teaser" class="random-card"> | ||
========================================================== */ | |||
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function () { | mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function () { | ||
var box = document.getElementById('random-teaser'); | var box = document.getElementById('random-teaser'); | ||
| Line 59: | Line 75: | ||
var api = new mw.Api(); | var api = new mw.Api(); | ||
var | var THUMB_W = 280; | ||
function esc(s) { return mw.html.escape(String(s || '')); } | function esc(s){ return mw.html.escape(String(s || '')); } | ||
function | function excerptFromHTML(html, maxChars) { | ||
var | var d = document.createElement('div'); | ||
d.innerHTML = html; | |||
var p = | // pick first meaningful paragraph | ||
var | var p = d.querySelector('p'); | ||
if ( | var t = (p ? p.innerText : d.innerText || '').replace(/\s+/g, ' ').trim(); | ||
return | if (t.length > maxChars) t = t.slice(0, maxChars).replace(/\s+\S*$/, '') + '…'; | ||
return t || 'No description available.'; | |||
} | } | ||
function | function firstRaster(list) { | ||
if (!Array.isArray(list) || !list.length) return null; | |||
// Prefer raster formats | |||
return null; | var pick = list.find(function (t) { return /\.(jpe?g|png|gif|webp)$/i.test(t || ''); }); | ||
return pick || list[0] || null; | |||
} | } | ||
function getThumbUrl(fileTitle) { | function getThumbUrl(fileTitle) { | ||
| Line 103: | Line 104: | ||
prop: 'imageinfo', | prop: 'imageinfo', | ||
iiprop: 'url', | iiprop: 'url', | ||
iiurlwidth: | iiurlwidth: THUMB_W | ||
}).then(function ( | }).then(function (r) { | ||
var p = | var p = r.query && r.query.pages && r.query.pages[0]; | ||
var ii = p && p.imageinfo && p.imageinfo[0]; | var ii = p && p.imageinfo && p.imageinfo[0]; | ||
return (ii && (ii.thumburl || ii.url)) || null; | return (ii && (ii.thumburl || ii.url)) || null; | ||
}).catch(function () { return null; }); | }).catch(function (e) { | ||
console.warn('[teaser] imageinfo failed:', e); | |||
return null; | |||
}); | |||
} | } | ||
function render(title, | function render(title, text, imgUrl) { | ||
var url = mw.util.getUrl(title); | var url = mw.util.getUrl(title); | ||
box.innerHTML = | box.innerHTML = | ||
| Line 119: | Line 123: | ||
'<div class="content">' + | '<div class="content">' + | ||
'<h3><a href="' + url + '">' + esc(title) + '</a></h3>' + | '<h3><a href="' + url + '">' + esc(title) + '</a></h3>' + | ||
'<p>' + esc( | '<p>' + esc(text) + '</p>' + | ||
'<div class="actions">' + | '<div class="actions">' + | ||
'<a class="btn" href="' + url + '">Open</a>' + | '<a class="btn" href="' + url + '">Open</a>' + | ||
| Line 126: | Line 130: | ||
'</div>' + | '</div>' + | ||
'</div>'; | '</div>'; | ||
box.classList.remove('loading'); | box.classList.remove('loading'); | ||
var | var btn = document.getElementById('rand-refresh'); | ||
if ( | if (btn) btn.addEventListener('click', function () { | ||
box.classList.add('loading'); | box.classList.add('loading'); | ||
load(); | |||
}); | }); | ||
} | } | ||
function | function load() { | ||
// 1) | // 1) Random page with pageid (stable) | ||
api.get({ | api.get({ | ||
action: 'query', | action: 'query', | ||
formatversion: 2, | formatversion: 2, | ||
generator: 'random', | |||
grnnamespace: 0, | |||
grnlimit: 1, | |||
}).then(function ( | prop: 'info' | ||
var | }).then(function (q) { | ||
if (! | var pg = q.query && q.query.pages && q.query.pages[0]; | ||
var title = | if (!pg) throw new Error('No random page'); | ||
var pageid = pg.pageid; | |||
var title = pg.title; | |||
// 2) | // 2) Parse via pageid → HTML + images (avoids missingtitle) | ||
return api.get({ | return api.get({ | ||
action: 'parse', | action: 'parse', | ||
pageid: pageid, | |||
prop: 'text|images', | prop: 'text|images', | ||
redirects: 1 | redirects: 1 | ||
}).then(function (p) { | }).then(function (p) { | ||
var html = p.parse && p.parse.text && p.parse.text['*'] || ''; | var html = p.parse && p.parse.text && p.parse.text['*'] || ''; | ||
var images = p.parse && p.parse.images || []; | var images = p.parse && p.parse.images || []; | ||
var | var text = excerptFromHTML(html, 420); | ||
var | var file = firstRaster(images); | ||
return getThumbUrl( | // 3) Resolve thumbnail (if any) | ||
render(title, | return getThumbUrl(file).then(function (thumb) { | ||
render(title, text, thumb); | |||
}); | }); | ||
}); | }); | ||
}).catch(function (e) { | }).catch(function (e) { | ||
console. | console.error('[teaser] failed:', e); | ||
box.classList.remove('loading'); | box.classList.remove('loading'); | ||
box.innerHTML = '<div class="content"><h3>Random page</h3><p>Could not load a preview.</p></div>'; | box.innerHTML = '<div class="content"><h3>Random page</h3><p>Could not load a preview.</p></div>'; | ||
| Line 171: | Line 179: | ||
} | } | ||
// Initial load | |||
load(); | load(); | ||
}); | }); | ||
Revision as of 10:08, 5 September 2025
/* Any JavaScript here will be loaded for all users on every page load. */
/* -----------------------------------------
jQuery UI tabs (safe) – won't break page
------------------------------------------*/
mw.loader.using(['jquery.ui']).then(function () {
try {
if ($("[class^=portal_vtab]").length) {
$("[class^=portal_vtab]").tabs().addClass("ui-tabs-vertical ui-helper-clearfix");
$("[class^=portal_vtab] li").removeClass("ui-corner-top").addClass("ui-corner-left");
}
var $tabs = $("#portal_slider");
if ($tabs.length) {
$tabs.tabs({ fx: { opacity: 'toggle', duration: 100 } });
function selectTab(idx) {
idx = parseInt(idx, 10) || 0;
$tabs.tabs("option", "active", idx);
}
$("[class*=portal_sliderlink]").on('click', function (e) {
e.preventDefault();
var m = this.className.match(/portal_sliderlink-(\d+)/);
if (m) selectTab(m[1]);
});
$('#portal_next').on('click', function (e) {
e.preventDefault();
var active = $tabs.tabs("option", "active");
var total = $tabs.find("> ul > li").length || 1;
selectTab((active + 1) % total);
});
$('#portal_prev').on('click', function (e) {
e.preventDefault();
var active = $tabs.tabs("option", "active");
var total = $tabs.find("> ul > li").length || 1;
selectTab((active - 1 + total) % total);
});
}
} catch (err) {
console.warn('[tabs] disabled due to error:', err);
}
});
/* -----------------------------------------
ReferencePopups lockdown + upload tweak
------------------------------------------*/
((window.dev = window.dev || {}).ReferencePopups = dev.ReferencePopups || {}).lockdown = true;
mw.config.set('UMFBypassLicenseCheck', true);
/* -----------------------------------------
Hide Admin toolbox for non-admins
------------------------------------------*/
mw.loader.using('mediawiki.util').then(function () {
try {
var g = mw.config.get('wgUserGroups') || [];
var isAdmin = g.indexOf('sysop') !== -1 || g.indexOf('interface-admin') !== -1;
if (!isAdmin) {
document.querySelectorAll('.only-sysop').forEach(function (el) { el.style.display = 'none'; });
}
} catch (e) {
console.warn('[only-sysop] hide failed:', e);
}
});
/* ==========================================================
RANDOM PAGE TEASER – robust, pageid-based, no extensions
Renders into <div id="random-teaser" class="random-card">
========================================================== */
mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function () {
var box = document.getElementById('random-teaser');
if (!box) return; // run only if the container exists
var api = new mw.Api();
var THUMB_W = 280;
function esc(s){ return mw.html.escape(String(s || '')); }
function excerptFromHTML(html, maxChars) {
var d = document.createElement('div');
d.innerHTML = html;
// pick first meaningful paragraph
var p = d.querySelector('p');
var t = (p ? p.innerText : d.innerText || '').replace(/\s+/g, ' ').trim();
if (t.length > maxChars) t = t.slice(0, maxChars).replace(/\s+\S*$/, '') + '…';
return t || 'No description available.';
}
function firstRaster(list) {
if (!Array.isArray(list) || !list.length) return null;
// Prefer raster formats
var pick = list.find(function (t) { return /\.(jpe?g|png|gif|webp)$/i.test(t || ''); });
return pick || list[0] || null;
}
function getThumbUrl(fileTitle) {
if (!fileTitle) return Promise.resolve(null);
return api.get({
action: 'query',
formatversion: 2,
titles: fileTitle,
prop: 'imageinfo',
iiprop: 'url',
iiurlwidth: THUMB_W
}).then(function (r) {
var p = r.query && r.query.pages && r.query.pages[0];
var ii = p && p.imageinfo && p.imageinfo[0];
return (ii && (ii.thumburl || ii.url)) || null;
}).catch(function (e) {
console.warn('[teaser] imageinfo failed:', e);
return null;
});
}
function render(title, text, imgUrl) {
var url = mw.util.getUrl(title);
box.innerHTML =
'<div class="thumb">' +
(imgUrl ? '<img src="' + esc(imgUrl) + '" alt="">' : '<span>🡲</span>') +
'</div>' +
'<div class="content">' +
'<h3><a href="' + url + '">' + esc(title) + '</a></h3>' +
'<p>' + esc(text) + '</p>' +
'<div class="actions">' +
'<a class="btn" href="' + url + '">Open</a>' +
'<button type="button" class="btn" id="rand-refresh">Another</button>' +
'<a class="btn" href="' + mw.util.getUrl('Special:Random') + '">Special:Random</a>' +
'</div>' +
'</div>';
box.classList.remove('loading');
var btn = document.getElementById('rand-refresh');
if (btn) btn.addEventListener('click', function () {
box.classList.add('loading');
load();
});
}
function load() {
// 1) Random page with pageid (stable)
api.get({
action: 'query',
formatversion: 2,
generator: 'random',
grnnamespace: 0,
grnlimit: 1,
prop: 'info'
}).then(function (q) {
var pg = q.query && q.query.pages && q.query.pages[0];
if (!pg) throw new Error('No random page');
var pageid = pg.pageid;
var title = pg.title;
// 2) Parse via pageid → HTML + images (avoids missingtitle)
return api.get({
action: 'parse',
pageid: pageid,
prop: 'text|images',
redirects: 1
}).then(function (p) {
var html = p.parse && p.parse.text && p.parse.text['*'] || '';
var images = p.parse && p.parse.images || [];
var text = excerptFromHTML(html, 420);
var file = firstRaster(images);
// 3) Resolve thumbnail (if any)
return getThumbUrl(file).then(function (thumb) {
render(title, text, thumb);
});
});
}).catch(function (e) {
console.error('[teaser] failed:', e);
box.classList.remove('loading');
box.innerHTML = '<div class="content"><h3>Random page</h3><p>Could not load a preview.</p></div>';
});
}
// Initial load
load();
});