// [[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)
//<pre><nowiki>
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' : '[[Wikipedia:Speedy keep|Speedy keep]]',
'SPK' : 'Speedy keep',
'C' : 'Comment',
'MC' : 'Metacomment',
'BJAODN,BJ' : 'BJAODN'
});
afd_vote.comment_shortcuts = Shortcuts( {
'PN' : 'per nomination',
'NN' : '[[WP:N|non-notable]]',
'V,VAIN,VANITY' : '[[WP:VAIN|vanity]]',
'NNBIO' : '[[WP:BIO|non-notable biography]]',
'NNVBIO' : '[[WP:BIO|non-notable vanity biography]]',
'NNWEB' : '[[WP:WEB|non-notable website]]',
'NNWEBCOMIC ' : '[[WP:WEB|non-notable webcomic]]',
'NNBLOG,NNWEBLOG' : '[[WP:WEB|non-notable weblog]] ',
'NNFORUM,NNWEBFORUM' : '[[WP:WEB|non-notable web forum]] ',
'NNSOFTWARE,NNSOFT,NNSW' : '[[WP:SOFTWARE|non-notable software]] ',
'NNCORP,NNCOMPANY' : '[[WP:CORP|non-notable corporation]]',
'NNMUSIC' : '[[WP:MUSIC|non-notable musical group]]',
'NNBAND' : '[[WP:MUSIC|non-notable band]]',
'NNUNEO' : '[[Wikipedia:Avoid_neologisms|non-notable unstable neologism, i.e. protologism]]',
'NNUUNEO' : '[[Wikipedia:Avoid_neologisms|non-notable unverifiable unstable neologism, i.e. protologism]]',
'NNFICT,NNFICTION' : '[[WP:FICT|non-notable reference to fictional work]]',
'NNFICTC,NNFICTCHAR,NNCHAR' : '[[WP:FICT|non-notable character from fictional work]] ',
'FANCRUFT,NNFAN' : '[[Wikipedia:Fancruft|fancruft]]',
'NNFANFIC' : '[[Wikipedia:Fancruft|non-notable fan fiction]]',
'NNGAME' : '[[WP:N|non-notable]] online gaming group',
'U' : '[[WP:V|unverifiable]]',
'UPH' : '[[WP:V|unverifiable]], possible [[WP:HOAX|hoax]]',
'OR' : '[[WP:NOR|original research]]',
'UOR' : '[[WP:V|unverifiable]] and/or [[WP:NOR|original research]]',
'H' : '[[WP:HOAX|hoax]]',
'HSANC,HSANCT,HSANCTION' : '[[WP:HOAX|hoax]], and sanction article author',
'ATTACK' : '[[WP:CSD|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' : '[[WP:NOT|unencyclopedic]]',
'NOT' : '[[WP:NOT|Wikipedia is not]]',
'NOTADVERT' : '[[WP:NOT|Wikipedia is not a vehicle for advertising]] ',
'NOTBALL,NOTCRYSTAL' : '[[WP:NOT|Wikipedia is not a crystal ball]] ',
'NOTCRUFT' : '[[WP:NOT|Wikipedia is not an indiscriminate collection of information]] ',
'NOTDICT,NOTDIC' : '[[WP:NOT|Wikipedia is not a dictionary]] (but [[Wiktionary]] is) ',
'NOTMEMORIAL' : '[[WP:NOT|Wikipedia is not a memorial]] ',
'NOTOR,NOTORIGINAL' : '[[WP:NOT|Wikipedia is not a publisher of original thought]] ',
'NOTSOAPBOX' : '[[WP:NOT|Wikipedia is not a soapbox]] ',
'NOTSW,NOTSWDIR' : '[[WP:NOT|Wikipedia is not a software directory]] ',
'NOTWEBHOST,NOTFREEHOST' : '[[WP:NOT|Wikipedia is not a free host or webspace provider]] ',
'NOTWEBDIR' : '[[WP:NOT|Wikipedia is not a web directory]] ',
'NFT,NOTSCHDAY,NOTSCH' : '[[WP:NFT|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 [[Wikipedia:User page|user page]] ',
'XPROTO,XPROTOLOGISM,PROTOX' : 'Protologisms may deserve listing at [[Wiktionary:List_of_protologisms]] ',
'BALLS,BALL' : '[[WP:BALLS|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 = ' [<a href="'+href+'" title="'+title+'">vote</a>]';
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 = "<i>(submitting...)</i>";
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 <h3> 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);
//</nowiki></pre>