MediaWiki:Common.js: Difference between revisions
From UAPedia
Jump to navigationJump to search
Created page with "→Any JavaScript here will be loaded for all users on every page load.: // Add a copyable 100px-wide thumb link on File: pages (good for portrait 440x587 -> ~100x133) mw.hook('wikipage.content').add(function ($content) { // Namespace 6 = File: if (mw.config.get('wgNamespaceNumber') !== 6) return; // On File: pages, wgTitle is usually the filename without "File:" var filename = mw.config.get('wgTitle'); if (!filename) return; // Build: /wiki/Special:Redir..." |
No edit summary |
||
| Line 1: | Line 1: | ||
/ | // UAPedia: File-page helper to generate & copy a 100px-wide thumbnail direct URL | ||
mw.hook('wikipage.content').add(function ($content) { | mw.hook('wikipage.content').add(function ($content) { | ||
// | // File namespace only | ||
if (mw.config.get('wgNamespaceNumber') !== 6) return; | if (mw.config.get('wgNamespaceNumber') !== 6) return; | ||
var fileTitle = mw.config.get('wgPageName'); // e.g. "File:Silouette-portrait.webp" | |||
var | if (!fileTitle) return; | ||
if (! | |||
// | var targetWidth = 100; // your desired thumb width (=> ~133px tall for 440x587) | ||
var | var api = new mw.Api(); | ||
function setStatus($box, msg) { | |||
$box.find('.uap-thumb-status').text(msg); | |||
} | |||
function copyText(text, $box) { | |||
if (navigator.clipboard && navigator.clipboard.writeText) { | |||
return navigator.clipboard.writeText(text).then(function () { | |||
setStatus($box, 'Copied!'); | |||
setTimeout(function () { setStatus($box, ''); }, 1200); | |||
}); | |||
} | |||
// fallback | |||
var $tmp = $('<textarea readonly></textarea>').val(text).css({ | |||
position: 'absolute', left: '-9999px', top: '-9999px' | |||
}).appendTo(document.body); | |||
$tmp[0].select(); | |||
try { document.execCommand('copy'); } catch (e) {} | |||
$tmp.remove(); | |||
setStatus($box, 'Copied!'); | |||
setTimeout(function () { setStatus($box, ''); }, 1200); | |||
return Promise.resolve(); | |||
} | |||
function fetchImageInfo() { | |||
// Get original URL + thumb URL at width=100 | |||
return api.get({ | |||
action: 'query', | |||
titles: fileTitle, | |||
prop: 'imageinfo', | |||
iiprop: 'url', | |||
iiurlwidth: targetWidth, | |||
format: 'json' | |||
}).then(function (data) { | |||
var pages = data && data.query && data.query.pages; | |||
if (!pages) throw new Error('No API pages returned'); | |||
var pageId = Object.keys(pages)[0]; | |||
var page = pages[pageId]; | |||
if (!page || !page.imageinfo || !page.imageinfo.length) { | |||
throw new Error('No imageinfo found (is this a file page?)'); | |||
} | |||
var ii = page.imageinfo[0]; | |||
return { | |||
originalUrl: ii.url || '', | |||
thumbUrl: ii.thumburl || '', | |||
thumbWidth: ii.thumbwidth || null, | |||
thumbHeight: ii.thumbheight || null | |||
}; | |||
}); | |||
} | |||
function forceGenerateThumb(thumbUrl, $box) { | |||
// Preload the thumb URL; this usually forces thumb generation if it wasn’t created yet. | |||
return new Promise(function (resolve, reject) { | |||
if (!thumbUrl) return reject(new Error('No thumb URL to generate')); | |||
var img = new Image(); | |||
img.onload = function () { resolve(); }; | |||
img.onerror = function () { reject(new Error('Thumb load failed')); }; | |||
// cache-bust to ensure a request actually happens | |||
img.src = thumbUrl + (thumbUrl.indexOf('?') === -1 ? '?' : '&') + 'uapgen=' + Date.now(); | |||
}); | |||
} | |||
// UI | |||
var $box = $( | |||
'<div class="uap-thumb-linkbox">' + | |||
'<div class="uap-thumb-title"><b>Thumbnail helper</b> <span class="uap-thumb-status"></span></div>' + | |||
'<div class="uap-thumb-row">' + | |||
'<div class="uap-thumb-label">Original file URL</div>' + | |||
'<input class="uap-thumb-input uap-original" type="text" readonly />' + | |||
'<button class="uap-thumb-copy-original mw-ui-button">Copy</button>' + | |||
'</div>' + | |||
'<div class="uap-thumb-row">' + | |||
'<div class="uap-thumb-label">Generate ' + targetWidth + 'px thumb</div>' + | |||
'<button class="uap-thumb-generate mw-ui-button mw-ui-progressive">Generate / Refresh</button>' + | |||
'<span class="uap-thumb-dims"></span>' + | |||
'</div>' + | |||
'<div class="uap-thumb-row">' + | '<div class="uap-thumb-row">' + | ||
'<input class="uap-thumb-input" type="text" readonly />' + | '<div class="uap-thumb-label">Direct thumb URL (' + targetWidth + 'px wide)</div>' + | ||
'<button class="uap-thumb-copy mw-ui-button | '<input class="uap-thumb-input uap-thumb" type="text" readonly />' + | ||
'<button class="uap-thumb-copy-thumb mw-ui-button">Copy</button>' + | |||
'</div>' + | '</div>' + | ||
'<div class="uap-thumb-note">' + | |||
'Use the <b>Direct thumb URL</b> in external <code><img src=""></code> tags. ' + | |||
'It points into <code>/wiki/images/thumb/...</code> and avoids Special-page redirects.' + | |||
'</div>' + | |||
'</div>' | |||
); | |||
// Insert somewhere stable across skins | |||
var $container = $('#mw-content-text'); | |||
($container.length ? $container : $content).prepend($box); | |||
// Wire buttons | |||
var state = { originalUrl: '', thumbUrl: '' }; | |||
function refreshUI(info) { | |||
state.originalUrl = info.originalUrl || ''; | |||
state.thumbUrl = info.thumbUrl || ''; | |||
$box.find('input.uap-original').val(state.originalUrl); | |||
$box.find('input.uap-thumb').val(state.thumbUrl); | |||
if (info.thumbWidth && info.thumbHeight) { | |||
$box.find('.uap-thumb-dims').text('(' + info.thumbWidth + '×' + info.thumbHeight + ')'); | |||
} else { | } else { | ||
$box.find('.uap-thumb-dims').text(''); | |||
} | } | ||
} | |||
function loadOnce() { | |||
setStatus($box, 'Loading…'); | |||
return fetchImageInfo() | |||
.then(function (info) { | |||
refreshUI(info); | |||
setStatus($box, ''); | |||
}) | |||
.catch(function (err) { | |||
setStatus($box, 'Error: ' + err.message); | |||
}); | |||
} | |||
$box.find('.uap-thumb-copy-original').on('click', function () { | |||
if (!state.originalUrl) return setStatus($box, 'No original URL yet'); | |||
copyText(state.originalUrl, $box); | |||
}); | }); | ||
$box.find('.uap-thumb-copy-thumb').on('click', function () { | |||
if (!state.thumbUrl) return setStatus($box, 'No thumb URL yet'); | |||
copyText(state.thumbUrl, $box); | |||
}); | |||
$box.find('.uap-thumb-generate').on('click', function () { | |||
} | setStatus($box, 'Generating…'); | ||
fetchImageInfo() | |||
.then(function (info) { | |||
refreshUI(info); | |||
return forceGenerateThumb(info.thumbUrl, $box).then(function () { | |||
// Re-fetch in case the thumb URL/dims change after generation | |||
return fetchImageInfo().then(function (info2) { | |||
refreshUI(info2); | |||
setStatus($box, 'Generated'); | |||
setTimeout(function () { setStatus($box, ''); }, 1200); | |||
}); | |||
}); | |||
}) | |||
.catch(function (err) { | |||
setStatus($box, 'Error: ' + err.message); | |||
}); | |||
}); | |||
// Initial load | |||
loadOnce(); | |||
}); | }); | ||
Latest revision as of 01:30, 7 February 2026
// UAPedia: File-page helper to generate & copy a 100px-wide thumbnail direct URL
mw.hook('wikipage.content').add(function ($content) {
// File namespace only
if (mw.config.get('wgNamespaceNumber') !== 6) return;
var fileTitle = mw.config.get('wgPageName'); // e.g. "File:Silouette-portrait.webp"
if (!fileTitle) return;
var targetWidth = 100; // your desired thumb width (=> ~133px tall for 440x587)
var api = new mw.Api();
function setStatus($box, msg) {
$box.find('.uap-thumb-status').text(msg);
}
function copyText(text, $box) {
if (navigator.clipboard && navigator.clipboard.writeText) {
return navigator.clipboard.writeText(text).then(function () {
setStatus($box, 'Copied!');
setTimeout(function () { setStatus($box, ''); }, 1200);
});
}
// fallback
var $tmp = $('<textarea readonly></textarea>').val(text).css({
position: 'absolute', left: '-9999px', top: '-9999px'
}).appendTo(document.body);
$tmp[0].select();
try { document.execCommand('copy'); } catch (e) {}
$tmp.remove();
setStatus($box, 'Copied!');
setTimeout(function () { setStatus($box, ''); }, 1200);
return Promise.resolve();
}
function fetchImageInfo() {
// Get original URL + thumb URL at width=100
return api.get({
action: 'query',
titles: fileTitle,
prop: 'imageinfo',
iiprop: 'url',
iiurlwidth: targetWidth,
format: 'json'
}).then(function (data) {
var pages = data && data.query && data.query.pages;
if (!pages) throw new Error('No API pages returned');
var pageId = Object.keys(pages)[0];
var page = pages[pageId];
if (!page || !page.imageinfo || !page.imageinfo.length) {
throw new Error('No imageinfo found (is this a file page?)');
}
var ii = page.imageinfo[0];
return {
originalUrl: ii.url || '',
thumbUrl: ii.thumburl || '',
thumbWidth: ii.thumbwidth || null,
thumbHeight: ii.thumbheight || null
};
});
}
function forceGenerateThumb(thumbUrl, $box) {
// Preload the thumb URL; this usually forces thumb generation if it wasn’t created yet.
return new Promise(function (resolve, reject) {
if (!thumbUrl) return reject(new Error('No thumb URL to generate'));
var img = new Image();
img.onload = function () { resolve(); };
img.onerror = function () { reject(new Error('Thumb load failed')); };
// cache-bust to ensure a request actually happens
img.src = thumbUrl + (thumbUrl.indexOf('?') === -1 ? '?' : '&') + 'uapgen=' + Date.now();
});
}
// UI
var $box = $(
'<div class="uap-thumb-linkbox">' +
'<div class="uap-thumb-title"><b>Thumbnail helper</b> <span class="uap-thumb-status"></span></div>' +
'<div class="uap-thumb-row">' +
'<div class="uap-thumb-label">Original file URL</div>' +
'<input class="uap-thumb-input uap-original" type="text" readonly />' +
'<button class="uap-thumb-copy-original mw-ui-button">Copy</button>' +
'</div>' +
'<div class="uap-thumb-row">' +
'<div class="uap-thumb-label">Generate ' + targetWidth + 'px thumb</div>' +
'<button class="uap-thumb-generate mw-ui-button mw-ui-progressive">Generate / Refresh</button>' +
'<span class="uap-thumb-dims"></span>' +
'</div>' +
'<div class="uap-thumb-row">' +
'<div class="uap-thumb-label">Direct thumb URL (' + targetWidth + 'px wide)</div>' +
'<input class="uap-thumb-input uap-thumb" type="text" readonly />' +
'<button class="uap-thumb-copy-thumb mw-ui-button">Copy</button>' +
'</div>' +
'<div class="uap-thumb-note">' +
'Use the <b>Direct thumb URL</b> in external <code><img src=""></code> tags. ' +
'It points into <code>/wiki/images/thumb/...</code> and avoids Special-page redirects.' +
'</div>' +
'</div>'
);
// Insert somewhere stable across skins
var $container = $('#mw-content-text');
($container.length ? $container : $content).prepend($box);
// Wire buttons
var state = { originalUrl: '', thumbUrl: '' };
function refreshUI(info) {
state.originalUrl = info.originalUrl || '';
state.thumbUrl = info.thumbUrl || '';
$box.find('input.uap-original').val(state.originalUrl);
$box.find('input.uap-thumb').val(state.thumbUrl);
if (info.thumbWidth && info.thumbHeight) {
$box.find('.uap-thumb-dims').text('(' + info.thumbWidth + '×' + info.thumbHeight + ')');
} else {
$box.find('.uap-thumb-dims').text('');
}
}
function loadOnce() {
setStatus($box, 'Loading…');
return fetchImageInfo()
.then(function (info) {
refreshUI(info);
setStatus($box, '');
})
.catch(function (err) {
setStatus($box, 'Error: ' + err.message);
});
}
$box.find('.uap-thumb-copy-original').on('click', function () {
if (!state.originalUrl) return setStatus($box, 'No original URL yet');
copyText(state.originalUrl, $box);
});
$box.find('.uap-thumb-copy-thumb').on('click', function () {
if (!state.thumbUrl) return setStatus($box, 'No thumb URL yet');
copyText(state.thumbUrl, $box);
});
$box.find('.uap-thumb-generate').on('click', function () {
setStatus($box, 'Generating…');
fetchImageInfo()
.then(function (info) {
refreshUI(info);
return forceGenerateThumb(info.thumbUrl, $box).then(function () {
// Re-fetch in case the thumb URL/dims change after generation
return fetchImageInfo().then(function (info2) {
refreshUI(info2);
setStatus($box, 'Generated');
setTimeout(function () { setStatus($box, ''); }, 1200);
});
});
})
.catch(function (err) {
setStatus($box, 'Error: ' + err.message);
});
});
// Initial load
loadOnce();
});