Created page with "// Code by Spottra of Clash of Clans Wiki, October 2013. // Current version: 1.01, November 2013. // // If you choose to copy this code, please leave the attribution at the to..."
New page
// Code by Spottra of Clash of Clans Wiki, October 2013.
// Current version: 1.01, November 2013.
//
// If you choose to copy this code, please leave the attribution at the top.
//
// Sub-navigation levels 4 and 5
// =============================
// This code extends the MediaWiki:Wiki-navigation to enable level 4 and 5
// submenus. Simply edit the MediaWiki:Wiki-navigation file as normal and
// use '****' and '*****' to indicate where level 4 and 5 submenus should
// appear.
//
// The corresponding CSS required for proper display of the level 4 and 5
// submenus is located at MediaWiki:Wikia.css/SubNav.css.
//
// Supports:
// * '****Link name' construct. Link spaces will be replaced by underscores.
// * '****Link name|Display name' construct. Link spaces also replaced.
// * '****<nowiki>Display name</nowiki>' construct for menus without links.
//
// Notes:
// * The navigation preview does not display the level 4 or 5 submenus, as it
// does not call any custom Javascript. You will need to publish your changes
// and then refresh the page in order to see their effects.
// * Publishing the Wiki-navigation page does not call any custom Javascript
// either, which is why the page refresh is necessary. The previous level 4
// and 5 submenus will appear until the page is refreshed. Note that you do
// not need to clear cache; a simple refresh is all that is required (or
// browse to another page).
//
// Limitations:
// * Currently, the level 3 submenus must either have unique links, or for
// level 3 submenus that are not configured as links
// (i.e. <nowiki>Menu name</nowiki>), they must be uniquely named. This code
// uses .find() to locate the proper level 3 submenu to build the extra HTML,
// and non-unique names will result in the menu being added to all matches.
function timeStamp_SubNav_js() {
return "2013.11.08 21:28 (UTC-8)";
}
function imgChevron(strDirection) {
if (strDirection == 'down')
return '<img class="chevron" src="data:image/gif;base64,' +
'R0lGODlhAQABAIABAAAAAP///yH5BAEAAAEALAAAAAABAAEAQAICTAEAOw%3D%3D">';
return '<img height="0" width="0" class="chevron-right" ' +
'src="data:image/gif;base64,' +
'R0lGODlhAQABAIABAAAAAP///yH5BAEAAAEALAAAAAABAAEAQAICTAEAOw%3D%3D">';
}
$.get("/wiki/MediaWiki:Wiki-navigation?action=raw").done(function(data) {
var arrNav = data.split('\n');
var strSubNav = '';
var strSubNavs = '';
var strSubMenu2 = '';
var strSubMenu2a = '';
var boolSubMenu4 = false;
console.log('SubNav.js: Creating custom menus');
for (var i = 0; i < arrNav.length; i ++) {
var intSubLevel = subNavLevel(arrNav[i]);
// Check for level 3 or greater subnav. We will build all level 3+ menus
// but only add them if we need to (i.e. if we encounter a level 4+
// somewhere.
if (intSubLevel >= 3) {
if (i == 0) {
console.log('SubNav.js: Exiting:\n' +
' Level 3+ subnav on first line of Wiki-navigation file.\n' +
' arrNav[' + i + ']=' + arrNav[i] + '\n' +
' intSubLevel=' + intSubLevel + '\n' +
' strSubNav=' + strSubNav);
return; // Shouldn't happen, but exit gracefully if it does.
}
// Check both the previous and the next entries.
intPrevSubLevel = subNavLevel(arrNav[i - 1]);
intNextSubLevel = (i == arrNav.length - 1 ? 0 : subNavLevel(arrNav[i + 1]));
if (intSubLevel > intPrevSubLevel + 1) {
// The only valid choices for submenus are:
// * intSubLevel == intPrevSubLevel (the current menu continues)
// * intSubLevel == intPrevSubLevel + 1 (new submenu)
// * intSubLevel < intPrevSubLevel (the current menu ends)
// Anything else and we simply exit due to bad formation.
console.log('SubNav.js: Exiting:\n' +
' Submenu structure badly formed.\n' +
' arrNav[' + i + ']=' + arrNav[i] + '\n' +
' intSubLevel=' + intSubLevel + '\n' +
' intPrevSubLevel=' + intPrevSubLevel + '\n' +
' intNextSubLevel=' + intNextSubLevel + '\n' +
' strSubNav=' + strSubNav);
return;
}
// If we've encountered a level 4+ submenu, we'll need to add it.
if (intSubLevel == 4)
boolSubMenu4 = true;
if (intNextSubLevel == intSubLevel + 1) {
// We've encountered the beginning of a new submenu.
if (intSubLevel > 3) {
// For sublevels > 3, add a new class.
strSubNav += (strSubNav == '' ? '' : '\n');
strSubNav += '<li class="subnav-' + (intNextSubLevel) + 'p">';
}
else {
// Otherwise just add a <li> tag.
strSubNav += (strSubNav == '' ? '' : '\n');
strSubNav += '<li>';
}
strSubNav += (strSubNav == '' ? '' : '\n');
strSubNav += subNavLevel(arrNav[i], 'fullsublink');
strSubNav += '\n' + '<ul class="subnav-' + (intSubLevel + 1) + '">';
}
else if (intNextSubLevel < intSubLevel) {
// We've encountered the end of a submenu.
strSubNav += (strSubNav == '' ? '' : '\n');
strSubNav += '<li>' + subNavLevel(arrNav[i], 'fulllink') + '</li>';
strSubNav += '\n' + '</ul></li>';
if (intSubLevel - intNextSubLevel > 1 && strSubNav != '') {
// If we're closing more than one submenu, add additional closing tags.
var intClosingTags = intSubLevel - intNextSubLevel;
while (intClosingTags > 1) {
strSubNav += '\n' + '</ul></li>';
intClosingTags --;
}
}
}
else if (intSubLevel == intNextSubLevel) {
// Garden variety submenu.
strSubNav += '\n' + '<li>' + subNavLevel(arrNav[i], 'fulllink') + '</li>';
}
else {
console.log('SubNav.js: Exiting:\n' +
' Fallthrough.\n' +
' arrNav[' + i + ']=' + arrNav[i] + '\n' +
' intSubLevel=' + intSubLevel + '\n' +
' intPrevSubLevel=' + intPrevSubLevel + '\n' +
' intNextSubLevel=' + intNextSubLevel + '\n' +
' strSubNav=' + strSubNav);
return; // Only should happen if the Wiki-navigation is poorly formed.
}
}
else {
// Close and reset the subnav string and start over
if (strSubNav != '') {
strSubNavs += strSubNav;
strSubNav = '';
}
}
// If we have dropped below level 3 and we've got submenus to add, do so.
if (intSubLevel < 3 && boolSubMenu4) {
var subnav3 = $('.WikiHeader nav').find(strSubMenu2);
// Non-links unfortunately match every non-link, so we need to find the
// correct one.
if (strSubMenu2a != '') {
subnav3.each(function(index) {
var subnav2 = $(this).parent().find('.subnav-2a');
// console.log('SubNav.js: HTML[' + index + ']=' + subnav2.html());
// Unfortunately the chevron string changes slightly so we
// can't match to the whole thing.
var strMatch = strSubMenu2a + imgChevron('down').substr(0, 5);
if (subnav2.html().substr(0, strMatch.length) == strMatch) {
// We've found the right one, so save just the one we want to modify.
subnav3 = $(this);
return false;
}
});
}
subnav3.addClass("subnav-3-with-subnav-4");
subnav3.html(strSubNavs);
// console.log('SubNav.js: Adding: ' + strSubMenu2 + '\n' + 'strSubNavs = ' + strSubNavs);
boolSubMenu4 = false;
}
// Grab any level 2 submenu we encounter and reset the subnavs string.
if (intSubLevel == 2) {
strSubMenu2 = subNavLevel(arrNav[i], 'findlink');
// For menu items with no links, store the displayname
if (Array.isArray(strSubMenu2)) {
strSubMenu2a = strSubMenu2[1];
strSubMenu2 = strSubMenu2[0];
}
else
strSubMenu2a = '';
strSubNavs = '';
boolSubMenu4 = false;
}
}
});
/*
* Function to determine the subnav level (i.e. the number of leading asterisks).
*
* The strReturnLink argument changes the behavior of this function in several ways:
* no argument - simply return the subnav level
* 'link' - returns the basic HTML link
* 'findlink' - returns HTML link text suitable for finding in Wikia nav HTML
* 'fulllink' - returns the full HTML link with display text and closing tag
* 'sublink' - returns the HTML link with the proper subnav class
* 'fullsublink' - return the full HTML link with display text, subnav and closing
* 'display' - returns the display name
*
* Example 1:
* subNavLevel('***Barbarian')
* return 3;
* subNavLevel('***Barbarian', 'findlink')
* return 'a[href="/wiki/Barbarian"] + .subnav-4';
* subNavLevel('***Barbarian', 'link')
* return '<a href="/wiki/Barbarian">';
* subNavLevel('***Barbarian', 'fulllink')
* return '<a href="/wiki/Barbarian">Barbarian</a>';
* subNavLevel('***Barbarian', 'sublink')
* return '<a href="/wiki/Barbarian" class="subnav-3a">';
* subNavLevel('***Barbarian', 'fullsublink')
* return '<a href="/wiki/Barbarian" class="subnav-3a">Barbarian' +
* imgChevron() + '</a>';
* subNavLevel('***Barbarian', 'display')
* return 'Barbarian';
*
* Example 2:
* subNavLevel('****Loading_Screen_Hints|Loading Screen Hints')
* return 4;
* subNavLevel('****User:Spottra|Spottra', 'findlink')
* return 'a[href="/wiki/User:Spottra"] + .subnav-5';
* subNavLevel('****User:Spottra|Spottra', 'link')
* return '<a href="/wiki/User:Spottra">';
* subNavLevel('****User:Spottra|Spottra', 'fulllink')
* return '<a href="/wiki/User:Spottra">Spottra</a>';
* subNavLevel('****User:Spottra|Spottra', 'sublink')
* return '<a href="/wiki/User:Spottra" class="subnav-4a">';
* subNavLevel('****User:Spottra|Spottra', 'fullsublink')
* return '<a href="/wiki/User:Spottra" class="subnav-4a">' +
* 'Spottra' + imgChevron() + '</a>';
* subNavLevel('****User:Spottra|Spottra', 'display)
* return 'Spottra';
*/
function subNavLevel(strNav, strReturnLink) {
if (strNav == undefined) return;
var idx = 0;
while (idx < strNav.length && strNav.substr(idx, 1) == '*')
idx ++;
if (!strReturnLink)
return idx;
strNav = strNav.substr(idx);
if (strNav.substr(0, 8) == '<nowiki>' &&
strNav.substr(strNav.length - 9) == '</nowiki>') {
// A nowiki tag means we use a nonfunctional link ('#') and use the
// entire string as the display.
strNav = ['#', strNav.substr(8, strNav.length - 17)];
}
else {
strNav = strNav.split('|');
if (strNav.length == 1)
strNav = [strNav[0], strNav[0]];
// Hopefully will fix Chinese URLs without breaking the others
strNav[0] = '/wiki/' +
encodeURIComponent(strNav[0].replace(new RegExp(' ', 'g'), '_'));
}
switch (strReturnLink) {
case 'link':
return '<a href="' + strNav[0] + '">';
case 'findlink': {
if (strNav[0] == '#')
return ['a[href="' + strNav[0] + '"] + .subnav-' + (idx + 1), strNav[1]];
return 'a[href="' + strNav[0] + '"] + .subnav-' + (idx + 1);
}
case 'sublink':
return '<a href="' + strNav[0] + '" class="subnav-' + idx + 'a">';
case 'fulllink':
return '<a href="' + strNav[0] + '">' + strNav[1] + '</a>';
case 'fullsublink':
return '<a href="' + strNav[0] + '" class="subnav-' + idx + 'a">' +
strNav[1] + imgChevron() + '</a>';
case 'display':
return strNav[1];
}
}