Tip of the Day
Check out our Portal, Reddit, and Discord for announcements, updates, and development blogs.

MediaWiki:Common.js: Difference between revisions

From Walkscape Walkthrough
mNo edit summary
Tag: Reverted
mNo edit summary
 
(32 intermediate revisions by the same user not shown)
Line 1: Line 1:
/* Any JavaScript here will be loaded for all users on every page load. */
/* Any JavaScript here will be loaded for all users on every page load. */
/* VARIABLES ***********************************************************************************************************************/
/* VARIABLES ***********************************************************************************************************************/
var currentPageUrl = window.location.href;
var currentPageUrl = window.location.href;
var currentPageEditUrl = mw.util.getUrl( null, { action: 'edit' } );
var currentPageEditUrl = mw.util.getUrl(null, {
var currentPageName = mw.util.getUrl( null, null ).replace('/wiki/', '');
action: 'edit'
});
var currentPageName = mw.util.getUrl(null, null).replace('/wiki/', '');
var currentPageNamespaceID = mw.config.get('wgNamespaceNumber');
var currentPageNamespaceID = mw.config.get('wgNamespaceNumber');
//variables needed after page load
//variables needed after page load
var buttons, contents, allLinks;
var buttons, contents, allLinks;
//variables needed for the infobutton
//variables needed for the infobutton
var infobutton, infopanel;
var infobutton, infopanel;
/* *********************************************************************************************************************************/
/* *********************************************************************************************************************************/
// Matomo
// Matomo
var _paq = window._paq = window._paq || [];
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/*
/*
_paq.push(['trackPageView']);
_paq.push(['trackPageView']);
Line 32: Line 26:
})();
})();
*/
*/
/* sticky edit button */
/* sticky edit button */
// display the button only if #mw-content is present, if we are not in the edit mode, and if we're not in the Special: or Community: namespace
// display the button only if #mw-content is present, if we are not in the edit mode, and if we're not in the Special: or Community: namespace
/*
/*
Line 47: Line 33:
}
}
*/
*/
///////////////////////////////////////// ADDING THE INFO BUTTON
///////////////////////////////////////// ADDING THE INFO BUTTON
var infotitle = currentPageName + '/doc';
var infotitle = currentPageName + '/doc';
// add the info button ONLY when we use the edit mode now
if (document.body.contains(document.getElementById("mw-content")) && (currentPageUrl.includes("action=edit") || currentPageUrl.includes("action=submit"))) {
mw.loader.using('mediawiki.api', function() {
var api = new mw.Api();
api.get({
action: "query",
titles: [infotitle],
}).then(function(ret) {
$.each(ret.query.pages, function() {
if (this.missing !== "") {
pageExists();
}
});
});


// add the info button ONLY when we use the edit mode now
function pageExists() {
if (document.body.contains(document.getElementById("mw-content")) && (currentPageUrl.includes("action=edit") || currentPageUrl.includes("action=submit")))
api.get({
{
action: 'parse',
mw.loader.using('mediawiki.api', function() {
page: infotitle,
var api = new mw.Api();
contentmodel: 'wikitext'
}).done(function(data) {
api.get( {
InsertInfoPanel(data.parse.text['*']);
    action: "query",
});
    titles: [infotitle],
}
} ).then( function( ret ) {
});
    $.each( ret.query.pages, function() {
        if ( this.missing !== "" ) {
            pageExists();
        }
    } );
});
function pageExists() {
api.get( {
    action: 'parse',
    page: infotitle,
    contentmodel: 'wikitext'
} ).done( function ( data ) {
InsertInfoPanel( data.parse.text['*'] );
});
}
}
});
}


