MediaWiki:Gadget-CargoHelper.js
From Angelina Jordan Wiki
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.
/* Gadget-CargoHelper.js
Lightweight loader for the CargoHelper gadget.
Loads the full Core module only when needed.
*/
( function () {
'use strict';
/*****************************************************************
* 1. Fast client-side checks
*****************************************************************/
function hasSongTemplate_Comment() {
var html = document.documentElement.innerHTML;
return html.indexOf(" Template:Infobox_song") !== -1;
}
function hasSongCategory() {
var CAT = "Songs";
var links = document.querySelectorAll('#mw-normal-catlinks a, #mw-hidden-catlinks a');
for (var i = 0; i < links.length; i++) {
var href = links[i].getAttribute('href') || "";
if (href.endsWith("/" + CAT.replace(/ /g, "_"))) {
console.log("CargoHelper: Songs category found")
return true;
}
}
return false;
}
function isSongPage_ClientOnly() {
var action = mw.config.get('wgAction');
if (action === 'view') {
if (hasSongTemplate_Comment()) {
console.log("CargoHelper: found {{Infobox song}} trace");
return true;
}
if (hasSongCategory()) return true;
return false;
}
if (action === 'edit') {
var ta = document.getElementById('wpTextbox1');
if (!ta) return false;
return /\{\{\s*Infobox song\b/i.test(ta.value);
}
return false;
}
function isSongNamespace() {
var ns = mw.config.get('wgNamespaceNumber');
var title = mw.config.get('wgPageName') || '';
if (ns !== 0) return false;
if (!title || title.indexOf(':') !== -1) return false;
return true;
}
/*****************************************************************
* 2. Popup dialog for warnings
*****************************************************************/
function showInfoDialog(message) {
mw.loader.using( ['oojs-ui-core', 'oojs-ui-windows'] ).then(function () {
function InfoDialog(config) { InfoDialog.super.call(this, config); }
OO.inheritClass(InfoDialog, OO.ui.MessageDialog);
InfoDialog.static.name = 'CargoHelperInfo';
InfoDialog.static.title = 'Cargo Helper';
InfoDialog.static.actions = [
{ action: 'close', label: 'Close', flags: ['primary'] }
];
var winMgr = new OO.ui.WindowManager();
$(document.body).append(winMgr.$element);
var dlg = new InfoDialog();
winMgr.addWindows([dlg]);
winMgr.openWindow(dlg, { message: message });
});
}
/*****************************************************************
* 3. Server-side check: Song entry in Cargo:Songs
*****************************************************************/
function fetchSongCargoEntry() {
return mw.loader.using('mediawiki.api').then(function () {
var page = mw.config.get('wgPageName') || '';
page = page.replace(/_/g, ' ');
page = $('<textarea/>').html(page).text();
var api = new mw.Api();
return api.get({
action: 'cargoquery',
tables: 'Songs',
fields: 'page',
where: 'page = "' + page.replace(/"/g, '\\"') + '"',
limit: 1
}).then(function (data) {
if (!data.cargoquery || !data.cargoquery.length) return null;
return data.cargoquery[0].title || null;
}).catch(function () { return null; });
});
}
function runSongPageCheck() {
return new Promise(function (resolve) {
fetchSongCargoEntry().then(function (row) {
if (!row) {
showInfoDialog(
'This page has no entry in the Songs Cargo table.\n' +
'The tool only works if the page uses {{Infobox song}} or {{Songs}}.'
);
resolve(false);
} else {
resolve(true);
}
});
});
}
/*****************************************************************
* 4. Add the "Add video" link (but only if likely a song page)
*****************************************************************/
function addActionLink() {
if (!mw.config.get('wgIsProbablyEditable')) return;
var ns = mw.config.get('wgNamespaceNumber');
var title = mw.config.get('wgPageName') || '';
if (ns !== 0 || !title || title.indexOf(':') !== -1) return;
if (!isSongPage_ClientOnly()) return;
var link,
portletIdCandidates = [ 'p-views', 'p-cactions' ];
for (var i = 0; i < portletIdCandidates.length && !link; i++) {
link = mw.util.addPortletLink(
portletIdCandidates[i],
'#',
'Add video',
'ca-add-video',
'Add a video / performance entry'
);
}
if (!link) {
var container = document.querySelector('.mw-page-actions, #p-views ul, #p-cactions ul');
if (container) {
var li = document.createElement('li');
var a = document.createElement('a');
a.href = '#';
a.id = 'ca-add-video';
a.textContent = 'Add video';
li.appendChild(a);
container.appendChild(li);
link = a;
}
}
if (!link) return;
$(link).on('click', function (e) {
e.preventDefault();
runSongPageCheck().then(function (allowed) {
if (!allowed) return;
// Lazy-load the Core module
mw.loader.using('ext.gadget.CargoHelperCore').then(function () {
if (window.CargoHelper && window.CargoHelper.ready) {
// Wait for full initialization
window.CargoHelper.ready.then(function() {
window.CargoHelper.openDialog();
}).catch(function(err) {
console.error('CargoHelperCore ready promise rejected:', err);
});
} else {
console.error('CargoHelperCore loaded, but ready promise not found.');
}
});
});
});
}
addActionLink();
}());