User:Quarl/wikipage.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// [[User:Quarl/wikipage.js]] - "WikiPage" class for page name, etc. functionality

// depends: util.js

// Suppose we are editing [[Template talk:Foo bar 'blah']].
//   WikiPage.editingP:             true;
//   ...

// wikiPage is a pre-initialized global variable using the current page's canonical URL.
// It uses the "Retrieved from" page hyperlink which is robust against redirections, editing, special characters, special pages.
//
//   wikiPage.url:         "http://en.wikipedia.org/wiki/Template_talk:Foo_bar_%27blah%27"
//   wikiPage.qurl:        "http://en.wikipedia.org/w/index.php?title=Template_talk:Foo_bar_%27blah%27"
//   wikiPage.page:        "Template talk:Foo bar 'blah'"
//   wikiPage.article:     "Foo bar 'blah'"
//   wikiPage.namespace:   "Template talk"
//   wikiPage.namespaceNT: "Template"
//   wikiPage.talkP:       true
//   wikiPage.nsTemplateP: true
//   wikiPage.nsMainP:     false
//   wikiPage.nsUserP:     false
//   wikiPage.nsCategoryP: false
//   wikiPage.nsSpecialP:  false
//   wikiPage.nsProjectP:  false    // (namespace "Wikipedia")

// To create new WikiPage object from a URL:
//   var wp = new WikiPage("http://en.wikipedia.org/wiki/Article_Name");
// To create a new WikiPage object from a page name:
//   var wp = new WikiPage(null, 'Article Name');

// <pre><nowiki>

/*
<div class="printfooter">
Retrieved from "<a href="http://en.wikipedia.org/wiki/Albert_Einstein">http://en.wikipedia.org/wiki/Albert_Einstein</a>"</div>
*/

// the "retrieved from" text contains the canonical article URL (even if we're looking at an edit or history page)
function getCanonPageURL0() {
    var pfooter = document.querySelectorAll("div.printfooter a")[0];
    return pfooter && pfooter.href;
}

function getUsername0(doc) {
    // read username from pt-userpage link.
    // <li id="pt-userpage"><a href="/wiki/User:Quarl">Quarl</a></li>
    return doc.getElementById('pt-userpage').getElementsByTagName('a')[0].text;
}

var wpNamespaces = {'Media':1, 'Special':1,
                    'Talk':1,
                    'User':1, 'User talk':1,
                    'Wikipedia':1, 'Wikipedia talk':1,
                    'Image':1, 'Image talk':1,
                    'MediaWiki':1, 'MediaWiki talk':1,
                    'Template':1, 'Template talk':1,
                    'Help':1, 'Help talk':1,
                    'Category':1, 'Category talk':1,
                    'Portal':1, 'Portal talk':1,
};

