MediaWiki:Common.js

/* Any JavaScript here will be loaded for all users on every page load. */

/***********************************************************************************

* This 'MediaWiki:Common.js' will be loaded via imported '/site' file, at the *top*

of page in ' '. Will load immediately before Wikia.js.

* The 'MediaWiki:Wikia.js' will be loaded via imported '/site' file, at the *top*

of page in ' '. Will load immediately after Common.js and before importArticles.

* Common 'importArticles' files will be loaded together via dynamic import as

'/load.php' file, separately appearing at the *bottom* of the page.

* All files will be checked and minified nearly the same.

* 'Common' files are supposed to be theme agnostic, and 'Wikia' files are supposed

to be a part of the default theme and are supposed theme specific. Currently on here,

there is *no* theme specific JS. Please error on the side of placing code in

Common.js rather than Wikia.js. *All* js code should be tolerant of thematic changes

and any degradation on the various devices.

************************************************************************************ /

/* ***************************************

How to Navigate Common.js

***************************************

Major section headers look like this:

*******************************************************************************************

SECTION   Namespace:File.css

*******************************************************************************************

There should be several main sections:

1) SECTION Standard Functions - a subset of the standard MediaWiki:Common.js function

2) SECTION Import - code from other files

3) SECTION Extensions - common extensions, or support/fixes for installable ones

4) SECTION Functions - functionality divided-up into functions, that arnt extensions

5) SECTION Startup - code to run on start, page startup event or timer, or inlined

Major startup code is placed here usually calling the 'single use' named functions for each

feature thatneeds to be loaded on page load complete.

* /

/*******************************************************************************************

SECTION  Standard Functions

******************************************************************************************** /

function getParamValue(name) {   // Extract a URL parameter. See wikipedia:User:Lupin/autoedit.js

var regex = RegExp('[&?]' + name + '=([^&]*)');

var h = document.location.href, m = regex.exec(h);

if (m) { try { return decodeURIComponent(m[1]); } catch (someError) {} }

return null;

}

/** name - cookie name, value - 'on' or 'off' or whatever, exdays - expiry of cookie in days */

function setCookie(name, value, exdays) {   // Sets a cookie

value = name + "=" + escape(value);

if (exdays !== null) { var d = new Date; value += ";expires=" + d.setDate(d.getDate + exdays).toGMTString; }

document.cookie = value;

}

/** name - cookie name, @return - cookie or empty string */

function getCookie(name) {    // Gets a cookie

var c = document.cookie;

if (c.length > 0) {

var s = c.indexOf(name + "=");

if (s !== -1) {

var e = c.indexOf(";", s = s + name.length + 1);

return unescape(c.substring(s, (e !== -1) ? e : e = c.length));

}

}

return "";

}

// <IE10 test for bugged wikia right rail code, specifically 'relatedpages'. this is classic horrible fixup

//  must be window, because caller uses 'context.addEventListener'

if (!window.addEventListener) {

window.addEventListener = window.addEventListener || function (event, callBack) {

event = (event === "load") ? "onreadystatechange" : "on" + event;

if (event === "onreadystatechange") {

callBack.readyStateCheck = callBack.readyStateCheck || function (e) {

if (self.readyState === "loaded") { callBack(e); }

};

}

this.attachEvent(event, (callBack.readyStateCheck || callBack));

};

}

if (!window.removeEventListener) {

window.removeEventListener = window.removeEventListener || function (event, callBack) {

event = (event === "load") ? "onreadystatechange" : "on" + event;

this.detachEvent(event, (callBack.readyStateCheck || callBack));

};

}

/*******************************************************************************************

SECTION  Import

******************************************************************************************** /

// needed by AjaxRC before loading script

var ajaxIndicator = ' https://images.wikia.nocookie.net/__cb1/wowwiki/images/0/0e/Progressbar.gif' ;

// Import Scripts

window.wwImportArticles = {              // allow other code to add imports before committing the list

type: 'script',

debug: true,

articles: [

'MediaWiki:jquery-ui/jquery.effects.js',  // working version of UI effects. used by 'FloatingToc' and 'SlideShow'

//'MediaWiki:Test.js',

'u:dev:MediaWiki:AjaxRC/code.js',         // intended as common ajax dependency for user extensions, like below

'MediaWiki:Countdown/code.js',

'MediaWiki:FloatingToc/code.js',          // popout TOC. static as is used nearly all pages but portals, etc...

'MediaWiki:Wikiaapp.js',

// 'MediaWiki:AjaxTables/code.js',        // ajax driven 'show table'. See 'MediaWiki:AjaxTables'

'MediaWiki:Map/code.js',                  // on page Map and Map lightbox support

'MediaWiki:SlideShow/code.js',            // general slide show and rotating banner support See 'Template:Slideshow'

'MediaWiki:UserTags/code.js',             // user tags like "INACTIVE", "ADMINISTRATOR" or "CRAZY PERSON" on talk pages

//'MediaWiki:UserTags/inactiveUsers.js',  // Merged into UserTags. Not used. MediaWiki:Wikia.js/userRightsIcons.js appears to override

//'MediaWiki:UserTags/userRightsIcons.js',// Merged into UserTags. Not used. puts things like "ADMINISTRATOR" or "CRAZY PERSON" tags on talk pages

]

};

//if (mw && mw.config && mw.config.set) mw.config.set('debug', true); /* extra debugging facility */

