MediaWiki:Common.js: Difference between revisions

From Pikipedia, the Pikmin wiki
Jump to navigation Jump to search
(Pikan will be disabled for maintenance for the next few hours.)
(And it's back in business. Probably.)
Line 700: Line 700:


/* Pikan */
/* Pikan */
/*
importScriptURI('//www.pikminwiki.com/index.php?title=User:Espyo/pikan-core.js'
importScriptURI('//www.pikminwiki.com/index.php?title=User:Espyo/pikan.js'
+ '&action=raw&ctype=text/javascript');
 
importScriptURI('//www.pikminwiki.com/index.php?title=User:Espyo/pikan-pikipedia.js'
+ '&action=raw&ctype=text/javascript');
+ '&action=raw&ctype=text/javascript');
*/

Revision as of 11:33, July 11, 2015

/* tooltips and access keys */
ta = new Object();
ta['pt-userpage'] = new Array('.','My user page');
ta['pt-anonuserpage'] = new Array('.','The user page for the ip you\'re editing as');
ta['pt-mytalk'] = new Array('n','My talk page');
ta['pt-anontalk'] = new Array('n','Discussion about edits from this ip address');
ta['pt-preferences'] = new Array('','My preferences');
ta['pt-watchlist'] = new Array('l','The list of pages you\'re monitoring for changes.');
ta['pt-mycontris'] = new Array('y','List of my contributions');
ta['pt-login'] = new Array('o','You are encouraged to log in, it is not mandatory however.');
ta['pt-anonlogin'] = new Array('o','You are encouraged to log in, it is not mandatory however.');
ta['pt-logout'] = new Array('o','Log out');
ta['ca-talk'] = new Array('t','Discussion about the content page');
ta['ca-edit'] = new Array('e','You can edit this page. Please use the preview button before saving.');
ta['ca-addsection'] = new Array('+','Add a comment to this discussion.');
ta['ca-viewsource'] = new Array('e','This page is protected. You can view its source.');
ta['ca-history'] = new Array('h','Past versions of this page.');
ta['ca-protect'] = new Array('=','Protect this page');
ta['ca-delete'] = new Array('d','Delete this page');
ta['ca-undelete'] = new Array('d','Restore the edits done to this page before it was deleted');
ta['ca-move'] = new Array('m','Move this page');
ta['ca-watch'] = new Array('w','Add this page to your watchlist');
ta['ca-unwatch'] = new Array('w','Remove this page from your watchlist');
ta['search'] = new Array('f','Search this wiki');
ta['p-logo'] = new Array('','Main Page');
ta['n-mainpage'] = new Array('z','Visit the Main Page');
ta['n-portal'] = new Array('','About the project, what you can do, where to find things');
ta['n-currentevents'] = new Array('','Find background information on current events');
ta['n-recentchanges'] = new Array('r','The list of recent changes in the wiki.');
ta['n-randompage'] = new Array('x','Load a random page');
ta['n-help'] = new Array('','The place to find out.');
ta['n-sitesupport'] = new Array('','Support us');
ta['t-whatlinkshere'] = new Array('j','List of all wiki pages that link here');
ta['t-recentchangeslinked'] = new Array('k','Recent changes in pages linked from this page');
ta['feed-rss'] = new Array('','RSS feed for this page');
ta['feed-atom'] = new Array('','Atom feed for this page');
ta['t-contributions'] = new Array('','View the list of contributions of this user');
ta['t-emailuser'] = new Array('','Send a mail to this user');
ta['t-upload'] = new Array('u','Upload images or media files');
ta['t-specialpages'] = new Array('q','List of all special pages');
ta['ca-nstab-main'] = new Array('c','View the content page');
ta['ca-nstab-user'] = new Array('c','View the user page');
ta['ca-nstab-media'] = new Array('c','View the media page');
ta['ca-nstab-special'] = new Array('','This is a special page, you can\'t edit the page itself.');
ta['ca-nstab-project'] = new Array('a','View the project page');
ta['ca-nstab-image'] = new Array('c','View the image page');
ta['ca-nstab-mediawiki'] = new Array('c','View the system message');
ta['ca-nstab-template'] = new Array('c','View the template');
ta['ca-nstab-help'] = new Array('c','View the help page');
ta['ca-nstab-category'] = new Array('c','View the category page');
ta['ca-nstab-forum'] = new Array('c','View the forum page');

 /* Test if an element has a certain class **************************************
  *
  * Description: Uses regular expressions and caching for better performance.
  * Maintainers: [[Wikipedia:User:Mike Dillon]], [[Wikipedia:User:R. Koot]], [[Wikipedia:User:SG]]
  */
 
 var hasClass = (function () {
     var reCache = {};
     return function (element, className) {
         return (reCache[className] ? reCache[className] : (reCache[className] = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)"))).test(element.className);
     };
 })();

 /** Collapsible tables *********************************************************
  *
  *  Description: Allows tables to be collapsed, showing only the header. See
  *               [[Wikipedia:NavFrame]].
  *  Maintainers: [[User:R. Koot]]
  */
 
 var autoCollapse = 2;
 var collapseCaption = "hide";
 var expandCaption = "show";
 
 function collapseTable( tableIndex )
 {
     var Button = document.getElementById( "collapseButton" + tableIndex );
     var Table = document.getElementById( "collapsibleTable" + tableIndex );
 
     if ( !Table || !Button ) {
         return false;
     }
 
     var Rows = Table.rows;
 
     if ( Button.firstChild.data == collapseCaption ) {
         for ( var i = 1; i < Rows.length; i++ ) {
             Rows[i].style.display = "none";
         }
         Button.firstChild.data = expandCaption;
     } else {
         for ( var i = 1; i < Rows.length; i++ ) {
             Rows[i].style.display = Rows[0].style.display;
         }
         Button.firstChild.data = collapseCaption;
     }
 }
 
 function createCollapseButtons()
 {
     var tableIndex = 0;
     var NavigationBoxes = new Object();
     var Tables = document.getElementsByTagName( "table" );
 
     for ( var i = 0; i < Tables.length; i++ ) {
         if ( hasClass( Tables[i], "collapsible" ) ) {
 
             var Header = null;
             /* the editor can override which table header element gets the button with a class */
             var OverrideHeader = Tables[i].getElementsByClassName("collapsiblebutton");
             if(OverrideHeader) OverrideHeader = OverrideHeader[0];
             if(OverrideHeader) Header = OverrideHeader;
 
             /* only add button and increment count if there is a header row to work with */
             if (!Header){
                 var HeaderRow = Tables[i].getElementsByTagName( "tr" )[0];
                 if (!HeaderRow) continue;
                 Header = HeaderRow.getElementsByTagName( "th" )[0];
                 if (!Header) continue;
             }

             NavigationBoxes[ tableIndex ] = Tables[i];
             Tables[i].setAttribute( "id", "collapsibleTable" + tableIndex );
 
             var Button     = document.createElement( "span" );
             var ButtonLink = document.createElement( "a" );
             var ButtonText = document.createTextNode( collapseCaption );
 
             Button.style.styleFloat = "right";
             Button.style.cssFloat = "right";
             Button.style.fontWeight = "normal";
             Button.style.textAlign = "right";
             Button.style.width = "6em";
             Button.style.marginLeft = "-100%";
             Button.setAttribute( "class", "collapsible-button" );
 
             ButtonLink.style.color = Header.style.color;
             ButtonLink.setAttribute( "id", "collapseButton" + tableIndex );
             ButtonLink.setAttribute( "href", "javascript:collapseTable(" + tableIndex + ");" );
             ButtonLink.appendChild( ButtonText );
 
             Button.appendChild( document.createTextNode( "[" ) );
             Button.appendChild( ButtonLink );
             Button.appendChild( document.createTextNode( "]" ) );
 
             Header.insertBefore( Button, Header.childNodes[0] );
             tableIndex++;
         }
     }
 
     for ( var i = 0;  i < tableIndex; i++ ) {
         if ( hasClass( NavigationBoxes[i], "collapsed" ) || ( tableIndex >= autoCollapse && hasClass( NavigationBoxes[i], "autocollapse" ) ) ) {
             collapseTable( i );
         }
     }
 }
 
 addOnloadHook( createCollapseButtons );

/* domReady.js by Tanny O'Haley (http://tanny.ica.com/ICA/TKO/test.nsf/js/domready.js), minified */

var domReadyEvent={name:"domReadyEvent",events:{},domReadyID:1,bDone:false,DOMContentLoadedCustom:null,add:function(handler){if(!handler.$$domReadyID){handler.$$domReadyID=this.domReadyID++;if(this.bDone){handler()}this.events[handler.$$domReadyID]=handler}},remove:function(handler){if(handler.$$domReadyID){delete this.events[handler.$$domReadyID]}},run:function(){if(this.bDone){return}this.bDone=true;for(var i in this.events){this.events[i]()}},schedule:function(){if(this.bDone){return}if(/KHTML|WebKit/i.test(navigator.userAgent)){if(/loaded|complete/.test(document.readyState)){this.run()}else{setTimeout(this.name+".schedule()",100)}}else if(document.getElementById("__ie_onload")){return true}if(typeof this.DOMContentLoadedCustom==="function"){if(typeof document.getElementsByTagName!=='undefined'&&(document.getElementsByTagName('body')[0]!==null||document.body!==null)){if(this.DOMContentLoadedCustom()){this.run()}else{setTimeout(this.name+".schedule()",250)}}}return true},init:function(){if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){domReadyEvent.run()},false)}setTimeout("domReadyEvent.schedule()",100);function run(){domReadyEvent.run()}if(typeof addEvent!=="undefined"){addEvent(window,"load",run)}else if(document.addEventListener){document.addEventListener("load",run,false)}else if(typeof window.onload==="function"){var oldonload=window.onload;window.onload=function(){domReadyEvent.run();oldonload()}}else{window.onload=run}}};var domReady=function(handler){domReadyEvent.add(handler)};domReadyEvent.init();

