User:Quarl/afd vote.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:Quarl/afd vote. |
// [[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>