Jump to content

User:Dudemanfellabra/Sandbox.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Dudemanfellabra (talk | contribs) at 21:36, 27 March 2016 (add code to dump data to subpages; remove old code; test with alerts for now). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
var wikitext = 'error'
var NRISOnlyStructure=[]; // NRISOnlyStructure[table][row]["Titles"][item].StatName to get info
var TotalToQuery=0;
var TotalQueried=0;
var OutputBase = "User:NationalRegisterBot/AllNRHPPages"
var ErrorCount=0;
var WarningCount=[["",0]]; // 0=status, 1=count
var InitialTime=0;
var ProgressDivTimer=0 // timer for updating ProgressDiv
var DefaultQueryPause=1 // number of milliseconds to wait between each API query; increased by code if rate limit reached

function CheckPermission() {
    if (mw.user.getName()!="NationalRegisterBot"&&mw.user.getName()!="Dudemanfellabra") {
        alert("Only NationalRegisterBot has been authorized to use the NRIS-only script!")
        return
    } else {
        NRISOnlyButtons()
    }
}

function NRISOnlyButtons() {
    var pageName=mw.config.get('wgPageName')
    var button=document.createElement("input")
    button.setAttribute("type", "button");
    button.setAttribute("id", "nrisonlybutton");
    var content=document.getElementById('mw-content-text')

    if (location.href.indexOf('action')==-1) {
        if (pageName=="Wikipedia:WikiProject_National_Register_of_Historic_Places/Progress") {
            button.setAttribute("value", "Update list for NationalRegisterBot (test)");
            button.setAttribute("onclick", "NRISOnlyClicked('update')");
        } else if (pageName=="User:NationalRegisterBot/AllNRHPPages/Duplications") {
            button.setAttribute("value", "Gather duplicate stats");
            button.setAttribute("onclick", "NRISOnlyClicked('duplicate')");
        } else if (pageName=="User:NationalRegisterBot/NRISOnly") {
            button.setAttribute("value", "Tag these articles");
            button.setAttribute("onclick", "NRISOnlyClicked('tag')");
        } else {
            return;
        }
        content.parentNode.insertBefore(button, content)
    }
}

function NRISOnlyClicked(action) { // after button is clicked, disable it and perform action
    var nrisonlybutton = document.getElementById('nrisonlybutton')
    nrisonlybutton.disabled = true
    var ProgressDiv = document.createElement("div")
    ProgressDiv.setAttribute("id", "ProgressDiv")
    ProgressDiv.setAttribute("style", "width:600px; border:1px solid black; padding:5px; background:#ffffff")
    nrisonlybutton.parentNode.insertBefore(ProgressDiv, nrisonlybutton)

    if (action=="update") {
        ProgressDiv.innerHTML = "Initializing..."
        getNRISOnlyProgressPageWikitext(mw.config.get('wgPageName')) // after wikitext fetched, SetupNRISOnlyTables() is called
    } else if (action=="duplicate") {
        CheckDuplicates();
    } else if (action=="tag") {
        TagNRISOnly();
    }
}

// create array of table structure to be populated later
function SetupNRISOnlyTables() {
    var table=document.getElementsByClassName('wikitable sortable');

    // extract list names from Progress page
    for (var i=1; i<table.length; i++) { // skip national table
        var tr=table[i].getElementsByTagName("tr")
        NRISOnlyStructure[i-1]=[];
        var skipOffset=1 // number of duplicate/skippable rows encountered so far
        for (var j=1; j<tr.length-2; j++) { // skip title row, statewide duplicates, and totals row
            var td=tr[j].getElementsByTagName("td") // fill in existing data in case error
            var link=td[1].getElementsByTagName("a")
            if (link.length!=0 && link[0].href.search("#")==-1) {
                NRISOnlyStructure[i-1][j-skipOffset]={};
                NRISOnlyStructure[i-1][j-skipOffset].Titles=[]; // Placeholder for article names

                link=decodeURI(link[0].href).split("/")
                link=link[link.length-1].replace(/_/g," ")
                NRISOnlyStructure[i-1][j-skipOffset].Link=link

                NRISOnlyStructure[i-1][j-skipOffset].ID=td[0].innerHTML.substr(0,5) // for finding empty counties

                NRISOnlyStructure[i-1][j-skipOffset].CatsQueried=0 // for querying later
                NRISOnlyStructure[i-1][j-skipOffset].TotalToCheck=0
                NRISOnlyStructure[i-1][j-skipOffset].TotalChecked=0
            } else { // must be a duplicate row
                skipOffset++
            }
        }
    }
    for (var i=0; i<NRISOnlyStructure.length; i++) { // count total number of lists to check
        TotalToQuery+=NRISOnlyStructure[i].length
    }

    var ProgressDiv=document.getElementById("ProgressDiv")
    ProgressDiv.innerHTML+=" Done!<br>"

    var ProgressSpan=document.createElement("span")
    ProgressSpan.setAttribute("id", "ProgressSpan")
    ProgressDiv.appendChild(ProgressSpan)
    ProgressSpan.innerHTML = "Querying articles in each list... 0 (0%) of "+TotalToQuery+" lists complete."

    var TimeSpan=document.createElement("span")
    TimeSpan.setAttribute("id", "TimeSpan")
    ProgressDiv.appendChild(TimeSpan)
    TimeSpan.innerHTML = ""

    var EditSpan=document.createElement("span")
    EditSpan.setAttribute("id", "EditSpan")
    ProgressDiv.appendChild(EditSpan)
    EditSpan.innerHTML = ""

    InitialTime=new Date() // record starting time
    UpdateNRISOnlyProgressDiv();
    LoadNRISOnlyList(0,0); // begin querying first page
}

// load next list to query
function LoadNRISOnlyList(currentTable,currentRow) {
    // check if we need to go to the next table
    if (currentRow>NRISOnlyStructure[currentTable].length-1) {
        currentRow=0
        currentTable++
    }
    // check if there are no more tables
    if (currentTable>NRISOnlyStructure.length-1) return;

    setTimeout(function(){ // short delay to prevent API overload
        getNRISOnlyListWikitext(currentTable,currentRow);
        LoadNRISOnlyList(currentTable,currentRow+1);
    }, DefaultQueryPause);
    return;
}