function WikiPage(url, page, doc) {
    if (!(this instanceof WikiPage)) return new WikiPage(url, page, doc);
    this.doc = doc;
    if (url) {
        url = "" + url;
        if (url.match( '^(?:(?:https?:|)//'+WikiPage.server+')?/wiki/')) {
            this.pageQuoted = RegExp.rightContext;
        } else if (url.match( '^(?:(?:https?:|)//'+WikiPage.server+')?/w/index\\.php\\?title=([^&]+)')) {
            this.pageQuoted = RegExp.$1;
        } else {
            alert("WikiPage: Couldn't parse page name from url '"+url+"'");
            return;
        }
        if(typeof wpadecode === 'undefined') {
                mw.log.error('Uncaught ReferenceError: wpadecode is not defined');
                return;
        }
        this.page = wpadecode(this.pageQuoted);
    } else if (page) {
        this.page = page.replace(/_/g, ' ');
        this.pageQuoted = wpaescape(page);
    } else {
        alert("WikiPage: must specify url or page"); return;
    }
    this.url = 'http://'+WikiPage.server+'/wiki/' + this.pageQuoted;
    this.qurl = 'http://'+WikiPage.server+'/w/index.php?title=' + this.pageQuoted;

    // Get term on the left of ":".  Not any string is a namespace though, only certain hardcoded ones!
    if (this.page.match(/:/) && wpNamespaces[RegExp.leftContext]) {
        this.namespace = RegExp.leftContext;
        this.article = RegExp.rightContext;
    } else {
        this.namespace = ''; // (main)
        this.article = this.page;
    }

    if (this.namespace == 'Talk') {
        this.talkP = true;
        this.namespaceNT = '';
    } else if (this.namespace.match(/ talk$/)) {
        this.talkP = true;
        this.namespaceNT = RegExp.leftContext;
    } else {
        this.talkP = false;
        this.namespaceNT = this.namespace;
    }

    if (this.article.match(/\//)) {
        this.superarticle = RegExp.leftContext;
        this.subarticle = RegExp.rightContext;
    } else {
        this.superarticle = this.article;
        this.subarticle = '';
    }

    this.nsMainP = (this.namespaceNT == '');
    this.nsMediaP = (this.namespaceNT == 'Media');
    this.nsSpecialP = (this.namespaceNT == 'Special');
    this.nsUserP = (this.namespaceNT == 'User');
    this.nsPortalP = (this.namespaceNT == 'Portal');
    this.nsImageP = (this.namespaceNT == 'Image');
    this.nsMediaWikiP = (this.namespaceNT == 'MediaWiki');
    this.nsTemplateP = (this.namespaceNT == 'Template');
    this.nsHelpP = (this.namespaceNT == 'Help');
    this.nsCategoryP = (this.namespaceNT == 'Category');
    this.nsProjectP = (this.namespaceNT == 'Wikipedia');

    this.talkPage = function() {
        if (this.talkP) { return this; }
        else if (this.namespaceNT == '') { return new WikiPage(null, 'Talk:'+this.article); }
        else { return new WikiPage(null, this.namespaceNT+' talk:'+this.article); }
    }

    this.notalkPage = function() {
        if (!this.talkP) { return this; }
        else if (this.namespaceNT == '') { return new WikiPage(null, this.article); }
        else { return new WikiPage(null, this.namespaceNT+':'+this.article); }
    }

    this.sandboxP     = Boolean(this.page.match(/sandbox$/i));

    this.setDoc = function(doc) {
        var wd = new WikiDocument(doc, this);

        if (wd.editingP) {
            this.editDoc = wd;
        } else {
            this.viewDoc = wd;
        }

        this.wd = wd;
    }

    if (doc) {
        // Note that a WikiPage may have more than one associated WikiDocument,
        // e.g. one from viewing and one from editing
        this.setDoc(doc);
        this.relevantUser = this.wd.relevantUser;
    } else {
        // this is less powerful than WikiDocument.relevantUser if we don't
        // have access to doc.
        this.relevantUser = getRelevantUser0(this, doc);
    }
}

function WikiDocument(doc, wp) {
    this.doc = doc;
    this.wp = wp;

    this.username     = getUsername0(doc);

    // Note: can't use "doc.editform" or "doc.forms.editform", because 'doc'
    // might actually be an XMLDocument (not HTMLDocument), if this is the
    // result of an XMLHTTPRequest.
    this.editForm     = doc.getElementById('editform');
    this.editingP     = Boolean(this.editForm);
    // obsolete method: document.title.match(/^Editing /)
    this.protectedP   = Boolean(doc.getElementById("ca-viewsource"));
    this.newSectionP  = this.editForm && (this.editForm.wpSection.value == "new");
    this.movePageP    = Boolean(doc.getElementById("movepage"));
    this.previewP     = Boolean(doc.getElementById("wikiPreview"));
    this.historyP     = Boolean(doc.getElementById("pagehistory"));
    this.permalinkP   = Boolean(doc.getElementById("t-ispermalink"));
    this.oldid        = getOldid0(doc, this.permalinkP);
    this.relevantUser = getRelevantUser0(wp, doc);
}

function getUsernameFromLink(link) {
    return link && (new WikiPage(link)).relevantUser;
}

function getRelevantUser0(wp, doc) {
    if (wp.nsUserP) return wp.superarticle;
    if (doc && wp.page == 'Special:Contributions') {
        var cdiv = doc.getElementById('contentSub');
        if (cdiv.textContent == "For newbies") return null;
        return getUsernameFromLink(cdiv.getElementsByTagName('a')[0]);
    }
    return null;
}

// Get the oldid ("permalink") for the current page.
// Note that we can't get oldid for editing pages, special pages, etc.
function getOldid0(doc, perm) {
    var tagid = perm ? 'ca-edit' : 't-permalink';
    var tag = doc.getElementById(tagid);
    if (!tag) return null;
    var href = tag.getElementsByTagName("a")[0].href;
    if (!href) return null;
    href.match(/&oldid=([0-9]+)/);
    return RegExp.$1;
}

function getQueryVars0(){
     var res = new Array();
     var pairs = location.search.substring(1).split("&");
     for(var i=0; i < pairs.length; i++){
         var pair = pairs[i].split("=");
         res[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
     }
     return res;
}

function initWikiPage() {
    WikiPage.server = window.location.host || 'en.wikipedia.org';

    window.wikiPage = new WikiPage(getCanonPageURL0(), null, document);
    window.wikiDoc = wikiPage.wd;

    WikiPage.queryVars    = window.queryVars    = getQueryVars0();

    // these are all deprecated
    if (typeof wikiDoc !== 'undefined') {
    WikiPage.username     = window.username     = wikiDoc.username;
    WikiPage.relevantUser = window.relevantUser = wikiDoc.relevantUser;
    WikiPage.editingP     = window.editingP     = wikiDoc.editingP;
    WikiPage.newSectionP  = window.newSectionP  = wikiDoc.newSectionP;
    WikiPage.movePageP    = window.movepageP    = wikiDoc.movePageP;
    WikiPage.previewP     = window.previewP     = wikiDoc.previewP;
    WikiPage.historyP     = window.historyP     = wikiDoc.historyP;
    WikiPage.sandboxP     = window.sandboxP     = wikiDoc.sandboxP;
    WikiPage.permalinkP   = window.permalinkP   = wikiDoc.permalinkP;
    WikiPage.oldid        = window.pageOldid    = wikiDoc.oldid;
    }
}

// DEPRECATED:
function getPname() { return wikiPage.page; }
function getPnameNS() { return wikiPage.namespace; }
function getPnameNoNS() { return wikiPage.article; }
function pageIsSpecial() { return wikiPage.nsSpecialP; }
function get_query_vars() { return queryVars; }

addOnloadHook(initWikiPage);

// obsolete method 1:
// function getPname0() {
//     var z=document.getElementById("content").childNodes;
//     for (var n=0;n<z.length;n++) {
//         if (z[n].className=="firstHeading") return z[n].textContent;
//     }
// }

// function getPname1() {
//     var t = getPname0();
//     t = t.replace(/^Editing /,'');
//     t = t.replace(/ \(section\)$/,'');

//     return t;
// }

// obsolete method 2:
//    document.title.substr(0, document.title.lastIndexOf(' - Wikipedia, the free'));

//</nowiki></pre>