/* Content tabber, version 1.0.5 by Greenpickle (GPL3) */

var switchableAnchorPrefix = '';
var switchableClass = 'switchable';
var switchableSectionClass = 'switch';
var switchableTabsClass = 'switchabletabs';
var switchableSectionTitleAttr = 'title';

function initialiseSwitchable () {
    // get the elements we care about
    switchable = myGetElementsByClassName(document, switchableClass);

    // some functions
    switchable.createTab = function (label, isAnchor, i, j) {
        var tab = document.createElement('li');
        var child;
        if (isAnchor) {
            child = document.createElement('a');
            child.href =
                'javascript:switchable.setVisible(' + i + ', ' + j + ');';
        } else child = document.createElement('strong');
        child.appendChild(document.createTextNode(label));
        tab.appendChild(child);
        return tab;
    }

    switchable.getVisible = function (i) {
        var visible = this[i].getAttribute('visiblesection');
        if (visible) visible = parseInt(visible);
        if (visible === null || isNaN(visible)) {
            visible = 0;
            this[i].setAttribute('visiblesection', visible.toString());
        }
        return Math.max(0, Math.min(visible, this[i].sections.length - 1));
    }

    switchable.updateVisible = function (i) {
        if (isNaN(parseInt(i))) {
            // update all switchables if no valid number given
            for (var i = 0; i < this.length; i++)
                this.updateVisible(i);
        } else {
            var visible = this.getVisible(i);
            var sections = this[i].sections;
            var tc = this[i].tabContainer;
            var currentTab;
            for (var j = 0; j < sections.length; j++) {
                if (j == visible) {
                    // change 'show' link
                    currentTab = this.createTab(sections[j].sectionName,
                                                    false);
                    currentTab.j = j;
                    tc.replaceChild(currentTab, tc.tabs[j]);
                    // show section
                    sections[j].style.display = '';
                } else {
                    // change 'show' link
                    if (tc.currentTab !== undefined && tc.currentTab.j == j)
                        tc.replaceChild(tc.tabs[j], tc.currentTab);
                    // hide section
                    sections[j].style.display = 'none';
                }
            }
            if (currentTab !== undefined) tc.currentTab = currentTab;
        }
    }

    switchable.setVisible = function (i, j) {
        this[i].setAttribute('visiblesection', j);
        this.updateVisible(i);
    }

    // initialise
    for (var i = 0; i < switchable.length; i++) {
        var sections = myGetElementsByClassName(switchable[i],
                                                switchableSectionClass);
        switchable[i].sections = sections;
        // create show/hide anchors
        var tabContainer = document.createElement('ul');
        tabContainer.className = switchableTabsClass;
        switchable[i].appendChild(tabContainer);
        switchable[i].tabContainer = tabContainer;
        tabContainer.tabs = [];
        for (var j = 0; j < sections.length; j++) {
            // re-append section to place it after links
            switchable[i].appendChild(sections[j]);
            // use section's name if it has one
            var sectionName = sections[j].getAttribute(
                                                switchableSectionTitleAttr);
            if (!sectionName) sectionName = j.toString();
            sections[j].sectionName = sectionName;
            // create anchor
            var tab = switchable.createTab(
                            switchableAnchorPrefix + sectionName, true, i, j);
            tabContainer.appendChild(tab);
            tabContainer.tabs.push(tab);
        }
    }
    this.switchable = switchable;
    // initial show/hide
    switchable.updateVisible();
}