function NRISOnlyWikitextFetched(ajaxResponse,status,currentTable,currentRow) {
    if (status!="success") {
        NewNRISOnlyWarning("Wikitext "+ajaxResponse.errorThrown)
        setTimeout(function(){ // try again after delay if rate limit reached
            getNRISOnlyListWikitext(currentTable,currentRow);
        }, 250);
        return;
    }
    // won't get here unless successful
    var responseText=JSON.parse(ajaxResponse.responseText)
    var pagetext=responseText.query.pages[responseText.query.pageids[0]].revisions[0]["*"]
    if (responseText.query.redirects) { // if redirect, find section
        var SectionName="Undefined"
        for (var r in responseText.query.redirects) {
            if (typeof responseText.query.redirects[r].tofragment!="undefined") SectionName=responseText.query.redirects[r].tofragment.replace(/.27/g,"'")
        }

        var regex = new RegExp("=[ ]*(\\[\\[(.*?\\|)?[ ]*)?"+SectionName+"([ ]*\\]\\])?[ ]*=", "g")
        var sectionheader=pagetext.match(regex)
        if (sectionheader == null) { // if no section found, check if one of known empty counties
            var EmptyCounties=["02270", "12067", "42023", "48017", "48023", "48033", "48069", "48075", "48079", "48083", "48103", "48107", "48119", "48131", "48155", "48165", "48195", "48207", "48219", "48247", "48269", "48279", "48341", "48369", "48389", "48415", "48421", "48431", "48433", "48437", "48445", "48461", "48475", "48501", "51735"]

            var ID = NRISOnlyStructure[currentTable][currentRow].ID
            var errorcode = 0
            for (var k=0; k<EmptyCounties.length; k++) {
                if (ID==EmptyCounties[k]) {errorcode=-1}
            }
            if (errorcode!=0) { // must be an empty county
                TotalQueried++
                if (TotalQueried==TotalToQuery) DoneQueryingNRIS()
                return;
            }
            // if we're here, must have been a redirect with no section, and not a known empty county
            sectionheader=pagetext.match(/{{NRHP header/g) // then look for tables without a section
            if (sectionheader==null||sectionheader.length>1) { // if still can't find a table or find multiple tables, fatal error
                NRISOnlyFatalError(0,currentTable,currentRow)
                return;
            }
        }
        var StartIndex=pagetext.indexOf(sectionheader[0])
        var sectiontext=pagetext.substr(StartIndex,pagetext.indexOf("\n==",StartIndex)-StartIndex) // only look at relevant section

        StartIndex=sectiontext.indexOf("{{NRHP header")
        if (StartIndex==-1) {
            if (sectiontext.indexOf("{{NRHP row")!=-1) {
                NRISOnlyFatalError(2,currentTable,currentRow) // incorrectly formatted table
                return;
            } else { // must be an empty county
                TotalQueried++
                if (TotalQueried==TotalToQuery) DoneQueryingNRIS()
                return;
            }
        }
        var tabletext=sectiontext.substr(StartIndex,sectiontext.indexOf("\n|}",StartIndex)-StartIndex)
    } else { // if not a redirect, default to first table on page
        var StartIndex=pagetext.indexOf("{{NRHP header")
        if (StartIndex==-1) {
            NRISOnlyFatalError(1,currentTable,currentRow) // no list found
            return;
        }
        var tabletext=pagetext.substr(StartIndex,pagetext.indexOf("\n|}",StartIndex)-StartIndex)
    }

    // now that tabletext has only relevant table, extract rows
    var Rows=[]
    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) { // skip any commented out rows
            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) { // make sure to find correct matching close brackets for row template
            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("{{[\\s]*NRHP row(\\s)*\\|", "g")
        if (template.match(regex)!=null) Rows.push(template) // make sure it's the row template and not some other one
        start++
    }
    for (var i=0; i<Rows.length; i++) { // get rid of false positives inside nowiki or pre tags
        var regex=new RegExp("<[ ]*?(nowiki|pre)[ ]*?>((?!<[ ]*?/[ ]*?(nowiki|pre)[ ]*?>)(.|\\n))*?"+Rows[i].replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")+"(.|\\n)*?<[ ]*?/[ ]*?(nowiki|pre)[ ]*?>", "g")
        if (tabletext.match(regex)!=null) {Rows.splice(i,1); i--}
    }

    for (var i=0; i<Rows.length; i++) { // extract titles for querying
        var ThisRow=Rows[i]

        var article=ThisRow.match(/\|[ ]*?article[ ]*?=[ ]*?.*?[\n|\|]/g)
        var blank=ThisRow.match(/\|[ ]*?article[ ]*?=[ ]*?[\n|\|]/g)                               // default to name param if article
        if (article==null||blank!=null) article=ThisRow.match(/\|[ ]*?name[ ]*?=[ ]*?.*?[\n|\|]/g) // blank or missing
        // strip param name, final line break
        article=article[0].replace(/\|[ ]*?(article|name)[ ]*?=[ ]*?/g,"").replace(/[\n|\|]/g,"").replace(/\<\!\-\-(.|[\r\n])*?\-\-\>/g,"").trim()
        article=decodeURIComponent(article.split("#")[0].trim())     // corrections for weird titles

        var refnum=ThisRow.match(/[0-9]{8}/g) // also extract refnums
        if (refnum!=null) {
            if (refnum[0]=="98000562"||refnum[0]=="98000563") refnum[0]="98000562,98000563"   // hard-code troublesome
            if (refnum[0]=="01000363"||refnum[0]=="01000364") refnum[0]="01000363,01000364"   // multistate duplicates
            if (refnum[0]=="02000529"||refnum[0]=="02000530") refnum[0]="02000529,02000530"   // ...
            refnum=refnum[0]
        } else {
            refnum="missing"
        }

        var temp=NRISOnlyStructure[currentTable][currentRow].Titles
        temp[temp.length]={"name":article, "refnum":refnum, "exists":true,
                           "isDab":false, "isTaggedNRISOnly":false, "isNRISOnly":false, "proseSize":0, "numberRefs":0}
        NRISOnlyStructure[currentTable][currentRow].Titles=temp
    }

    var StartIndex=0
    LoadNextNRISOnlyListQuery(StartIndex,currentTable,currentRow)
    return;
}

// ready next batch of articles to query
function LoadNextNRISOnlyListQuery(StartIndex,currentTable,currentRow) {
    if (StartIndex==NRISOnlyStructure[currentTable][currentRow].Titles.length) { // all queries begun for this list
        return;
    }
    // must have some more rows to query
    if (NRISOnlyStructure[currentTable][currentRow].Titles.length-StartIndex>50) {
        var TempTitles=NRISOnlyStructure[currentTable][currentRow].Titles.slice(StartIndex,StartIndex+50)
    } else {
        var TempTitles=NRISOnlyStructure[currentTable][currentRow].Titles.slice(StartIndex)
    }

    for (var i=0; i<TempTitles.length; i++) { // only extract article names
        TempTitles[i]=TempTitles[i].name
    }

    StartIndex+=TempTitles.length
    setTimeout(function(){ // short delay to prevent API overload
        QueryNRISOnlyCats(TempTitles,StartIndex,currentTable,currentRow)
        LoadNextNRISOnlyListQuery(StartIndex,currentTable,currentRow)
    }, DefaultQueryPause);
    return;
}

// query next batch of articles
function QueryNRISOnlyCats(TempTitles,StartIndex,currentTable,currentRow) {
    var TitleList=TempTitles.join("|")
    $.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: TitleList,
            redirects: 'true'
        },
        error: function(ArticlejsonObject,status,errorThrown) {ArticlejsonObject.errorThrown=errorThrown},
        complete: function(ArticlejsonObject,status) {
                NRISOnlyCatsChecked(ArticlejsonObject,status,TempTitles,StartIndex,currentTable,currentRow)
            }
    });
    return;
}

