User:Quarl/afd vote.js

// User:Quarl/afd_vote.js - AFD auto-voting and shortcuts

// depends: wikipage.js, wikipageAfd.js, wikiedit.js, util.js, shortcuts.js, datestamp.js // enhanced by: advanced_sig.js

// originally based on http://en.wikipedia.org/wiki/User:Jnothman/afd_helper/script.js // User:Jnothman/afd_helper/script.js

// - asynchronous updating (never opens new windows) // - live updating of log page // - huge list of shortcut expansions and other shortcut features // - more "vote" buttons such as in original article // - escaping bugs ('&&', '+', etc) fixed // - refuse to create AFD pages (in case of more escaping bugs)

//

if(typeof window.makeSignature=='undefined')makeSignature=function{return "~"};

afd_vote = new Object;

afd_vote.summary_prompt = true;

afd_vote.shortcuts = Shortcuts({           'D'         : 'Delete',            'DA'        : 'Delete all',            'K'         : 'Keep',            'M'         : 'Merge',            'MV'        : 'Move',            'R,RD'      : 'Redirect',            'RW'        : 'Rewrite',            'T'         : 'Transwiki',            'WD'        : 'Weak delete',            'SD'        : 'Strong delete',            'SP'        : 'Speedy delete',            'SK'        : 'Strong keep',            'SM'        : 'Slight merge',            'WK'        : 'Weak keep',            //'SPK'     : 'Speedy keep',            'SPK'       : 'Speedy keep',            'C'         : 'Comment',            'MC'        : 'Metacomment',            'BJAODN,BJ' : 'BJAODN'            });

afd_vote.comment_shortcuts = Shortcuts( {           'PN'                          : 'per nomination',            'NN'                          : 'non-notable',            'V,VAIN,VANITY'               : 'vanity',            'NNBIO'                       : 'non-notable biography',            'NNVBIO'                      : 'non-notable vanity biography',            'NNWEB'                       : 'non-notable website',            'NNWEBCOMIC '                 : 'non-notable webcomic',            'NNBLOG,NNWEBLOG'             : 'non-notable weblog ',            'NNFORUM,NNWEBFORUM'          : 'non-notable web forum ',            'NNSOFTWARE,NNSOFT,NNSW'      : 'non-notable software ',            'NNCORP,NNCOMPANY'            : 'non-notable corporation',            'NNMUSIC'                     : 'non-notable musical group', 'NNBAND'                     : 'non-notable band', 'NNUNEO'                     : 'non-notable unstable neologism, i.e. protologism', 'NNUUNEO'                    : 'non-notable unverifiable unstable neologism, i.e. protologism', 'NNFICT,NNFICTION'           : 'non-notable reference to fictional work', 'NNFICTC,NNFICTCHAR,NNCHAR'  : 'non-notable character from fictional work ', 'FANCRUFT,NNFAN'             : 'fancruft', 'NNFANFIC'                   : 'non-notable fan fiction', 'NNGAME'                     : 'non-notable online gaming group', 'U'                          : 'unverifiable', 'UPH'                        : 'unverifiable, possible hoax', 'OR'                         : 'original research', 'UOR'                        : 'unverifiable and/or original research', 'H'                          : 'hoax', 'HSANC,HSANCT,HSANCTION'     : 'hoax, and sanction article author', 'ATTACK'                     : 'attack page', 'WISHSP,WISHEXPAND'          : 'I wish for expansion of WP:CSD so that this kind of article could be speedy-deleted when no notability is asserted ', 'UNENC,UNENCYCLO,NOTPEDIC'   : 'unencyclopedic', 'NOT'                        : 'Wikipedia is not', 'NOTADVERT'                  : 'Wikipedia is not a vehicle for advertising ', 'NOTBALL,NOTCRYSTAL'         : 'Wikipedia is not a crystal ball ', 'NOTCRUFT'                   : 'Wikipedia is not an indiscriminate collection of information ', 'NOTDICT,NOTDIC'             : 'Wikipedia is not a dictionary (but Wiktionary is) ', 'NOTMEMORIAL'                : 'Wikipedia is not a memorial ', 'NOTOR,NOTORIGINAL'          : 'Wikipedia is not a publisher of original thought ', 'NOTSOAPBOX'                 : 'Wikipedia is not a soapbox ', 'NOTSW,NOTSWDIR'             : 'Wikipedia is not a software directory ', 'NOTWEBHOST,NOTFREEHOST'     : 'Wikipedia is not a free host or webspace provider ', 'NOTWEBDIR'                  : 'Wikipedia is not a web directory ', 'NFT,NOTSCHDAY,NOTSCH'       : 'Wikipedia is not for things made up in school one day ', 'XBIO,BIOX'                  : 'Recommend the article author see WikiMe for writing biographies and/or WikiTree for writing genealogies ', 'XUSERFY,USERFYX'            : 'Article author may want to consider moving the content to his user page ', 'XPROTO,XPROTOLOGISM,PROTOX' : 'Protologisms may deserve listing at List_of_protologisms ', 'BALLS,BALL'                 : 'Complete bollocks' });

afd_vote._load = function { if (afdLogP) { // log page afd_vote.annotateAfd; } else if (afdP) { // AFD page afd_vote.annotateAfd; addTab('javascript:afd_vote.doVote', 'vote', 'ca-vote', "Vote on this AFD"); } else { afd_vote.annotateArticle; } }

afd_vote.annotateArticle = function { // is this a regular article that has an AFD notice? var afd = document.getElementById('afd'); if (!afd) return;

var href = 'javascript:afd_vote.doVote'; var title = 'Vote on deletion of '+wikiPage.page;

var anchors = copyArray(afd.getElementsByTagName('a')); for (i in anchors) { if (anchors[i].text == "this article's entry" &&           anchors[i].href.match(/Wikipedia:Articles_for_deletion\/.*/)) {           var span = document.createElement('span'); span.innerHTML = ' [vote]'; add_after(anchors[i], span); break; }   }

addTab(href, 'vote', 'ca-vote', title); }

afd_vote.annotateAfd = function { var url_re = /(\/w\/index.php\?title=Wikipedia:Articles_for_deletion\/([^&]+))&action=edit&/; var url, matches; afd_vote.sectionDivs = getElementsByClass('editsection', document.getElementById('bodyContent'), 'div'); afd_vote.labeledSectionDivs = {};

for (var i in afd_vote.sectionDivs) { var div = afd_vote.sectionDivs[i]; div.i = i;       var anchor = div.getElementsByTagName('a')[0]; if (!( anchor.text == "edit" && (matches = anchor.href.match(url_re)) && (matches[2].substr(0, 4) != 'Log/')) ) continue; var title = ""+unescape(matches[2]).replace(/_/g,' ');

// setup for easy lookup and traversal later afd_vote.labeledSectionDivs[title] = div;

var closed = Boolean(anchor.parentNode.parentNode.getAttribute('class')=='boilerplate metadata vfd');

if (!closed) { var vote_href = "javascript:afd_vote.doVote("+string_quote_escape(title)+")"; add_after(anchor, createHref(vote_href, 'Vote on deletion of '+title, 'vote')); add_after(anchor, document.createTextNode("] [")); }       var log_href = "/w/index.php?title=Special:Log&page=" + wpaescape(title); add_before(anchor, createHref(log_href, title, 'log')); add_before(anchor, document.createTextNode("] [")); var afd_href = matches[1]; add_before(anchor, createHref(afd_href, title, 'afd')); add_before(anchor, document.createTextNode("] [")); } }

// return true if string ends with period (can also have symbols such as closing paren after period) afd_vote._ends_with_period = function(str) { return Boolean(str.match(/[.?!][^a-zA-Z]*$/)); }

// return true if comment needs to be prefixed by 'as ' afd_vote._comment_needs_as = function(comment) { var m = comment.match(/^([a-zA-Z]+)(.*)$/); var word1 = m && m[1]; if (!word1) return false; if (word1 == 'or') return false; // special case for lowercase 'or' if (word1.toUpperCase == 'PN') return false; // special case for 'PN' return afd_vote.comment_shortcuts.substP(word1); }

afd_vote.expand_vote = function(vote) { vote = afd_vote.shortcuts.substFirstWord(vote); vote = afd_vote.shortcuts.substUppercaseWords(vote); return vote; }

afd_vote.expand_comment = function(vote, comment) { // if first word is a shortcut other than 'per nomination', prefix with 'as'

var need_as = afd_vote._comment_needs_as(comment);

comment = afd_vote.comment_shortcuts.substUppercaseWords(comment); if (!comment.match(/^or /)) { // "or" is too common as first word... use uppercase "OR" if that's intended. comment = afd_vote.comment_shortcuts.substFirstWord(comment); }

if (need_as) { comment = 'as ' + comment; }

if (!afd_vote._ends_with_period(comment)) { comment += "."; }

// prefix with space if necessary if (!comment.match(/^[.,:; ]/)) { comment = " " + comment; if (vote == 'Comment') comment = ":" + comment; }

// common mistake comment = comment.replace(//, '$1');

return comment; }

afd_vote._comment_possibly_unexpanded = function(comment) { // did user typo one of the shortcuts? return comment.match(/[A-Z][A-Z][A-Z]+(?![\]A-Z\|])/); }

afd_vote.doVote = function(pagename) { if (pagename) { afd_vote.doVoteWP(new WikiPage(null,pagename)); } else { afd_vote.doVoteWP(wikiPage); } }

afd_vote.doVoteWP = function(wp) { wp = wp.afdPageX; if (!(wp instanceof WikiPage)) { alert("## internal error bfc4b745-0e83-4e9a-9a16-7107c8e046ef: afd_vote: not a WikiPage"); return; } var vote0 = window.prompt("Enter your vote.  " + afd_vote.shortcuts.msg); if (!vote0) return; var vote = afd_vote.expand_vote(vote0); var vote_used_shortcut = (vote != vote0);

var comment0prev; var comment0 = ''; var comment; var pr = "Enter your comment. ";

while(true) { comment0 = window.prompt(pr + afd_vote.comment_shortcuts.msg, comment0); if (typeof comment0 != 'string') return; comment = afd_vote.expand_comment(vote, comment0);

if (comment0 != comment0prev &&           afd_vote._comment_possibly_unexpanded(comment)) {           comment0prev = comment0; pr = "Did you really mean '"+RegExp.lastMatch+"'? Correct if you want.  "; continue; }       break; }

var default_summary = "vote '"+vote+"'"; var summary;

if (afd_vote.summary_prompt && !vote_used_shortcut) { summary = window.prompt("Enter the edit summary:", default_summary); if (typeof summary != 'string') return; }   summary = summary || default_summary;

var newtext = "* "+vote+""+comment+" " + makeSignature; wp.getEditorAsync(afd_vote._edit, newtext, summary); }

afd_vote._edit = function(editor, newtext, summary) { if (editor.refuseCreate) return;

editor.wpTextbox1 = trim_lines(editor.wpTextbox1) + '\n' + newtext; editor.wpSummary += summary;

// are we at a log page? (Note that 'window.location.href' is not as good as wikiPage because of shortcut redirects such as WP:AFD/Today)

var title = editor.wp.afdTargetPage.page; if (!title) { alert("## afd_vote._edit: bad page name (error b2e39d30-fd3d-405e-adf1-5f0c7c034e53)"); }

var div, sec_end; if (afdP || afdLogP) { // show status if we're on an AFD or AFD Log page if (afdLogP) { div = afd_vote.labeledSectionDivs[title]; if (!div) { alert("## No labeledSectionDivs['"+title+"']"); return; } sec_end = afd_vote.sectionDivs[parseInt(div.i)+1]; if (!sec_end) { // No next entry, must be end of page. Add an empty div. sec_end = document.createElement('div'); div.parentNode.appendChild(sec_end); } else if (sec_end.parentNode.id != 'bodyContent') { // if the next entry is a closed discussion then we need to go               // one node up the tree sec_end = sec_end.parentNode; }       } else { sec_end = getElementsByClass('printfooter', document, 'div')[0]; }       var statusDiv = document.createElement('div'); statusDiv.innerHTML = "(submitting...)"; add_before( sec_end, statusDiv ); }

if (afdLogP) { // We're looking at a log page. Submit this asynchronously and replace // the content of this section of the log page with new content.

editor.submitAsync(null, afd_vote.log_update, div, sec_end); } else { // submit and go to changed page editor.submit; } }

afd_vote.log_update = function(req, div, sec_end) { if (req.status != 200) { alert ("Error submitting vote!"); return; } if (!div || !sec_end) { alert ("## afd_vote.log_update error"); return; }

// Replace nodes between div and next div with new content. // Start at the tag, because the afd page text doesn't have a   // section number (1.123), but the log text does. var newnodes_start = getElementsByClass('editsection', req.responseXML, 'div')[0].nextSibling.nextSibling.nextSibling.nextSibling.nextSibling; var newnodes_end = getElementsByClass('printfooter', req.responseXML, 'div')[0]; var replacement_nodes = getNodesInRange(newnodes_start, newnodes_end); var newnode = document.createElement('div'); for (i in replacement_nodes) { newnode.appendChild(replacement_nodes[i]); }

var oldnodes_start = div.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling; removeNodesInRange(oldnodes_start, sec_end); add_after(div.nextSibling.nextSibling.nextSibling.nextSibling, newnode); }

$(afd_vote._load);

//