MediaWiki:Common.js: Difference between revisions
From Sanatan Hindu Dharma
No edit summary |
No edit summary |
||
| Line 565: | Line 565: | ||
}); | }); | ||
| Line 577: | Line 578: | ||
mw.loader.using( [ 'mediawiki.util', 'mediawiki.api' ] ).then( function () { | mw.loader.using( [ 'mediawiki.util', 'mediawiki.api' ] ).then( function () { | ||
const api = new mw.Api(); | |||
const isLoggedIn = !!mw.config.get( 'wgUserName' ); | |||
const cfg = { | |||
minSearchChars: 2, | minSearchChars: 2, | ||
searchLimit: 8, | searchLimit: 8, | ||
subpageSeparator: '/', | subpageSeparator: '/', | ||
categoryNs: | categoryNs: 14 // Category namespace | ||
}; | }; | ||
/* ------------------------- Category Prompt ------------------------- */ | |||
if ( isLoggedIn && mw.config.get('wgNamespaceNumber') === cfg.categoryNs ) { | |||
const catBaseTitle = mw.config.get('wgTitle'); | |||
const storageKey = 'auto_create_page_for_category_' + catBaseTitle; | |||
function askAndCreateCategoryPage() { | |||
if ( sessionStorage.getItem( storageKey ) ) return; | |||
sessionStorage.setItem( storageKey, 'done' ); | |||
const ok = window.confirm( | |||
`✅ You just created the new category "${catBaseTitle}".\n\n` + | |||
`Do you want to create a mainspace page with the same name? It will automatically belong to this category.` | |||
); | |||
if ( ok ) { | |||
const mainTitle = catBaseTitle; // main namespace page | |||
const url = mw.util.getUrl(mainTitle, { | |||
action: 'edit', | |||
veaction: 'edit', | |||
preloadtext: '[[' + 'Category:' + catBaseTitle + ']]\n\n' | |||
}); | |||
window.location.href = url; | |||
} | } | ||
} | } | ||
// | // Trigger after save (SourceEditor + VE) | ||
mw.hook('postEdit').add(askAndCreateCategoryPage); | |||
// VE | // Fallback for VE popstate | ||
$( window ).on( 'popstate', function () { | $(window).on('popstate', function () { | ||
if ( mw.config.get('wgAction') !== 'view' ) return; | |||
if ( mw.config.get( 'wgAction' ) !== 'view' ) return; | if ( sessionStorage.getItem(storageKey) ) return; | ||
api.get({ | |||
api.get( { | |||
action: 'query', | action: 'query', | ||
titles: 'Category:' + catBaseTitle, | titles: 'Category:' + catBaseTitle, | ||
prop: 'info', | prop: 'info', | ||
format: 'json' | format: 'json' | ||
} ).done( function ( data ) { | }).done(function (data) { | ||
const page = Object.values(data.query.pages)[0]; | |||
if ( page && typeof page.missing === 'undefined' ) { | |||
askAndCreateCategoryPage(); | |||
} | } | ||
} ) | }); | ||
}); | |||
} | |||
/* ------------------------- Parent Page Prompt ------------------------- */ | |||
function searchPages( query ) { | |||
if ( !query || query.length < cfg.minSearchChars ) return Promise.resolve([]); | |||
return api.get({ | |||
/* ------------------------- Parent | |||
function searchPages( | |||
if ( ! | |||
return api.get( { | |||
action: 'opensearch', | action: 'opensearch', | ||
search: | search: query, | ||
limit: cfg.searchLimit, | limit: cfg.searchLimit, | ||
namespace: 0 | namespace: 0 | ||
}).then(data => data[1] || []).catch(() => []); | |||
} ).then | |||
} | } | ||
function promptForParentTitle() { | |||
function promptForParentTitle( | return new Promise( resolve => { | ||
const $overlay = $('<div>').css({ | |||
return new Promise | position: 'fixed', top:0,left:0,width:'100%',height:'100%', | ||
background:'rgba(0,0,0,0.45)', display:'flex', alignItems:'center', justifyContent:'center', | |||
zIndex:999999 | |||
position: 'fixed', top: 0, left: 0, | }); | ||
background: 'rgba(0,0,0,0.45)', display: 'flex', alignItems: 'center', justifyContent: 'center', | const $box = $('<div>').css({ | ||
zIndex: 999999 | background:'#fff', padding:'18px', borderRadius:'8px', width:'420px', boxShadow:'0 6px 18px rgba(0,0,0,0.3)' | ||
} ); | }); | ||
$box.append($('<h3/>').text('Select Parent Page')); | |||
background: '#fff', padding: '18px', borderRadius: '8px', width: '420px', boxShadow: '0 6px 18px rgba(0,0,0,0.3)' | const $input = $('<input type="search"/>').css({ width:'100%', padding:'8px', border:'1px solid #ccc', borderRadius:'4px' }); | ||
} ); | const $list = $('<ul/>').css({ listStyle:'none', margin:'10px 0 0', padding:0, maxHeight:'150px', overflowY:'auto', border:'1px solid #eee', borderRadius:'4px' }).hide(); | ||
$box.append( $( '<h3/>' ).text( 'Select Parent Page' ) ); | const $btns = $('<div/>').css({ marginTop:'12px', textAlign:'right' }); | ||
const $confirm = $('<button/>').text('Confirm').css({ marginRight:'8px' }); | |||
const $noParent = $('<button/>').text('No Parent'); | |||
$btns.append($confirm,$noParent); | |||
$box.append($input,$list,$btns); | |||
$overlay.append($box); | |||
$('body').append($overlay); | |||
$btns.append( $confirm, $noParent ); | |||
$box.append( $input, $list, $btns ); | |||
$overlay.append( $box ); | |||
$( 'body' ).append( $overlay ); | |||
let debounce; | |||
$input.on( 'input', function () { | $input.on('input', function(){ | ||
const q = $input.val().trim(); | |||
if ( debounce ) clearTimeout( debounce ); | if ( debounce ) clearTimeout(debounce); | ||
debounce = setTimeout( | debounce = setTimeout(()=>{ | ||
if ( q.length < cfg.minSearchChars ) { | if ( q.length < cfg.minSearchChars ) { $list.empty().hide(); return; } | ||
$list.empty().show().append($('<li/>').text('Searching…').css({ color:'#666', padding:'6px' })); | |||
searchPages(q).then(titles=>{ | |||
$list.empty().show().append( $( '<li/>' ).text( 'Searching…' ).css( { color: '#666', padding: '6px' } ) ); | |||
searchPages( q ).then | |||
$list.empty(); | $list.empty(); | ||
if ( ! | if (!titles.length){ $list.append($('<li/>').text('No results').css({color:'#666',padding:'6px'})); return; } | ||
titles.forEach(t=>{ | |||
const $li = $('<li/>').text(t).css({ padding:'6px 10px', cursor:'pointer' }); | |||
$li.on('click', ()=>{ $input.val(t); $list.hide(); }); | |||
titles.forEach | $li.hover(()=>{$li.css('background','#f5f5f5');}, ()=>{$li.css('background','');}); | ||
$list.append($li); | |||
$li.on( 'click', | }); | ||
}); | |||
},220); | |||
}); | |||
$li.hover( | |||
$list.append( $li ); | |||
} ); | |||
} ); | |||
}, 220 ); | |||
} ); | |||
$confirm.on( 'click', | $confirm.on('click', ()=>{ cleanup(); resolve($input.val().trim() || null); }); | ||
$noParent.on('click', ()=>{ cleanup(); resolve(null); }); | |||
$overlay.on('click', e=>{ if(e.target===$overlay[0]){} }); | |||
} ); | |||
function cleanup(){ $overlay.remove(); } | |||
}); | |||
} ); | |||
} | } | ||
function askParentIfNewPage() { | |||
function | if ( mw.config.get('wgAction') !== 'edit' ) return; | ||
if ( mw.config.get('wgNamespaceNumber') !== 0 ) return; | |||
if ( | |||
const pageKey = 'parent_prompt_' + mw.config.get('wgPageName'); | |||
if ( | if ( sessionStorage.getItem(pageKey) ) return; | ||
sessionStorage.setItem(pageKey,'done'); | |||
setTimeout(async ()=>{ | |||
setTimeout( | const selected = await promptForParentTitle(); | ||
promptForParentTitle( | const title = mw.config.get('wgPageName'); | ||
if ( selected === null ) { // No parent | |||
window.location.href = mw.util.getUrl(title, { veaction:'edit' }); | |||
window.location.href = mw.util.getUrl( | |||
return; | return; | ||
} | } | ||
const childSegment = title.includes(cfg.subpageSeparator) ? title.split(cfg.subpageSeparator).pop() : title; | |||
const newTitle = selected + cfg.subpageSeparator + childSegment; | |||
window.location.href = mw.util.getUrl(newTitle, { veaction:'edit' }); | |||
}, 600); | |||
} | |||
window.location.href = mw.util.getUrl( newTitle, { veaction: 'edit' } ); | |||
} ); | |||
} | |||
$(function(){ | |||
if ( mw.config.get('wgAction')==='edit' ) askParentIfNewPage(); | |||
try{ mw.hook('ve.activationComplete').add(askParentIfNewPage); }catch(e){} | |||
}); | |||
// | /* ------------------------- Reminder banner ------------------------- */ | ||
try { | try{ | ||
mw.hook( 'wikipage.content' ).add( function ( $content ) { | mw.hook('wikipage.content').add(function($content){ | ||
const action = mw.config.get('wgAction'); | |||
if ( action === 'edit' || action === 'submit' ) { | if ( action==='edit' || action==='submit' ){ | ||
$content.prepend($('<div/>').css({ | |||
background: '#fff8c4', border: '1px solid #e0c14b', padding: '10px', marginBottom: '10px', | background:'#fff8c4',border:'1px solid #e0c14b',padding:'10px',marginBottom:'10px',borderRadius:'6px',textAlign:'center',fontWeight:600 | ||
}).text('🪶 Tip: Remember to set a parent page before saving.')); | |||
} ).text( '🪶 Tip: Remember to set a parent page before saving.' ) | |||
} | } | ||
} ); | }); | ||
} catch ( e ) { | }catch(e){} | ||
console.log('✅ Category + Parent prompt JS initialized.'); | |||
} ).catch | }).catch( err => console.error('LeadWriterControl loader error:', err) ); | ||
} )( mediaWiki, jQuery ); | } )( mediaWiki, jQuery ); | ||
Revision as of 15:48, 5 November 2025
mw.loader.using('mediawiki.util').done(function () {
console.log("Common.js loaded safely");
});
/* Any JavaScript here will be loaded for all users on every page load. */
/*
document.addEventListener("DOMContentLoaded", function() {
const btn = document.querySelector(".toggle-btn");
const content = document.querySelector(".toggle-content");
if (btn && content) {
btn.addEventListener("click", function() {
content.style.display = (content.style.display === "block") ? "none" : "block";
});
}
});
// Auto-add parent category when editing/creating a subpage
( function () {
if ( mw.config.get('wgAction') !== 'edit' ) return;
// wgTitle contains title without namespace, e.g. "Ancient-education/Subpage"
var title = mw.config.get('wgTitle') || '';
if ( title.indexOf('/') === -1 ) return; // not a subpage
var parent = title.split('/')[0]; // "Ancient-education"
// jQuery available
$( function () {
var textarea = $('#wpTextbox1');
if ( !textarea.length ) return;
// Only append if not present
var current = textarea.val() || '';
var catTag = '\n[[Category:' + parent + ']]';
if ( current.indexOf(catTag.trim()) === -1 ) {
// Insert the category at the end of the text area (preserve existing text)
textarea.val(current + catTag);
}
} );
}() );
$(document).ready(function () {
// Skip special pages
if (mw.config.get('wgNamespaceNumber') < 0) return;
var $content = $('#mw-content-text');
// Fetch all page titles from the API (main namespace only)
$.get(mw.util.wikiScript('api'), {
action: 'query',
list: 'allpages',
aplimit: 'max',
format: 'json'
}).done(function (data) {
var titles = data.query.allpages.map(function (p) { return p.title; });
var html = $content.html();
titles.forEach(function (title) {
// Safe regex for whole words
var safeTitle = title.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
var regex = new RegExp('\\b(' + safeTitle + ')\\b', 'g');
html = html.replace(regex, '<a href="/wiki/' + encodeURIComponent(title.replace(/ /g, '_')) + '">$1</a>');
});
$content.html(html);
});
});
$(document).ready(function() {
if (mw.config.get('wgNamespaceNumber') >= 0) { // Only show on normal pages
var pageName = mw.config.get('wgPageName');
var uploadUrl = mw.util.getUrl('Form:UploadVideo', { 'page': pageName });
$('<div style="position:fixed; bottom:20px; right:20px; background:#007bff; color:white; padding:10px; border-radius:5px; cursor:pointer; font-weight:bold;">Upload a Video</div>')
.click(function() {
window.location.href = uploadUrl;
}).appendTo('body');
}
});
*/
/* Functions of Slider One */
(function () {
function initSliders() {
var sliders = document.querySelectorAll('.mw-slider');
sliders.forEach(function (slider) {
// Avoid double-init
if (slider._mwSliderInited) return;
slider._mwSliderInited = true;
var viewport = slider.querySelector('.mw-slider-viewport');
var track = slider.querySelector('.mw-slider-track');
var items = Array.from(slider.querySelectorAll('.mw-slider-item'));
var btnPrev = slider.querySelector('.mw-slider-btn.prev');
var btnNext = slider.querySelector('.mw-slider-btn.next');
var currentIndex = 0;
var itemsToShow = getItemsToShow();
var gap = parseFloat(getComputedStyle(track).columnGap || getComputedStyle(track).gap || 16);
function getItemsToShow() {
var w = window.innerWidth;
if (w <= 600) return 1;
if (w <= 900) return 2;
return 3;
}
function updateSizes() {
itemsToShow = getItemsToShow();
// compute single item width including gap
if (!items[0]) return;
var itemRect = items[0].getBoundingClientRect();
gap = parseFloat(getComputedStyle(track).columnGap || getComputedStyle(track).gap || 16);
var single = itemRect.width + gap;
// ensure currentIndex in range
var maxIndex = Math.max(0, items.length - itemsToShow);
currentIndex = Math.min(currentIndex, maxIndex);
// apply transform
var translateX = -currentIndex * single;
track.style.transform = 'translateX(' + translateX + 'px)';
updateButtons();
}
function updateButtons() {
var maxIndex = Math.max(0, items.length - itemsToShow);
if (btnPrev) btnPrev.disabled = currentIndex <= 0;
if (btnNext) btnNext.disabled = currentIndex >= maxIndex;
}
function gotoIndex(index) {
var maxIndex = Math.max(0, items.length - itemsToShow);
currentIndex = Math.max(0, Math.min(maxIndex, index));
updateSizes();
}
if (btnPrev) btnPrev.addEventListener('click', function () {
gotoIndex(currentIndex - 1);
});
if (btnNext) btnNext.addEventListener('click', function () {
gotoIndex(currentIndex + 1);
});
// Keyboard support
slider.addEventListener('keydown', function (e) {
if (e.key === 'ArrowLeft') gotoIndex(currentIndex - 1);
if (e.key === 'ArrowRight') gotoIndex(currentIndex + 1);
});
// Resize handling
var resizeTimeout;
window.addEventListener('resize', function () {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(updateSizes, 120);
});
// Touch / drag support
(function () {
var startX = 0;
var currentTranslate = 0;
var dragging = false;
var pointerId = null;
function pointerDown(e) {
if (e.pointerType === 'mouse' && e.button !== 0) return;
dragging = true;
pointerId = e.pointerId;
startX = e.clientX;
track.style.transition = 'none';
track.setPointerCapture && track.setPointerCapture(pointerId);
}
function pointerMove(e) {
if (!dragging || e.pointerId !== pointerId) return;
var dx = e.clientX - startX;
var itemRect = items[0] && items[0].getBoundingClientRect();
var single = itemRect ? (itemRect.width + gap) : 0;
var baseTranslate = -currentIndex * single;
track.style.transform = 'translateX(' + (baseTranslate + dx) + 'px)';
}
function pointerUp(e) {
if (!dragging || e.pointerId !== pointerId) return;
dragging = false;
track.style.transition = '';
var dx = e.clientX - startX;
var threshold = Math.max(40, (items[0] ? items[0].getBoundingClientRect().width : 200) * 0.15);
if (dx > threshold) {
gotoIndex(currentIndex - 1);
} else if (dx < -threshold) {
gotoIndex(currentIndex + 1);
} else {
updateSizes();
}
try { track.releasePointerCapture(pointerId); } catch (err) {}
pointerId = null;
}
track.addEventListener('pointerdown', pointerDown);
window.addEventListener('pointermove', pointerMove);
window.addEventListener('pointerup', pointerUp);
track.addEventListener('pointercancel', pointerUp);
})();
// Initial sizes
setTimeout(updateSizes, 60);
});
}
// init on DOM ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initSliders);
} else {
initSliders();
}
// If new content is loaded via AJAX on the wiki, re-init
if (window.mw && mw.hook) {
mw.hook('wikipage.content').add(initSliders);
}
})();
/* Full width Slider */
(function () {
function initFullSliders() {
var sliders = document.querySelectorAll('.mw-fullslider');
sliders.forEach(function (slider) {
if (slider._fullSliderInit) return;
slider._fullSliderInit = true;
var track = slider.querySelector('.mw-fullslider-track');
var slides = Array.from(track.children);
var btnPrev = slider.querySelector('.mw-fullslider-btn.prev');
var btnNext = slider.querySelector('.mw-fullslider-btn.next');
var dots = Array.from(slider.querySelectorAll('.mw-fullslider-dots .dot'));
var current = 0;
var slideCount = slides.length;
function goTo(index, animate) {
current = (index % slideCount + slideCount) % slideCount;
var x = -current * slider.clientWidth;
if (animate === false) track.style.transition = 'none';
else track.style.transition = '';
track.style.transform = 'translateX(' + x + 'px)';
updateControls();
if (animate === false) {
// force reflow then restore
void track.offsetWidth;
track.style.transition = '';
}
}
function updateControls() {
if (btnPrev) btnPrev.disabled = false;
if (btnNext) btnNext.disabled = false;
// update dots
dots.forEach(function (d) {
d.classList.toggle('active', +d.getAttribute('data-index') === current);
d.setAttribute('aria-pressed', (+d.getAttribute('data-index') === current).toString());
});
}
if (btnPrev) btnPrev.addEventListener('click', function () { goTo(current - 1); });
if (btnNext) btnNext.addEventListener('click', function () { goTo(current + 1); });
dots.forEach(function (dot) {
dot.addEventListener('click', function () {
var idx = parseInt(this.getAttribute('data-index'), 10);
goTo(idx);
});
});
// Resize handling: ensure slide width matches viewport
var resizeTimer;
function onResize() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
// Recompute translate in case width changed
goTo(current, false);
}, 80);
}
window.addEventListener('resize', onResize);
// Touch / drag support
(function () {
var startX = 0, startTranslate = 0, dragging = false, pointerId = null;
function down(e) {
if (e.pointerType === 'mouse' && e.button !== 0) return;
dragging = true;
pointerId = e.pointerId;
startX = e.clientX;
var style = window.getComputedStyle(track);
var matrix = new WebKitCSSMatrix(style.transform);
startTranslate = matrix.m41 || 0;
track.style.transition = 'none';
e.target.setPointerCapture && e.target.setPointerCapture(pointerId);
}
function move(e) {
if (!dragging || e.pointerId !== pointerId) return;
var dx = e.clientX - startX;
track.style.transform = 'translateX(' + (startTranslate + dx) + 'px)';
}
function up(e) {
if (!dragging || e.pointerId !== pointerId) return;
dragging = false;
track.style.transition = '';
var dx = e.clientX - startX;
var threshold = Math.max(40, slider.clientWidth * 0.12);
if (dx > threshold) goTo(current - 1);
else if (dx < -threshold) goTo(current + 1);
else goTo(current);
try { e.target.releasePointerCapture(pointerId); } catch (err) {}
pointerId = null;
}
track.addEventListener('pointerdown', down);
window.addEventListener('pointermove', move);
window.addEventListener('pointerup', up);
track.addEventListener('pointercancel', up);
})();
// Autoplay (optional): change interval or set autoplay = false
var autoplay = true;
var autoplayInterval = 4500; // ms
var autoplayTimer = null;
function startAutoplay() {
if (!autoplay) return;
stopAutoplay();
autoplayTimer = setInterval(function () { goTo(current + 1); }, autoplayInterval);
}
function stopAutoplay() {
if (autoplayTimer) { clearInterval(autoplayTimer); autoplayTimer = null; }
}
slider.addEventListener('mouseenter', stopAutoplay);
slider.addEventListener('mouseleave', startAutoplay);
slider.addEventListener('focusin', stopAutoplay);
slider.addEventListener('focusout', startAutoplay);
// Respect prefers-reduced-motion
var rmq = window.matchMedia('(prefers-reduced-motion: reduce)');
if (rmq.matches) autoplay = false;
// Ensure initial sizing: make each slide exactly slider.clientWidth
function layoutSlides() {
var w = slider.clientWidth;
slides.forEach(function (s) { s.style.minWidth = w + 'px'; s.style.maxWidth = w + 'px'; });
goTo(current, false);
}
// Wait for images then layout
function imgsReady(cb) {
var imgs = Array.from(slider.querySelectorAll('img'));
var rem = imgs.length;
if (!rem) return cb();
imgs.forEach(function (img) {
if (img.complete) { rem--; if (!rem) cb(); }
else {
img.addEventListener('load', function () { rem--; if (!rem) cb(); });
img.addEventListener('error', function () { rem--; if (!rem) cb(); });
}
});
}
imgsReady(function () {
layoutSlides();
startAutoplay();
window.addEventListener('resize', onResize);
});
// expose for debug (optional)
slider._goTo = goTo;
});
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initFullSliders);
else initFullSliders();
if (window.mw && mw.hook) mw.hook('wikipage.content').add(initFullSliders);
})();
// --- Disable Tools Option for all users except admin ---
mw.loader.using(['mediawiki.user'], function () {
$(function () {
mw.user.getGroups().then(function (groups) {
// If the user is NOT an admin (sysop)
if (groups.indexOf('sysop') === -1) {
// Disable Tools menu and its dropdown items
$('a, span').filter(function () {
return $(this).text().trim() === 'Tools';
}).each(function () {
const link = $(this);
link.css({
'pointer-events': 'none',
'opacity': '0.5',
'cursor': 'not-allowed'
});
link.attr('title', 'Restricted to admins');
link.closest('.dropdown').find('a').css({
'pointer-events': 'none',
'opacity': '0.5',
'cursor': 'not-allowed'
});
});
// Disable any link to Special:SpecialPages
$('a[href*="Special:SpecialPages"]').css({
'pointer-events': 'none',
'opacity': '0.5',
'cursor': 'not-allowed'
}).attr('title', 'Restricted to admins');
// Disable MediaWiki namespace links
$('a[href*="MediaWiki:"]').css({
'pointer-events': 'none',
'opacity': '0.5',
'cursor': 'not-allowed'
}).attr('title', 'Restricted to admins');
}
});
});
});
// Collapsible Related Pages on Mobile
mw.loader.using('jquery', function () {
$(function () {
var header = $('.page-links-header');
var content = $('.page-links-content');
if (header.length && content.length) {
header.on('click', function () {
$(this).toggleClass('active');
content.toggleClass('open');
});
}
});
});
/* === Auto-Link Page Titles in Paragraphs (exclude header/footer) === */
(function (mw, $) {
'use strict';
var MAX_TITLES = 1000;
function escapeRegExp(s) {
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function run(titles) {
if (!titles || titles.length === 0) return;
var filtered = titles
.filter(function (t) {
return t && t.length > 3;
})
.sort(function (a, b) {
return b.length - a.length;
})
.slice(0, MAX_TITLES);
// Select only main content paragraphs (not header/footer)
$('#content p').each(function () {
if ($(this).find('a, code, pre, .no-auto-link').length) return;
var html = $(this).html();
filtered.forEach(function (title) {
var display = title.includes(':')
? title.split(':').pop()
: title;
var pattern = display.replace(/[_-]+/g, '[ _-]');
var re = new RegExp('\\b' + escapeRegExp(pattern) + '\\b', 'gi');
html = html.replace(re, function (match) {
return (
'<a href="' +
mw.util.getUrl(title) +
'" class="auto-linked-page">' +
match +
'</a>'
);
});
});
$(this).html(html);
});
}
$(function () {
var title = mw.config.get('wgPageName');
if (!title) return;
$.getJSON(
mw.util.wikiScript() +
'?title=Special:AutoLinkTitles&format=json&pageTitle=' +
encodeURIComponent(title)
)
.done(function (data) {
if (data && Array.isArray(data.titles)) {
run(data.titles);
}
})
.fail(function () {
console.warn('AutoLinkTitles: failed to load title list.');
});
});
})(mediaWiki, jQuery);
// == Showing Template as default footer
$(document).ready(function () {
// Remove Chameleon’s default footer
$('.footercontainer, #footer, #mw-footer').remove();
// Prevent duplicate inserts
if ($('#mw-custom-footer').length) return;
// Load your custom footer
$.ajax({
url: '/index.php?title=Template:Custom-footer&action=render',
type: 'GET',
success: function (data) {
const footer = $('<div id="mw-custom-footer"></div>').html(data);
$('body').append(footer);
},
error: function () {
console.warn('⚠️ Custom footer could not be loaded.');
}
});
});
( function ( mw, $ ) {
'use strict';
mw.loader.using( [ 'mediawiki.util', 'mediawiki.api' ] ).then( function () {
const api = new mw.Api();
const isLoggedIn = !!mw.config.get( 'wgUserName' );
const cfg = {
minSearchChars: 2,
searchLimit: 8,
subpageSeparator: '/',
categoryNs: 14 // Category namespace
};
/* ------------------------- Category Prompt ------------------------- */
if ( isLoggedIn && mw.config.get('wgNamespaceNumber') === cfg.categoryNs ) {
const catBaseTitle = mw.config.get('wgTitle');
const storageKey = 'auto_create_page_for_category_' + catBaseTitle;
function askAndCreateCategoryPage() {
if ( sessionStorage.getItem( storageKey ) ) return;
sessionStorage.setItem( storageKey, 'done' );
const ok = window.confirm(
`✅ You just created the new category "${catBaseTitle}".\n\n` +
`Do you want to create a mainspace page with the same name? It will automatically belong to this category.`
);
if ( ok ) {
const mainTitle = catBaseTitle; // main namespace page
const url = mw.util.getUrl(mainTitle, {
action: 'edit',
veaction: 'edit',
preloadtext: '[[' + 'Category:' + catBaseTitle + ']]\n\n'
});
window.location.href = url;
}
}
// Trigger after save (SourceEditor + VE)
mw.hook('postEdit').add(askAndCreateCategoryPage);
// Fallback for VE popstate
$(window).on('popstate', function () {
if ( mw.config.get('wgAction') !== 'view' ) return;
if ( sessionStorage.getItem(storageKey) ) return;
api.get({
action: 'query',
titles: 'Category:' + catBaseTitle,
prop: 'info',
format: 'json'
}).done(function (data) {
const page = Object.values(data.query.pages)[0];
if ( page && typeof page.missing === 'undefined' ) {
askAndCreateCategoryPage();
}
});
});
}
/* ------------------------- Parent Page Prompt ------------------------- */
function searchPages( query ) {
if ( !query || query.length < cfg.minSearchChars ) return Promise.resolve([]);
return api.get({
action: 'opensearch',
search: query,
limit: cfg.searchLimit,
namespace: 0
}).then(data => data[1] || []).catch(() => []);
}
function promptForParentTitle() {
return new Promise( resolve => {
const $overlay = $('<div>').css({
position: 'fixed', top:0,left:0,width:'100%',height:'100%',
background:'rgba(0,0,0,0.45)', display:'flex', alignItems:'center', justifyContent:'center',
zIndex:999999
});
const $box = $('<div>').css({
background:'#fff', padding:'18px', borderRadius:'8px', width:'420px', boxShadow:'0 6px 18px rgba(0,0,0,0.3)'
});
$box.append($('<h3/>').text('Select Parent Page'));
const $input = $('<input type="search"/>').css({ width:'100%', padding:'8px', border:'1px solid #ccc', borderRadius:'4px' });
const $list = $('<ul/>').css({ listStyle:'none', margin:'10px 0 0', padding:0, maxHeight:'150px', overflowY:'auto', border:'1px solid #eee', borderRadius:'4px' }).hide();
const $btns = $('<div/>').css({ marginTop:'12px', textAlign:'right' });
const $confirm = $('<button/>').text('Confirm').css({ marginRight:'8px' });
const $noParent = $('<button/>').text('No Parent');
$btns.append($confirm,$noParent);
$box.append($input,$list,$btns);
$overlay.append($box);
$('body').append($overlay);
let debounce;
$input.on('input', function(){
const q = $input.val().trim();
if ( debounce ) clearTimeout(debounce);
debounce = setTimeout(()=>{
if ( q.length < cfg.minSearchChars ) { $list.empty().hide(); return; }
$list.empty().show().append($('<li/>').text('Searching…').css({ color:'#666', padding:'6px' }));
searchPages(q).then(titles=>{
$list.empty();
if (!titles.length){ $list.append($('<li/>').text('No results').css({color:'#666',padding:'6px'})); return; }
titles.forEach(t=>{
const $li = $('<li/>').text(t).css({ padding:'6px 10px', cursor:'pointer' });
$li.on('click', ()=>{ $input.val(t); $list.hide(); });
$li.hover(()=>{$li.css('background','#f5f5f5');}, ()=>{$li.css('background','');});
$list.append($li);
});
});
},220);
});
$confirm.on('click', ()=>{ cleanup(); resolve($input.val().trim() || null); });
$noParent.on('click', ()=>{ cleanup(); resolve(null); });
$overlay.on('click', e=>{ if(e.target===$overlay[0]){} });
function cleanup(){ $overlay.remove(); }
});
}
function askParentIfNewPage() {
if ( mw.config.get('wgAction') !== 'edit' ) return;
if ( mw.config.get('wgNamespaceNumber') !== 0 ) return;
const pageKey = 'parent_prompt_' + mw.config.get('wgPageName');
if ( sessionStorage.getItem(pageKey) ) return;
sessionStorage.setItem(pageKey,'done');
setTimeout(async ()=>{
const selected = await promptForParentTitle();
const title = mw.config.get('wgPageName');
if ( selected === null ) { // No parent
window.location.href = mw.util.getUrl(title, { veaction:'edit' });
return;
}
const childSegment = title.includes(cfg.subpageSeparator) ? title.split(cfg.subpageSeparator).pop() : title;
const newTitle = selected + cfg.subpageSeparator + childSegment;
window.location.href = mw.util.getUrl(newTitle, { veaction:'edit' });
}, 600);
}
$(function(){
if ( mw.config.get('wgAction')==='edit' ) askParentIfNewPage();
try{ mw.hook('ve.activationComplete').add(askParentIfNewPage); }catch(e){}
});
/* ------------------------- Reminder banner ------------------------- */
try{
mw.hook('wikipage.content').add(function($content){
const action = mw.config.get('wgAction');
if ( action==='edit' || action==='submit' ){
$content.prepend($('<div/>').css({
background:'#fff8c4',border:'1px solid #e0c14b',padding:'10px',marginBottom:'10px',borderRadius:'6px',textAlign:'center',fontWeight:600
}).text('🪶 Tip: Remember to set a parent page before saving.'));
}
});
}catch(e){}
console.log('✅ Category + Parent prompt JS initialized.');
}).catch( err => console.error('LeadWriterControl loader error:', err) );
} )( mediaWiki, jQuery );