// parse API response for article query
function NRISOnlyCatsChecked(ArticlejsonObject,status,TempTitles,StartIndex,currentTable,currentRow) {
    if (status!="success") {
        NewNRISOnlyWarning("Articles "+ArticlejsonObject.errorThrown)

        setTimeout(function(){ // try again after delay if rate limit reached
            QueryNRISOnlyCats(TempTitles,StartIndex,currentTable,currentRow)
        }, 250);
        return;
    }
    // won't get here unless successful
    NRISOnlyStructure[currentTable][currentRow].CatsQueried+=TempTitles.length

    var responseText=JSON.parse(ArticlejsonObject.responseText)
    if (responseText.query.normalized) { // normalize any weird titles
        for (var n in responseText.query.normalized) {
            for (var i=0; i<TempTitles.length; i++) {
                if (TempTitles[i]==responseText.query.normalized[n].from) TempTitles[i]=responseText.query.normalized[n].to
            }
            for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) { // also update in main data array
                if (NRISOnlyStructure[currentTable][currentRow].Titles[i].name==responseText.query.normalized[n].from) {
                    NRISOnlyStructure[currentTable][currentRow].Titles[i].name=responseText.query.normalized[n].to
                }
            }
        }
    }
    if (responseText.query.redirects) { // resolve any redirects also
        for (var r in responseText.query.redirects) {
            for (var i=0; i<TempTitles.length; i++) {
                if (TempTitles[i]==responseText.query.redirects[r].from) TempTitles[i]=responseText.query.redirects[r].to
            }
            for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) { // also update in main data array
                if (NRISOnlyStructure[currentTable][currentRow].Titles[i].name==responseText.query.redirects[r].from) {
                    NRISOnlyStructure[currentTable][currentRow].Titles[i].name=responseText.query.redirects[r].to
                }
            }
        }
    }

    // now determine if dab/NRIS-only
    for (var page in responseText.query.pages) {
        var pagetitle=responseText.query.pages[page].title
        // mark as redlink
        if (typeof responseText.query.pages[page].missing!="undefined") {
            for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) {
                if (NRISOnlyStructure[currentTable][currentRow].Titles[i].name==pagetitle) {
                    NRISOnlyStructure[currentTable][currentRow].Titles[i].exists=false
                }
            }
        }
        if (responseText.query.pages[page].categories) {
            for (var category in responseText.query.pages[page].categories) {
                // mark as link to dab
                if (responseText.query.pages[page].categories[category].title=="Category:All disambiguation pages") {
                    for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) {
                        if (NRISOnlyStructure[currentTable][currentRow].Titles[i].name==pagetitle) {
                            NRISOnlyStructure[currentTable][currentRow].Titles[i].exists=false // dab=redlink
                            NRISOnlyStructure[currentTable][currentRow].Titles[i].isDab=true
                        }
                    }
                }
                // mark already tagged NRIS-only
                if (responseText.query.pages[page].categories[category].title.indexOf("sourced only to NRIS")!=-1) {
                    for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) {
                        if (NRISOnlyStructure[currentTable][currentRow].Titles[i].name==pagetitle) {
                            NRISOnlyStructure[currentTable][currentRow].Titles[i].isTaggedNRISOnly=true
                        }
                    }
                }
            }
        }
    }

    if (NRISOnlyStructure[currentTable][currentRow].CatsQueried==NRISOnlyStructure[currentTable][currentRow].Titles.length) {
        var Titles=[];
        for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) { // tally up articles to query
            if (NRISOnlyStructure[currentTable][currentRow].Titles[i].exists) {
                Titles.push(NRISOnlyStructure[currentTable][currentRow].Titles[i].name)
                NRISOnlyStructure[currentTable][currentRow].TotalToCheck++
            }
        }
        // now begin querying article content and checking if NRIS-only
        StartIndex=0
        LoadNextNRISOnlyPageQuery(Titles,StartIndex,currentTable,currentRow)
    }
}

// load each existing page to check if it should be tagged NRIS-only
function LoadNextNRISOnlyPageQuery(Titles,StartIndex,currentTable,currentRow) {
    if (StartIndex==Titles.length) { // all queries begun for this list
        if (Titles.length==0) { // some lists have no bluelinks
            TotalQueried++
            if (TotalQueried==TotalToQuery) DoneQueryingNRIS()
        }
        return;
    }
    // must have some more rows to query
    setTimeout(function(){ // short delay to prevent API overload
        QueryNextNRISOnlyPage(Titles,StartIndex,currentTable,currentRow)
        StartIndex++
        LoadNextNRISOnlyPageQuery(Titles,StartIndex,currentTable,currentRow)
    }, DefaultQueryPause);
    return;
}

// query the next page
function QueryNextNRISOnlyPage(Titles,StartIndex,currentTable,currentRow) {
    $.ajax({
        dataType: "json",
        url: mw.util.wikiScript('api'),
        data: {
            format: 'json',
            action: 'query',
            prop: 'revisions',
            rvprop: 'content',
            titles: Titles[StartIndex],
            indexpageids: true,
            redirects: 'true'
        },
        error: function(ajaxResponse,status,errorThrown) {ajaxResponse.errorThrown=errorThrown},
        complete: function(ajaxResponse,status) {
            NRISOnlyPageWikitextFetched(ajaxResponse,status,Titles,StartIndex,currentTable,currentRow)
        }
    })
    return;
}

