User:Dudemanfellabra/NRHPstats.js

In this article we will analyze the relevance of User:Dudemanfellabra/NRHPstats.js in the current context, exploring its implications in various areas. User:Dudemanfellabra/NRHPstats.js has been an object of interest and study for a long time, and its influence continues to be a cause for debate and reflection. Throughout history, User:Dudemanfellabra/NRHPstats.js has played a fundamental role in different areas, from politics to culture, technology and society in general. In this sense, it is crucial to understand the importance of User:Dudemanfellabra/NRHPstats.js in today's world, as well as its potential to shape the future. Through an in-depth and multidisciplinary analysis, this article aims to shed light on the relevance of User:Dudemanfellabra/NRHPstats.js today, offering a critical and reflective look at its impact and possible long-term implications.
function Shell() {
    if ((mw.config.get('wgPageName').search("National_Register_of_Historic_Places_listings") != -1||mw.config.get('wgPageName').search("National_Historic_Landmarks_in") != -1) && mw.config.get('wgNamespaceNumber')==0 && location.href.indexOf('action')==-1 && mw.config.get('wgArticleId')!=0) {
    // if on NRHP list
        if (typeof(NRHPstatsAuto)!='undefined') {
            if (NRHPstatsAuto=='false') {
                mw.util.addPortletLink('p-tb','javascript:LoadNRHPstats()','NRHP Progress stats','t-NRHP','NRHP Progress stats','','');
            } else {
                LoadNRHPstats();
            }
        } else {
            LoadNRHPstats();
        }
    } else if (mw.config.get('wgPageName') == "Wikipedia:WikiProject_National_Register_of_Historic_Places/Progress") {
    // if on Progress page
        if (typeof(NRHPstatsAuto)!='undefined') {
            if (NRHPstatsAuto=='false') {
                mw.util.addPortletLink('p-tb','javascript:NRHPTotals()','Check stats','t-NRHP','Check stats','','');
            } else {
                NRHPTotals();
            }
        } else {
            NRHPTotals();
        }
    } else {
    // if on some other article
        return;
    }
}

function ToggleDisp() {
    var Disps = document.getElementsByClassName('NRHPdisp')
    if (Disps.style.display == '') {
        for (var i=0; i<Disps.length; i++) {
            Disps.style.display='none'
        }
    } else {
        for (var i=0; i<Disps.length; i++) {
            Disps.style.display=''
        }
    }
}


/*
   The following function only works on NRHP list articles; it calculates how many listings in the page's table(s)
   have articles, how many have images, and a host of other statistics useful for gauging "completeness" of a list.
   For more information, including a compilation of these statistics nationwide, see WP:NRHPPROGRESS.
*/


// global variables
var NRHPstats_HTMLTables=;
var NRHPstats_HTMLRows = ;
var NRHPstats_Rows = ;
var TableStructure = ;
var TotalToQuery = 0;
var TotalQueried = 0;