function InsertInfoPanel( text )
function InsertInfoPanel(text) {
{
//check which namespace we're in and adapt the text to it
//check which namespace we're in and adapt the text to it
var infopanelTitle = 'Page';
var infopanelTitle = 'Page';
if (currentPageNamespaceID == 10) { //Template
if (currentPageNamespaceID == 10) { //Template
infopanelTitle = 'Template';
infopanelTitle = 'Template';
}
} else if (currentPageNamespaceID == 828) { //Module
else if (currentPageNamespaceID == 828) { //Module
infopanelTitle = 'Module';
infopanelTitle = 'Module';
}
}
// insert the panel and button
// insert the panel and button
document.getElementById("mw-content").insertAdjacentHTML('afterbegin', '<div id="custom-infobutton"></div><div id="custom-infopanel" style="display: none"><div id="custom-infopanel-title">' + infopanelTitle + ' Info</div><div id="custom-infopanel-content">' + text + '</div></div>');
document.getElementById("mw-content").insertAdjacentHTML('afterbegin', '<div id="custom-infobutton"></div><div id="custom-infopanel" style="display: none"><div id="custom-infopanel-title">' + infopanelTitle + ' Info</div><div id="custom-infopanel-content">' + text + '</div></div>');
//set up containers
//set up containers
infopanel = document.getElementById("custom-infopanel");
infopanel = document.getElementById("custom-infopanel");
infobutton = document.getElementById("custom-infobutton");
infobutton = document.getElementById("custom-infobutton");
//add an event listener to the button
//add an event listener to the button
infobutton.addEventListener("click", infobuttonClicked);
infobutton.addEventListener("click", infobuttonClicked);
}
}


 
function infobuttonClicked() {
 
if (infopanel.style.display == 'none') {
function infobuttonClicked()
{
if (infopanel.style.display == 'none')
{
infopanel.style.display = 'block';
infopanel.style.display = 'block';
}
} else {
else
{
infopanel.style.display = 'none';
infopanel.style.display = 'none';
}
}
}
}
/* rename the "DISCUSSION" talk page button to "DOCUMENTATION" */
/* rename the "DISCUSSION" talk page button to "DOCUMENTATION" */
//if there is such a button and we're in the Template: namespace
//if there is such a button and we're in the Template: namespace
if (document.body.contains(document.getElementById("ca-talk")) && currentPageNamespaceID == 10) {
if (document.body.contains(document.getElementById("ca-talk")) && currentPageNamespaceID == 10) {
document.getElementById("ca-talk").innerHTML = '<svg class="cosmos-button-icon" width="28" height="28" viewBox="-2 -2 20 20"><path d="M 4 2 Q 4 0 6 0 L 14 0 Q 16 0 16 2 L 8 2 Q 8 0 6 0 Q 4 0 4 2 L 4 12 Q 4 14 2 14 Q 0 14 0 12 L 2 12 L 0 12 Q 0 14 2 14 L 12 14 Q 14 14 14 12 L 14 4"></path></svg><span class="cosmos-button-text">Documentation</span>';
document.getElementById("ca-talk").innerHTML = '<svg class="cosmos-button-icon" width="28" height="28" viewBox="-2 -2 20 20"><path d="M 4 2 Q 4 0 6 0 L 14 0 Q 16 0 16 2 L 8 2 Q 8 0 6 0 Q 4 0 4 2 L 4 12 Q 4 14 2 14 Q 0 14 0 12 L 2 12 L 0 12 Q 0 14 2 14 L 12 14 Q 14 14 14 12 L 14 4"></path></svg><span class="cosmos-button-text">Documentation</span>';
}
}
/* call specific functions when the page loads */
/* call specific functions when the page loads */
// old browsers or already loaded
// old browsers or already loaded
if (document.readyState!="loading") AfterPageLoad();
if (document.readyState != "loading") AfterPageLoad();
// modern browsers
// modern browsers
else if (document.addEventListener) document.addEventListener("DOMContentLoaded", AfterPageLoad);
else if (document.addEventListener) document.addEventListener("DOMContentLoaded", AfterPageLoad);
/* FUNCTIONS **********************************************************************************************************************/
/* FUNCTIONS **********************************************************************************************************************/
 
