MediaWiki:Gadget-Prosesize.js

This is an old revision of this page, as edited by Galobtter (talk | contribs) at 02:38, 13 August 2019 (format). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
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.
//copy of [[User:Dr_pda/prosesize.js]]
//TODO: modernize (User:Shubinator/DYKcheck.js may have useful code? or use xtools api ) and fix to work on all maintained skins propose to become gadget
//Wikipedia:Village_pump_(technical)/Archive_161#"Page_size"_Tool:_"Word_count"_script_'User:Dr_pda/prosesize.js'_does_not_work_with_skin_=_Timeless
//<nowiki>
//This function adds a link to the toolbox which, when clicked, displays the size of the page
//and the size of the prose. See the talk page for more details.
//
//To use this function add {{subst:js|User:Dr pda/prosesize.js}} to your monobook.js
//
function loadXMLDocPassingTemplate(url, handler, page) {
    // branch for native XMLHttpRequest object
    if (window.XMLHttpRequest) {
        var req = new XMLHttpRequest();
    }
    // branch for IE/Windows ActiveX version
    else if (window.ActiveXObject) {
        var req = new ActiveXObject("Microsoft.XMLHTTP");
    }
    if (req) {
        req.onreadystatechange = function() {
            handler(req, page)
        };
        req.open("GET", url, true);
        req.send("");
    }
}

function getWikiText(req, page) {
    // only if req shows "loaded"
    if (req.readyState == 4) {
        // only if "OK"
        if (req.status == 200) {
            // ...processing statements go here...
            response = req.responseXML.documentElement;
            var rev = response.getElementsByTagName('rev');
            if (rev.length > 0) {
                result = rev[0].getAttribute('size');
                if (result > 10240) {
                    result = (result / 1024).toFixed(0) + '&nbsp;kB';
                } else {
                    result = result + '&nbsp;B';
                }
                wiki_value = document.createElement("li");
                wiki_value.id = "wiki-size";
                wiki_value.innerHTML = '<b>Wiki text: </b>' + result;
                var output = document.getElementById("document-size-stats");
                prose_value = document.getElementById("prose-size");
                output.insertBefore(wiki_value, prose_value);
            } else {
                //alert("There was a problem using the Wikipedia Search to find the wiki text size\nEither the search is not working or the correct article did not appear on the first page of results");
                wiki_value = document.createElement("li");
                wiki_value.id = "wiki-size";
                wiki_value.innerHTML = '<b>Wiki text: </b>Problem getting wiki text size';
                var output = document.getElementById("document-size-stats");
                prose_value = document.getElementById("prose-size");
                output.insertBefore(wiki_value, prose_value);
            }
        } else {
            alert("There was a problem retrieving the XML data:\n" +
                req.statusText);
        }
    }
}

function getFileSize(req, page) {
    // only if req shows "loaded"
    if (req.readyState == 4) {
        // only if "OK"
        if (req.status == 200) {
            // ...processing statements go here...
            var fsize = req.responseText.length;
            window.status = fsize;
            var total_value = document.createElement("li");
            total_value.id = "total-size";
            total_value.innerHTML = '<b>File size: </b>' + (fsize / 1024).toFixed(0) + '&nbsp;kB';
            var output = document.getElementById("document-size-stats");
            var prose_html_value = document.getElementById("prose-size-html");
            output.insertBefore(total_value, prose_html_value);
        } else {
            alert("There was a problem retrieving the XML data:\n" +
                req.statusText + "\n(" + url + ")");
        }
    }
}

function getLength(id) {
    var textLength = 0;
    for (var i = 0; i < id.childNodes.length; i++) {
        if (id.childNodes[i].nodeType === Node.TEXT_NODE) {
            textLength += id.childNodes[i].nodeValue.length;
        } else if (id.childNodes[i].nodeType === Node.ELEMENT_NODE &&
            (id.childNodes[i].id == 'coordinates' || id.childNodes[i].className.indexOf('emplate') != -1)) {
            //special case for {{coord}} and {{fact}}-like templates
            //Exclude from length, and don't set background yellow
            id.childNodes[i].style.cssText = 'background-color:white';
        } else {
            textLength += getLength(id.childNodes[i]);
        }
    }
    return textLength;
}