// parse API response for page wikitext
function NRISOnlyPageWikitextFetched(ajaxResponse,status,Titles,StartIndex,currentTable,currentRow) {
    if (status!="success") {
        NewNRISOnlyWarning("Articles wikitext "+ajaxResponse.errorThrown)

        setTimeout(function(){ // try again after delay if rate limit reached
            QueryNextNRISOnlyPage(Titles,StartIndex,currentTable,currentRow)
        }, 250);
        return;
    }
    // won't get here unless successful
    NRISOnlyStructure[currentTable][currentRow].TotalChecked++

    // now determine prose size, number of references, etc.
    var responseText=JSON.parse(ajaxResponse.responseText)
    for (var page in responseText.query.pages) {
        var pagetext = responseText.query.pages[page].revisions[0]['*'];

        var prose=pagetext.replace(/\<\!\-\-(.|[\r\n])*?\-\-\>/g,"")                        // strip comments
        // strip refs
        prose=prose.replace(/\<ref([ ]+?name[ ]*?=[ ]*?"?[^\>]*?"?[ ]*?\/[ ]*?\>|[^e](.|[\r\n])*?\<\/ref[ ]*?\>)/gi,"")
        prose=prose.replace(/==[ ]*?External links[ ]*?==(.|\n)*?(?=(==.*?==|$))/gi,"")     // strip external links section
        prose=prose.replace(/==[ ]*?See also[ ]*?==(.|\n)*?(?=(==.*?==|$))/gi,"")           // strip see also section
        prose=prose.replace(/==[ ]*?(References|Notes)[ ]*?==(.|\n)*?(?=(==.*?==|$))/gi,"") // strip references section
        // strip further reading section
        prose=prose.replace(/==[ ]*?(Further|Additional) reading[ ]*?==(.|\n)*?(?=(==.*?==|$))/gi,"")
        prose=prose.replace(/={2,5}.*?={2,5}/g,"")                                          // strip section titles
        // replace wikilinks with displayed text
        prose=prose.replace(/\[\[(?![ ]*?Category:|[ ]*?Image:|[ ]*?File:)([^\]]*?\|)?(.*?)\]\]/gi,"$2")
        prose=prose.replace(/\[[ ]*?http.*? (.*?)\]/g,"$1")                 // replace inline external links with displayed text
        prose=prose.replace(/'{2,5}(.*?)'{2,5}/g,"$1")                      // replace bold/italic with displayed text
        prose=prose.replace(/\[\[[ ]*?Category:.*?\]\]/g,"")                                // strip categories
        prose=prose.replace(/\[\[[ ]*?(Image|File):.*?\]\]/g,"")                            // strip images
        prose=prose.replace(/\<[ ]*?gallery(.|\n)*?\<[ ]*?\/[ ]*?gallery[ ]*?\>/gi,"")      // strip galleries
        while(true) {                                                                       // strip templates
            var str="{{"
            var start=prose.indexOf(str)
            if (start==-1) break
            var open=1
            var index=start+str.length
            while (open!=0 && index<prose.length) {
                if (prose.substr(index,2)=="}}") {
                    open--
                    index++
                } else if (prose.substr(index,2)=="{{") {
                    open++
                    index++
                }
                index++
            }
            prose=prose.replace(prose.substr(start,index-start),"")
        }
        prose=prose.replace(/{\|(.|\n)*?\|}/g,"")                   // strip tables
        prose=prose.replace(/&nbsp;/g," ")                          // replace nbsp with regular space
        prose=prose.replace(/<[ ]*?br.*?>/g, "\n")                  // replace HTML line break with string line break
        prose=prose.replace(/[ \n]+/g," ")                          // replace multiple spaces/linebreaks with single space
        prose=prose.trim()

        for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) { // record prose size
            if (NRISOnlyStructure[currentTable][currentRow].Titles[i].name==Titles[StartIndex]) {
                NRISOnlyStructure[currentTable][currentRow].Titles[i].proseSize=prose.length
            }
        }

        var hasSpecialRefs=false
        if (pagetext.indexOf("{{GR")!=-1||pagetext.indexOf("{{sfn")!=-1||pagetext.indexOf("{{Sfn")!=-1) { // these count as refs
            hasSpecialRefs=true
        }

        var Refs=pagetext.match(/\<ref[^e](.|[\r\n])*?([ ]*?\/|\<\/ref[ ]*?)\>/gi)
        var comments=pagetext.match(/\<\!\-\-(.|[\r\n])*?\-\-\>/g)

        if (Refs==null) { // if no refs, skip page (default numberRefs=0)
            if (!hasSpecialRefs) continue;
            Refs=[]
        }

        if (comments!=null) {
            for (var l=0; l<comments.length; l++) {
                var CommentedRefs=comments[l].match(/\<ref[^e](.|[\r\n])*?([ ]*?\/|\<\/ref[ ]*?)\>/gi)
                if (CommentedRefs==null) continue
                for (var m=0; m<CommentedRefs.length; m++) {
                    for (var n=0; n<Refs.length; n++) {
                        if (Refs[n]==CommentedRefs[m]) {Refs.splice(n,1); n--}
                    }
                }
            }
        }

        if (Refs.length==0) { // if all refs commented out, skip page (default numberRefs=0)
            if (!hasSpecialRefs) continue;
        }

        var citesNRIS=false
        for (var l=0; l<Refs.length; l++) {
            if (Refs[l].indexOf("{{NRISref")!=-1) citesNRIS=true // check if NRISref is one of the refs
        }

        var namedRefs=[];
        for (var l=0; l<Refs.length; l++) { // extract names of refs
            var nameOfRef=Refs[l].match(/name[ ]*?=.*?(\/|\>)/gi)
            if (nameOfRef==null) {
                continue
            } else {
                nameOfRef = nameOfRef[0].replace(/("| )/g,'')
                nameOfRef = nameOfRef.substr(5,nameOfRef.length-6)
            }
            namedRefs.push(nameOfRef)
        }

        var Duplicates=0
        for (var l=0; l<namedRefs.length; l++) { // remove duplicate named refs
            for (var m=l+1; m<namedRefs.length; m++) {
                if (namedRefs[m]==namedRefs[l]) {
                    Duplicates++
                    namedRefs.splice(m,1)
                    m--
                }
            }
        }

        var DistinctRefs = Refs.length-Duplicates
        if (hasSpecialRefs) DistinctRefs++

        for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) { // record number of refs
            if (NRISOnlyStructure[currentTable][currentRow].Titles[i].name==Titles[StartIndex]) {
                NRISOnlyStructure[currentTable][currentRow].Titles[i].numberRefs=DistinctRefs
            }
        }

        if (DistinctRefs>1) continue; // not NRIS-only if more than one ref

        if (citesNRIS&&DistinctRefs==1) { // if one ref and is NRIS-only, then tag
            for (var i=0; i<NRISOnlyStructure[currentTable][currentRow].Titles.length; i++) { // record number of refs
                if (NRISOnlyStructure[currentTable][currentRow].Titles[i].name==Titles[StartIndex]) {
                    NRISOnlyStructure[currentTable][currentRow].Titles[i].isNRISOnly=true
                }
            }
        }
    }

    if (NRISOnlyStructure[currentTable][currentRow].TotalChecked==NRISOnlyStructure[currentTable][currentRow].TotalToCheck) {
        TotalQueried++
        if (TotalQueried==TotalToQuery) DoneQueryingNRIS()
        return;
    }
}

// keep track of warnings encountered while querying API
function NewNRISOnlyWarning(warning) {
    var NewWarning=true
    for (var i=0; i<WarningCount.length; i++) { // check if already encountered error
        if (warning==WarningCount[i][0]||WarningCount[i][0]=="") {WarningCount[i][0]=warning; WarningCount[i][1]++; NewWarning=false;}
    }
    if (NewWarning) WarningCount[WarningCount.length]=[warning,1] // if new warning, make new entry

    var test=0
    for (var i=0; i<WarningCount.length; i++) {
        test+=WarningCount[i][1]
    }
    if (test%50==0) DefaultQueryPause++ // for every 50 errors encountered, increase time between each query to throttle speed
}