function AfterPageLoad() {
 
StartTabs();
 
 
function AfterPageLoad()
{
StartTabs();
}
}
/* Tabs */
/* Tabs */
function StartTabs() {
buttons = document.getElementsByClassName("tab-button");
contents = document.getElementsByClassName("tab-content");
if (buttons.length > 0) {
clickfunction(buttons[0]);
for (var i = 0; i < buttons.length; i++) {
//console.log("Added Event Listener!");
buttons[i].addEventListener("click", clickfunction);
}
}
}


function StartTabs()
function clickfunction(thing) {
{
if (thing.id == null) {
buttons = document.getElementsByClassName("tab-button");
thing = this;
contents = document.getElementsByClassName("tab-content");
}
 
//buttons
if (buttons.length > 0){
for (var i = 0; i < buttons.length; i++) {
clickfunction(buttons[0]);
if (buttons[i].id == thing.id) {
 
buttons[i].classList.remove("tab-disabled");
for (var i = 0; i < buttons.length; i++)
buttons[i].classList.add("tab-active");
  {
} else {
    //console.log("Added Event Listener!");
buttons[i].classList.remove("tab-active");
    buttons[i].addEventListener("click", clickfunction);
buttons[i].classList.add("tab-disabled");
  }
}
}
}
//contents
for (var i = 0; i < contents.length; i++) {
if (contents[i].id == thing.id) {
contents[i].style.display = 'block'
} else {
contents[i].style.display = 'none'
}
}
}
}


mw.hook('wikipage.content').add(function ($content) {
  var $wrap = $content.find('.tabberresize').first();
  if (!$wrap.length) return;


 
  function recalc() {
function clickfunction(thing) {
    if (window.matchMedia('(max-width: 850px)').matches) {
  if (thing.id == null)
      // Mobile: leave sizing to CSS
    {
      $wrap.css({ width: '100%', float: 'none', display: 'block' });
       thing = this;
       return;
     }
     }
 
  //buttons
for (var i = 0; i < buttons.length; i++)
  {
    if (buttons[i].id == thing.id)
      {
        buttons[i].classList.remove("tab-disabled");
        buttons[i].classList.add("tab-active");
      }
    else
      {
        buttons[i].classList.remove("tab-active");
        buttons[i].classList.add("tab-disabled");
      }
  }
  //contents
  for (var i = 0; i < contents.length; i++)
  {
    if (contents[i].id == thing.id)
      {
        contents[i].style.display = 'block'
      }
    else
      {
        contents[i].style.display = 'none'
      }
  }
}


/* Click-to-select rows in tables with class "mw-lighttable" */
    // 1) Find widest tab label (measured as rendered <a.tabber__tab>)
mw.loader.using('jquery', function () {
     var maxTab = 0;
  $(function () {
     $wrap.find('.tabber__tab').each(function () {
     // Single-select behavior (one active row per table)
       // offsetWidth includes padding/border; safe for equal sizing
     $('table.mw-lighttable').on('click', 'tbody tr', function (e) {
       maxTab = Math.max(maxTab, Math.ceil(this.offsetWidth));
       // Let clicks on interactive elements behave normally
    });
       if ($(e.target).closest('a, button, input, label, select, textarea').length) return;
    if (!maxTab) maxTab = 90; // fallback


      var $table = $(this).closest('table');
    // Expose to CSS grid
      var $tbody = $(this).closest('tbody');
    $wrap.get(0).style.setProperty('--tab-w', maxTab + 'px');


      // Clear previous selection in this <tbody> only (keeps header/footer safe)
    // 2) Measure the infobox table width (first one in the active panel)
      $tbody.find('tr').removeClass('highlight-on').attr('aria-selected', 'false');
    var $table = $wrap.find('table.ItemInfobox, table.wikitable.ItemInfobox').first();
    var tableW = $table.length ? Math.ceil($table.outerWidth()) : 0;


      // Set the new active row
    // 3) Set wrapper width to max(table width, 3 × tab width)
      $(this).addClass('highlight-on').attr('aria-selected', 'true');
    var target = Math.max(tableW, maxTab * 3 + 12);
    $wrap.css({
      width: target + 'px !important' ,
      float: 'right',
      display: 'inline-block',
      maxWidth: '100%'
     });
     });
  }


    // Optional: keyboard support (Enter/Space toggles on focused row)
  // Initial + on resize (debounced enough for this use)
    $('table.mw-lighttable').attr('role', 'grid').find('tbody tr').attr('tabindex', '0');
  recalc();
    $('table.mw-lighttable').on('keydown', 'tbody tr', function (e) {
  $(window).on('resize', recalc);
      if (e.key === 'Enter' || e.key === ' ') {
        e.preventDefault();
        $(this).trigger('click');
      }
    });
  });
});
});