/*******************************************************************************************

SECTION  Extensions

******************************************************************************************** /

//****************************************

//****    Wowhead Tooltips            ****

//****************************************

// As Wikia does not support attributes on links, we need to pass the attribute from a parent span to the child.

// Simply wrap the link ( Alt ) in span tags with the "wikia-wowhead-tooltip class, and the "data-rel" attribute which holds the rel the anchor would normally hold. For instance, Alt

var wowheadLinks = $('.wikia-wowhead-tooltip').length - 1;

$('.wikia-wowhead-tooltip').each(function(index) {

var rel = $(this).attr('data-rel');

$('a',this).attr('rel',rel);

// Once the links are converted, load the Wowhead script

if (index === wowheadLinks) {

$.getScript('//static.wowhead.com/widgets/power.js', function {

wowhead_tooltips = { "colorlinks": true, "iconizelinks": true, "renamelinks": true };

});

}

});

//****************************************

//****    Tooltips                    ****

//****************************************

// See Help:Tooltips

// default setting to turn tooltips on

var tooltipsOn = true;

//// allow users to specify an external db to change links to

//var extDB = " https://www.wowwiki.com/ ";

var $tfb;

var $ttfb;

var $htt;

// hides the tooltip

function hideTip {

$tfb.html("").removeClass("tooltip-ready").addClass("hidden").css("visibility", "hidden");

}

// displays the tooltip

function displayTip(e) {

$htt.not(":empty").removeClass("hidden").addClass("tooltip-ready");

moveTip(e);

$htt.not(":empty").css("visibility", "visible");

}

// moves the tooltip

function moveTip(e) {

var newTop = e.clientY + ((e.clientY > ($(window).height / 2)) ? -($htt.not(".hidden").innerHeight + 20) : 20);

var newLeft = e.clientX + ((e.clientX > ($(window).width / 2)) ? -($htt.not(".hidden").innerWidth + 20) : 20);

$htt.not(".hidden").css({

"position": "fixed",

"top": newTop + "px",

"left": newLeft + "px"

});

}

// AJAX tooltips

function showTip(e) {

$t = $(this);

$p = $t.parent;

if ($p.hasClass("selflink") == false) {

$t.removeAttr("title");

$p.removeAttr("title");

$tfb.load("/wiki/" + $t.data("tt").replace(/ /g, "_").replace(/\?/g, "%3F") + "?action=render div.tooltip-content", function {

if ($tfb.html == "") $tfb.html(' Error This target either has no tooltip or was not intended to have one.  ');

$tfb.find(".tooltip-content").css("display", "");

displayTip(e);

});

}

}

// quick tooltips

function hideTemplateTip {

$ttfb.html("").removeClass("tooltip-ready").addClass("hidden");

}

function showTemplateTip(e) {

$ttfb.html(' ' + $(this).next.html + ' ');

displayTip(e);

}

// add the tooltip calls to the page

function eLink(db, nm) {

dbs = new Array(" https://us.battle.net/wow/en/search?q= ", " https://www.wowhead.com/?search= ", /*" https://db.mmo-champion.com/search/all/ ",*/ " https://www.wowdb.com/search?search= ");

dbTs = new Array("Armory", "Wowhead", /*"DB MMO-Champion",*/ "WoWDB");

dbHs = new Array("&amp;real; ", "&amp;omega; ", /*"&amp;delta; ",*/ "&amp;piv; ");

el = ' ' + dbHs[db] + ' ';

return el;

}

function ttBind {

$t = $(this);

$p = $t.parent;

if ($p.hasClass("selflink") == false) {

$t.data("tt", $p.attr("title").replace(" (page does not exist)", "").replace("?", "%3F")).mouseover(showTip).mouseout(hideTip).mousemove(moveTip);

if ($p.hasClass("new")) {

els = ' ';

y = ($t.hasClass("itemlink")) ? 0 : 1;

z = ($t.hasClass("achievementlink")) ? 3 : 3;

for (x = y; x < z; x++) els += eLink(x, $t.data("tt").replace("Quest:", ""));

$p.after(els + '     ');

}

//if (extDB != " https://www.wowwiki.com/ ") {

//  fullextURL = extDB + $t.data("tt");

//  $p.attr("href", fullextURL);

//}

}

}