// these errors require user input; can't just be ignored
function NRISOnlyFatalError(code,currentTable,currentRow) {
    var errorArray = ['No county section found for ','No list found for ','Incorrectly formatted list for ']
    var retry=confirm(errorArray[code]+NRISOnlyStructure[currentTable][currentRow].Link+"!\n\nCancel=Skip                   OK=Retry")
    if (retry) {
        getNRISOnlyListWikitext(currentTable,currentRow);
    } else { // if chose to skip, add one to error count
        TotalQueried++
        ErrorCount++
        if (TotalQueried==TotalToQuery) DoneQueryingNRIS()
    }
    return;
}

// update ProgressDiv to let user know what's going on
function UpdateNRISOnlyProgressDiv() {
    var ProgressSpan=document.getElementById("ProgressSpan")
    var TimeSpan=document.getElementById("TimeSpan")

    var PercentQueried=Math.round(TotalQueried/TotalToQuery*1000)/10
    ProgressSpan.innerHTML = "Querying articles in each list... "+TotalQueried+" ("+PercentQueried+"%) of "+TotalToQuery+" lists complete."

    if (TotalQueried>10) {
        var CurrentTime=new Date()
        var MinutesElapsed = (CurrentTime-InitialTime)/60000
        var Average = MinutesElapsed/TotalQueried
        MinutesElapsed = Math.round(MinutesElapsed)
        var MinutesRemaining = Math.round(Average*(TotalToQuery-TotalQueried))
        if (MinutesRemaining == 0) MinutesRemaining="Less than one"

        var TimeRemainingStr = MinutesRemaining+" min"
        var TimeElapsedStr = ""
        if (MinutesElapsed!=0) TimeElapsedStr=MinutesElapsed+" min"
        if (TimeElapsedStr!="") TimeRemainingStr+=" ("+TimeElapsedStr+" elapsed)"
    } else {
        var TimeRemainingStr="Calculating..."
    }
    TimeSpan.innerHTML="<br>Estimated time remaining: "+TimeRemainingStr

    if (TotalQueried!=TotalToQuery) { // update ProgressDiv only at regular intervals to prevent CPU overload; stop once done
        ProgressDivTimer=setTimeout(function(){
            UpdateNRISOnlyProgressDiv();
        }, 500);
    }
    return;
}

// get here once done querying everything
function DoneQueryingNRIS() {
    clearTimeout(ProgressDivTimer)
    var ProgressSpan=document.getElementById("ProgressSpan")
    var TimeSpan=document.getElementById("TimeSpan")

    var CurrentTime=new Date()
    var MinutesElapsed=Math.round((CurrentTime-InitialTime)/60000)
    ProgressSpan.innerHTML="Querying articles in each list... Done! Time elapsed: "+MinutesElapsed+" min"

    TimeSpan.innerHTML="<br>Compiling data (this could take a while)... "

    setTimeout(function() {CalculateNRISOnlyTotals()},100); // small delay for non-Firefox browsers to update screen
}