function getRefMarkLength(id, html) {
    var textLength = 0;
    for (var i = 0; i < id.childNodes.length; i++) {
        if (id.childNodes[i].nodeType === Node.ELEMENT_NODE && id.childNodes[i].className == 'reference') {
            textLength += (html) ? id.childNodes[i].innerHTML.length : getLength(id.childNodes[i]);
        }
    }
    return textLength;
}

function getDocumentSize() {
    var bodyContent;
    if ($.inArray(mw.config.get('skin'), ['vector', 'monobook']) !== -1) {
        bodyContent = $('#mw-content-text .mw-parser-output');
    }
    //Same for all skins if previewing page
    if (mw.config.get('wgAction') == 'submit') {
        bodyContent = $('#wikiPreview .mw-parser-output');
    }

    if (bodyContent.length === 0) {
        return;
    }
    bodyContent = bodyContent[0];

    if (document.getElementById("document-size-stats")) {
        //if statistics already exist, turn them off and remove highlighting
        var output = document.getElementById("document-size-stats");
        var oldStyle = output.className;
        var pList = bodyContent.getElementsByTagName("p");
        for (var i = 0; i < pList.length; i++) {
            if (pList[i].parentNode == bodyContent) {
                pList[i].style.cssText = oldStyle;
            }
        }
        output.parentNode.removeChild(output);
        var header = document.getElementById("document-size-header");
        header.parentNode.removeChild(header);
    } else {
        var output = document.createElement("ul");
        output.id = "document-size-stats";

        var prose_html_value = document.createElement("li");
        prose_html_value.id = "prose-size-html";
        output.appendChild(prose_html_value);

        var ref_html_value = document.createElement("li");
        ref_html_value.id = "ref-size-html";
        output.appendChild(ref_html_value);

        var prose_value = document.createElement("li");
        prose_value.id = "prose-size";
        output.appendChild(prose_value);
        output.className = bodyContent.getElementsByTagName("p").item(0).style.cssText;

        var ref_value = document.createElement("li");
        ref_value.id = "ref-size";
        output.appendChild(ref_value);

        bodyContent.insertBefore(output, bodyContent.firstChild);

        var header = document.createElement("span");
        header.id = "document-size-header";
        header.innerHTML = '<br/>Document statistics: <small><i>(See <a href="//en.wikipedia.org/wiki/User_talk:Dr_pda/prosesize.js">here</a> for details.)<i></small>';
        bodyContent.insertBefore(header, output);

        //File size not well defined for preview mode or section edit
        if (mw.config.get('wgAction') != 'submit') {
            loadXMLDocPassingTemplate(___location.pathname, getFileSize, '');
        }

        //Get size of images only if browser supports filesize property (IE)
        var iList = bodyContent.getElementsByTagName("img");
        if (iList.length > 0 && iList[0].fileSize) {
            //Get size of images included in document
            var image_size = 0;
            var first_magnify = true;

            for (var i = 0; i < iList.length; i++) {
                var im = iList[i];
                if (im.getAttribute("src").indexOf("magnify-clip.png") != -1) {
                    if (first_magnify) {
                        image_size += im.fileSize * 1;
                        first_magnify = false;
                    }
                } else {
                    image_size += im.fileSize * 1;
                }
            }
            var image_value = document.createElement("li");
            image_value.id = "image-size";
            image_value.innerHTML = '<b>Images: </b>' + (image_size / 1024).toFixed(0) + '&nbsp;kB';
            output.appendChild(image_value);

        }
        //Calculate prose size and size of reference markers ([1] etc)
        var pList = bodyContent.getElementsByTagName("p");

        prose_size = 0;
        prose_size_html = 0;
        refmark_size = 0;
        refmark_size_html = 0;
        word_count = 0;
        for (var i = 0; i < pList.length; i++) {
            var para = pList[i];
            if (para.parentNode == bodyContent) {
                prose_size += getLength(para);
                prose_size_html += para.innerHTML.length;
                refmark_size += getRefMarkLength(para, false);
                refmark_size_html += getRefMarkLength(para, true);
                word_count += para.innerHTML.replace(/(<([^>]+)>)/ig, "").split(' ').length;
                para.style.cssText = "background-color:yellow";
            }
        }

        if ((prose_size - refmark_size) > 10240) {
            prose_value.innerHTML = '<b>Prose size (text only): </b>' + ((prose_size - refmark_size) / 1024).toFixed(0) + '&nbsp;kB (' + word_count + ' words) "readable prose size"';
        } else {
            prose_value.innerHTML = '<b>Prose size (text only): </b>' + (prose_size - refmark_size) + '&nbsp;B (' + word_count + ' words) "readable prose size"';
        }

        if ((prose_size_html - refmark_size_html) > 10240) {
            prose_html_value.innerHTML = '<b>Prose size (including all HTML code): </b>' + ((prose_size_html - refmark_size_html) / 1024).toFixed(0) + '&nbsp;kB';
        } else {
            prose_html_value.innerHTML = '<b>Prose size (including all HTML code): </b>' + (prose_size_html - refmark_size_html) + '&nbsp;B';
        }

        //Calculate size of references (i.e. output of <references/>)
        var rList = bodyContent.getElementsByTagName("ol");
        var ref_size = 0;
        var ref_size_html = 0;
        for (var i = 0; i < rList.length; i++) {
            if (rList[i].parentNode.className == "references") {
                ref_size = getLength(rList[i]);
                ref_size_html = rList[i].innerHTML.length;
            }
        }

        if ((ref_size + refmark_size) > 10240) {
            ref_value.innerHTML = '<b>References (text only): </b>' + ((ref_size + refmark_size) / 1024).toFixed(0) + '&nbsp;kB';
        } else {
            ref_value.innerHTML = '<b>References (text only): </b>' + (ref_size + refmark_size) + '&nbsp;B';
        }

        if ((ref_size_html + refmark_size_html) > 10240) {
            ref_html_value.innerHTML = '<b>References (including all HTML code): </b>' + ((ref_size_html + refmark_size_html) / 1024).toFixed(0) + '&nbsp;kB';
        } else {
            ref_html_value.innerHTML = '<b>References (including all HTML code): </b>' + (ref_size_html + refmark_size_html) + '&nbsp;B';
        }

        //get correct name of article from wikipedia-defined global variables
        var pageNameUnderscores = mw.config.get('wgPageName');
        var pageNameSpaces = pageNameUnderscores.replace(/_/g, ' ');

        //if page is a permalink, diff, etc don't try to search
        if (!___location.pathname.match('/w/index.php')) {
            //Get revision size from API
            var searchURL = mw.config.get('wgScriptPath') + '/api.php?action=query&prop=revisions&rvprop=size&format=xml&revids=' + mw.config.get('wgCurRevisionId');
            loadXMLDocPassingTemplate(searchURL, getWikiText, pageNameSpaces);
        } else if (mw.config.get('wgAction') == 'submit') {
            //Get size of text in edit box
            result = document.getElementById('wpTextbox1').value.length;
            if (result > 10240) {
                result = (result / 1024).toFixed(0) + '&nbsp;kB';
            } else {
                result = result + '&nbsp;B';
            }
            wiki_value = document.createElement("li");
            wiki_value.id = "wiki-size";
            wiki_value.innerHTML = '<b>Wiki text: </b>' + result;
            var output = document.getElementById("document-size-stats");
            prose_value = document.getElementById("prose-size");
            output.insertBefore(wiki_value, prose_value);
        }
    }
}

jQuery(function() {
    if ($.inArray(mw.config.get('skin'), ['vector', 'monobook']) === -1) {
        return;
    }
    mw.loader.using(['mediawiki.util'], function() {
        if (mw.config.get('wgAction') == 'edit' || (mw.config.get('wgAction') == 'submit' && document.getElementById('wikiDiff'))) {
            $(mw.util.addPortletLink('p-tb', '#', 'Page size', 't-page-size', 'Calculate page and prose size'))
                .click(function(e) {
                    e.preventDefault();
                    alert("You need to preview the text for the prose size script to work in edit mode.");
                });
            document.getElementById("t-page-size").firstChild.style.cssText = "color:black;";
        } else if ($.inArray(mw.config.get('wgAction'), ['view', 'submit', 'historysubmit', 'purge']) !== -1) {
            $(mw.util.addPortletLink('p-tb', '#', 'Page size', 't-page-size', 'Calculate page and prose size'))
                .click(function(e) {
                    e.preventDefault();
                    getDocumentSize();
                });
        }
    });
});

//</nowiki>