// I'd extend Node.prototype, but apparently IE fails...
function myGetElementsByClassName (node, cls) {
    var result = [];
    var pool = node.getElementsByTagName("*");
    var re = new RegExp('\\b' + cls + '\\b');
    for (var i = 0; i < pool.length; i++)
        if (re.test(pool[i].className)) result.push(pool[i]);
    return result;
}

// initialise on page load
domReady(initialiseSwitchable);

/* table.hideable, version 1.1.1 by Greenpickle (GPL3) */

var hideImageURL = 'http://www.pikminwiki.com/images/9/96/Hide.png';
var showImageURL = 'http://www.pikminwiki.com/images/1/15/Show.png';
var hideableColClass = 'hideable';
var hiddenColClass = 'hidden';
var hideableShowClass = 'showcol';

function getElementsByTagNames (node) {
    // return an array of elements in the node with the given tag names
    var nodes = [];
    for (var i = 1; i < arguments.length; i++) {
        var newNodes = node.getElementsByTagName(arguments[i]);
        try {
            // no idea where this'll fail if it does
            newNodes = Array.prototype.slice.call(newNodes);
            nodes = nodes.concat(newNodes);
        } catch (e) {
            // do it the slow way
            for (var j = 0; j < newNodes.length; j++) nodes.push(newNodes[j]);
        }
    }
    return nodes;
}