Latest revision as of 02:58, 8 November 2025

/* Any JavaScript here will be loaded for all users on every page load. */
/* VARIABLES ***********************************************************************************************************************/
var currentPageUrl = window.location.href;
var currentPageEditUrl = mw.util.getUrl(null, {
	action: 'edit'
});
var currentPageName = mw.util.getUrl(null, null).replace('/wiki/', '');
var currentPageNamespaceID = mw.config.get('wgNamespaceNumber');
//variables needed after page load
var buttons, contents, allLinks;
//variables needed for the infobutton
var infobutton, infopanel;
/* *********************************************************************************************************************************/
// Matomo
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/*
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
  var u="https://matomo.tools.walkscape.app/";
  _paq.push(['setTrackerUrl', u+'matomo.php']);
  _paq.push(['setSiteId', '5']);
  var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
  g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
*/
/* sticky edit button */
// display the button only if #mw-content is present, if we are not in the edit mode, and if we're not in the Special: or Community: namespace
/*
if (document.body.contains(document.getElementById("mw-content")) && !currentPageUrl.includes("action=") && currentPageNamespaceID != -1 && currentPageNamespaceID != 3004)  {
document.getElementById("mw-content").insertAdjacentHTML('afterbegin', '<a href="https://wiki-temp.walkscape.app/' + currentPageEditUrl + '"><div id="custom-editbutton"><svg width="40" height="40" viewBox="-12 -10 50 50"><path d="M 20 2 L 26 8 L 8 26 L 2 26 L 2 20 Z M 16 6 L 22 12"></path></svg></div></a>');
}
*/
///////////////////////////////////////// ADDING THE INFO BUTTON
var infotitle = currentPageName + '/doc';
// add the info button ONLY when we use the edit mode now
if (document.body.contains(document.getElementById("mw-content")) && (currentPageUrl.includes("action=edit") || currentPageUrl.includes("action=submit"))) {
	mw.loader.using('mediawiki.api', function() {
		var api = new mw.Api();
		api.get({
			action: "query",
			titles: [infotitle],
		}).then(function(ret) {
			$.each(ret.query.pages, function() {
				if (this.missing !== "") {
					pageExists();
				}
			});
		});

		function pageExists() {
			api.get({
				action: 'parse',
				page: infotitle,
				contentmodel: 'wikitext'
			}).done(function(data) {
				InsertInfoPanel(data.parse.text['*']);
			});
		}
	});
}

function InsertInfoPanel(text) {
	//check which namespace we're in and adapt the text to it
	var infopanelTitle = 'Page';
	if (currentPageNamespaceID == 10) { //Template
		infopanelTitle = 'Template';
	} else if (currentPageNamespaceID == 828) { //Module
		infopanelTitle = 'Module';
	}
	// insert the panel and button
	document.getElementById("mw-content").insertAdjacentHTML('afterbegin', '<div id="custom-infobutton"></div><div id="custom-infopanel" style="display: none"><div id="custom-infopanel-title">' + infopanelTitle + ' Info</div><div id="custom-infopanel-content">' + text + '</div></div>');
	//set up containers
	infopanel = document.getElementById("custom-infopanel");
	infobutton = document.getElementById("custom-infobutton");
	//add an event listener to the button
	infobutton.addEventListener("click", infobuttonClicked);
}

