ผู้ใช้:Nullzero/DYKcheck.js

จากวิกิพีเดีย สารานุกรมเสรี

หมายเหตุ: หลังเผยแพร่ คุณอาจต้องล้างแคชเว็บเบราว์เซอร์ของคุณเพื่อดูการเปลี่ยนแปลง

  • ไฟร์ฟอกซ์ / ซาฟารี: กด Shift ค้างขณะคลิก Reload หรือกด Ctrl-F5 หรือ Ctrl-R (⌘-R บนแมค)
  • กูเกิล โครม: กด Ctrl-Shift-R (⌘-Shift-R บนแมค)
  • อินเทอร์เน็ตเอกซ์พลอเรอร์ และ Edge: กด Ctrl ค้างขณะคลิก Refresh หรือกด Ctrl-F5
  • โอเปร่า: กด Ctrl-F5
    // ***************************************************************** //
    //                          DYKcheck tool                            //
    //                           Version 1.1                             //
    // For quick installation, add                                       //
    // importScript('User:Nullzero/DYKcheck.js');                        //
    // to your vector.js                                                 //
    // See [[User:Shubinator/DYKcheck]] for more info, including         //
    // configurable options and how tดo use the tool without installation //
    // or logging in.                                                    //
    // First version written by Shubinator in February 2009              //
    // ***************************************************************** //

var wgAction = mw.config.get('wgAction');
var wgNamespaceNumber = mw.config.get('wgNamespaceNumber');
var  wgScriptPath = mw.config.get('wgScriptPath');
var onTTDYK, nextSection, urlJump, sections, currentTitle;
var partsProcessing, articleTitles, dates, nom5x;
var dateFormat, hookLengthYellow, hookLengthRed, check5xNoms, unlock, fixedSidebar; //configurable options
var MINSIZE = 2000;
var MINEXPAND = 3.0;
var MINDAY = 14;
var MINEXPANDSTR = "2";
if (!hookLengthYellow) hookLengthYellow = 1;
if (!hookLengthRed) hookLengthRed = 0;
if (!check5xNoms) check5xNoms = "ifnom5x";
if (!fixedSidebar) fixedSidebar = "never";

function scanArticle(title, output, html) {
    // the meat of the DYKcheck tool
    // calculates prose size of the given html
    // checks for inline citations and stub templates in the given html
    // passes info to checkTalk(), getFirstRevision(), checkMove(), and checkExpansion()
    
    if (!onTTDYK || (check5xNoms == "always") || (check5xNoms == "ifnom5x" && nom5x)) {
        partsProcessing = new Array(4);
    } else {
        partsProcessing = new Array(3);
    }
    dates = new Array(3);

    var proseDisp = document.createElement("li");
    proseDisp.id = "dyk-prose";
    output.appendChild(proseDisp);

    // calculate prose size
    var prose = calculateProse(html, true);
    var pList = html.getElementsByTagName("p");
    proseDisp.innerHTML='<b>จำนวนอักขระของความเรียง: </b>' + prose + '&nbsp;อักขระ';
    if (prose < MINSIZE) proseDisp.style.cssText = "background-color:pink";
    // check for inline citations
    if (html.innerHTML.indexOf('id="cite_ref-') == -1 && html.innerHTML.indexOf('id=cite_ref-') == -1) {
        var noref = document.createElement("li");
        noref.id = "no-ref";
        output.appendChild(noref);
        noref.innerHTML = 'ไม่มีอ้างอิงในบรรทัด';
        noref.style.cssText = "background-color:pink";
    }
        
    // find creator of article and date
    getFirstRevision(title, output);
    partsProcessing[2] = true;
    // check for expansion start date, assuming now expanded to 5x (last 500 edits)
    if (!onTTDYK || (check5xNoms == "always") || (check5xNoms == "ifnom5x" && nom5x)) {
        checkExpansion(title, output, prose);
    }
}

