MediaWiki:Gadget-HotArticleRate.js

From RationalWiki
Jump to navigation Jump to search

Note: After saving, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Go to Menu → Settings (Opera → Preferences on a Mac) and then to Privacy & security → Clear browsing data → Cached images and files.
//<nowiki>

var ArticleRatings = {
    0 : {'option' : 'Significantly problematic', 'value' : 0, 'template' : '', 'comment' : 'significantly problematic'},
    1 : {'option' : 'No brainstar (default)', 'value' : 1, 'template' : '', 'comment' : 'ordinary' },
    2 : {'option' : 'Bronze', 'value' : 2, 'template' : '{{bronze}}', 'comment' : '[[Category:Bronze-level articles|bronze]]' },
    3 : {'option' : 'Silver', 'value' : 3, 'template' : '{{silver}}', 'comment' : '[[Category:Silver-level articles|silver]]' },
    4 : {'option' : 'Gold',   'value' : 4,   'template' : '{{gold}}',   'comment' : '[[Category:Cover story articles|gold]]' }
}

var ArticleRatingCats = ["", "Bronze-level articles", "Silver-level articles", "Cover story articles"];

var MaxRatings = 4;

var ArticleImportance = {
   0 : {'option' : 'LOW',  'value' : 'LOW',  'comment' : '[[:Category:LOW priority articles|LOW]]' },
   1 : {'option' : 'MID',  'value' : 'MID',  'comment' : '[[:Category:MID priority articles|MID]]' },
   2 : {'option' : 'HIGH', 'value' : 'HIGH', 'comment' : '[[:Category:HIGH priority articles|HIGH]]' }
}

var ArticleImportanceNames = {
   'LOW' : 0,
   'MID' : 1,
   'HIGH' : 2
}

var MaxImportance = 2;