function matchTagName (node) {
    // check if node.tagName is one of given names, case-insensitively
    if (node.tagName === undefined) return false;
    tag = node.tagName.toLowerCase();
    for (var i = 1; i < arguments.length; i++) {
        if (arguments[i].toLowerCase() == tag) return true;
    }
    return false;
}

function getContainer (node, tag) {
    // return nearest parent with given tag name
    tag = tag.toLowerCase();
    var container = node;
    do {
        container = container.parentNode;
        if (container === document) return undefined;
    } while (container.tagName.toLowerCase() != tag);
    return container;
}

function nextElement (e) {
    do e = e.nextSibling;
    while (e !== null && e.nodeType != 1);
    return e;
}

function previousElement (e) {
    do e = e.previousSibling;
    while (e !== null && e.nodeType != 1);
    return e;
}

var hasClass = (function () {
    var reCache = {};
    return function (element, className) {
        return (reCache[className] ? reCache[className] : (reCache[className]
            = new RegExp("(?:\\s|^)" + className + "(?:\\s|$)")))
            .test(element.className);
    };
})();

var hideable = {};

hideable.showCallback = function () {
    hideable.show(this.parentNode);
    return false;
};

hideable.hideCallback = function () {
    hideable.hide(this.parentNode);
    return false;
};

