_ _    _ _____  ___   __                       
 __      _(_) | _(_)___ / ( _ ) / /_   ___ ___  _ __ ___  
 \ \ /\ / / | |/ / | |_ \ / _ \| '_ \ / __/ _ \| '_ ` _ \ 
  \ V  V /| |   <| |___) | (_) | (_) | (_| (_) | | | | | |
   \_/\_/ |_|_|\_\_|____/ \___/ \___(_)___\___/|_| |_| |_|

User:Dudemanfellabra/NRHPstats.js

In this article, we are going to explore in depth the fascinating world of User:Dudemanfellabra/NRHPstats.js. This topic is of great relevance today, since its impact extends to different areas of society, from politics to popular culture. Along these lines, we will analyze the different aspects related to User:Dudemanfellabra/NRHPstats.js, examining its origins, its evolution over time and the implications it has on people's lives. Through an interdisciplinary approach, we will take a look at the multiple dimensions of User:Dudemanfellabra/NRHPstats.js, presenting data, research and opinions from experts in the field. At the end of this article, we hope to have a more complete and enriching vision of User:Dudemanfellabra/NRHPstats.js, which will allow us to better understand its importance and influence in today's world.
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);