// now compile all the data
function CalculateNRISOnlyTotals() {
    var AllTitles = [];             // [name,refnum,list] - includes redlinks; used to find duplicates later

    var Dabs = [];                  // [name,list]
    var MissingRefnum = [];         // [name,list]
    var ExistingTitles = [];        // name               - only bluelinks

    var ToBeTagged = [];            // name
    var ToBeUntagged = [];          // name

    var AllNRISOnly = [];           // name               - includes manually tagged articles
    var OneRefNotNRIS = [];         // name
    var Unreferenced = [];          // name

    var ShortNRIS = [];             // [name,length]      - NRIS-only with <325 bytes prose
    var ShortNotNRIS = [];          // [name,length]      - not NRIS-only with <325 bytes prose
    var LongNRIS = [];              // [name,length]      - NRIS-only with >=325 bytes prose

    var WorstNotNRIS = [];          // [name,length]      - 100 smallest non-NRIS-only
    var WorstNRIS = [];             // [name,length]      - 100 smallest NRIS-only

    var Duplications = [];          // [name,refnum,[list1,..listn]]

    for (var table=0; table<NRISOnlyStructure.length; table++) {
        for (var row=0; row<NRISOnlyStructure[table].length; row++) {
            for (var item=0; item<NRISOnlyStructure[table][row].Titles.length; item++) {
                var thisItem=NRISOnlyStructure[table][row].Titles[item]
                if (thisItem.refnum=="missing") {
                    MissingRefnum[MissingRefnum.length]=[thisItem.name,NRISOnlyStructure[table][row].Link]
                } else {
                    AllTitles[AllTitles.length]=[thisItem.name,thisItem.refnum,NRISOnlyStructure[table][row].Link]
                }
                if (thisItem.isDab) Dabs[Dabs.length]=[thisItem.name,NRISOnlyStructure[table][row].Link]
                if (!thisItem.exists) continue; // if redlink, no longer care about it

                // now no longer have to check for existence
                ExistingTitles.push(thisItem.name)

                // tagging
                if (thisItem.isNRISOnly&&!thisItem.isTaggedNRISOnly) ToBeTagged.push(thisItem.name)
                // only untag if more than one ref; sometimes tag is added manually to NRIS mirrors
                if (!thisItem.isNRISOnly&&thisItem.isTaggedNRISOnly&&thisItem.numberRefs>1) ToBeUntagged.push(thisItem.name)

                // referencing
                if (thisItem.isNRISOnly||(!thisItem.isNRISOnly&&thisItem.isTaggedNRISOnly&&thisItem.numberRefs<=1)) {
                    // also include manually tagged in output
                    AllNRISOnly.push(thisItem.name)
                }
                if (!thisItem.isNRISOnly&&thisItem.numberRefs==1) OneRefNotNRIS.push(thisItem.name)
                if (thisItem.numberRefs==0) Unreferenced.push(thisItem.name)

                // prose length
                if (thisItem.proseSize<325&thisItem.isNRISOnly) ShortNRIS[ShortNRIS.length]=[thisItem.name,thisItem.proseSize]
                if (thisItem.proseSize<325&!thisItem.isNRISOnly) ShortNotNRIS[ShortNotNRIS.length]=[thisItem.name,thisItem.proseSize]
                if (thisItem.proseSize>=325&thisItem.isNRISOnly) LongNRIS[LongNRIS.length]=[thisItem.name,thisItem.proseSize]
            }
        }
    }

    // remove duplicates
    for (var i=0;i<ExistingTitles.length; i++) {
        for (var j=i+1;j<ExistingTitles.length; j++) {
            if (ExistingTitles[i]==ExistingTitles[j]) {ExistingTitles.splice(j,1);j--}
        }
    }
    for (var i=0;i<ToBeTagged.length; i++) {
        for (var j=i+1;j<ToBeTagged.length; j++) {
            if (ToBeTagged[i]==ToBeTagged[j]) {ToBeTagged.splice(j,1);j--}
        }
    }
    for (var i=0;i<ToBeUntagged.length; i++) {
        for (var j=i+1;j<ToBeUntagged.length; j++) {
            if (ToBeUntagged[i]==ToBeUntagged[j]) {ToBeUntagged.splice(j,1);j--}
        }
    }
    for (var i=0;i<AllNRISOnly.length; i++) {
        for (var j=i+1;j<AllNRISOnly.length; j++) {
            if (AllNRISOnly[i]==AllNRISOnly[j]) {AllNRISOnly.splice(j,1);j--}
        }
    }
    for (var i=0;i<OneRefNotNRIS.length; i++) {
        for (var j=i+1;j<OneRefNotNRIS.length; j++) {
            if (OneRefNotNRIS[i]==OneRefNotNRIS[j]) {OneRefNotNRIS.splice(j,1);j--}
        }
    }
    for (var i=0;i<Unreferenced.length; i++) {
        for (var j=i+1;j<Unreferenced.length; j++) {
            if (Unreferenced[i]==Unreferenced[j]) {Unreferenced.splice(j,1);j--}
        }
    }
    for (var i=0;i<ShortNRIS.length; i++) {
        for (var j=i+1;j<ShortNRIS.length; j++) {
            if (ShortNRIS[i]==ShortNRIS[j]) {ShortNRIS.splice(j,1);j--}
        }
    }
    for (var i=0;i<ShortNotNRIS.length; i++) {
        for (var j=i+1;j<ShortNotNRIS.length; j++) {
            if (ShortNotNRIS[i]==ShortNotNRIS[j]) {ShortNotNRIS.splice(j,1);j--}
        }
    }
    for (var i=0;i<LongNRIS.length; i++) {
        for (var j=i+1;j<LongNRIS.length; j++) {
            if (LongNRIS[i]==LongNRIS[j]) {LongNRIS.splice(j,1);j--}
        }
    }

    // sort by length
    ShortNRIS.sort(function(a,b){if (a[1] < b[1]) return -1; if (a[1] > b[1]) return 1; return 0;})
    ShortNotNRIS.sort(function(a,b){if (a[1] < b[1]) return -1; if (a[1] > b[1]) return 1; return 0;})
    // extract worst
    WorstNRIS=ShortNRIS.slice(0,100)
    WorstNotNRIS=ShortNotNRIS.slice(0,100)
    // now sort by name
    ShortNRIS.sort(function(a,b){if (a[0] < b[0]) return -1; if (a[0] > b[0]) return 1; return 0;})
    ShortNotNRIS.sort(function(a,b){if (a[0] < b[0]) return -1; if (a[0] > b[0]) return 1; return 0;})

    // sort the other arrays by name
    LongNRIS.sort(function(a,b){if (a[0] < b[0]) return -1; if (a[0] > b[0]) return 1; return 0;})
    Dabs.sort(function(a,b){if (a[0] < b[0]) return -1; if (a[0] > b[0]) return 1; return 0;})
    MissingRefnum.sort(function(a,b){if (a[0] < b[0]) return -1; if (a[0] > b[0]) return 1; return 0;})
    // custom sort not needed for these
    ExistingTitles.sort()
    ToBeTagged.sort()
    ToBeUntagged.sort()
    AllNRISOnly.sort()
    OneRefNotNRIS.sort()
    Unreferenced.sort()

    // now find duplicates across county lines
    for (var i=0;i<AllTitles.length; i++) {
        Duplications[Duplications.length]=[AllTitles[i][0],AllTitles[i][1],[AllTitles[i][2]]] // [name,refnum,[list]]
        for (var j=i+1;j<AllTitles.length; j++) {
            if (AllTitles[i][1]==AllTitles[j][1]) {
                Duplications[Duplications.length-1][2].push(AllTitles[j][2])
                AllTitles.splice(j,1)
                j--
            }
        }
        if (Duplications[Duplications.length-1][2].length==1) Duplications.pop() // if no other lists added, not duplicate
    }

    // now dump data to subpages
    var TimeSpan=document.getElementById("TimeSpan")
    var EditSpan=document.getElementByID("EditSpan")
    TimeSpan.innerHTML+="Done!"
    EditSpan.innerHTML="<br>Dumping existing titles to subpages of <a href='http://en.wikipedia.org/wiki/"+OutputBase+"'>"
    EditSpan.innerHTML+=OutputBase+"</a>... 0 edits made."

    var d=new Date();
    var months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
    var year=d.getYear();
    if (year < 1000) year += 1900
    var DateStr = months[d.getMonth()]+" "+d.getDate()+", "+year

    var subpages=0
    var firstletter=ExistingTitles[0].substr(0,1)
    var basewikitext = ""
    var partialwikitext = "=="+firstletter+"==\n{{refbegin|3}}\n"
    for (var k=0; k<ExistingTitles.length; k++) {
        var oldfirstletter = firstletter
        firstletter = ExistingTitles[k].substr(0,1)
        if (firstletter!=oldfirstletter) { // must be starting a new subpage, so edit the previous one
            partialwikitext+='{{refend}}'
            subpages++

            NRISOnlyDump({
                title: OutputBase+'/'+oldfirstletter,
                text: partialwikitext,
                summary:'Generate list of all NRHP articles beginning with '+oldfirstletter+' linked from county lists as of '+DateStr
            },EditSpan,subpages,"no");

            basewikitext+='*[[/'+oldfirstletter+']]\n'
            partialwikitext='=='+firstletter+'==\n{{refbegin|3}}\n# <li value="'+parseFloat(k+1)+'">[['+ExistingTitles[k]+']]\n'
        } else {
            partialwikitext+='# [['+ExistingTitles[k]+']]\n'
        }
    }
    partialwikitext+="{{refend}}"
    subpages++
    NRISOnlyDump({ // manually edit final subpage
        title: OutputBase+'/'+firstletter,
        text: partialwikitext,
        summary:'Generate list of all NRHP articles beginning with '+firstletter+' linked from county lists as of '+DateStr
    },EditSpan,subpages,"no");

    basewikitext+='*[[/'+firstletter+']]\n<hr />*[[/Duplications]]'
    subpages++

    NRISOnlyDump({
        title: OutputBase,
        text: basewikitext,
        summary: 'Generate list of all NRHP articles linked from county lists as of '+DateStr
    },EditSpan,subpages,"no");

    // now dump list of duplicates
    basewikitext = "{{TOC right}}\n<div id=\"duplicates-div\">\n"
    if (Duplications.length>0) {
        var multistate="==Multi-state==\n<div id=\"multistate\">\n{{refbegin|2}}\n"
        var unknown="==Unknown==\n<div id=\"unknown\">\n{{refbegin|2}}\n"
        var oldstate=""
        var state=""
        var prevstate=""
        var multiflag=false
        var unknownflag=false
        var firststateflag=true
        var partialwikitext=""
        for (var k=0; k<Duplications.length; k++) {
            partialwikitext="# [["+Duplications[k][0]+"]]&nbsp;(#"+Duplications[k][1]+") <small>("
            multiflag=false
            unknownflag=false
            for (var l=0; l<Duplications[k][2].length; l++) {
                state=getState(Duplications[k][2][l])
                if (l>0) {
                    if (oldstate==""||state=="") {
                        unknownflag=true
                    } else if (state!=oldstate) {
                        multiflag=true
                    }
                }
                oldstate=state
                partialwikitext+="[["+Duplications[k][2][l]+"|"
                partialwikitext+=Duplications[k][2][l].replace(/National Register of Historic Places listings (i|o)n /g,"")+"]]; "
            }
            partialwikitext=partialwikitext.substr(0,partialwikitext.length-2)
            partialwikitext+=")</small>\n"
            if (unknownflag) {
                unknown+=partialwikitext
            } else if (multiflag) {
                multistate+=partialwikitext
            } else {
                if (state!=prevstate) {
                    if (firststateflag) {
                        basewikitext+="=="+state+"==\n{{refbegin|2}}\n"
                        firststateflag=false
                    } else {
                        basewikitext+="{{refend}}\n\n=="+state+"==\n{{refbegin|2}}\n"
                    }
                }
                var smalltext=partialwikitext.match(/<small>(.)*?<\/small>/g)[0]
                var newsmalltext=smalltext.replace(/,[a-zA-Z .,]*?]]/g,"]]") // remove state names from dupes inside single state
                partialwikitext=partialwikitext.replace(smalltext,newsmalltext)
                basewikitext+=partialwikitext
                prevstate=state
            }
        }
        basewikitext+="{{refend}}\n</div>"
        if (multistate!="==Multi-state==\n<div id=\"multistate\">\n{{refbegin|2}}\n") {
            basewikitext+="\n\n"+multistate+"\n{{refend}}\n</div>"
        }
        if (unknown!="==Unknown==\n<div id=\"unknown\">\n{{refbegin|2}}\n") {
            basewikitext+="\n\n"+unknown+"\n{{refend}}\n</div>"
        }
    }
    NRISOnlyDump({
        title: OutputBase+'/Duplications',
        text: basewikitext,
        summary:'Generate list of all NRHP articles duplicated across county lines as of '+DateStr
    },EditSpan,subpages,"yes");

    // now dump NRIS-only data
    var OutputPage="User:NationalRegisterBot/NRISOnly"
    EditSpan.innerHTML+="<br>Now outputting data to <a href='http://en.wikipedia.org/wiki/"+OutputPage+"'>"+OutputPage+"</a>... "

    basewikitext="{{TOC right}}\n"
    if (ToBeTagged.length>0) {
        basewikitext+="==Articles that need to be tagged==\n<div id=\"tobetagged-div\">\n{{refbegin|3}}\n"
        for (var k=0; k<ToBeTagged.length; k++) {
            basewikitext+='# [['+ToBeTagged[k]+']]\n'
        }
        basewikitext+="{{refend}}</div>\n\n"
    }
    if (ToBeUntagged.length>0) {
        basewikitext+="==Articles that need to be untagged==\n<div id=\"tobeuntagged-div\">\n{{refbegin|3}}\n"
        for (var k=0; k<ToBeUntagged.length; k++) {
            basewikitext+='# [['+ToBeUntagged[k]+']]\n'
        }
        basewikitext+="{{refend}}</div>\n\n"
    }
    if (Dabs.length>0) {
        basewikitext+="==Links to disambiguation pages==\n{{refbegin|3}}\n"
        for (var k=0; k<Dabs.length; k++) {
            basewikitext+='# [['+Dabs[k][0]+']]&nbsp;([['+Dabs[k][1]+'|'
            basewikitext+=Dabs[k][1].replace(/National Register of Historic Places listings (i|o)n /g,"")+']])\n'
        }
        basewikitext+="{{refend}}\n\n"
    }
    if (MissingRefnum.length>0) {
        basewikitext+="==Missing refnum in county list==\n{{refbegin|3}}\n"
        for (var k=0; k<MissingRefnum.length; k++) {
            basewikitext+='# [['+MissingRefnum[k][0]+']]&nbsp;([['+MissingRefnum[k][1]+'|'
            basewikitext+=MissingRefnum[k][1].replace(/National Register of Historic Places listings (i|o)n /g,"")+']])\n'
        }
        basewikitext+="{{refend}}\n\n"
    }
    if (Unreferenced.length>0) {
        basewikitext+="==Articles with no references==\n<div id=\"unreferenced-div\">\n{{refbegin|3}}\n"
        for (var k=0; k<Unreferenced.length; k++) {
            basewikitext+='# [['+Unreferenced[k]+']]\n'
        }
        basewikitext+="{{refend}}</div>\n\n"
    }
    if (OneRefNotNRIS.length>0) {
        basewikitext+="==Articles with only one source that is not NRIS==\n{{refbegin|3}}\n"
        for (var k=0; k<OneRefNotNRIS.length; k++) {
            basewikitext+='# [['+OneRefNotNRIS[k]+']]\n'
        }
        basewikitext+="{{refend}}\n\n"
    }
    NRISOnlyDump({
        title: OutputPage,
        text: basewikitext,
        summary:'Generate list of all NRHP articles to be tagged/untagged with [[Template:NRIS-only]] as of '+DateStr
    },EditSpan,subpages,"");

    // now substubs
    OutputPage="User:NationalRegisterBot/Substubs"
    basewikitext=""
    if (WorstNRIS.length>0) {
        basewikitext+="==Smallest 100 NRIS-only articles by prose size==\n{{refbegin|3}}\n"
        for (var k=0; k<WorstNRIS.length; k++) {
            basewikitext+='# [['+WorstNRIS[k][0]+']] ('+WorstNRIS[k][1]+'&nbsp;bytes)\n'
        }
        basewikitext+="{{refend}}\n\n"
    }
    if (WorstNotNRIS.length>0) {
        basewikitext+="==Smallest 100 articles by prose size NOT tagged NRIS-only==\n{{refbegin|3}}\n"
        for (var k=0; k<WorstNotNRIS.length; k++) {
            basewikitext+='# [['+WorstNotNRIS[k][0]+']] ('+WorstNotNRIS[k][1]+'&nbsp;bytes)\n'
        }
        basewikitext+="{{refend}}\n\n"
    }

    if (ShortNRIS.length>0||ShortNotNRIS.length>0) {
        basewikitext+="==Articles with less than 325 bytes of prose==\n"
        if (ShortNotNRIS.length>0) {
            basewikitext+="===Not tagged NRIS-only===\n{{refbegin|3}}\n"
            for (var k=0; k<ShortNotNRIS.length; k++) {
                basewikitext+='# [['+ShortNotNRIS[k][0]+']] ('+ShortNotNRIS[k][1]+'&nbsp;bytes)\n'
            }
            basewikitext+="{{refend}}\n\n"
            if (ShortNRIS.length>0) basewikitext+="===Tagged NRIS-only===\n"
        }
        if (ShortNRIS.length>0) {
            basewikitext+="{{refbegin|3}}\n"
            for (var k=0; k<ShortNRIS.length; k++) {
                basewikitext+='# [['+ShortNRIS[k][0]+']] ('+ShortNRIS[k][1]+'&nbsp;bytes)\n'
            }
            basewikitext+="{{refend}}\n\n"
        }
    }
    if (LongNRIS.length>0) {
        basewikitext+="==Articles tagged NRIS-only with more than 325 bytes of prose==\n{{refbegin|3}}\n"
        for (var k=0; k<LongNRIS.length; k++) {
            basewikitext+='# [['+LongNRIS[k][0]+']] ('+LongNRIS[k][1]+'&nbsp;bytes)\n'
        }
        basewikitext+="{{refend}}\n\n"
    }
    NRISOnlyDump({
        title: OutputPage,
        text: basewikitext,
        summary:'Generate list of all minimal (<325 bytes) NRHP stubs as of '+DateStr
    },EditSpan,subpages,"");

    // now all NRIS-only
    OutputPage="User:NationalRegisterBot/NRISOnly/All"
    basewikitext = "{{TOC right}}\n<div id=\"NRISOnly-div\">\n"
    if (AllNRISOnly.length>0) {
        var firstletter=AllNRISOnly[0].substr(0,1)
        basewikitext += "=="+firstletter+"==\n{{refbegin|3}}\n"
        for (var k=0; k<AllNRISOnly.length; k++) {
            var oldfirstletter = firstletter
            firstletter = AllNRISOnly[k].substr(0,1)
            if (firstletter!=oldfirstletter) {
                basewikitext+='{{refend}}\n=='+firstletter+'==\n{{refbegin|3}}\n# <li value="'
                basewikitext+=parseFloat(k+1)+'">[['+AllNRISOnly[k]+']]\n'
            } else {
                basewikitext+='# [['+AllNRISOnly[k]+']]\n'
            }
        }
        basewikitext+="{{refend}}</div>"
    }
    editPageNRISOnly({
        title: OutputPage,
        text: basewikitext,
        summary:'Generate list of all NRHP articles sourced only to NRIS as of '+DateStr
    },EditSpan,subpages,"NRIS");
}