// check to see if it is active then do it

function ttMouseOver(foo) {

if (tooltipsOn && getCookie("wiki-tiploader") != "no") {

$("#WikiaArticle").mouseover(hideTip);

$("#WikiaArticle").append('    ');

$tfb = $("#tfb");

$ttfb = $("#templatetfb");

$htt = $("#tfb,#templatetfb");

if (foo == 1) {

$("#WikiaArticle span.ajaxttlink").each(ttBind);

}

$("#WikiaArticle span.tttemplatelink").mouseover(showTemplateTip).mouseout(hideTemplateTip).mousemove(moveTip);

}

}

//****************************************

//****    ScribbleMap                 ****

//****************************************

//* BROKEN?

function wwScribbleMaps {           // see Template:ScribbleMap

$("#WikiaArticle div.wwSM").each(function {

var mapID = $(this).attr("class").replace("wwSM map-", ""), width = $(this).width, height = $(this).height;

if (mapID.length > 20) mapID = ""; if (width <= 0) width = 550; if (height <= 0) height = Math.floor(width / 11 * 8);

$(this).html(' ');

});

}

//****************************************

//****    Semantic Mediawiki          ****

//****************************************

// this is pretty much ineffective, as I think there is no more 'mw-data-after-content' id. i cant find one.

function smwToggleFacts {

if ($("#SMWFactToggle").text == "hide") {

$("#mw-data-after-content table.smwfacttable tr").hide;

setCookie("hideSMWFacts", "true");

$("#SMWFactToggle").text("show");

} else {

$("#mw-data-after-content table.smwfacttable tr").show;

setCookie("hideSMWFacts", "false");

$("#SMWFactToggle").text("hide");

}

}

// setup for fast on demand init, only if page contains tag

function smwInitPage {

if ($("#mw-data-after-content table.smwfacttable tr").length == 0) {

$("#mw-data-after-content div.smwfact").hide;

} else {

$("#mw-data-after-content span.smwrdflink").after(' [hide ] & nbsp;  ');

}

if (getCookie("hideSMWFacts") == "true") { smwToggleFacts; }

}

//****************************************

//****    Tabber                      ****

//****************************************

/* NOTE: needs to be reconciled with updated tabber extension

// needs to represent the 'bare minimum' needed to evaluate if needs to load

function wwTabberInit {

var tabbers = $(".tabber");

if (tabbers.length == 0) return;

window.wwImportArticles.articles.push('MediaWiki:Tabber/code.js');

}

* /

//****************************************

//****    TwitterFeed                 ****

//****************************************

// needs to represent the 'bare minimum' needed to evaluate if needs to load

function wwTwitterFeedInit {

var twitters = $(".twitter-timeline");

if (twitters.length == 0) return;

twitters.each(function { // fix the stupid twitter api attribute thing

var feed = $(this);

var w = feed.data('tt-width'); if (w) feed.attr('width', w);

var h = feed.data('tt-height'); if (h) feed.attr('height', h);

var a = feed.data('tt-id'); if (a) feed.attr('href', ' https://twitter.com/' + a);

});

if ($("#twitter-wjs").length == 0) { $(window.document.head)

.append(' '); }

}

//****************************************

//****    GoogleChart                 ****

//****************************************

// augment removed media wiki #imagelink functionality to allow embeded googlecharts

function wwGoogleChartInit {

var charts = $(".ww-googlechart");

if (charts.length == 0) return;

charts.each(function {

var chart = $(this);

var w = chart.data('gc-width');

var h = chart.data('gc-height');

var o = chart.data('gc-options');

if (o) {

o = ' https://chart.apis.google.com/chart?' + o;

$('').appendTo(chart);

}

});

}

/*******************************************************************************************

SECTION  Functions

******************************************************************************************** /

// fix Special:Upload to require license - relatively inexpensive as scoped to particular page.

function wwRequireImageLicense {

if (wgPageName != "Special:Upload" || getParamValue("wpDestFile") != null) return;

$wpu = $("#mw-upload-form").find("[name=wpUpload]").not("#wpUpload");

$wpu.attr("disabled", "true");

$("#wpLicense").change(function {

if ($("#wpLicense").val) {

$wpu.removeAttr("disabled");

} else {

$wpu.attr("disabled", "true");

}

});

}

function wwDuplicateImages(gf) {

if ($("#mw-dupimages").length == 0) return;

var dil = window.ww.dil = window.ww.dil || [];

$.getJSON('/api.php?action=query&generator=allimages&prop=duplicatefiles&gailimit=500&format=json' + ((gf) ? ('&gaifrom=' + gf) : '' ), function (data) {

if (!data.query) return;

var pages = data.query.pages, output = "";

for (pageID in pages) {

var dils = "," + dil.join;

if (dils.indexOf("," + pages[pageID].title) == -1 && pages[pageID].title.indexOf("File::") == -1 && pages[pageID].duplicatefiles) {

output += " " + pages[pageID].title + "</a> \n <ul>\n";

for (x = 0; x < pages[pageID].duplicatefiles.length; x++) {

output += " <li>File:" + pages[pageID].duplicatefiles[x].name + "</a> </li> \n";

dil.push("File:" + pages[pageID].duplicatefiles[x].name.replace(/_/g, " "));

}

output += " </ul> \n\n"

}

}

$("#mw-dupimages").append(output);

if (data["query-continue"]) setTimeout("wwDuplicateImages('" + data["query-continue"].allimages.gaifrom + "');", 5000);

});

}

function wwGuildList {

if ($("#gslist").length == 0) return;

function sortDays(a, b) { return b.substring(b.indexOf(";") + 1) - a.substring(a.indexOf(";") + 1); }

var dateRE = /(\d{4})-(\d\d)-(\d\d).*/, tsDate = new Date, today = new Date;