function checkDocument() {
    // prepares for scan and passes info to scanArticle()
    onTTDYK = false;
    if (document.getElementById("dyk-stats-0")) {
        clearStats();
    } else {
        var output = document.createElement("ul");
        output.id = "dyk-stats-0";
        
        var body = getBody();
        var dummy = body.getElementsByTagName("div")[0];
        if (dummy.nextSibling && dummy.nextSibling.id == 'siteNotice') { // if siteNotice is below siteSub
            dummy = dummy.nextSibling;
        } else if (dummy.nextSibling.nextSibling && dummy.nextSibling.nextSibling.id == 'siteNotice') {
            dummy = dummy.nextSibling.nextSibling;
        }
        dummy.parentNode.insertBefore(output, dummy.nextSibling);
        createHeaderAndProcessing(output);
        currentTitle = 0;
        var normalizedTitle = wgTitle.replace(/\%/g,"%25").replace(/\+/g, "%2B").replace(/\//g,"%2F");
        normalizedTitle = normalizedTitle.replace(/\?/g,"%3F").replace(/\#/g,"%23").replace(/\&/g,"%26");
        if (wgNamespaceNumber == 2) {
            normalizedTitle = "User:" + normalizedTitle;
        }
        scanArticle(normalizedTitle, output, body);
    }
}

function redirectPitStop(title, output, i) {
    // checks if the nominated article is a redirect, passes info to checkTitle()
    var api = sajax_init_object();
    api.open('GET', wgScriptPath + '/api.php?action=query&titles=' + title + '&redirects&format=xml', true);
    api.onreadystatechange = function() {
        if (api.readyState  == 4) {
            if (api.status  == 200) {
                var response = api.responseXML.documentElement;
                var rs = response.getElementsByTagName("r");
                if (rs[0]) {
                    title = rs[0].getAttribute("to");
                }
                checkTitle(title, output, i);
            } else {
                alert("XML error");
            }
        }
    };
    api.send(null);
}

function checkTitle(title, output, i) {
    // gets the given title from Wikipedia's server and passes it to scanArticle()
    var normalizedTitle = title.replace(/\%/g,"%25").replace(/\+/g, "%2B").replace(/\//g,"%2F");
    normalizedTitle = normalizedTitle.replace(/\?/g,"%3F").replace(/\#/g,"%23").replace(/\&/g,"%26");
    var api = sajax_init_object();
    api.open('GET', wgScriptPath + '/index.php?title=' + normalizedTitle + '&action=render', true);
    api.onreadystatechange = function() {
        if (api.readyState  == 4) {
            if (api.status  == 200) {
                var ttdykTemp = document.createElement("div");
                ttdykTemp.id = "ttdyk-temp" + i;
                ttdykTemp.innerHTML = api.responseText;
                scanArticle(normalizedTitle, output, ttdykTemp);
            } else {
                alert("XML error");
            }
        }
    };
    api.send(null);
}

function clearStats() {
    // if scan results already exist, turn them off and remove highlighting
    if (!onTTDYK) {
        var oldStyle = document.getElementById("dyk-stats-0").className;
        var mainContent = getBody();
        var pList = mainContent.getElementsByTagName("p");
        for (var i=0; i < pList.length; i++) {
            if (pList[i].parentNode == mainContent || pList[i].parentNode.parentNode == mainContent) {
                pList[i].style.cssText = oldStyle;
            }
        }
    }
    if (document.getElementById("error-disp")) {
        var errorDisp = document.getElementById("error-disp");
        errorDisp.parentNode.removeChild(errorDisp);
    }
    var i=0;
    while (document.getElementById("dyk-stats-" + i)) {
        var output = document.getElementById("dyk-stats-" + i);
        output.parentNode.removeChild(output);
        i++;
    }
    if (document.getElementById("hook-container")) {
        var hookOutput = document.getElementById("hook-container");
        hookOutput.parentNode.removeChild(hookOutput);
    }
    if (document.getElementById("dyk-header")) {
        var header = document.getElementById("dyk-header");
        header.parentNode.removeChild(header);
    }
    if (document.getElementById("dyk-processing")) {
        var processing = document.getElementById("dyk-processing");
        processing.parentNode.removeChild(processing);
    }
}

function calculateProse(doc, visible) {
    // calculates the prose of a given document
    // this function and its helper below are modified versions of
    // the prosesize tool (http://en.wikipedia.org/wiki/User:Dr_pda/prosesize.js)
    var pList = doc.getElementsByTagName("p");
    var prose_size = 0;
    
    var i = 0;
    if (wgAction == 'submit' && visible) i = 1; // Avoid the "Remember that this is only a preview" text
    for (; i < pList.length; i++) {
        if (pList[i].parentNode == doc || pList[i].parentNode.parentNode.id == getBodyId()) {
            prose_size += getReadable(pList[i], visible);
            if (!onTTDYK && visible) {
                pList[i].style.cssText = 'background-color:yellow';
            }
        }
    }
    return prose_size;
}

function getReadable(id, visible) {
    // helper method for calculateProse()
    var textReadable = 0;
    for (var i=0; i < id.childNodes.length; i++) {
        if (id.childNodes[i].nodeName == '#text') {
            textReadable += id.childNodes[i].nodeValue.length;
        } else if (id.childNodes[i].className != 'reference' && id.childNodes[i].className.indexOf('emplate') == -1 &&
                id.childNodes[i].id != 'coordinates') {
            textReadable += getReadable(id.childNodes[i], visible);
        } else if (visible) { // if it's an inline maintenance tag (like [citation needed]) or geocoordinates
            if (document.getElementById("dyk-stats-0").className != "") {
                id.childNodes[i].style.cssText = document.getElementById("dyk-stats-0").className;
            } else {
                id.childNodes[i].style.cssText = 'background-color:white';
            }    
        }
    }
    return textReadable;
}

function checkExpansion(title, output, current) {  
    // finds the start of expansion date (last 500 edits)
    // gets the last 500 unique revision ids for past revisions of the article and passes to helper function
    var api = sajax_init_object();
    api.open('GET', wgScriptPath + '/api.php?action=query&prop=revisions&titles=' +
            title + '&&rvlimit=500&rvprop=ids|timestamp&rvdir=older&format=xml', true);
    api.onreadystatechange = function() {
        if (api.readyState  == 4) {
            if (api.status  == 200) {
                var expandTemp = document.createElement("div");
                expandTemp.id = "expand-temp";
                var response = api.responseXML.documentElement;
                var revIds = response.getElementsByTagName('rev');
                checkExpansionHelper(title, current, output, expandTemp, revIds, 0, revIds.length-1, -1);
            } else {
                alert("XML error");
            }
        }
    };
    api.send(null);
}


function checkExpansionHelper(title, current, output, expandTemp, revIds, min, max, expandIndex) {
    // helper for expansion check, used recursively
    // searches for start of expansion date using a binary search algorithm
    // assumes the article has been more or less increasing in size all the time
    // if the article length has yoyo-ed, this function won't give accurate results
    var mid = Math.ceil((max + min)/2);
    if ((((max - min) < 2) && (max != revIds.length - 1 || expandIndex != -1)) || expandIndex == -2) {
        if (expandIndex >= 0) dates[2] = toDateObject(revIds[expandIndex-1].getAttribute('timestamp'));
        partsProcessing[3] = true;
        doneProcessing();
        return;
    } else if ((max - min) < 2 && max == revIds.length - 1) {
        expandIndex = -2;
    }
    var api = sajax_init_object();
    api.open('GET', wgScriptPath + '/index.php?title=' + title +
            '&action=render&redirect=no&oldid=' + revIds[mid].getAttribute('revid'), true);
    api.onreadystatechange = function() {
        if (api.readyState  == 4) {
            if (api.status  == 200) {
                expandTemp.innerHTML = api.responseText;
                var prose = calculateProse(expandTemp, false);
                // alert("Prose: " + prose + " 1x: " + current/5 + " Mid: " + mid + " Expand index: " + expandIndex);
                // use above line to debug the expansion check
                if (prose < (current/MINEXPAND)) {
                    if ((expandIndex > mid) || (expandIndex < 0)) {
                        expandIndex = mid;
                    }
                    checkExpansionHelper(title, current, output, expandTemp, revIds, min, mid, expandIndex);
                } else {
                    checkExpansionHelper(title, current, output, expandTemp, revIds, mid, max, expandIndex);
                }
            } else {
                alert("XML error");
                partsProcessing[3] = true;
                doneProcessing();
            }
        }
    };
    api.send(null);
}

function getFirstRevision(title, output) {
    // finds the creator of the article, and the date created
    // also checks if the article was created as a redirect, finds non-redirect date if so
    var created = document.createElement("li");
    created.id = "creation-info";
    output.appendChild(created);
        
    var api = sajax_init_object();
    api.open('GET', wgScriptPath + '/api.php?action=query&prop=revisions&format=xml&titles=' +
            title + '&rvlimit=4&rvprop=timestamp|user|content&rvdir=newer&redirect=no', true);
    api.onreadystatechange = function() {
        if (api.readyState  == 4) {
            if (api.status  == 200) {
                var response = api.responseXML.documentElement;
                var revisions = response.getElementsByTagName('rev');
                var user = revisions[0].getAttribute('user');
                var timestamp = revisions[0].getAttribute('timestamp');
                created.innerHTML='<b>สร้างบทความ </b> โดย ' + user +
                        ' ในวันที่ ' + toNormalDate(timestamp.substring(0,10));
                dates[0] = toDateObject(timestamp);
                for (var i=0; i < revisions.length; i++) {
                    if (revisions[i].firstChild) {
                        var content = revisions[i].firstChild.nodeValue.replace(' ', '').replace(':', '').toUpperCase();
                        if (content.indexOf('#REDIRECT[[') != -1 && i == 0) {
                            created.innerHTML = created.innerHTML + ' as a redirect';
                        } else if (content.indexOf('#REDIRECT[[') == -1) {
                            if (i != 0) {
                                var unRedirect = document.createElement("li");
                                unRedirect.id = "expanded-from-redirect";
                                output.appendChild(unRedirect);
                                var urUser = revisions[i].getAttribute('user');
                                var urTimestamp = revisions[i].getAttribute('timestamp');
                                unRedirect.innerHTML = 'Article became a non-redirect on ' +
                                        toNormalDate(urTimestamp.substring(0,10)) + ' by ' + urUser;
                                dates[0] = toDateObject(urTimestamp);
                            }
                            break;
                        }
                    }
                }
                partsProcessing[1] = true;
                doneProcessing();
            } else {
                alert("XML error");
                partsProcessing[1] = true;
                doneProcessing();
            }
        }
    };
    api.send(null);
}

function doneProcessing() {
    // checks if all parts are done processing
    // if they are, the dates of creation and expansion are checked for within 10 days (rounded down, in nominator's favor)
    // then the next title (for multiple article noms) is processed (required to combat asynchronous threads)
    // if there are no more titles left (or not on T:TDYK), the processing message is removed
    var titleComplete = true;
    for (i=1; i < partsProcessing.length; i++) {
        if (partsProcessing[i] != true) {
            titleComplete = false;
            break;
        }
    }
    if (document.getElementById("dyk-processing") && titleComplete) {
        var curDate = new Date();
        var round1Winner = new Date();
        var winner = new Date();
        if (dates[1]) {
            round1Winner = dates[1];
        } else {
            round1Winner = dates[0];
        }
        if (dates[2] > round1Winner) {
            winner = dates[2];
        } else {
            winner = round1Winner;
        }
        var dateDifference = Math.floor((curDate.getTime() - winner.getTime())/(1000*60*60*24));
        if (dateDifference > (MINDAY * 1)) {
            var output = document.getElementById("dyk-stats-" + currentTitle);
            var notRecent = document.createElement("li");
            notRecent.id = "not-recent";
            output.appendChild(notRecent);
            notRecent.innerHTML = "เนื้อหาบทความไม่ได้เพิ่มขึ้น " + MINEXPANDSTR + " เท่าภายใน " + MINDAY + " วันที่แล้ว (" +
                        dateDifference + " วัน)";
            notRecent.style.cssText = 'background-color:pink';
        }
        var processing = document.getElementById("dyk-processing");
        processing.parentNode.removeChild(processing);
    }
}

// taken from the prosesize tool (http://en.wikipedia.org/wiki/User:Dr_pda/prosesize.js)
function getBodyId() {
    var contentName;
    if (skin == 'monobook' || skin == 'chick' || skin == 'myskin' || skin == 'simple') {
        contentName = 'bodyContent';
    } else if (skin == 'modern') {
        contentName = 'mw_contentholder';
    } else if (skin == 'standard' || skin == 'cologneblue' || skin == 'nostalgia') {
        contentName = 'article';
    } else {
        // fallback case; the above covers all currently existing skins
        contentName = 'bodyContent';
    }
    // Same for all skins if previewing page
    if (wgAction == 'submit') contentName = 'wikiPreview';
    return contentName;
}

function getBody() {
    // gets the HTML body of the page
    // taken from the prosesize tool (http://en.wikipedia.org/wiki/User:Dr_pda/prosesize.js)
    return document.getElementById(getBodyId());
}

function getFirstNom() {
    var firstNom = 0;
    
    // Find the first "Articles created/expanded on ..." h3 section
    var elementIterator = sections[firstNom].previousSibling;
    while (!(elementIterator.nodeName.toLowerCase() == "h3")) {
        elementIterator = elementIterator.previousSibling;
    }
    while (!(elementIterator.nodeName.toLowerCase() == "h3" &&
            elementIterator.innerHTML.indexOf("Articles created/expanded on") != -1)) {
        if (elementIterator.nodeName.toLowerCase() == "h4") {
            firstNom++;
        }
        elementIterator = elementIterator.nextSibling;
    }
    return firstNom;
}

function createHeaderAndProcessing(output) {
    // makes the header above the scan results
    var header = document.createElement("span");
    header.id = "dyk-header";
    header.innerHTML = '<br /><b>เครื่องมือตรวจสอบบทความรู้ไหมว่าในวิกิพีเดียภาษาไทย พัฒนามาจาก <a href="//en.wikipedia.org/wiki/' +
            'User:Shubinator/DYKcheck">เครื่องมือในวิกิพีเดียภาษาอังกฤษ</a></b>';
    output.parentNode.insertBefore(header,output);
    var processing = document.createElement("span");
    processing.id = "dyk-processing";
    processing.innerHTML = '<br /><b><font color="crimson"> กำลังประมวลผล... </font></b>';
    output.parentNode.insertBefore(processing, header);
}

function toNormalDate(utc) {
    // converts the date part of a Wikipedia timestamp to a readable date
    var months=new Array("blank","มกราคม","กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน",
            "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลงคม", "พฤศจิกายน", "ธันวาคม");
    return (utc.substring(8,10) * 1) + ' ' + months[utc.substring(5,7) * 1] + ' พ.ศ. ' + ((utc.substring(0,4) * 1) + 543);
}

function toDateObject(timestamp) {
    // converts a Wikipedia timestamp to a Javascript Date object
    var date = new Date();
    date.setUTCFullYear(timestamp.substring(0,4), timestamp.substring(5,7) - 1, timestamp.substring(8,10));
    date.setUTCHours(timestamp.substring(11,13), timestamp.substring(14,16), timestamp.substring(17,19));
    return date;
}

$(function () {
    if (((wgAction == 'view' || wgAction == 'submit' || wgAction == 'purge') &&
            (wgNamespaceNumber == 0 || wgNamespaceNumber == 2)) || unlock) {
        mw.util.addPortletLink('p-tb', 'javascript:checkDocument()', 'ตรวจสอบบทความรู้ไหมว่า',
                't-dyk-check', 'ตรวจว่าบทความนี้ผ่านเกณฑ์เบื้องต้นของบทความรู้ไหมว่าหรือไม่', '', '');
    }
});