function infobuttonClicked() {
	if (infopanel.style.display == 'none') {
		infopanel.style.display = 'block';
	} else {
		infopanel.style.display = 'none';
	}
}
/* rename the "DISCUSSION" talk page button to "DOCUMENTATION" */
//if there is such a button and we're in the Template: namespace
if (document.body.contains(document.getElementById("ca-talk")) && currentPageNamespaceID == 10) {
	document.getElementById("ca-talk").innerHTML = '<svg class="cosmos-button-icon" width="28" height="28" viewBox="-2 -2 20 20"><path d="M 4 2 Q 4 0 6 0 L 14 0 Q 16 0 16 2 L 8 2 Q 8 0 6 0 Q 4 0 4 2 L 4 12 Q 4 14 2 14 Q 0 14 0 12 L 2 12 L 0 12 Q 0 14 2 14 L 12 14 Q 14 14 14 12 L 14 4"></path></svg><span class="cosmos-button-text">Documentation</span>';
}
/* call specific functions when the page loads */
// old browsers or already loaded
if (document.readyState != "loading") AfterPageLoad();
// modern browsers
else if (document.addEventListener) document.addEventListener("DOMContentLoaded", AfterPageLoad);
/* FUNCTIONS **********************************************************************************************************************/
function AfterPageLoad() {
	StartTabs();
}
/* Tabs */
function StartTabs() {
	buttons = document.getElementsByClassName("tab-button");
	contents = document.getElementsByClassName("tab-content");
	if (buttons.length > 0) {
		clickfunction(buttons[0]);
		for (var i = 0; i < buttons.length; i++) {
			//console.log("Added Event Listener!");
			buttons[i].addEventListener("click", clickfunction);
		}
	}
}

function clickfunction(thing) {
	if (thing.id == null) {
		thing = this;
	}
	//buttons
	for (var i = 0; i < buttons.length; i++) {
		if (buttons[i].id == thing.id) {
			buttons[i].classList.remove("tab-disabled");
			buttons[i].classList.add("tab-active");
		} else {
			buttons[i].classList.remove("tab-active");
			buttons[i].classList.add("tab-disabled");
		}
	}
	//contents
	for (var i = 0; i < contents.length; i++) {
		if (contents[i].id == thing.id) {
			contents[i].style.display = 'block'
		} else {
			contents[i].style.display = 'none'
		}
	}
}

mw.hook('wikipage.content').add(function ($content) {
  var $wrap = $content.find('.tabberresize').first();
  if (!$wrap.length) return;

  function recalc() {
    if (window.matchMedia('(max-width: 850px)').matches) {
      // Mobile: leave sizing to CSS
      $wrap.css({ width: '100%', float: 'none', display: 'block' });
      return;
    }

    // 1) Find widest tab label (measured as rendered <a.tabber__tab>)
    var maxTab = 0;
    $wrap.find('.tabber__tab').each(function () {
      // offsetWidth includes padding/border; safe for equal sizing
      maxTab = Math.max(maxTab, Math.ceil(this.offsetWidth));
    });
    if (!maxTab) maxTab = 90; // fallback

    // Expose to CSS grid
    $wrap.get(0).style.setProperty('--tab-w', maxTab + 'px');

    // 2) Measure the infobox table width (first one in the active panel)
    var $table = $wrap.find('table.ItemInfobox, table.wikitable.ItemInfobox').first();
    var tableW = $table.length ? Math.ceil($table.outerWidth()) : 0;

    // 3) Set wrapper width to max(table width, 3 × tab width)
    var target = Math.max(tableW, maxTab * 3 + 12);
    $wrap.css({
      width: target + 'px !important' ,
      float: 'right',
      display: 'inline-block',
      maxWidth: '100%'
    });
  }

  // Initial + on resize (debounced enough for this use)
  recalc();
  $(window).on('resize', recalc);
});