MediaWiki:Common.js: Difference between revisions
No edit summary Tag: Reverted |
No edit summary Tag: Reverted |
||
| Line 243: | Line 243: | ||
}).catch(function (e) { | }).catch(function (e) { | ||
console.warn('Random teaser error:', e); | console.warn('Random teaser error:', e); | ||
box.classList.remove('loading'); | |||
box.innerHTML = '<div class="content"><h3>Random page</h3><p>Could not load a preview.</p></div>'; | |||
}); | |||
} | |||
loadRandom(); | |||
}); | |||
/* Random Page Teaser — works without PageImages/TextExtracts */ | |||
$(function () { | |||
var box = document.getElementById('random-teaser'); | |||
if (!box) return; | |||
var api = new mw.Api(); | |||
var THUMB_WIDTH = 280; | |||
function esc(s){ return mw.html.escape(String(s || '')); } | |||
function makeExcerptFromHTML(html, maxChars) { | |||
// Build a sandbox DOM, pick first paragraph text | |||
var tmp = document.createElement('div'); | |||
tmp.innerHTML = html; | |||
var p = tmp.querySelector('p'); | |||
var txt = (p ? p.innerText : tmp.innerText || '').replace(/\s+/g, ' ').trim(); | |||
if (txt.length > maxChars) txt = txt.slice(0, maxChars).replace(/\s+\S*$/, '') + '…'; | |||
return txt || 'No description available.'; | |||
} | |||
function pickImageTitle(list) { | |||
if (!Array.isArray(list) || !list.length) return null; | |||
// Prefer common raster formats | |||
var preferred = list.find(function (t) { return /\.(jpe?g|png|gif|webp)$/i.test(t); }); | |||
return preferred || 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_WIDTH | |||
}).then(function (res) { | |||
var p = res.query && res.query.pages && res.query.pages[0]; | |||
var ii = p && p.imageinfo && p.imageinfo[0]; | |||
return (ii && (ii.thumburl || ii.url)) || null; | |||
}).catch(function(){ return null; }); | |||
} | |||
function render(title, extract, 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(extract) + '</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 refreshBtn = document.getElementById('rand-refresh'); | |||
if (refreshBtn) refreshBtn.addEventListener('click', function () { | |||
box.classList.add('loading'); | |||
loadRandom(); | |||
}); | |||
} | |||
function loadRandom() { | |||
// 1) Get random article (namespace 0) | |||
api.get({ | |||
action: 'query', | |||
formatversion: 2, | |||
list: 'random', | |||
rnnamespace: 0, | |||
rnlimit: 1 | |||
}).then(function (r) { | |||
var item = r && r.query && r.query.random && r.query.random[0]; | |||
if (!item) throw new Error('No random page'); | |||
var title = item.title; | |||
// 2) Parse HTML + list images (no extensions needed) | |||
return api.get({ | |||
action: 'parse', | |||
page: title, | |||
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 excerpt = makeExcerptFromHTML(html, 420); | |||
var fileTitle = pickImageTitle(images); | |||
// 3) Resolve thumbnail URL (if any) | |||
return getThumbUrl(fileTitle).then(function (thumb) { | |||
render(title, excerpt, thumb); | |||
}); | |||
}); | |||
}).catch(function (e) { | |||
// Graceful fallback | |||
console.warn('Random 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>'; | ||