hideable.createLink = function (isHide) {
    // create a show/hide link
    var lnk = document.createElement('a');
    lnk.href = '#';
    lnk.onclick = isHide ? hideable.hideCallback : hideable.showCallback;
    var img = document.createElement('img');
    img.alt = isHide ? 'hide' : 'show';
    img.src = isHide ? hideImageURL : showImageURL;
    lnk.appendChild(img);
    return lnk;
};

hideable.getColSpan = function (cell, orig) {
    return orig ? cell.origColSpan || cell.colSpan : cell.colSpan;
};

hideable.setColSpan = function (cell, colSpan) {
    if (cell.origColSpan === undefined)
        // store original colspan
        cell.origColSpan = cell.colSpan;
    cell.colSpan = colSpan;
};

hideable.getCol = function (targetCell, orig) {
    var row = getContainer(targetCell, 'tr');
    if (row === undefined) throw('cell not in a table row');
    // sum colspans along row
    var col = 0;
    var children = getElementsByTagNames(row, 'th', 'td');
    for (var i = 0; i < children.length; i++) {
        var cell = children[i];
        if (cell === targetCell) break;
        if (orig || cell.style.display != 'none')
            // cell is not hidden, or we want hidden cells: add its colspan
            col += hideable.getColSpan(cell, orig);
    }
    return col;
};

hideable.cellAtCol = function (row, targetCol, orig) {
    var col = 0;
    var cells = getElementsByTagNames(row, 'th', 'td');
    for (var i = 0; i < cells.length; i++) {
        var cell = cells[i];
        if (orig || cell.style.display != 'none') {
            // cell is not hidden, or we want hidden cells: add its colspan
            col += hideable.getColSpan(cell, orig);
            if (col > targetCol) return cell;
        }
    }
}

hideable.cellsInCol = function (cell) {
    // return array of cells in the same column as the given one
    if (!matchTagName(cell, 'td', 'th')) throw('not a table cell');
    var table = getContainer(cell, 'table');
    if (table === undefined) throw('cell not in a table');
    var col = hideable.getCol(cell, true);
    var rows = table.getElementsByTagName('tr');
    var cells = [];
    for (var i = 0; i < rows.length; i++) {
        cells.push(hideable.cellAtCol(rows[i], col, true));
    }
    return cells;
};

hideable.hide = function (cell) {
    var cells = hideable.cellsInCol(cell);
    for (var i = 0; i < cells.length; i++) {
        if (i == 0) {
            // replace header with 'show' button
            var showCell = document.createElement(cells[i].tagName);
            showCell.colspan = cells[i].colSpan;
            showCell.className = hideableShowClass;
            showCell.appendChild(hideable.createLink(false));
            hideable.hiddenHeaders[hideable.getCol(cells[i], false)] =
                cells[i].parentNode.replaceChild(showCell, cells[i]);
        } else {
            // hide this column's cells
            cells[i].style.display = 'none';
            // expand next visible column's cells, if any, to this one
            var expand = cells[i];
            do expand = nextElement(expand);
            while (expand !== null &&
                (expand.nodeType != 1 || expand.style.display == 'none'))
            if (expand === null) {
                // couldn't find a next column: look for a previous one
                expand = cells[i];
                do expand = previousElement(expand);
                while (expand !== null &&
                    (expand.nodeType != 1 || expand.style.display == 'none'))
            }
            if (expand !== null)
                hideable.setColSpan(expand, expand.colSpan + cells[i].colSpan);
        }
    }
};