// subroutine to determine state from list name
function getState(title) {
    var temp=title.split(", ")
    var state=temp[temp.length-1]
    if (state=="Philadelphia") state="Pennsylvania"
    if (temp[0]==state||state.indexOf(':')!=-1) {
        if (title.indexOf("Chicago")!=-1) state="Illinois"
        else if (title.indexOf("St. Louis")!=-1) state="Missouri"
        else if (title.indexOf("Kansas City")!=-1) state="Missouri"
        else if (title.indexOf("Baltimore")!=-1) state="Maryland"
        else if (title.indexOf("Manhattan")!=-1) state="New York"
        else if (title.indexOf("Philadelphia")!=-1) state="Pennsylvania"
        else if (title.indexOf("Zion")!=-1) state="Utah"
        else state=""
    }
    return state
}

// dump lists to subpages
function NRISOnlyDump(info,Span,subpages,doneEditing) {
    // test with alert first
    alert(info.title+"\n\n"+info.summary+"\n\n"+info.text)

/*
    var api = new mw.Api();

    api.postWithToken( "edit", {
        action: "edit",
        title: info.title,
        summary: info.summary,
        text: info.text,
        bot: 'true'
        },
        {async:false})
    .done( function(data) {
        if (data && data.edit && data.edit.result && data.edit.result=="Success") {
            if (doneEditing=="no") {
                Span.innerHTML=Span.innerHTML.replace(/\d+/g,subpages)
            } else if (doneEditing=="yes") {
                Span.innerHTML="<br>Dumping existing titles to subpages of <a href='http://en.wikipedia.org/wiki/"+OutputBase+"'>"
                Span.innerHTML+=OutputBase+"</a>... Done! "+subpages+" subpages edited successfully!"
            } else if (doneEditing=="NRIS") {
                Span.innerHTML+="Done! Click link to see output!"

                // output technical information to console
                var WarningText="NRHP Progress Warnings: "
                for (var i=0; i<WarningCount.length; i++) {
                    WarningText+=WarningCount[i][0]+" ("+WarningCount[i][1]+"), "
                }
                if (WarningCount[0][0]!="") {
                    WarningText=WarningText.substr(0,WarningText.length-2)
                } else {
                    WarningText="NRHP Progress Warnings: none"
                }
                console.log(WarningText)
            }
        } else {
            Span.innerHTML += " The edit query returned an error! Aborting script."
            alert('Edit query error:\n'+data.error.code+': '+data.error.info+'\nClick OK to view raw wikitext for latest subpage.');
            var popup = open("");
            var div = popup.document.createElement("div");
            div.innerHTML=info.title+"<br><hr><br>"+info.text
            popup.document.body.appendChild(div);
        }
    })
    .fail( function() {
            Span.innerHTML += " The edit query returned an error! Aborting script."
            alert('Ajax failure. Click OK to view raw wikitext for latest subpage.');
            var popup = open("");
            var div = popup.document.createElement("div");
            div.innerHTML=info.title+"<br><hr><br>"+info.text
            popup.document.body.appendChild(div);
    });

*/
}

