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 [http://www.wikime.org/ WikiMe] for writing biographies and/or [http://www.wikitree.org 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 Wiktionary: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(/{{(nn-?bio|nn-?band|db-attack|db-repost)}}/, '{{tl|$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);

//