hideable.show = function (cell) {
    var cells = hideable.cellsInCol(cell);
    for (var i = 0; i < cells.length; i++) {
        // show this column's cells
        cells[i].style.display = '';
        if (i == 0) {
            // remove 'show' button
            var col = hideable.getCol(cells[i], false);
            var origCell = hideable.hiddenHeaders[col];
            cells[i] = cells[i].parentNode.replaceChild(origCell, cells[i]);
        } else {
            cell = cells[i];
            // work out where we want the ends of the cell to be
            var leftEdge = hideable.getCol(cell, true);
            var rightEdge = leftEdge + (cell.origColSpan || cell.colSpan);
            var change = 0;
            var prevCell = previousElement(cell);
            while (prevCell !== null) {
                if (prevCell.style.display == 'none')
                    // move left to cover hidden cells directly to the left
                    leftEdge -= prevCell.origColSpan || prevCell.colSpan;
                else {
                    // shrink the first visible cell to the left if it covers
                    // any hidden cells we want this cell to cover
                    var pos = hideable.getCol(prevCell, false);
                    if (pos + prevCell.colSpan > leftEdge) {
                        change = pos + prevCell.colSpan - leftEdge;
                        hideable.setColSpan(prevCell, leftEdge - pos);
                    }
                    break;
                }
                prevCell = previousElement(prevCell);
            }
            var nextCell = nextElement(cell);
            var flowRight = 0;
            // need to explicitly set to undefined as we reuse it
            var nextVisible = undefined;
            while (nextCell !== null) {
                if (nextCell.style.display == 'none')
                    // expand to cover hidden cells to the right
                    flowRight += nextCell.origColSpan || nextCell.colSpan;
                else {
                    // until we encounter a visible one, which should cover
                    // them instead
                    flowRight = 0;
                    nextVisible = nextCell;
                    break;
                }
                nextCell = nextElement(nextCell);
            }
            rightEdge += flowRight;
            // expand cell as far right as needed
            hideable.setColSpan(cell, rightEdge - leftEdge);
            change -= cell.colSpan;
            if (nextVisible !== undefined)
                // expand or shrink the visible cell directly to the right to
                // adjust for the changes we've made
                hideable.setColSpan(nextVisible, nextVisible.colSpan + change);
        }
    }
};

hideable.init = function () {
    var tables = document.getElementsByTagName('table');
    if (tables.length == 0) return;
    hideable.hiddenHeaders = [];
    // load images
    new Image().src = hideImageURL;
    new Image().src = showImageURL;
    for (var i = 0; i < tables.length; i++) {
        // operate on first row
        var row = tables[i].getElementsByTagName('tr')[0];
        var cells = getElementsByTagNames(row, 'th', 'td');
        for (var j = 0; j < cells.length; j++) {
            if (hasClass(cells[j], hideableColClass)) {
                // add 'hide' button
                cells[j].appendChild(hideable.createLink(true));
                // hide column now if want to
                if (hasClass(cells[j], hiddenColClass))
                    hideable.hide(cells[j]);
            }
        }
    }
};

// initialise on page load
domReady(hideable.init);

// JavaScript countdown timer 2.0, by Splarka
//
//  <span class="countdown" style="display:none;">
//  Only <span class="countdowndate">January 01 2013 00:00:00 PST</span> until New years.
//  </span>
//  <span class="nocountdown">Javascript disabled.</span>