function LoadNRHPstats() {
    var portlet=document.getElementById('t-NRHP')
    if (portlet!=null) {
        portlet.getElementsByTagName('a').href="javascript:ToggleDisp()"
        portlet.getElementsByTagName('a').innerHTML="Show/hide NRHP stats"
    }

    var wikitext=getNRHPstatsWikitext(mw.config.get('wgPageName'))
    if (wikitext=="error") {
        alert("Could not retrieve wikitext! NRHPstats script aborted!")
        return;
    }

    var table=document.getElementsByClassName('wikitable sortable');
    if (table == null) return;
    for (var i=0; i<table.length; i++) {   // get rid of non-NRHP tables
        var tr=table.getElementsByTagName("tr")
        if (tr.getElementsByTagName("th").length >= 5) {
            var disp = document.createElement( 'div' )
            disp.setAttribute('style', 'font-size:125%; background-color:yellow; width:400px; padding:5px; text-align:center')
            disp.setAttribute('class', 'NRHPdisp')
            disp.innerHTML="<br><br><br>Loading statistics...<br><br><br><br>"
            table.parentNode.insertBefore(disp , table)

            NRHPstats_HTMLTables.push(table)
            NRHPstats_HTMLRows=
            TableStructure=
            for (var j=1; j<tr.length; j++) {
                NRHPstats_HTMLRows.push(tr)
                TableStructure=
                // 0=title, 1=illustrated, 2=articled, 3=stub, 4=NRIS-only, 5=Start+, 6=unassessed, 7=untagged
            }
        }
    }

    // get rows from wikitext
    var TableStartIndex=0
    while (true) {
        TableStartIndex=wikitext.search(/{{*NRHP (former )?header/)  // find next table
        if (TableStartIndex==-1) {
            break;
        }
        NRHPstats_Rows=
        wikitext=wikitext.substr(TableStartIndex+1,wikitext.length-TableStartIndex)  // get rid everything before current table

        var tabletext=wikitext.substr(0,wikitext.indexOf("\n|}"))

        var str = "{{"
        var start=0
        var commentstart=0
        while (true) {
            commentstart=tabletext.indexOf("<!--",start)
            start=tabletext.indexOf(str,start)
            if (start==-1) break
            while (commentstart<start&&commentstart!=-1) {
                start=tabletext.indexOf("-->",commentstart)
                commentstart=tabletext.indexOf("<!--",start)
                start=tabletext.indexOf(str,start)
            }
            if (start==-1) break
            var open=1
            var index=start+str.length
            while (open!=0 && index<tabletext.length) {
                if (tabletext.substr(index,2)=="}}") {
                    open--
                    index++
                } else if (tabletext.substr(index,2)=="{{") {
                    open++
                    index++
                }
                index++
            }
            var template=tabletext.substr(start,index-start)
            var regex = new RegExp("{{*NRHP row(\\s)*\\|", "g")
            if (template.match(regex)!=null) NRHPstats_Rows.push(template)
            start++
        }
        for (var i=0; i<NRHPstats_Rows.length; i++) { // get rid of false positives inside nowiki or pre tags
            var regex=new RegExp("<*?(nowiki|pre)*?>((?!<*?/*?(nowiki|pre)*?>)(.|\\n))*?"+NRHPstats_Rows.replace(/\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")+"(.|\\n)*?<*?/*?(nowiki|pre)*?>", "g")
            if (tabletext.match(regex)!=null) {NRHPstats_Rows.splice(i,1); i--}
        }
    }
    for (var i=0; i<NRHPstats_Rows.length; i++) {
        TotalToQuery+=NRHPstats_Rows.length
    }
    TotalQueried=0;
    NRHPstats_NextRow(0,0);
}

function NRHPstats_NextRow(NRHPstats_currentTable,NRHPstats_currentRow) {
    // check if we need to go to the next table
    if (NRHPstats_currentRow>NRHPstats_Rows.length-1) {
        NRHPstats_currentRow=0
        NRHPstats_currentTable++
    }
    // check if there are no more tables
    if (NRHPstats_currentTable>NRHPstats_Rows.length-1) return;

    var ThisRow=NRHPstats_Rows
    var test=ThisRow.match(/\|*?image*?=.*?(\n|\||}})/g)
    if (test!=null) {
        test=test.replace(/\|*?image*?=/g,"").replace(/(\n|\||}})/g,"").replace(/\<\!\-\-(.|)*?\-\-\>/g,"").trim()
        if (test!="") {
            TableStructure=true;  // only true if image param there and non-blank
            NRHPstats_HTMLRows.className+=" NRHPstats-illustrated"
        }
    }
    var article=ThisRow.match(/\|*?article*?=*?.*?/g)
    var blank=ThisRow.match(/\|*?article*?=*?/g)                               // default to name param if article
    if (article==null||blank!=null) article=ThisRow.match(/\|*?name*?=*?.*?/g) // blank or missing

    // strip param name, comments, final line break
    article=article.replace(/\|*?(article|name)*?=*?/g,"").replace(//g,"").replace(/\<\!\-\-(.|)*?\-\-\>/g,"").trim()
    article=decodeURIComponent(article.split("#").trim())     // corrections for weird titles
    TableStructure=article

    $.ajax({
        dataType: "json",
        url: mw.util.wikiScript('api'),
        data: {
            format: 'json',
            action: 'query',
            prop: 'categories',
            clcategories: 'Category:All disambiguation pages|Category:All articles sourced only to NRIS',
            cllimit: 'max',
            titles: article,
            redirects: 'true'
        },
        success: function(ArticlejsonObject) {ArticleChecked(ArticlejsonObject,NRHPstats_currentTable,NRHPstats_currentRow)}
    });
    NRHPstats_NextRow(NRHPstats_currentTable,NRHPstats_currentRow+1);
    return;
}

function ArticleChecked(ArticlejsonObject,NRHPstats_currentTable,NRHPstats_currentRow) {
    if (ArticlejsonObject.query.normalized) { // normalize any weird titles
        for (var n in ArticlejsonObject.query.normalized) {
            TableStructure=ArticlejsonObject.query.normalized.to
        }
    }
    if (ArticlejsonObject.query.redirects) { // resolve any redirects
        for (var r in ArticlejsonObject.query.redirects) {
            TableStructure=ArticlejsonObject.query.redirects.to
        }
    }

    TableStructure=true // default to articled
    NRHPstats_HTMLRows.className+=" NRHPstats-articled"
    for (var page in ArticlejsonObject.query.pages) {
        if (typeof ArticlejsonObject.query.pages.missing!="undefined") {
            // redlink=unarticled
            TableStructure=false
            NRHPstats_HTMLRows.className=NRHPstats_HTMLRows.className.replace(" NRHPstats-articled","")
        }
        if (ArticlejsonObject.query.pages.categories) {
            for (var category in ArticlejsonObject.query.pages.categories) {
                if (ArticlejsonObject.query.pages.categories.title=="Category:All disambiguation pages") {
                    // dab=unarticled
                    TableStructure=false
                    NRHPstats_HTMLRows.className=NRHPstats_HTMLRows.className.replace(" NRHPstats-articled","")
                }
                if (ArticlejsonObject.query.pages.categories.title.indexOf("sourced only to NRIS")!=-1) {
                    // mark as NRIS-only
                    TableStructure=true
                    NRHPstats_HTMLRows.className+=" NRHPstats-NRIS"
                }
            }
        }
    }

    if (TableStructure) { // if articled, check talk page
        var catlist='Category:FA-Class National Register of Historic Places articles‎|Category:A-Class National Register of Historic '
        catlist+='Places articles‎|Category:GA-Class National Register of Historic Places articles‎|Category:B-Class National Register '
        catlist+='of Historic Places articles‎|Category:C-Class National Register of Historic Places articles‎|Category:Start-Class '
        catlist+='National Register of Historic Places articles‎|Category:Stub-Class National Register of Historic Places articles‎'
        catlist+='|Category:Unassessed National Register of Historic Places articles‎|Category:List-Class National Register of '
        catlist+='Historic Places articles|Category:Redirect-Class National Register of Historic Places articles'

        $.ajax({
            dataType: "json",
            url: mw.util.wikiScript('api'),
            data: {
                format: 'json',
                action: 'query',
                prop: 'categories',
                clcategories: catlist,
                cllimit: 'max',
                titles: "Talk:"+TableStructure
            },
            success: function(TalkjsonObject) {TalkChecked(TalkjsonObject,NRHPstats_currentTable,NRHPstats_currentRow)}
        });
    } else { // if unarticled, no need to check talk page; send empty jsonObject
        TalkChecked({"query":{"pages":}},NRHPstats_currentTable,NRHPstats_currentRow)
    }
    return;
}

function TalkChecked(TalkjsonObject,NRHPstats_currentTable,NRHPstats_currentRow) {
    for (var page in TalkjsonObject.query.pages) {
        TableStructure=true // default to untagged
        if (TalkjsonObject.query.pages.categories) {
            TableStructure=false // if cat hit, mark as tagged
            for (var category in TalkjsonObject.query.pages.categories) {
                var CatTitle=TalkjsonObject.query.pages.categories.title
                if (CatTitle.indexOf("Stub")!=-1) {
                    TableStructure=true // mark as stub
                    NRHPstats_HTMLRows.className+=" NRHPstats-stub"
                }
                if (CatTitle.indexOf("Unassessed")!=-1||CatTitle.indexOf("Redirect")!=-1) {
                    TableStructure=true // mark as unassessed
                    NRHPstats_HTMLRows.className+=" NRHPstats-unassessed"
                }
                if  (CatTitle.indexOf("List")!=-1) { // count links to other county/MPS lists as unarticled; other list-class as stubs
                    if (TalkjsonObject.query.pages.title.indexOf("National Register of Historic Places")!=-1){
                        TableStructure=false
                        NRHPstats_HTMLRows.className=NRHPstats_HTMLRows.className.replace(" NRHPstats-articled","")
                    } else {
                        TableStructure=true
                        NRHPstats_HTMLRows.className+=" NRHPstats-stub"
                    }
                }
            }
        }
        if (TableStructure==true) { // if no category hits, mark as untagged
            NRHPstats_HTMLRows.className+=" NRHPstats-untagged"
        }

        var temp=TableStructure
        if (temp&&!temp&&!temp&&!temp) { // if articled but not stub, unassessed, or untagged, must be Start+
            TableStructure=true
            NRHPstats_HTMLRows.className+=" NRHPstats-Start+"
        }
    }

    TotalQueried++
    // if we've queried all rows, add up statistics and display them
    if (TotalQueried==TotalToQuery) CalculateNRHPStatistics();
    return;
}

function CalculateNRHPStatistics() {
    for (var NRHPstats_currentTable=0; NRHPstats_currentTable<TableStructure.length; NRHPstats_currentTable++) {
        var listings=TableStructure.length
        var articled=0
        var illustrated=0
        var stubs=0
        var NRIS=0
        var start=0
        var unassessed=0
        var untagged=0
        var temp=TableStructure
        for (var i=0; i<listings; i++) {
            if (temp) illustrated++
            if (temp) articled++
            if (temp) stubs++
            if (temp) NRIS++
            if (temp) start++
            if (temp) unassessed++
            if (temp) untagged++
        }
        var percentIllustrated=Math.round(illustrated/listings*1000)/10
        var percentArticled=Math.round(articled/listings*1000)/10
        var percentStartPlus=Math.round(start/listings*1000)/10
        var netQuality = (start+0.5*stubs+0.5*unassessed-0.5*untagged-0.75*NRIS)/listings
            netQuality = Math.round((0.75*netQuality+0.25*illustrated/listings)*1000)/10
        if (netQuality<0) netQuality = 0

        // update yellow box
        var disp=NRHPstats_HTMLTables.previousSibling
        var str1 = "<b>Total Listings:</b> " + listings
        var str2 = "<br /><b>No. Illustrated:</b> " + illustrated + " (" + percentIllustrated + "%)"
        var str3 = "<br /><b>No. Articled:</b> " + articled + " (" + percentArticled + "%)"
        var str4 = "<br /><b>No. Stubs:</b> " + stubs
        var str5 = "<br /><b>No. NRIS-only:</b> "+ NRIS
        var str6 = "<br /><b>No. Start+:</b> " + start + " (" + percentStartPlus + "%)"
        var str7 = "<br /><b>No. Unassessed:</b> " + unassessed
        var str8 = "<br /><b>No. Untagged:</b> " + untagged
        var str9 = "<br /><b>Net Quality Rating:</b> " + netQuality + "%"

        disp.setAttribute('style', 'font-size:125%; background-color:yellow; width:400px; padding:5px')
        disp.innerHTML = str1 + "&nbsp;<small><a onclick='ToggleRows(\"all\","+NRHPstats_currentTable+")'>(Show all)</a></small>"
        var Span2 = document.createElement('span')
        Span2.innerHTML = str2 + "&nbsp;<small><a onclick='ToggleRows(\"illustrated\","+NRHPstats_currentTable+")'>(Show only unillustrated)</a></small>"
        disp.appendChild(Span2)
        var Span3 = document.createElement('span')
        Span3.innerHTML = str3 + "&nbsp;<small><a onclick='ToggleRows(\"articled\","+NRHPstats_currentTable+")'>(Show only unarticled)</a></small>"
        disp.appendChild(Span3)
        var Span4 = document.createElement('span')
        Span4.innerHTML = str4 + "&nbsp;<small><a onclick='ToggleRows(\"stub\","+NRHPstats_currentTable+")'>(Show only stubs)</a></small>"
        disp.appendChild(Span4)
        if (NRIS > 0) {
            var Span5 = document.createElement('span')
            Span5.innerHTML = str5 + "&nbsp;<small><a onclick='ToggleRows(\"NRIS\","+NRHPstats_currentTable+")'>(Show only NRIS-only)</a></small>"
            disp.appendChild(Span5)
            Span5.style.color = 'red'
        }
        var Span6 = document.createElement('span')
        Span6.innerHTML = str6 + "&nbsp;<small><a onclick='ToggleRows(\"Start+\","+NRHPstats_currentTable+")'>(Show only Start+)</a></small>"
        disp.appendChild(Span6)
        if (unassessed > 0) {
            var Span7 = document.createElement('span')
            Span7.innerHTML = str7 + "&nbsp;<small><a onclick='ToggleRows(\"unassessed\","+NRHPstats_currentTable+")'>(Show only unassessed)</a></small>"
            disp.appendChild(Span7)
            Span7.style.color = 'red'
        }
        if (untagged > 0) {
            var Span8 = document.createElement('span')
            Span8.innerHTML = str8 + "&nbsp;<small><a onclick='ToggleRows(\"untagged\","+NRHPstats_currentTable+")'>(Show only untagged)</a></small>"
            disp.appendChild(Span8)
            Span8.style.color = 'red'
        }
        var Span9 = document.createElement('span')
        Span9.innerHTML = str9
        disp.appendChild(Span9)
    }
}

function ToggleRows(show,tableNumber) {
    var HTMLTables=
    var table=document.getElementsByClassName('wikitable sortable');
    if (table == null) return;
    for (var i=0; i<table.length; i++) {   // get rid of non-NRHP tables
        var tr=table.getElementsByTagName("tr")
        if (tr.getElementsByTagName("th").length >= 5) {
            HTMLTables.push(table)
        }
    }
    tr=HTMLTables.getElementsByTagName("tr")
    switch (show) {
        case "all":
            for (var i=1; i<tr.length; i++) {tr.style.display=""}
            break;
        case "illustrated":
        case "articled":
            for (var i=1; i<tr.length; i++) {
                if (tr.className.indexOf("NRHPstats-"+show)!=-1) {
                    tr.style.display="none"
                } else {
                    tr.style.display=""
                }
            }
            break;
        case "stub":
        case "NRIS":
        case "Start+":
        case "unassessed":
        case "untagged":
            for (var i=1; i<tr.length; i++) {
                if (tr.className.indexOf("NRHPstats-"+show)==-1) {
                    tr.style.display="none"
                } else {
                    tr.style.display=""
                }
            }
            break;
    }
}


/*
   The following function only triggers on the NRHP Progress page; it adds up totals for each state table
   as well as for the national table at the top of the page. It outputs a yellow box similar to LoadNRHPstats()
*/


function NRHPTotals() {
    var portlet=document.getElementById('t-NRHP')
    if (portlet!=null) {
        portlet.getElementsByTagName('a').href="javascript:ToggleDisp()"
        portlet.getElementsByTagName('a').innerHTML="Show/hide stats"
    }
    var table=document.getElementsByClassName('wikitable sortable');

    for (var i=0; i<table.length; i++){
        var rows=table.getElementsByTagName('tr');
        var Total = 0
        var TotalIllustrated = 0
        var TotalArticled = 0
        var TotalStubs = 0
        var TotalNRISOnly = 0
        var TotalStartPlus = 0
        var TotalUnassessed = 0
        var TotalUntagged = 0
        var CountySub = 0
        var CountyIllustratedSub = 0
        var CountyArticledSub = 0
        var CountyStubsSub = 0
        var CountyNRISOnlySub = 0
        var CountyStartPlusSub = 0
        var CountyUnassessedSub = 0
        var CountyUntaggedSub = 0

        for (var j=1; j<rows.length-1; j++) {
            var tds=rows.getElementsByTagName('td');

            // if on a duplicate row, alert user if no info; subtract if numbers there
            if (j == rows.length-2) {
                if (isNaN(parseFloat(tds.innerHTML))) {
                    tds.style.backgroundColor="#FF9999"
                    tds.title="Duplicate information needed!"
                } else {
                    Total = Total - parseFloat(tds.innerHTML.replace(/,/g,''))   // replace ignores commas in numbers>999
                }
                if (isNaN(parseFloat(tds.innerHTML))) {
                    tds.style.backgroundColor="#FF9999"
                    tds.title="Duplicate information needed!"
                } else {
                    TotalIllustrated = TotalIllustrated - parseFloat(tds.innerHTML.replace(/,/g,''))
                }
                if (isNaN(parseFloat(tds.innerHTML))) {
                    tds.style.backgroundColor="#FF9999"
                    tds.title="Duplicate information needed!"
                } else {
                    TotalArticled = TotalArticled - parseFloat(tds.innerHTML.replace(/,/g,''))
                }
                if (isNaN(parseFloat(tds.innerHTML))) {
                    tds.style.backgroundColor="#FF9999"
                    tds.title="Duplicate information needed!"
                } else {
                    TotalStubs = TotalStubs - parseFloat(tds.innerHTML.replace(/,/g,''))
                }
                if (isNaN(parseFloat(tds.innerHTML))) {
                    tds.style.backgroundColor="#FF9999"
                    tds.title="Duplicate information needed!"
                } else {
                    TotalNRISOnly = TotalNRISOnly - parseFloat(tds.innerHTML.replace(/,/g,''))
                }
                if (isNaN(parseFloat(tds.innerHTML))) {
                    tds.style.backgroundColor="#FF9999"
                    tds.title="Duplicate information needed!"
                } else {
                    TotalStartPlus = TotalStartPlus - parseFloat(tds.innerHTML.replace(/,/g,''))
                }
                if (isNaN(parseFloat(tds.innerHTML))) {
                    tds.style.backgroundColor="#FF9999"
                    tds.title="Duplicate information needed!"
                } else {
                    TotalUnassessed = TotalUnassessed - parseFloat(tds.innerHTML.replace(/,/g,''))
                }
                if (isNaN(parseFloat(tds.innerHTML))) {
                    tds.style.backgroundColor="#FF9999"
                    tds.title="Duplicate information needed!"
                } else {
                    TotalUntagged = TotalUntagged - parseFloat(tds.innerHTML.replace(/,/g,''))
                }
            }
            else {
                if (CountySub != 0) {    // if inside county sublists, add to subtotal or subtract if duplicates
                    if (isNaN(parseFloat(tds.innerHTML))) {
                        if (tds.innerHTML.search("ddddd") != -1) {
                            if (isNaN(parseFloat(tds.innerHTML))) { // alert if no duplicates there
                                tds.style.backgroundColor="#FF9999"
                                tds.title="Duplicate information needed!"
                            } else {
                                CountySub = CountySub - parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (isNaN(parseFloat(tds.innerHTML))) {
                                tds.style.backgroundColor="#FF9999"
                                tds.title="Duplicate information needed!"
                            } else {
                                CountyIllustratedSub = CountyIllustratedSub - parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (isNaN(parseFloat(tds.innerHTML))) {
                                tds.style.backgroundColor="#FF9999"
                                tds.title="Duplicate information needed!"
                            } else {
                                CountyArticledSub = CountyArticledSub - parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (isNaN(parseFloat(tds.innerHTML))) {
                                tds.style.backgroundColor="#FF9999"
                                tds.title="Duplicate information needed!"
                            } else {
                                CountyStubsSub = CountyStubsSub - parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (isNaN(parseFloat(tds.innerHTML))) {
                                tds.style.backgroundColor="#FF9999"
                                tds.title="Duplicate information needed!"
                            } else {
                                CountyNRISOnlySub = CountyNRISOnlySub - parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (isNaN(parseFloat(tds.innerHTML))) {
                                tds.style.backgroundColor="#FF9999"
                                tds.title="Duplicate information needed!"
                            } else {
                                CountyStartPlusSub = CountyStartPlusSub - parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (isNaN(parseFloat(tds.innerHTML))) {
                                tds.style.backgroundColor="#FF9999"
                                tds.title="Duplicate information needed!"
                            } else {
                                CountyUnassessedSub = CountyUnassessedSub - parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (isNaN(parseFloat(tds.innerHTML))) {
                                tds.style.backgroundColor="#FF9999"
                                tds.title="Duplicate information needed!"
                            } else {
                                CountyUntaggedSub = CountyUntaggedSub - parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                        }
                        else {
                            if (!isNaN(parseFloat(tds.innerHTML))) { // skip if blank
                                CountySub = CountySub + parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (!isNaN(parseFloat(tds.innerHTML))) {
                                CountyIllustratedSub = CountyIllustratedSub + parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (!isNaN(parseFloat(tds.innerHTML))) {
                                CountyArticledSub = CountyArticledSub + parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (!isNaN(parseFloat(tds.innerHTML))) {
                                CountyStubsSub = CountyStubsSub + parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (!isNaN(parseFloat(tds.innerHTML))) {
                                CountyNRISOnlySub = CountyNRISOnlySub + parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (!isNaN(parseFloat(tds.innerHTML))) {
                                CountyStartPlusSub = CountyStartPlusSub + parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (!isNaN(parseFloat(tds.innerHTML))) {
                                CountyUnassessedSub = CountyUnassessedSub + parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                            if (!isNaN(parseFloat(tds.innerHTML))) {
                                CountyUntaggedSub = CountyUntaggedSub + parseFloat(tds.innerHTML.replace(/,/g,''))
                            }
                        }
                    }
                    else {    // if now at end of county sublists, total up everything
                        var ScriptCountyPercentIllus = Math.round (CountyIllustratedSub/CountySub * 1000) / 10
                        var ScriptCountyPercentArt = Math.round (CountyArticledSub/CountySub * 1000) / 10
                        var ScriptCountyPercentStartPlus = Math.round (CountyStartPlusSub/CountySub * 1000) / 10
                        var ScriptCountyNetQuality = CountyStartPlusSub+0.5*CountyStubsSub+0.5*CountyUnassessedSub
                            ScriptCountyNetQuality = ScriptCountyNetQuality-0.5*CountyUntaggedSub-0.75*CountyNRISOnlySub
                            ScriptCountyNetQuality = 0.75*ScriptCountyNetQuality/CountySub+0.25*CountyIllustratedSub/CountySub
                            ScriptCountyNetQuality = Math.round(ScriptCountyNetQuality*1000)/10
                        if (ScriptCountyNetQuality<0) ScriptCountyNetQuality = 0

                        // check script output against what's entered
                        var EnteredCountyTotal = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyIllusTotal = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyPercentIllus = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyArtTotal = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyPercentArt = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyStubs = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyNRISOnly = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyStartPlus = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyPercentStartP = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyUnass = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyUntag = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var EnteredCountyNetQuality = parseFloat(tds.innerHTML.replace(/,/g,''))

                        if (EnteredCountyTotal != CountySub && !isNaN(CountySub)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountySub
                        }
                        if (EnteredCountyIllusTotal != CountyIllustratedSub && !isNaN(CountyIllustratedSub)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountyIllustratedSub
                        }
                        if (EnteredCountyPercentIllus != ScriptCountyPercentIllus && !isNaN(ScriptCountyPercentIllus)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + ScriptCountyPercentIllus + "%"
                        }
                        if (EnteredCountyArtTotal != CountyArticledSub && !isNaN(CountyArticledSub)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountyArticledSub
                        }
                        if (EnteredCountyPercentArt != ScriptCountyPercentArt && !isNaN(ScriptCountyPercentArt)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + ScriptCountyPercentArt + "%"
                        }
                        if (EnteredCountyStubs != CountyStubsSub && !isNaN(CountyStubsSub)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountyStubsSub
                        }
                        if (EnteredCountyNRISOnly != CountyNRISOnlySub && !isNaN(CountyNRISOnlySub)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountyNRISOnlySub
                        }
                        if (EnteredCountyStartPlus != CountyStartPlusSub && !isNaN(CountyStartPlusSub)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountyStartPlusSub
                        }
                        if (EnteredCountyPercentStartP != ScriptCountyPercentStartPlus && !isNaN(ScriptCountyPercentStartPlus)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + ScriptCountyPercentStartPlus + "%"
                        }
                        if (EnteredCountyUnass != CountyUnassessedSub && !isNaN(CountyUnassessedSub)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountyUnassessedSub
                        }
                        if (EnteredCountyUntag != CountyUntaggedSub && !isNaN(CountyUntaggedSub)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountyUntaggedSub
                        }
                        if (EnteredCountyNetQuality != ScriptCountyNetQuality && !isNaN(ScriptCountyNetQuality)) {
                           tds.style.backgroundColor="#FF9999"
                           tds.title="Script output: " + CountyUntaggedSub
                        }

                        // update total then reset subtotals
                        Total = Total + CountySub
                        TotalIllustrated = TotalIllustrated + CountyIllustratedSub
                        TotalArticled = TotalArticled + CountyArticledSub
                        TotalStubs = TotalStubs + CountyStubsSub
                        TotalNRISOnly = TotalNRISOnly + CountyNRISOnlySub
                        TotalStartPlus = TotalStartPlus + CountyStartPlusSub
                        TotalUnassessed = TotalUnassessed + CountyUnassessedSub
                        TotalUntagged = TotalUntagged + CountyUntaggedSub

                        CountySub = 0
                        CountyIllustratedSub = 0
                        CountyArticledSub = 0
                        CountyStubsSub = 0
                        CountyNRISOnlySub = 0
                        CountyStartPlusSub = 0
                        CountyUnassessedSub = 0
                        CountyUntaggedSub = 0
                    }
                }
                else {   // regular counties
                    if (isNaN(parseFloat(tds.innerHTML)) && tds.length == 15) { // if first in line of sublists, begin subtotal
                        if (!isNaN(parseFloat(tds.innerHTML))) {
                            CountySub = parseFloat(tds.innerHTML.replace(/,/g,''))
                        }
                        if (!isNaN(parseFloat(tds.innerHTML))) {
                            CountyIllustratedSub = parseFloat(tds.innerHTML.replace(/,/g,''))
                        }
                        if (!isNaN(parseFloat(tds.innerHTML))) {
                            CountyArticledSub = parseFloat(tds.innerHTML.replace(/,/g,''))
                        }
                        if (!isNaN(parseFloat(tds.innerHTML))) {
                            CountyStubsSub = parseFloat(tds.innerHTML.replace(/,/g,''))
                        }
                        if (!isNaN(parseFloat(tds.innerHTML))) {
                            CountyNRISOnlySub = parseFloat(tds.innerHTML.replace(/,/g,''))
                        }
                        if (!isNaN(parseFloat(tds.innerHTML))) {
                            CountyStartPlusSub = parseFloat(tds.innerHTML.replace(/,/g,''))
                        }
                        if (!isNaN(parseFloat(tds.innerHTML))) {
                            CountyUnassessedSub = parseFloat(tds.innerHTML.replace(/,/g,''))
                        }
                        if (!isNaN(parseFloat(tds.innerHTML))) {
                            CountyUntaggedSub = parseFloat(tds.innerHTML.replace(/,/g,''))
                        }
                    }
                    else {
                        var RowTotal = parseFloat(tds.innerHTML.replace(/,/g,''))
                        if (!isNaN(RowTotal)) Total = Total + RowTotal                                    // skip if blank
                        var RowIllustrated = parseFloat(tds.innerHTML.replace(/,/g,''))
                        if (!isNaN(RowIllustrated)) TotalIllustrated = TotalIllustrated + RowIllustrated
                        var RowArticled = parseFloat(tds.innerHTML.replace(/,/g,''))
                        if (!isNaN(RowArticled)) TotalArticled = TotalArticled + RowArticled
                        var RowStubs = parseFloat(tds.innerHTML.replace(/,/g,''))
                        if (!isNaN(RowStubs)) TotalStubs = TotalStubs + RowStubs
                        var RowNRISOnly = parseFloat(tds.innerHTML.replace(/,/g,''))
                        if (!isNaN(RowNRISOnly)) TotalNRISOnly = TotalNRISOnly + RowNRISOnly
                        var RowStartPlus = parseFloat(tds.innerHTML.replace(/,/g,''))
                        if (!isNaN(RowStartPlus)) TotalStartPlus = TotalStartPlus + RowStartPlus
                        var RowUnassessed = parseFloat(tds.innerHTML.replace(/,/g,''))
                        if (!isNaN(RowUnassessed)) TotalUnassessed = TotalUnassessed + RowUnassessed
                        var RowUntagged = parseFloat(tds.innerHTML.replace(/,/g,''))
                        if (!isNaN(RowUntagged)) TotalUntagged = TotalUntagged + RowUntagged

                        // check script against what's entered
                        var EnteredPercentIllustrated = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var ScriptPercentIllustrated = Math.round(RowIllustrated/RowTotal*1000)/10
                        var EnteredPercentArticled = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var ScriptPercentArticled = Math.round(RowArticled/RowTotal*1000)/10
                        var EnteredPercentStartPlus = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var ScriptPercentStartPlus = Math.round(RowStartPlus/RowTotal*1000)/10
                        var EnteredNetQuality = parseFloat(tds.innerHTML.replace(/,/g,''))
                        var ScriptNetQuality = RowStartPlus+0.5*RowStubs+0.5*RowUnassessed-0.5*RowUntagged-0.75*RowNRISOnly
                            ScriptNetQuality = Math.round((0.75*ScriptNetQuality/RowTotal+0.25*RowIllustrated/RowTotal)*1000)/10
                        if (ScriptNetQuality<0) ScriptNetQuality=0

                        if (EnteredPercentIllustrated != ScriptPercentIllustrated && !isNaN(ScriptPercentIllustrated)) {
                            tds.style.backgroundColor="#FF9999"
                            tds.title="Script output: " + ScriptPercentIllustrated + "%"
                        }
                        if (EnteredPercentArticled != ScriptPercentArticled && !isNaN(ScriptPercentArticled)) {
                            tds.style.backgroundColor="#FF9999"
                            tds.title="Script output: " + ScriptPercentArticled + "%"
                        }
                        if (EnteredPercentStartPlus != ScriptPercentStartPlus && !isNaN(ScriptPercentStartPlus)) {
                            tds.style.backgroundColor="#FF9999"
                            tds.title="Script output: " + ScriptPercentStartPlus + "%"
                        }
                        if (EnteredNetQuality != ScriptNetQuality && !isNaN(ScriptNetQuality)) {
                            tds.style.backgroundColor="#FF9999"
                            tds.title="Script output: " + ScriptNetQuality + "%"
                        }
                    }
                }
            }
        }

        // output totals for each state in yellow box
        var ScriptTotalPercentIllustrated = Math.round(TotalIllustrated/Total*1000)/10
        var ScriptTotalPercentArticled = Math.round(TotalArticled/Total*1000)/10
        var ScriptTotalPercentStartPlus = Math.round(TotalStartPlus/Total*1000)/10
        var ScriptTotalNetQuality = TotalStartPlus+0.5*TotalStubs+0.5*TotalUnassessed-0.5*TotalUntagged-0.75*TotalNRISOnly
            ScriptTotalNetQuality = Math.round((0.75*ScriptTotalNetQuality/Total+0.25*TotalIllustrated/Total)*1000)/10
        if (ScriptTotalNetQuality<0) ScriptTotalNetQuality = 0

        var str = "<b>Total Listings:</b> " + Total
            str = str + "<br /><b>No. Illustrated:</b> " + TotalIllustrated + " (" + ScriptTotalPercentIllustrated
            str = str + "%)<br /><b>No. Articled:</b> " + TotalArticled + " (" + ScriptTotalPercentArticled + "%)"
            str = str + "<br /><b>No. Stubs:</b> " + TotalStubs + "<br /><b>No. NRIS-only:</b> "+TotalNRISOnly
            str = str + "<br /><b>No. Start+:</b> " + TotalStartPlus + " (" + ScriptTotalPercentStartPlus
            str = str + "%)<br /><b>No. Unassessed:</b> " + TotalUnassessed + "<br /><b>No. Untagged:</b> " + TotalUntagged
            str = str + "<br /><b>Net Quality Rating:</b> " + ScriptTotalNetQuality + "%"

        var disp = document.createElement( 'div' )

        disp.setAttribute('style', 'font-size:125%; background-color:yellow; width:240px; padding:5px')
        disp.setAttribute('class', 'NRHPdisp')
        table.parentNode.insertBefore(disp , table)
        disp.innerHTML = str

        // check script totals against what's entered
        var Totaltds=rows.getElementsByTagName('th')
        var EnteredTotal = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredTotalIllustrated = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredPercentIllustrated = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredTotalArticled = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredPercentArticled = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredStubs = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredNRISOnly = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredStartPlus = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredPercentStartPlus = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredUnassessed = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredUntagged = parseFloat(Totaltds.innerHTML.replace(/,/g,''))
        var EnteredNetQuality = parseFloat(Totaltds.innerHTML.replace(/,/g,''))

        if (EnteredTotal != Total && !isNaN(Total)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + Total
        }
        if (EnteredTotalIllustrated != TotalIllustrated && !isNaN(TotalIllustrated)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + TotalIllustrated
        }
        if (EnteredPercentIllustrated != ScriptTotalPercentIllustrated && !isNaN(ScriptTotalPercentIllustrated)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + ScriptTotalPercentIllustrated + "%"
        }
        if (EnteredTotalArticled != TotalArticled && !isNaN(TotalArticled)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + TotalArticled
        }
        if (EnteredPercentArticled != ScriptTotalPercentArticled && !isNaN(ScriptTotalPercentArticled)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + ScriptTotalPercentArticled + "%"
        }
        if (EnteredStubs != TotalStubs && !isNaN(TotalStubs)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + TotalStubs
        }
        if (EnteredNRISOnly != TotalNRISOnly && !isNaN(TotalNRISOnly)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + TotalNRISOnly
        }
        if (EnteredStartPlus != TotalStartPlus && !isNaN(TotalStartPlus)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + TotalStartPlus
        }
        if (EnteredPercentStartPlus != ScriptTotalPercentStartPlus && !isNaN(ScriptTotalPercentStartPlus)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + ScriptTotalPercentStartPlus + "%"
        }
        if (EnteredUnassessed != TotalUnassessed && !isNaN(TotalUnassessed)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + TotalUnassessed
        }
        if (EnteredUntagged != TotalUntagged && !isNaN(TotalUntagged)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + TotalUntagged
        }
        if (EnteredNetQuality != ScriptTotalNetQuality && !isNaN(ScriptTotalNetQuality)) {
           Totaltds.style.backgroundColor="#FF9999"
           Totaltds.title="Script output: " + ScriptTotalNetQuality + "%"
        }

        // check national table against what's entered in each state table
        if (i != 0) {
            var StateRows = table.getElementsByTagName('tr')
            var ThisStateRow = StateRows.getElementsByTagName('td')

            var StateTableTotal = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTableIllustrated = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTablePercentIllustrated = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTableArticled = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTablePercentArticled = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTableStubs = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTableNRISOnly = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTableStartPlus = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTablePercentStartPlus = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTableUnassessed = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTableUntagged = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))
            var StateTableNetQuality = parseFloat(ThisStateRow.innerHTML.replace(/,/g,''))

            if (EnteredTotal != StateTableTotal) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredTotal + ")"
            }
            if (EnteredTotalIllustrated != StateTableIllustrated) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredTotalIllustrated + ")"
            }
            if (EnteredPercentIllustrated != StateTablePercentIllustrated) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredPercentIllustrated + "%)"
            }
            if (EnteredTotalArticled != StateTableArticled) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredTotalArticled + ")"
            }
            if (EnteredPercentArticled != StateTablePercentArticled) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredPercentArticled + "%)"
            }
            if (EnteredStubs != StateTableStubs) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredStubs + ")"
            }
            if (EnteredNRISOnly != StateTableNRISOnly) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredNRISOnly + ")"
            }
            if (EnteredStartPlus != StateTableStartPlus) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredStartPlus + ")"
            }
            if (EnteredPercentStartPlus != StateTablePercentStartPlus) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredPercentStartPlus + "%)"
            }
            if (EnteredUnassessed != StateTableUnassessed) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredUnassessed + ")"
            }
            if (EnteredUntagged != StateTableUntagged) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredUntagged + ")"
            }
            if (EnteredNetQuality != StateTableNetQuality) {
               ThisStateRow.style.backgroundColor="#FF9999"
               ThisStateRow.title="Does not match table below! (" + EnteredNetQuality + ")"
            }
        }
    }
}

function getNRHPstatsWikitext(title) {
    try {
        var output=JSON.parse(
            $.ajax({
                dataType: "json",
                url: mw.util.wikiScript('api'),
                data: {
                    format: 'json',
                    action: 'query',
                    prop: 'revisions',
                    rvprop: 'content',
                    titles: title,
                    indexpageids: true,
                    redirects: 'true'
                },
                async:false
            })
            .responseText
        );
        for (page in output.query.pages) {
            wikitext = output.query.pages.revisions;
        }
        return wikitext
    }
    catch(err) {
        return "error"
    }
}

$(window).on('load', Shell);