function getNRISOnlyProgressPageWikitext(title) {    // asynchronous fetch of Progress page wikitext
    $.ajax({
        dataType: "json",
        url: mw.util.wikiScript('api'),
        data: {
            format: 'json',
            action: 'query',
            prop: 'revisions',
            rvprop: 'content',
            titles: title,
            indexpageids: true,
            redirects: 'true'
        },
        error: function() {wikitext="error"},
        success: function(output) {
            for (page in output.query.pages) {
                wikitext=output.query.pages[page].revisions[0]['*'];
            }
        },
        complete: function() {
            if (wikitext=="error") {
                var ProgressDiv=document.getElementById("ProgressDiv")
                ProgressDiv.innerHTML+=" Unable to fetch wikitext! Script aborted."
            } else {
                SetupNRISOnlyTables()
            }
        }
    })
}

function getNRISOnlyListWikitext(currentTable,currentRow) {   // asynchronous fetch of each list's wikitext
    $.ajax({
        dataType: "json",
        url: mw.util.wikiScript('api'),
        data: {
            format: 'json',
            action: 'query',
            prop: 'revisions',
            rvprop: 'content',
            titles: NRISOnlyStructure[currentTable][currentRow].Link,
            indexpageids: true,
            redirects: 'true'
        },
        error: function(ajaxResponse,status,errorThrown) {ajaxResponse.errorThrown=errorThrown},
        complete: function(ajaxResponse,status) {NRISOnlyWikitextFetched(ajaxResponse,status,currentTable,currentRow)}
    })
}

$(window).load(CheckPermission);