MediaWiki:Common.js: Difference between revisions
From Sanatan Hindu Dharma
No edit summary |
No edit summary |
||
| Line 418: | Line 418: | ||
// --- Add "Create Subpage" button automatically on every page --- | // --- Add "Create Subpage" button automatically on every page --- | ||
// === Auto Parent Page | // === Auto Parent Page Selector for New Pages === | ||
// Forces user to pick either a Parent Page or No Parent before editing | |||
mw.loader.using(['mediawiki.util', 'mediawiki.api']).then(function () { | mw.loader.using(['mediawiki.util', 'mediawiki.api']).then(function () { | ||
console.log("✅ Common.js | console.log("✅ Common.js: Parent selector active."); | ||
const api = new mw.Api(); | |||
mw.hook('ve.activationComplete').add(function () { | |||
mw.hook(' | console.log("✅ VisualEditor activated."); | ||
const title = mw.config.get('wgPageName'); | const title = mw.config.get('wgPageName'); | ||
const action = mw.config.get('wgAction'); | const action = mw.config.get('wgAction'); | ||
| Line 447: | Line 434: | ||
if (action === 'edit' && isNewPage) { | if (action === 'edit' && isNewPage) { | ||
setTimeout(() => showParentPopup(title), 1500); | |||
} | |||
}); | |||
function showParentPopup(title) { | |||
if (document.getElementById('parent-popup')) return; | |||
const | |||
// Overlay | |||
} | const $popup = $('<div id="parent-popup">').css({ | ||
position: 'fixed', | |||
top: '0', | |||
left: '0', | |||
width: '100%', | |||
height: '100%', | |||
background: 'rgba(0,0,0,0.6)', | |||
zIndex: '9999', | |||
display: 'flex', | |||
justifyContent: 'center', | |||
alignItems: 'center' | |||
}); | |||
// Box | |||
const $box = $('<div>').css({ | |||
background: '#fff', | |||
borderRadius: '10px', | |||
padding: '20px 25px', | |||
width: '420px', | |||
boxShadow: '0 4px 12px rgba(0,0,0,0.3)', | |||
textAlign: 'center' | |||
}); | |||
$box.append('<h3 style="margin-bottom:15px;">Select Parent Page</h3>'); | |||
const $input = $('<input type="text" placeholder="Start typing parent page name...">').css({ | |||
width: '100%', | |||
padding: '8px 10px', | |||
border: '1px solid #aaa', | |||
borderRadius: '6px' | |||
}); | |||
const $list = $('<ul id="parent-suggestions">').css({ | |||
listStyle: 'none', | |||
margin: '10px 0 0', | |||
padding: '0', | |||
maxHeight: '150px', | |||
overflowY: 'auto', | |||
border: '1px solid #ccc', | |||
borderRadius: '6px', | |||
display: 'none', | |||
textAlign: 'left' | |||
}); | |||
const $confirmBtn = $('<button>Confirm</button>').css({ | |||
marginTop: '15px', | |||
background: '#007bff', | |||
color: '#fff', | |||
border: 'none', | |||
borderRadius: '6px', | |||
padding: '8px 14px', | |||
cursor: 'pointer' | |||
}); | |||
const $noParentBtn = $('<button>No Parent</button>').css({ | |||
marginLeft: '10px', | |||
marginTop: '15px', | |||
background: '#999', | |||
color: '#fff', | |||
border: 'none', | |||
borderRadius: '6px', | |||
padding: '8px 14px', | |||
cursor: 'pointer' | |||
}); | |||
$box.append($input, $list, $('<div>').append($confirmBtn, $noParentBtn)); | |||
$popup.append($box); | |||
$('body').append($popup); | |||
// --- Autocomplete logic --- | |||
$input.on('input', async function () { | |||
const val = $(this).val().trim(); | |||
$list.empty(); | |||
if (val.length < 2) { | |||
$list.hide(); | |||
return; | |||
} | |||
try { | |||
const data = await api.get({ | |||
action: 'opensearch', | |||
search: val, | |||
limit: 6, | |||
namespace: 0 | |||
}); | |||
const suggestions = data[1] || []; | |||
if (suggestions.length > 0) { | |||
$list.show(); | |||
suggestions.forEach(s => { | |||
const $li = $('<li>') | |||
.text(s) | |||
.css({ | |||
padding: '6px 10px', | |||
cursor: 'pointer' | |||
}) | |||
.hover(function () { | |||
$(this).css('background', '#f0f0f0'); | |||
}, function () { | |||
$(this).css('background', 'transparent'); | |||
}) | |||
.on('click', function () { | |||
$input.val($(this).text()); | |||
$list.hide(); | |||
}); | |||
$list.append($li); | |||
}); | |||
} else { | |||
$list.hide(); | |||
} | } | ||
}, | } catch (err) { | ||
} | console.warn("Parent search failed:", err); | ||
} | |||
}); | |||
// --- Confirm Button --- | |||
$confirmBtn.on('click', function () { | |||
const parent = $input.val().trim(); | |||
if (!parent) { | |||
alert("⚠️ Please enter or select a parent page name, or click 'No Parent'."); | |||
return; | |||
} | |||
const newTitle = parent + "/" + title; | |||
if (confirm("Create under: " + newTitle + "?")) { | |||
const newUrl = mw.util.getUrl(newTitle) + "?veaction=edit"; | |||
window.location.href = newUrl; | |||
} | |||
}); | |||
// --- No Parent Button --- | |||
$noParentBtn.on('click', function () { | |||
if (confirm("Create this page without a parent?")) { | |||
$popup.remove(); // continue editing normally | |||
} | |||
}); | |||
// Prevent closing without a choice | |||
$popup.on('click', function (e) { | |||
if (e.target.id === 'parent-popup') { | |||
alert("⚠️ Please choose a Parent or click 'No Parent' to continue."); | |||
} | |||
}); | |||
} | } | ||
}); | }); | ||
Revision as of 18:02, 3 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);
})();
$(document).ready(function() {
// Prevent multiple inserts
if ($('#mw-custom-footer').length) return;
// Load HTML footer template safely
$.ajax({
url: '/index.php?title=Template:Custom-footer&action=render',
type: 'GET',
success: function(data) {
// Wrap the footer in a container for CSS control
var footer = $('<div id="mw-custom-footer"></div>').html(data);
// Append after the content area but before closing body
// Prefer the footer tag or body end if missing
if ($('#footer').length) {
$('#footer').before(footer);
} else {
$('body').append(footer);
}
},
error: function() {
console.warn('Custom footer could not be loaded.');
}
});
});
// --- Add "Create Subpage" button automatically on every page ---
// === Auto Parent Page Selector for New Pages ===
// Forces user to pick either a Parent Page or No Parent before editing
mw.loader.using(['mediawiki.util', 'mediawiki.api']).then(function () {
console.log("✅ Common.js: Parent selector active.");
const api = new mw.Api();
mw.hook('ve.activationComplete').add(function () {
console.log("✅ VisualEditor activated.");
const title = mw.config.get('wgPageName');
const action = mw.config.get('wgAction');
const isNewPage = mw.config.get('wgCurRevisionId') === 0;
if (action === 'edit' && isNewPage) {
setTimeout(() => showParentPopup(title), 1500);
}
});
function showParentPopup(title) {
if (document.getElementById('parent-popup')) return;
// Overlay
const $popup = $('<div id="parent-popup">').css({
position: 'fixed',
top: '0',
left: '0',
width: '100%',
height: '100%',
background: 'rgba(0,0,0,0.6)',
zIndex: '9999',
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
});
// Box
const $box = $('<div>').css({
background: '#fff',
borderRadius: '10px',
padding: '20px 25px',
width: '420px',
boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
textAlign: 'center'
});
$box.append('<h3 style="margin-bottom:15px;">Select Parent Page</h3>');
const $input = $('<input type="text" placeholder="Start typing parent page name...">').css({
width: '100%',
padding: '8px 10px',
border: '1px solid #aaa',
borderRadius: '6px'
});
const $list = $('<ul id="parent-suggestions">').css({
listStyle: 'none',
margin: '10px 0 0',
padding: '0',
maxHeight: '150px',
overflowY: 'auto',
border: '1px solid #ccc',
borderRadius: '6px',
display: 'none',
textAlign: 'left'
});
const $confirmBtn = $('<button>Confirm</button>').css({
marginTop: '15px',
background: '#007bff',
color: '#fff',
border: 'none',
borderRadius: '6px',
padding: '8px 14px',
cursor: 'pointer'
});
const $noParentBtn = $('<button>No Parent</button>').css({
marginLeft: '10px',
marginTop: '15px',
background: '#999',
color: '#fff',
border: 'none',
borderRadius: '6px',
padding: '8px 14px',
cursor: 'pointer'
});
$box.append($input, $list, $('<div>').append($confirmBtn, $noParentBtn));
$popup.append($box);
$('body').append($popup);
// --- Autocomplete logic ---
$input.on('input', async function () {
const val = $(this).val().trim();
$list.empty();
if (val.length < 2) {
$list.hide();
return;
}
try {
const data = await api.get({
action: 'opensearch',
search: val,
limit: 6,
namespace: 0
});
const suggestions = data[1] || [];
if (suggestions.length > 0) {
$list.show();
suggestions.forEach(s => {
const $li = $('<li>')
.text(s)
.css({
padding: '6px 10px',
cursor: 'pointer'
})
.hover(function () {
$(this).css('background', '#f0f0f0');
}, function () {
$(this).css('background', 'transparent');
})
.on('click', function () {
$input.val($(this).text());
$list.hide();
});
$list.append($li);
});
} else {
$list.hide();
}
} catch (err) {
console.warn("Parent search failed:", err);
}
});
// --- Confirm Button ---
$confirmBtn.on('click', function () {
const parent = $input.val().trim();
if (!parent) {
alert("⚠️ Please enter or select a parent page name, or click 'No Parent'.");
return;
}
const newTitle = parent + "/" + title;
if (confirm("Create under: " + newTitle + "?")) {
const newUrl = mw.util.getUrl(newTitle) + "?veaction=edit";
window.location.href = newUrl;
}
});
// --- No Parent Button ---
$noParentBtn.on('click', function () {
if (confirm("Create this page without a parent?")) {
$popup.remove(); // continue editing normally
}
});
// Prevent closing without a choice
$popup.on('click', function (e) {
if (e.target.id === 'parent-popup') {
alert("⚠️ Please choose a Parent or click 'No Parent' to continue.");
}
});
}
});