if ($('body.page-Main_Page').length) {

;(function (module, mw, $) {
    
    'use strict';
    
    var translations = $.extend(true, {
        en: {
            and: 'and',
            second: 'second',
            seconds: 'seconds',
            minute: 'minute',
            minutes: 'minutes',
            hour: 'hour',
            hours: 'hours',
            day: 'day',
            days: 'days'
        }
    }, module.translations || {}),
    i18n = translations[
        mw.config.get('wgContentLanguage')
    ] || translations.en;

    var countdowns = [];
    
    var NO_LEADING_ZEROS = 1;
    
    function output (i, diff) {
        /*jshint bitwise:false*/
        var delta, result, parts = [];
        delta = diff % 60;
        parts.unshift(delta + ' ' + i18n[delta === 1 ? 'second' : 'seconds']);
        diff = Math.floor(diff / 60);
        delta = diff % 60;
        parts.unshift(delta + ' ' + i18n[delta === 1 ? 'minute' : 'minutes']);
        diff = Math.floor(diff / 60);
        delta = diff % 24;
        parts.unshift(delta + ' ' + i18n[delta === 1 ? 'hour'   : 'hours'  ]);
        diff = Math.floor(diff / 24);
        parts.unshift(diff  + ' ' + i18n[diff  === 1 ? 'day'    : 'days'   ]);
        result = parts.pop();
        if (countdowns[i].opts & NO_LEADING_ZEROS) {
            while (parts.length && parts[0][0] === '0') {
                parts.shift();
            }
        }
        if (parts.length) {
            result = parts.join(', ') + ' ' + i18n.and + ' ' + result;
        }
        countdowns[i].node.text(result);
    }
    
    function end(i) {
        var c = countdowns[i].node.parent();
        switch (c.attr('data-end')) {
            case 'remove':
                c.remove();
                countdowns.splice(i, 1);
                return;
            case 'stop':
                output(i, 0);
                countdowns.splice(i, 1);
                return;
            case 'toggle':
                var toggle = c.attr('data-toggle');
                if (toggle && $(toggle).length) {
                    $(toggle).css('display', 'inline');
                    c.css('display', 'none');
                    countdowns.splice(i, 1);
                    return;
                }
                break;
            case 'callback':
                var callback = c.attr('data-callback');
                if (callback && $.isFunction(module[callback])) {
                    output(i, 0);
                    countdowns.splice(i, 1);
                    module[callback].call(c);
                    return;
                }
                break;
        }
        countdowns[i].countup = true;
        output(i, 0);
    }
    
    function update () {
        var now = Date.now();
        $.each(countdowns.slice(0), function (i, countdown) {
            var diff = Math.floor((countdown.date - now) / 1000);
            if (diff <= 0 && !countdown.countup) {
                end(i);
            } else {
                output(i, Math.abs(diff));
            }
        });
        if (countdowns.length) {
            window.setTimeout(function () {
                update();
            }, 1000);
        }
    }
    
    function getOptions (node) {
        /*jshint bitwise:false*/
        var text = node.parent().attr('data-options'),
            opts = 0;
        if (text) {
            if (/no-leading-zeros/.test(text)) {
                opts |= NO_LEADING_ZEROS;
            }
        }
        return opts;
    }
    
    $(function () {
        var countdown = $('.countdown');
        if (!countdown.length) return;
        $('.nocountdown').css('display', 'none');
        countdown
        .css('display', 'inline')
        .find('.countdowndate')
        .each(function () {
            var $this = $(this),
                date = (new Date($this.text())).valueOf();
            if (isNaN(date)) {
                $this.text('BAD DATE');
                return;
            }
            countdowns.push({
                node: $this,
                opts: getOptions($this),
                date: date,
            });
        });
        if (countdowns.length) {
            update();
        }
    });
    
}(window.countdownTimer = window.countdownTimer || {}, mediaWiki, jQuery));

}

/* move game icons into #content for more consistent positioning */
$(function () {$('#game-icons').css('margin-top', '5px').insertBefore($('#firstHeading'))})

/* Pikan */
importScriptURI('//www.pikminwiki.com/index.php?title=User:Espyo/pikan-core.js'
+ '&action=raw&ctype=text/javascript');

importScriptURI('//www.pikminwiki.com/index.php?title=User:Espyo/pikan-pikipedia.js'
+ '&action=raw&ctype=text/javascript');