User:Lunarity/global.js

"use strict";

/** * Utility function. * Determines whether the given DOMElement is in the document tree (true), or * detached from it (false). 2nd param is optional but can be used to check if * the node is descended from an arbitrary node instead of window.document. */ if (!window.isNodeInDocument) { window.isNodeInDocument = function(aElem, aDoc) { if (!aElem) return false; if (!aDoc) { if (this && this.document) aDoc = this.document else aDoc = window.document; }   do { if (aElem === doc) return true; } while (aElem = aElem.parentNode); return false; } }

/** * JavaScript to Toggle the Wikia Rail on and off. * Adds a button to the toolbar that allows expand/shrink. * * Exploits oasis-one-column for formatting. one-column occurs normally * on special pages like Edit, RecentChanges, Diff, etc so we don't do * anything on those pages. (Edit still has the Rail but it provides a * built-in collapser for it) */

if (window.skin === "oasis") { $(function($) {   // Arrow (symbol) for Unicode codings    var _expandMsg = "Expand Content \u2192", // 2192 is arrow-right        _shrinkMsg = "Shrink Content \u2190"; // 2190 is arrow-left

function expandContent {       $("#WikiaRail").hide; $("#WikiaPageHeader").append($("#WikiaSearch").detach); $(document.body).addClass("oasis-one-column"); }   function shrinkContent {       $(document.body).removeClass("oasis-one-column"); $("#WikiaRail").prepend($("#WikiaSearch").detach).show; }   function handleClick(event) {       var $this = $(this); if ($this.text === _expandMsg) { expandContent; $this.text(_shrinkMsg); } else { shrinkContent; $this.text(_expandMsg); }       return false; }

if (!/\boasis-one-column\b/.test(document.body.className)) { var toolbar = $("#WikiaFooter > .toolbar > ul.tools"); if (toolbar.length) { $(document.createElement('a')) .prop('href', '#') .text(_expandMsg) .click(handleClick) .appendTo(document.createElement('li')) .parent .appendTo(toolbar) ;       }    } }); }

/** * Fix the MediaWiki diffs (including AJAX ones). * Display the diffs in monospace font with white-space preservation. * We can't just use CSS for this because MediaWiki generates bad diffs; there are * unnecessary new-lines added at the start and end of each modified line in the * diff which obviously end up being shown unless we fix it. * This script strips the unnecessary new-line characters as well as setting * the inline styles to monospace/pre-wrap (Easier to manage all in one place). * * The Edit page fixing only works in browsers with MutationObserver support. * Those are Firefox14+ or Chrome18+. */ $(function($) {   var _selectors = 'td.diff-addedline > div, td.diff-deletedline > div, td.diff-context > div';    function fixDiffNewlines($aDiffTable)    {        var rows = $(_selectors, $aDiffTable),            i = rows.length,            n;        $aDiffTable.hide; // Minimise reflows by setting display:none        while (i--) {            /*rows[i].style.fontFamily = 'monospace';            rows[i].style.whiteSpace = 'pre-wrap';*/            //rows[i].innerHTML = rows[i].innerHTML.replace(/(^\s*?\n|\n\s*$)/g, "");            rows[i].normalize; // Merge adjacent text nodes to simplify this            n = rows[i].firstChild;            if (n.nodeType === /*n.TEXT_NODE*/3)                n.data = n.data.replace(/^\s*?\n/, "");            n = rows[i].lastChild;            if (n.nodeType === /*n.TEXT_NODE*/3)                n.data = n.data.replace(/\n\s*$/, "");        }        $aDiffTable.show; // Reset }   var _observer; function observeDialog(mutations) {       // mutations is an Array of MutationRecord /*interface MutationRecord { readonly attribute DOMString type; readonly attribute Node target; readonly attribute NodeList? addedNodes; //? means optional readonly attribute NodeList? removedNodes; readonly attribute Node? previousSibling; readonly attribute Node? nextSibling; readonly attribute DOMString? attributeName; readonly attribute DOMString? attributeNamespace; readonly attribute DOMString? oldValue; };*/       /*var m, $node; for (var i = mutations.length ; i-- ; ) { //if (m.type === 'childList') { // We are *only* observing childList m = mutations[i].addedNodes; for (var j = m.length ; j-- ; ) { $node = $(m[j]); if ($node.is('#wikiDiff table.diff')) { // Bingo. We've got the table. // We're assuming that the table is fully built. fixDiffNewlines($node); return; }            }             //}        }*/        // The mutation list, despite inspecting subtrees, only generates a        // mutation for the top level when div#wikiDiff is attached, it does not // generate events for the child nodes. That makes sense but it means // that we need to do this ourself. var $n = $('#wikiDiff table.diff', mutations[0].target); if ($n.length) fixDiffNewlines($node); }   function observeBody(mutations) {       // ASSUME: The table is inserted in bulk instead of        //   being constructed a row at a time inside the DOM tree. var m, j;       for (var i = mutations.length ; i-- ; ) { m = mutations[i].addedNodes; for (j = m.length ; j-- ; ) { if (m[j].id === 'EditPageDialog') { // Check if the table already exists. We can process it                     // immediately if it does (unlikely but possible). var $node = $('#wikiDiff table.diff', m[j]); if ($node.length) { fixDiffNewlines($node); } else { _observer.disconnect; // Make sure it's empty _observer.observe(m[j], {                             childList: true,                              subtree: true // All children of all sub-nodes                          }); }                     // Mutations are in order, since we're using a reverse loop // the dialog we just processed was newest so we can stop. return; }            }             // Check for the dialog being removed. // We want to kill the observer so it doesn't leak the node tree. m = mutations[i].removedNodes; for (j = m.length ; j-- ; ) { if (m[j].id === 'EditPageDialog') { _observer.disconnect; return; }            }        }    }

// Build custom stylesheet. var t = document.createElement('style'); t.setAttribute("type", "text/css"); t.appendChild(document.createTextNode(_selectors + "{" + "font-family: monospace;" // Chrome has a nice bug that causes it to render better than Firefox. // Chrome complies with pre+break-word. Firefox just applies normal text // processing rules (break at spaces, hyphens, etc) which sucks. + ($.browser.webkit           ? "white-space: pre; word-wrap: break-word;"            : "white-space: pre-wrap;") + "}"));   document.head.appendChild(t); t = null; // If we're on a diff page then run the fix. // Regex uses look-ahead (?= means "followed by"). The trick is that the line // is not *consumed* by the look-ahead matches so the 2nd (or more) // look-aheads get to walk over the same characters. if ((window.wgAction === 'historysubmit' || (window.mw.config && window.mw.config.get('wgAction') === 'view') && /^[^\?]+(?=.*?[\?&]diff)(?=.*?[\?&]oldid=)/.test(window.location.href))) {       // :first avoids trickery, like tables in articles with .diff class t = $("#WikiaArticle table.diff").filter(':first'); if (t.length) { fixDiffNewlines(t); }       t = null; }

// If we're on an edit page then we need to watch for pop-up Diff overlays // mw.config is MediaWiki 1.18+, global is 1.16.1 if (window.wgIsEditPage === true || (window.mw.config && window.mw.config.get('wgAction') === 'edit')) { // We use the DOM4 MutationObserver to detect when the pop-up is shown. var observer_factory = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; if (observer_factory) { var observer = new observer_factory(observeBody); _observer = new observer_factory(observeDialog); // We observe nodes added to the body *directly*, not any of its // children. This is more efficient since the overlay is always added // to and we won't get events caused by the WYSIWYG editor. observer.observe(document.body, {childList: true/*, subtree: true*/}); }   } });