var HAR = new function() {

    this.form = null;

    this.textToSave = '';

    this.parameters = {}

    this.display = "table";

    this.token = "";
    this.basetimestamp = "";
    this.starttimestamp = "";

    this.submitted = false;

    this.modified = false;

    this.scanTemplates = function(text) {
        var i = 0;
        var nestingLevel = 0;
        var openingBrackets = 0;
        var closingBrackets = 0;
        var openingLBrackets = 0;
        var closingLBrackets = 0;
        var openingComment = 0;
        var closingComment = 0;
        var templateName = '';
        var inComment = false;
        var linkNesting = 0;
        var templateStart = 0;
        var paramStart = 0;
        var unnamedParam = 0;
        var paramName = '';
        var parameters = new Array();
        var state = new Array();
        state.push({'ts':templateStart,'tn':templateName,'up':unnamedParam,'pn':paramName,'ps' : paramStart,'p':parameters});
        var templates = new Array();


        while (i < text.length) {
            if (
                 ( text.charAt(i) == '!' && openingComment == 1 ) ||
                 ( text.charAt(i) == '-' && ( openingComment == 2 || openingComment == 3 ) )
            ) {
                openingComment++;
            } else {
                if ( text.charAt(i) == '<' ) {
                    openingComment = 1;
                } else {
                    openingComment = 0;
                }
            }

            if ( inComment ) {
                if (
                     ( text.charAt(i) == '-' && closingComment == 1 ) ||
                     ( text.charAt(i) == '>' && closingComment == 2 )
                ) {
                    closingComment++;
                } else {
                    if ( text.charAt(i) == '-' ) {
                        if ( closingComment != 2 ) {
                            closingComment = 1;
                        }
                    } else {
                        closingComment = 0;
                    }
                }

                if ( closingComment == 3 ) {
                    inComment = false;
                }

                //skip further processing for commented out stuff
                i++;
                continue;

            }

            if ( openingComment == 4 ) {
                inComment = true;
                i++;
                continue;
            }

            //end comment handling

            if (text.charAt(i) == '[') {
                openingLBrackets++;
            } else {
                openingLBrackets = 0;
            }
            if (text.charAt(i) == ']') {
                closingLBrackets++;
            } else {
                closingLBrackets = 0;
            }

            if ( openingLBrackets == 2 ) {
                linkNesting++;
            }

            if ( closingLBrackets == 2 && linkNesting > 0 ) {
                linkNesting--;
            }

            if ( linkNesting > 0 ) {
                i++;
                continue;
            }
            
            //end link handling

            if (text.charAt(i) == '{') {
                openingBrackets++;
            } else {
                openingBrackets = 0;
            }
            if (text.charAt(i) == '}') {
                closingBrackets++;
            } else {
                closingBrackets = 0;
            }


            if ( text.charAt(i) == '=' && templateName != '' ) {
                paramName = text.substring(paramStart+1,i);
            }
            
            if ( text.charAt(i) == '|' || ( closingBrackets == 2 && nestingLevel > 0 ) ) {
                if ( templateName == '' ) {
                    if ( nestingLevel > 0 ) {
                        templateName = text.substring(templateStart+1,( text.charAt(i) == '|' ? i : i-1 ) );
                        templateName = templateName.replace(/^\s*([\S\s]*?)\s*$/, '$1');
                        //alert('template name: ' + templateName);
                        if ( text.charAt(i) == '|' ) {
                            paramStart = i;
                        }
                    }
                } else {
                    var paramstring = text.substring(paramStart+1,( text.charAt(i) == '|' ? i : i-1 ) );
                    //alert('paramstring: ' + paramstring);

                    if ( paramName.replace(/^\s*([\S\s]*?)\s*$/, '$1') != '' ) {                        
                        var paramValue = paramstring.substring(paramName.length+1);
                        paramName = paramName.replace(/^\s*([\S\s]*?)\s*$/, '$1');
                        paramValue = paramValue.replace(/^\s*([\S\s]*?)\s*$/, '$1');
                        parameters[paramName] = paramValue;
                        paramName = '';
                    } else {
                        unnamedParam++;
                        //the mediawiki parser does not trim unnamed parameters, we want to keep that behaviour
                        parameters[unnamedParam] = paramstring; //.replace(/^\s*([\S\s]*?)\s*$/, '$1');
                    }

                    if ( text.charAt(i) == '|' ) {
                        paramStart = i;
                    }
                }

            }
            
            if ( openingBrackets == 2 ) {
                nestingLevel++;
                state.push({'ts':templateStart,'tn':templateName,'up':unnamedParam,'pn':paramName,'ps' : paramStart,'p':parameters});
                templateStart = i;
                templateName = '';
                unnamedParam = 0;
                openingBrackets = 0;
                paramName = '';
                paramStart = i;
                parameters = new Array();
            }
            if ( closingBrackets == 2 && nestingLevel > 0 ) {
                nestingLevel--;
                templates.push({'name':templateName,'params':parameters,'start':templateStart-1,'end':i});
                s = state.pop();
                templateStart = s['ts'];
                templateName = s['tn'];
                unnamedParam = s['up'];
                paramName = s['pn'];
                paramStart = s['ps'];
                parameters = s['p']
                closingBrackets = 0;
            }

            i++;
        }

        return templates;
    };

    this.lcfirst = function(s) {
        return s.charAt(0).toLowerCase() + s.substr(1);
    };

    this.searchForRated = function(text) {
        var templates = this.scanTemplates(text);
        for ( var i=0; i<templates.length; ++i ) {
            //change this to accommodate redirects if necessary
            if ( this.lcfirst(templates[i]['name']) == 'rated' ) {
                this.modified = true;
                //cut out any and all occurrences of rated
                text = ( templates[i]['start'] > 0 ? text.substring(0,templates[i]['start']-1) : "" ) + text.substring(templates[i]['end']+1);
                //adjust start and end of other templates
                for ( var j=0; j<templates.length; ++j ) {
                    if ( templates[j]['start'] > templates[i]['end'] ) {
                        templates[j]['start'] -= (templates[i]['end'] - templates[i]['start']) + 1;
                    }
                    if ( templates[j]['end'] > templates[i]['end'] ) {
                        templates[j]['end'] -= (templates[i]['end'] - templates[i]['start']) + 1;
                    }
                }
                //extract parameters
                this.parameters[1] = templates[i]['params'][1];
                this.parameters[2] = templates[i]['params'][2];
                this.parameters[3] = templates[i]['params'][3];
                this.parameters[4] = templates[i]['params'][4];
                this.parameters[5] = templates[i]['params'][5];
            }
        }
        this.textToSave = text;
    };

    this.preloadValues = function() {
        if ( this.parameters[1] != undefined ) {
            ratingInput = document.getElementById('ratingInput');
            if ( ratingInput ) {
                for(var i = 0; i < ratingInput.length; i++) {
                    if ( ratingInput.options[i].value == this.parameters[1] ) {
                        if ( this.submitted && ratingInput.selectedIndex != i ) {
                            element = document.getElementById('ratingInput');
                            if ( element ) {
                                element.parentNode.appendChild(document.createTextNode("Edit conflict: " + ArticleRatings[this.parameters[1]]['option']));
                            }
                        } else {
                            ratingInput.selectedIndex = i;
                        }
                    }
                }
            }
        }

        if ( this.parameters[2] != undefined ) {
            var categoryPreloaded = false;
            catInput = document.getElementById('catInput');
            if ( catInput ) {
                for(var i = 0; i < catInput.length; i++) {
                    if ( catInput.options[i].value == this.parameters[2] ) {
                        categoryPreloaded = true;
                        if ( this.submitted && catInput.selectedIndex != i ) {
                            catInput.parentNode.appendChild(document.createTextNode("Edit conflict: " + this.parameters[2]));
                        } else {
                            catInput.selectedIndex = i;
                        }
                    }
                }
            }
            if ( !categoryPreloaded ) {
                catInputText = document.getElementById('catInputText');
                if ( catInputText ) {
                    if ( this.submitted ) { 
                        if ( catInputText.value != this.parameters[2] ) {
                            catInputText.parentNode.appendChild(document.createTextNode("Edit conflict: " + this.parameters[2]));
                        }
                    } else {
                        catInputText.value = this.parameters[2];
                    }
                }
            }
        }

        if ( this.parameters[3] != undefined ) {
            iconInput = document.getElementById('iconInput');
            if ( iconInput ) {
                if ( this.submitted ) {
                    if ( iconInput.value != this.parameters[3] ) {
                        iconInput.parentNode.appendChild(document.createTextNode("Edit conflict: " + this.parameters[3]));
                    }
                } else {
                    iconInput.value = this.parameters[3];
                }
            }
        }
        if ( this.parameters[4] != undefined ) {
            importanceInput = document.getElementById('importanceInput');
            if ( importanceInput ) {
                for(var i = 0; i < importanceInput.length; i++) {
                    if ( importanceInput.options[i].value == this.parameters[4] ) {
                        if ( this.submitted && importanceInput.selectedIndex != i ) {
                            element = document.getElementById('importanceInput');
                            if ( element ) {
                                element.parentNode.appendChild(document.createTextNode("Edit conflict: " + this.parameters[4] ));
                            }
                        } else {
                            importanceInput.selectedIndex = i;
                        }
                    }
                }
            }
        }
        if ( this.parameters[5] != undefined ) {
            commentsInput = document.getElementById('commentsInput');
            if ( commentsInput ) {
                if ( this.submitted ) {
                    if ( commentsInput.value != this.parameters[5] ) {
                        commentsInput.value += this.parameters[5];
                    }
                } else {
                    commentsInput.value = this.parameters[5];
                }
            }
        }

        ratebutton = document.getElementById('rate_button');
        if ( ratebutton ) ratebutton.disabled = false;

    };

    this.getTalkProp = function() {

        var req = sajax_init_object();
        req.open("GET", wgServer + wgScriptPath + "/api.php?format=json&action=query&prop=revisions|info&rvprop=timestamp&intoken=edit&indexpageids&titles=" 
                  + wgFormattedNamespaces["1"] +  ":" + wgTitle  , true);
        _self = this;
        req.onreadystatechange = function() {
            if (req.readyState == 4 && req.status == 200) {
                var response = eval('(' + req.responseText + ')');
                _self.edittoken = response['query']['pages'][response['query']['pageids'][0]]['edittoken'];
                _self.starttimestamp = response['query']['pages'][response['query']['pageids'][0]]['starttimestamp'];
                if ( response['query']['pageids'][0] == "-1" ) {
                    _self.basetimestamp = _self.starttimestamp;
                } else {
                    _self.basetimestamp = response['query']['pages'][response['query']['pageids'][0]]['revisions']['0']['timestamp'];
                    _self.scanTalkPage(response['query']['pages'][response['query']['pageids'][0]]['lastrevid']);
                }
            }
        }
        req.send(null);
    };

    this.scanTalkPage = function(currid) {
        var req = sajax_init_object();
        var _self = this;
        req.onreadystatechange = function() {
            if (req.readyState == 4) { 
                if ( req.status == 200) {
                    _self.searchForRated(req.responseText);
                }
                _self.preloadValues();
            }
        };
        //we don't know if we're on the article or its talk page, but wgTitle return the page name without the namespace, so it doesn't matter
        req.open("GET", wgServer + wgScript + "?title=" + wgFormattedNamespaces["1"] +  ":" + wgTitle + "&action=raw&oldid=" + currid, true);
        req.send(null);
    };

    this.updateArticle = function(rating) {
        var req = sajax_init_object();
        req.open("GET", wgServer + wgScriptPath + "/api.php?format=json&action=query&prop=revisions|info&rvprop=timestamp&intoken=edit&indexpageids&titles=" 
                  + wgTitle  , true);
        _self = this;

        var articletoken;
        var articlestarttime;
        var articleedittime;

        req.onreadystatechange = function() {
            if (req.readyState == 4 && req.status == 200) {
                var response = eval('(' + req.responseText + ')');
                articletoken = response['query']['pages'][response['query']['pageids'][0]]['edittoken'];
                articlestarttime = response['query']['pages'][response['query']['pageids'][0]]['starttimestamp'];
                if ( response['query']['pageids'][0] != "-1" ) {
                    articleedittime = response['query']['pages'][response['query']['pageids'][0]]['revisions']['0']['timestamp'];
                    var currid = response['query']['pages'][response['query']['pageids'][0]]['lastrevid'];

                    var req2 = sajax_init_object();

                    req2.onreadystatechange = function() {
                        if (req2.readyState == 4) { 
                            if ( req2.status == 200) {
                                var articletext = ArticleRatings[rating]['template'] + req2.responseText.replace(/{{(copper|bronze|silver|gold)}}/g,"");
                                var comment = "Added brainstar";

                                var params = "action=edit&format=json&title=" + encodeURIComponent(wgTitle) +
                                             ((wgUserGroups.indexOf("bot") == -1) ? "" : "&bot=1" ) +
                                             "&text=" + encodeURIComponent(articletext) +
                                             "&summary=" + encodeURIComponent(comment) +
                                             "&token=" + encodeURIComponent(articletoken) +
                                             "&starttimestamp=" + encodeURIComponent(articlestarttime) +
                                             "&basetimestamp=" + encodeURIComponent(articleedittime);


                                var req3 = sajax_init_object();

                                req3.onreadystatechange = function() {
                                    if (req3.readyState == 4) { 
                                        if ( req3.status == 200) {
                                            var response = eval('(' + req3.responseText + ')');
                                            if ( response['edit'] != undefined && response['edit']['result'] != undefined && response['edit']['result'] == "Success" ) {
                                                window.location.reload();
                                            } else if ( response['error'] != undefined && response['error']['code'] != undefined && response['error']['code'] == "editconflict") {
                                                alert('Edit conflict detected, please reload and try again.');
                                            } else if ( response['error'] != undefined && response['error']['code'] != undefined && response['error']['info'] != undefined) {
                                                alert('Error editing talk page: ' + response['error']['info'] );
                                            } else {
                                                alert('Error editing talk page: ' + req3.responseText );
                                            }
                                        }
                                    }
                                };
                                req3.open("POST",wgServer+wgScriptPath+"/api.php",true);
                                req3.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
                                req3.setRequestHeader('Connection', 'keep-alive');
                                req3.setRequestHeader('Content-length', params.length);
                                req3.send(params);

                            }
                        }
                    };

                    req2.open("GET", wgServer + wgScript + "?title=" + wgTitle + "&action=raw&oldid=" + currid, true);
                    req2.send(null);
                }
            }
        }
        req.send(null);

    };

    this.rate = function() {
        ratebutton = document.getElementById('rate_button');
        ratebutton.disabled = true;

        var rating = document.getElementById("ratingInput").value;
        var cat = "";
        if (document.getElementById("catInputText").value != "") {
            cat = document.getElementById("catInputText").value;
        } else {
            if ( document.getElementById("catInput") ) {
                cat = document.getElementById("catInput").value;
            }
        }
        var icon = document.getElementById("iconInput").value;
        var imp = document.getElementById("importanceInput").value;
        var comments = document.getElementById("commentsInput").value;

        var pr = "{{rated|1=" + rating + "|2=" + cat;
	if (icon != "") pr += "|3=" + icon;
	pr += "|4=" + imp;
	if (comments != "") pr += "|5=\n" + comments + "\n";
	pr += "}}\n\n";

        var comment = (this.modified ? "Changed" : "Added") + " article rating " + (this.modified ? "to " : "") + ArticleRatings[rating]['comment'] + 
                      ", " + ArticleImportance[ArticleImportanceNames[imp]]['comment'] + 
                      ( cat != "" ? ", in category " +  cat : ", uncategorized" ) +
                      " using [[Special:Gadgets|HotArticleRate]]";

        var params = "action=edit&format=json&title=" + encodeURIComponent(wgFormattedNamespaces["1"] +  ":" + wgTitle) +
                 ((wgUserGroups.indexOf("bot") == -1) ? "" : "&bot=1" ) +
                 "&text=" + encodeURIComponent(pr + this.textToSave.replace(/^\s+/, '')) +
                 "&summary=" + encodeURIComponent(comment) +
                 "&token=" + encodeURIComponent(this.edittoken) +
                 "&starttimestamp=" + encodeURIComponent(this.starttimestamp) +
                 "&basetimestamp=" + encodeURIComponent(this.basetimestamp);


        var req = sajax_init_object();
        var _self = this;
        req.onreadystatechange = function() {
            if (req.readyState == 4) { 
                if ( req.status == 200) {
                    var response = eval('(' + req.responseText + ')');
                    if ( response['edit'] != undefined && response['edit']['result'] != undefined && response['edit']['result'] == "Success" ) {
                        _self.updateArticle(rating);
                    } else if ( response['error'] != undefined && response['error']['code'] != undefined && response['error']['code'] == "editconflict") {
                        //alert('Edit conflict detected, please reload and try again.');
                        _self.getTalkProp();
                    } else if ( response['error'] != undefined && response['error']['code'] != undefined && response['error']['info'] != undefined) {
                        alert('Error editing talk page: ' + response['error']['info'] );
                        ratebutton = document.getElementById('rate_button');
                        if ( ratebutton ) ratebutton.disabled = false;
                    } else {
                        alert('Error editing talk page: ' + req.responseText );
                        ratebutton = document.getElementById('rate_button');
                        if ( ratebutton ) ratebutton.disabled = false;
                    }
                }
            }
        };
        req.open("POST",wgServer+wgScriptPath+"/api.php",true);
        req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        req.setRequestHeader('Connection', 'keep-alive');
        req.setRequestHeader('Content-length', params.length);
        this.submitted = true;
        req.send(params);
    };

    this.buildForm = function() {
        this.form = document.createElement("form");
        this.form.id = "ratingForm";
        var fieldset = document.createElement("fieldset")
        this.form.appendChild(fieldset);

        var _self = this;
        this.form.onsubmit = function() { _self.rate(); return false; };

        var element;
        var option;

        element = document.createElement("legend");
        element.appendChild(document.createTextNode("Rate this article"));
        fieldset.appendChild(element);

        var table = document.createElement("table");
        fieldset.appendChild(table);
        var tbody = document.createElement("tbody");
        table.appendChild(tbody);

        var trow;
        var tcell;

        trow = document.createElement("tr");
        tcell = document.createElement("td");
        tcell.className = "mw-label";

        element = document.createElement("label");
        element.htmlFor = "ratingInput";
        element.appendChild(document.createTextNode("Rating:"));
        tcell.appendChild(element);
        trow.appendChild(tcell);

        tcell = document.createElement("td");
        tcell.className = "mw-input";

        var ratings_element = document.createElement("select");
        ratings_element.id = "ratingInput";

        for (var i=0; i<=MaxRatings; ++i) {
            option = document.createElement("option");
            option.value = ArticleRatings[i]['value'];
            option.appendChild(document.createTextNode(ArticleRatings[i]['option']));
            ratings_element.appendChild(option);
        }
        ratings_element.selectedIndex = 1;
        tcell.appendChild(ratings_element);

        trow.appendChild(tcell);
        tbody.appendChild(trow);

        trow = document.createElement("tr");
        tcell = document.createElement("td");
        tcell.className = "mw-label";

        element = document.createElement("label");
        element.appendChild(document.createTextNode("Category:"));

        //TODO: load categories via api if we're on the talk page.
        var categories = wgCategories;
        categories = categories.filter(function(i) {return !(ArticleRatingCats.indexOf(i) > -1);});

        if ( categories.length > 0 && wgNamespaceNumber == 0 ) {

            element.htmlFor = "catInput";
            tcell.appendChild(element);
            trow.appendChild(tcell);

            tcell = document.createElement("td");
            tcell.className = "mw-input";

            element = document.createElement("select");
            element.id = "catInput";

            var problemCats = new Array();
            var d = new Date();
            var month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
            var monthName= month[d.getMonth()] + " ";
            for (var c in categories) {
                if (categories[c] == "Articles needing RWification") { problemCats.push("{{Rated/problem|RWify|" + monthName + d.getFullYear() + "}}"); continue; }
                if (categories[c] == "Articles needing explanation") { problemCats.push("{{Rated/problem|Explain|" + monthName + d.getFullYear() + "}}"); continue; }
                if (categories[c] == "Articles needing updates") { problemCats.push("{{Rated/problem|Update|" + monthName + d.getFullYear() + "}}"); continue; }
                if (categories[c] == "Articles requiring deconservapediafication") { problemCats.push("{{Rated/problem|DeCP|" + monthName + d.getFullYear() + "}}"); continue; }
                if (categories[c] == "Articles that might not further the RW mission") { problemCats.push("{{Rated/problem|Mission|" + monthName + d.getFullYear() + "}}"); continue; }
                if (categories[c] == "Articles with unsourced statements") { problemCats.push("{{Rated/problem|Unsourced|" + monthName + d.getFullYear() + "}}"); continue; }
                if (categories[c] == "Needs Goat") { problemCats.push("{{Rated/problem|Goat|" + monthName + d.getFullYear() + "}}"); continue; }
                if (categories[c] == "Pages with broken external links") { problemCats.push("{{Rated/problem|External links|" + monthName + d.getFullYear() + "}}"); continue; }
                option = document.createElement("option");
                option.value = categories[c];
                option.appendChild(document.createTextNode(categories[c]));
                element.appendChild(option);
            }
            
            tcell.appendChild(element);
            trow.appendChild(tcell);
            tbody.appendChild(trow);

            trow = document.createElement("tr");
            tcell = document.createElement("td");
            tcell.className = "mw-label";

            element = document.createElement("label");
            element.appendChild(document.createTextNode("Other category:"));

        }

        element.htmlFor = "catInputText";
        tcell.appendChild(element);
        trow.appendChild(tcell);

        tcell = document.createElement("td");
        tcell.className = "mw-input";

        element = document.createElement("input");
        element.id = "catInputText";
        element.size = "45";
        tcell.appendChild(element);
        trow.appendChild(tcell);
        tbody.appendChild(trow);

        if ( categories.length > 0 && wgNamespaceNumber == 0 ) {
            trow = document.createElement("tr");
            tcell = document.createElement("td");
            trow.appendChild(tcell);
            tcell = document.createElement("td");
            tcell.className = "htmlform-tip";
            tcell.appendChild(document.createTextNode("Other category will override the category selected in the dropdown box."))
            trow.appendChild(tcell);
            tbody.appendChild(trow);
        }

        trow = document.createElement("tr");
        tcell = document.createElement("td");
        tcell.className = "mw-label";

        element = document.createElement("label");
        element.appendChild(document.createTextNode("Icon (optional):"));
        element.htmlFor = "iconInput";
        tcell.appendChild(element);
        trow.appendChild(tcell);

        tcell = document.createElement("td");
        tcell.className = "mw-input";

        element = document.createElement("input");
        element.id = "iconInput";
        element.size = "45";
        tcell.appendChild(element);
        trow.appendChild(tcell);
        tbody.appendChild(trow);

        trow = document.createElement("tr");
        tcell = document.createElement("td");
        trow.appendChild(tcell);
        tcell = document.createElement("td");
        tcell.className = "htmlform-tip";
        tcell.innerHTML = 'The icon defaults to "Icon <i>category</i>.svg". If "Icon <i>category</i>.svg" doesn\'t exist, consider making a redirect to an appropriate icon in <a' + '  href="/wiki/Category:Portal_icons" title="">Category:Portal icons</a> instead of specifying an icon explicitly.';
        trow.appendChild(tcell);
        tbody.appendChild(trow);

        trow = document.createElement("tr");
        tcell = document.createElement("td");
        tcell.className = "mw-label";

        element = document.createElement("label");
        element.htmlFor = "importanceInput";
        element.appendChild(document.createTextNode("Importance:"));
        tcell.appendChild(element);
        trow.appendChild(tcell);

        tcell = document.createElement("td");
        tcell.className = "mw-input";

        element = document.createElement("select");
        element.id = "importanceInput";

        for (var i=0; i<=MaxImportance; ++i) {
            option = document.createElement("option");
            option.value = ArticleImportance[i]['value'];
            option.appendChild(document.createTextNode(ArticleImportance[i]['option']));
            element.appendChild(option);
        }
        tcell.appendChild(element);

        trow.appendChild(tcell);
        tbody.appendChild(trow);

        trow = document.createElement("tr");
        tcell = document.createElement("td");
        tcell.className = "mw-label";

        element = document.createElement("label");
        element.htmlFor = "commentsInput";
        element.appendChild(document.createTextNode("Comments (optional):"));
        tcell.appendChild(element);
        trow.appendChild(tcell);

        tcell = document.createElement("td");
        tcell.className = "mw-input";

        var comments_element = document.createElement("textarea");
        comments_element.id = "commentsInput";
        comments_element.rows = "10";
        comments_element.placeholder = "Some editorial comments on what would improve the article.";
        tcell.appendChild(comments_element);
        trow.appendChild(tcell);
        tbody.appendChild(trow);

        trow = document.createElement("tr");
        tcell = document.createElement("td");
        tcell.style.paddingTop = "1em";
        trow.appendChild(tcell);
        tcell = document.createElement("td");
        tcell.className = "mw-submit";
        tcell.style.paddingTop = "1em";
        element = document.createElement("button");
        element.id = "rate_button";
        element.appendChild(document.createTextNode("Rate"));
        tcell.appendChild(element);
        trow.appendChild(tcell);
        tbody.appendChild(trow);

        if (problemCats.length > 0) { 
                ratings_element.selectedIndex = 0;
                var editorialText = ""; 
                for (var comment in problemCats) { 
                    if (editorialText == "") { editorialText = editorialText.concat("* " + problemCats[comment]); continue; }
                    editorialText = editorialText.concat("\n* " + problemCats[comment]);
                }
                comments_element.value = editorialText;
        }

    };

    this.toggleForm = function() {
        tempform = document.getElementById("ratingForm");
        if ( tempform ) {
            //remove the form from the page and store it in this.form
            this.form = tempform.parentNode.removeChild(tempform);
            document.getElementById("ca-rate").className = '';
            ratingbox = document.getElementById("ratingbox");
            if ( ratingbox ) {
                ratingbox.style.display = this.display;
            }
            return;
        }
        content = document.getElementById("content");
        bodyContent = document.getElementById("bodyContent");
        //bail out if we can't insert the form
        if ( !content || !bodyContent ) return;
        
        ratingbox = document.getElementById("ratingbox");
        if ( ratingbox ) {
            this.display = ratingbox.style.display;
            ratingbox.style.display = "none";
        }

        //check if we already have the form
        var firstTime = false;
        if ( !this.form ) {
            //we need to construct the form
            firstTime = true;
            this.buildForm();
        }
        content.insertBefore(this.form, bodyContent);
        document.getElementById("ca-rate").className = 'selected';
        if ( firstTime ) {
            this.getTalkProp();
        }
    };

    this.setup = function() {
        if ( wgNamespaceNumber != 0 && wgNamespaceNumber != 1) return;
        //exit if we're on the main page or its talk page
        if ( wgTitle == wgMainPageTitle ) return;
        edittab = document.getElementById("ca-edit");
        //if we can't edit the page, we won't be able to rate it.
        if ( !edittab ) return;

        var ratebutton = document.createElement("a");
        ratebutton.title = "Rate this article";
        var ratespan = document.createElement("span");
        ratebutton.appendChild(document.createTextNode("Rate"));
        ratespan.appendChild(ratebutton);
        var _self = this;
        ratebutton.onclick = function() { _self.toggleForm(); };
        var holdingtab = document.createElement("li");
        holdingtab.id = "ca-rate";
        holdingtab.appendChild(ratespan);
        if ( edittab.nextSibling ) {
            edittab.parentNode.insertBefore(holdingtab,edittab.nextSibling);
        } else {
            edittab.parentNode.appendChild(holdingtab);
        }
    };
}

function setupHAR() {
    HAR.setup();
}

addOnloadHook(setupHAR);

 
//</nowiki>