var pArr = [];

$.getJSON(" https://www.wowwiki.com/api.php?action=query&generator=categorymembers&gcmlimit=500&gcmsort=timestamp&gcmdir=desc&gcmtitle=Category:Guild_stubs&prop=revisions&rvprop=timestamp&format=json&callback= ?", function (data) {

if (!data.query) return;

var pages = data.query.pages;

for (pageID in pages) {

var timestamp = pages[pageID].revisions[0].timestamp;

var dateREd = dateRE.exec(timestamp);

tsDate.setFullYear(dateREd[1], dateREd[2] - 1, dateREd[3]);

var daysElapsed = Math.round((today - tsDate) / 86400000);

pArr[pArr.length] = pages[pageID].title + ";" + daysElapsed;

}

var pArr2 = pArr.sort(sortDays);

var gslBuffer = " <ul>";

for (n in pArr2) {

var guild = pArr2[n].substring(0, pArr2[n].indexOf(";"));

var daysE = pArr2[n].substring(pArr2[n].indexOf(";") + 1);

daysE = (daysE < 0) ? 0 : daysE;

daysE = (daysE > 29) ? ' (' + daysE + ' days) ' : '(' + daysE + ' days)';

gslBuffer += ' <li>' + guild + '</a> ' + daysE + ' - History</a> & bull; Delete</a>  </li> ';

}

gslBuffer += " </ul> ";

$("#gslist").html(gslBuffer);

});

}

/*******************************************************************************************

SECTION  Startup

******************************************************************************************** /

// Startup Now

(function {

window.ww = window.ww || {};      // ensure has ww JS table, as curtesy for funcs on this page

/* wwTabberInit; */

wwTwitterFeedInit;

wwGoogleChartInit;

});

// Startup on DOM ready

//   Needs cleanup badly.

$(function {

// Part of AJAX RC Comment out when using dev.wikia.com version

//for (x in ajaxPages) { if (wgPageName == ajaxPages[x] && $("#ajaxToggle").length==0) ajaxRC; }

if (wgPageName == "Special:Upload") { wwRequireImageLicense; }

if (wgPageName == "WoWWiki:Guild_list") { wwGuildList; }

if (wgPageName == "WoWWiki:Duplicate_image_search") { wwDuplicateImages; }

if (wgUserName != null) { $(".insertusername").html(wgUserName); }

/*

if ($(".smwfacttable").length > 0) { console.log("found: .smwfacttable"); }

if ($("#mw-data-after-content").length > 0) { console.log("found: #mw-data-after-content"); }

if ($("#SMWFactToggle").length > 0) { console.log("found: #SMWFactToggle"); }

if ($(".smwrdflink").length > 0) { console.log("found: .smwrdflink"); }

if ($(".smwfact").length > 0) { console.log("found: .smwfact"); }

*/

if ($("#mw-data-after-content").length > 0) { smwInitPage; }

ttMouseOver(1);

wwScribbleMaps;

// Make Wowhead 3D model viewer button links open a new tab when clicked.

$('a[href*="modelviewer"]').attr({ target: '_blank' });

});

//****************************************

//****    Loaders                     ****

//****************************************

/* Load Loaders that were registered and just waiting for mw and jq to run their own

boot-strap functionality. There's a very long detailed reason for yet another loader. */

(function {

var loaders = window.wwLoaders;

if (!loaders) return;

for (var i=0, l=loaders.length; i < l; i++)

{

var loader = loaders[i];

if (typeof loader == 'function') { loader; }

}

});

/* Load collected imports */

(function {

var imports = window.wwImportArticles;

if (!imports) return;

var articles = imports.articles;

if (!articles || articles.length == 0) return;

importArticles( imports );

});