User:Werdan7/twinklespeedy.js
Note: After publishing, 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: Press Ctrl-F5.
// If TwinkleConfig aint exist.
if( typeof( TwinkleConfig ) == 'undefined' ) {
TwinkleConfig = {};
}
/**
TwinkleConfig.summaryAd (string)
If ad should be added or not to summary, default [[WP:TWINKLE|TWINKLE]]
*/
if( typeof( TwinkleConfig.summaryAd ) == 'undefined' ) {
TwinkleConfig.summaryAd = "";
}
/**
TwinkleConfig.deletionSummaryAd (string)
If ad should be added or not to deletion summary, default [[WP:TWINKLE|TWINKLE]]
*/
if( typeof( TwinkleConfig.deletionSummaryAd ) == 'undefined' ) {
TwinkleConfig.deletionSummaryAd = "";
}
/**
TwinkleConfig.watchSpeedyPages (array)
What types of actions that should result in forced addition to watchlist
*/
if( typeof( TwinkleConfig.watchSpeedyPages ) == 'undefined' ) {
TwinkleConfig.watchSpeedyPages = [];
}
/**
TwinkleConfig.markSpeedyPagesAsMinor (boolean)
If, when applying speedy template to page, to mark the edit as minor, default true
*/
if( typeof( TwinkleConfig.markSpeedyPagesAsMinor ) == 'undefined' ) {
TwinkleConfig.markSpeedyPagesAsMinor = true;
}
/**
TwinkleConfig.openUserTalkPageOnSpeedyDelete (array)
What types of actions that should result user talk page to be opened
*/
if( typeof( TwinkleConfig.openUserTalkPageOnSpeedyDelete ) == 'undefined' ) {
TwinkleConfig.openUserTalkPageOnSpeedyDelete = [];
}
/**
TwinkleConfig.userTalkPageMode may take arguments:
'window': open a new window, remmenber the opened window
'tab': opens in a new tab, if possible.
'blank': force open in a new window, even if a such window exist
*/
if( typeof( TwinkleConfig.userTalkPageMode ) == 'undefined' ) {
TwinkleConfig.userTalkPageMode = 'tab';
}
/**
TwinkleConfig.deleteTalkPageOnDelete
If talk page if exists should also be deleted (CSD G8) when spedying a page (admin only)
*/
if( typeof( TwinkleConfig.deleteTalkPageOnDelete ) == 'undefined' ) {
TwinkleConfig.deleteTalkPageOnDelete = false;
}
/**
TwinkleConfig.toolboxButtons (string)
If id defined in this array, the button of the action is located inthe toolbox instead of in
the actions bar.
*/
if( typeof( TwinkleConfig.toolboxButtons ) == 'undefined' ) {
TwinkleConfig.toolboxButtons = [t-qd];
}
function twinkleSpeedyDelete() {
if( wgNamespaceNumber < 0 || wgCurRevisionId == false ) {
return;
}
if( userIsInGroup( 'sysop' ) ) {
mw.util.addPortletLink( chooseBox( 'tw-qd', TwinkleConfig.toolboxButtons ), "javascript:twinklespeedy( 'qd' )", "db (qd)", "tw-qd", "Speedy delete according to WP:QD", "");
} else {
mw.util.addPortletLink( chooseBox( 'tw-qd', TwinkleConfig.toolboxButtons ), "javascript:twinklespeedy( 'csd' )", "db (qd)", "tw-qd", "Request speedy deletion according to WP:QD", "");
}
}
$(twinkleSpeedyDelete);
function twinklespeedy( type ) {
twinklespeedy.type = type;
switch( type ) {
case 'qd':
twinklespeedy.Window = new SimpleWindow( 800, 400 );
twinklespeedy.Window.setTitle( "Choose criteria for quick deletion" );
function createOption( value, text ) {
var div = document.createElement( 'div' );
var input = document.createElement( 'input' );
input.setAttribute( 'value', value );
input.setAttribute( 'name', 'qd' );
input.setAttribute( 'id', 'wp' + value );
input.setAttribute( 'type', 'radio' );
var label = document.createElement( 'label' );
label.setAttribute( 'for', 'wp' + value );
label.appendChild( document.createTextNode( text ) );
div.appendChild( input );
div.appendChild( label );
return div;
}
var form = document.createElement( 'form' );
form.addEventListener( 'change', twinklespeedy.csd, true );
if( wgNamespaceNumber == 6 ) {
form.appendChild( createOption( 'noimages', 'I1: No images allowed.' ) );
form.appendChild( document.createElement( 'hr' ) );
}
form.appendChild( createOption( 'nonsense', 'G1: Patent nonsense.' ) );
form.appendChild( createOption( 'test', 'G2: Test page.' ) );
form.appendChild( createOption( 'vandalism', 'G3: Vandalism.' ) );
form.appendChild( createOption( 'pagemove', 'G3: Nonsense redirects that are created from the cleanup of page move vandalism.' ) );
form.appendChild( createOption( 'repost', 'G4: Copies of material that was previously deleted after an XfD discussion.' ) );
form.appendChild( createOption( 'banned', 'G5: Contributions made by a banned user.' ) );
form.appendChild( createOption( 'histmerge', 'G6: History merge.' ) );
form.appendChild( createOption( 'move', 'G6: Making way for a noncontroversial move.' ) );
form.appendChild( createOption( 'afd', 'G6: An admin has closed an Articles for deletion debate as a "delete".' ) );
form.appendChild( createOption( 'g6', 'G6: Other non-controversial "housekeeping" tasks' ) );
form.appendChild( createOption( 'author', 'G7: Speedy request by only editor.' ) );
form.appendChild( createOption( 'blanked', 'G7: Page blanked by only editor.' ) );
form.appendChild( createOption( 'talk', 'G8: Talk page of a deleted or nonexistent page.' ) );
form.appendChild( createOption( 'attack', 'G10: Attack page intended to disparage its subject.' ) );
form.appendChild( createOption( 'spam', 'G11: Pages that exist only to promote a company, product, or service.' ) );
form.appendChild( createOption( 'copyvio', 'G12: Blatant copyright violation.' ) );
form.appendChild( document.createElement( 'hr' ) );
form.appendChild( createOption( 'nocontext', 'A1: Very short articles without context.' ) );
form.appendChild( createOption( 'nocontent', 'A2: No content other than external links of whatever kind, or an attempt to contact subject of article.' ) );
form.appendChild( createOption( 'transwiki', 'A3: Transwikification completed.' ) );
form.appendChild( createOption( 'bio', 'A4: Non-notable biography / article about a person, group, company, or website that does not assert the notability of the subject.' ) );
form.appendChild( createOption( 'band', 'A4: Article about a band, singer, musician, or musical ensemble that does not assert the importance or significance of the subject.' ) );
form.appendChild( createOption( 'club', 'A4: Article about a club that does not assert the importance or significance of the subject.' ) );
form.appendChild( createOption( 'inc', 'A4: Article about a company or corporation that does not assert the importance or significance of the subject.' ) );
form.appendChild( createOption( 'web', 'A4: Article about a web site, blog, online forum, webcomic, podcast, or similar web content that does not assert the importance or significance of its subject.' ) );
form.appendChild( document.createElement( 'hr' ) );
form.appendChild( createOption( 'redirnone', 'R1: Redirect to non-existent page.' ) );
form.appendChild( createOption( 'rediruser', 'R2: Redirect to user page.' ) );
form.appendChild( createOption( 'redirtypo', 'R3: Redirect that is a result of an implausible typo.' ) );
form.appendChild( document.createElement( 'hr' ) );
form.appendChild( createOption( 'catempty', 'C1: Category that is empty for at least four days and has never contained anything other than links to parent categories.' ) );
form.appendChild( createOption( 'cattypo', 'C2: Category that is has been replaced with a different spelling.' ) );
form.appendChild( createOption( 'catfd', 'C3: Category that is used solely by a template that has been deleted.' ) );
form.appendChild( document.createElement( 'hr' ) );
form.appendChild( createOption( 'userreq', 'U1: User\'s subpage requested to be deleted by the user with whom it is associated.' ) );
form.appendChild( createOption( 'nouser', 'U2: Userpages of users who do not exist.' ) );
form.appendChild( document.createElement( 'hr' ) );
form.appendChild( createOption( 'disparage', 'T1: Templates that are insulting or hateful.' ) );
twinklespeedy.Window.setContent( form );
twinklespeedy.Window.display();
break;
case 'reason':
var criteria = prompt( "Enter reason for quick deletion" );
if( !criteria ) {
return; // User abort action
}
if( userIsInGroup( 'sysop' ) ) {
twinklespeedy.summary = "Speedy deletion, with reason: " + criteria + "." + TwinkleConfig.deletionSummaryAd;
} else {
twinklespeedy.summary = "Requesting speedy deletion." + TwinkleConfig.summaryAd;
}
twinklespeedy.code = "{{Q" + "D|" + ( criteria ? '|' + criteria : '' ) + "}}";
Status.init( document.getElementById('bodyContent') );
Status.status( 'Grabbing page' );
editXML = sajax_init_object();
editXML.overrideMimeType('text/xml');
if( userIsInGroup( 'sysop' ) ) {
editXML.open( 'GET' , wgServer + wgScriptPath + '/index.php?' + QueryString.create( { 'title': wgPageName, 'action': 'delete' } ), true);
} else {
editXML.open( 'GET' , wgServer + wgScriptPath + '/index.php?' + QueryString.create( { 'title': wgPageName, 'action': 'submit' } ), true);
}
editXML.onreadystatechange = twinklespeedyCallback;
editXML.send( null );
break;
}
}
twinklespeedy.csd = function(e) {
var convarr = {
'nonsense': 'g1',
'test': 'g2',
'vandalism': 'g3',
'pagemove': 'g3',
'repost': 'g4',
'banned': 'g5',
'histmerge': 'g6',
'move': 'g6',
'afd': 'g6',
'g6': 'g6',
'author': 'g7',
'blanked': 'g7',
'talk': 'g8',
'attack': 'g10',
'spam': 'g11',
'copyvio': 'g12',
'nocontext': 'a1',
'foreign': 'a2',
'nocontent': 'a3',
'transwiki': 'a5',
'bio': 'a7',
'inc': 'a7',
'web': 'a7',
'band': 'a7',
'club': 'a7',
'redirnone': 'r1',
'rediruser': 'r2',
'redirtypo': 'r3',
'noimages': 'i1',
'catempty': 'c1',
'cattypo': 'c2',
'catfd': 'c3',
'userreq': 'u1',
'nouser': 'u2',
'u3': 'u3',
'disparage': 't1',
'emptyportal': 'p2'
};
var reasarr = {
'nonsense': 'was patent nonsense with no meaningful content',
'test': 'was a test page',
'vandalism': 'was pure vandalism',
'pagemove': 'was a redirect created during cleanup of page move vandalism',
'repost': 'was a copy of material previously deleted per discussion',
'banned': 'was a contribution was made by a banned user',
'histmerge': 'temporary deletion in order to merge page histories',
'move': 'making way for a non-controversial move',
'afd': 'deleting page per result of RfD discussion',
'g6': 'non-controversial housekeeping deletion',
'author': 'only editor requested deletion',
'blanked': 'only editor has blanked the page',
'talk': 'was a talk page whose corresponding page does not exist',
'attack': 'was a attack page intented to insult its subject',
'spam': 'was advertising, used only to promote someone or something',
'copyvio': 'was a copyright infringement',
'nocontext': 'was a very short article providing little or no context',
'foreign': 'was a foreign language article that exists on another Wikimedia project',
'nocontent': 'had no content whatsoever except possibly links elsewhere, a rephrasing of the title, and/or attempts to correspond',
'transwiki': 'was properly transwikified elsewhere',
'bio': 'was an article about a real person, group of people, band, club, company, or web content that didn\'t assert the importance or significance of its subject',
'web': 'was an article about a web site, blog, online forum, webcomic, podcast, or similar web content that didn\'t assert the importance or significance of its subject.',
'inc': 'was an article about a company or corporation that didn\'t assert the importance or significance of its subject.',
'club': 'was an article about a club that didn\'t assert the importance or significance of the subject.',
'band': 'was an article about a band, singer, musician, or musical ensemble that didn\'t assert the importance or significance of the subject.',
'redirnone': 'was a redirect to an non-existent page',
'rediruser': 'was a redirect to the Talk:, User: or User talk: space',
'redirtypo': 'was a redirect based on an implausible typo',
'noimages': 'was an image, which are not allowed',
'catempty': 'was an empty category for at least four days',
'catfd': 'was a category solely populated from a now deleted template',
'userreq': 'was a user page whose user requested deletion',
'nouser': 'was a user page of a user that did not exist',
'u3': 'was a gallery in the user space which consisted mostly of fair use images',
'disparage': 'was an divisive and inflammatory template',
};
var value = e.target.value;
var normalized = convarr[ value ];
twinklespeedy.watch = TwinkleConfig.watchSpeedyPages.indexOf( normalized ) != -1;
twinklespeedy.usertalk = TwinkleConfig.openUserTalkPageOnSpeedyDelete.indexOf( normalized ) != -1;
var reason = reasarr[ value ];
if( userIsInGroup( 'sysop' ) ) {
twinklespeedy.summary = "Speedy deleted per ([[WP:QD#" + normalized + "|QD " + normalized + "]]), " + reason + "." + TwinkleConfig.deletionSummaryAd;
} else {
twinklespeedy.summary = "Requesting speedy deletion ([[WP:QD#" + normalized + "|QD " + normalized + "]])." + TwinkleConfig.summaryAd;
switch( normalized ) {
case 'g12':
url = prompt( 'please enter url if available, including the http://' );
if( url == null ) {
return;
}
twinklespeedy.code = "{{d" + "b-" + value + "(" + url + ")}}";
break;
default:
twinklespeedy.code = "{{d" + "b-" + value + "}}";
break;
}
}
twinklespeedy.Window.close();
Status.init( document.getElementById('bodyContent') );
Status.status( 'Grabbing page' );
editXML = sajax_init_object();
editXML.overrideMimeType('text/xml');
if( userIsInGroup( 'sysop' ) ) {
editXML.open( 'GET' , wgServer + wgScriptPath + '/index.php?' + QueryString.create( { 'title': wgPageName, 'action': 'delete' } ), true);
} else {
editXML.open( 'GET' , wgServer + wgScriptPath + '/index.php?' + QueryString.create( { 'title': wgPageName, 'action': 'submit' } ), true);
}
editXML.onreadystatechange = twinklespeedyCallback;
editXML.send( null );
}
function twinklespeedyCallback() {
if ( editXML.readyState != 4 ){
Status.progress('.');
return;
}
if( editXML.status != 200 ){
Status.error('Bad status , bailing out');
return;
}
// when we grabbed the page, it wasn't there
if( editXML.responseText.indexOf( 'var wgCurRevisionId = false;' ) != -1 ) {
Status.error( "It seems that the page doesn't exists, perhaps it has already been deleted'" );
return;
}
var doc = editXML.responseXML;
var form;
if( userIsInGroup( 'sysop' ) ) {
Status.status( 'Deleting page...' );
form = doc.getElementById( 'deleteconfirm' );
form.style.display = 'none';
doc.getElementById( 'wpReason' ).value = twinklespeedy.summary;
if( twinklespeedy.watch ) {
doc.getElementById( 'wpWatch' ).checked = true;
}
if( TwinkleConfig.deleteTalkPageOnDelete && wgNamespaceNumber % 2 == 0 && document.getElementById( 'ca-talk' ).className != 'new' ) {
Status.status( 'Deleting talk page' );
var talk_page = namespaces[ wgNamespaceNumber + 1 ] + ':' + wgTitle;
var query = {
'title': talk_page,
'action': 'delete'
};
talkPageXML = sajax_init_object();
talkPageXML.overrideMimeType('text/xml');
talkPageXML.open( 'GET' , wgServer + wgScriptPath + '/index.php?' + QueryString.create( query ), false);
talkPageXML.send( null );
var talkdoc = talkPageXML.responseXML;
if( talkdoc.getElementById( 'deleteconfirm' ) ) {
var postData = {
'wpWatch': ( twinklespeedy.watch ? true : talkdoc.getElementById( 'wpWatch' ).checked ),
'wpReason': "Speedy deleted per ([[WP:CSD#g8|CSD g8]]), was a talk page of deleted page." + TwinkleConfig.deletionSummaryAd,
'wpEditToken': talkdoc.getElementsByTagName('form')[0].wpEditToken.value
}
talkPageXML = sajax_init_object();
talkPageXML.overrideMimeType('text/xml');
talkPageXML.open( 'POST' , wgServer + wgScriptPath + '/index.php?' + QueryString.create( query ), false);
talkPageXML.setRequestHeader('Content-type','application/x-www-form-urlencoded');
talkPageXML.send( QueryString.create( postData ) );
} else {
Status.warn( 'No delete form for talk page found, won\'t try to delete talk page' );
}
}
} else {
form = doc.getElementById( 'editform' );
form.style.display = 'none';
var textbox = doc.getElementById( 'wpTextbox1' );
var text = textbox.value;
Status.status( 'Checking for tags on the page...' );
var tag = /(\{\{(?:qb-?|delete)\|?.*?\}\})/.exec( text );
if( tag ) {
Status.warn( [ htmlNode( 'strong', tag[0] ) , " is alread placed on the page." ] )
return;
}
var xfd = /(\{\{(?:[aitcm]fd|md1)[^{}]*?\}\})/i.exec( text );
if( xfd && !confirm( "The deletion related template " + xfd[0] + " is already present on the page, do you still want to apply CSD template?" ) ) {
return;
}
Status.status( 'Submitting form...' );
textbox.value = twinklespeedy.code + "\n" + textbox.value;
doc.getElementById( 'wpSummary' ).value = twinklespeedy.summary;
if( TwinkleConfig.markSpeedyPagesAsMinor ) {
doc.getElementById( 'wpMinoredit' ).checked = true;
}
if( twinklespeedy.watch ) {
doc.getElementById( 'wpWatchthis' ).checked = false;
}
}
twinklespeedy.form = form;
if( twinklespeedy.usertalk ) {
Status.status( 'Getting data for first contributor' );
var query = {
'action': 'query',
'prop': 'revisions',
'titles': wgPageName,
'rvlimit': 1,
'rvprop': 'user',
'rvdir': 'newer',
'format': 'xml'
}
userTalkXML = sajax_init_object();
userTalkXML.overrideMimeType('text/xml');
userTalkXML.onreadystatechange = twinklespeedyCallbackUserTalk;
userTalkXML.open( 'GET' , wgServer + wgScriptPath + '/api.php?' + QueryString.create( query ), true );
userTalkXML.send( null );
} else {
document.getElementById('globalWrapper').appendChild( twinklespeedy.form )
twinklespeedy.form.submit();
}
}
function twinklespeedyCallbackUserTalk() {
if ( userTalkXML.readyState != 4 ){
Status.progress( '.' );
return;
}
if( userTalkXML.status != 200 ){
Status.error( 'Bad status , bailing out' );
return;
}
var user = userTalkXML.responseXML.documentElement.getElementsByTagName('rev')[0].getAttribute('user');
Status.status( 'Opening user talk page' );
var query = {
'title': 'User talk:' + user,
'action': 'edit',
'vanarticle': wgPageName.replace(/_/g, ' '),
}
switch( TwinkleConfig.userTalkPageMode ) {
case 'tab':
window.open( wgServer + wgScriptPath + '/index.php?' + QueryString.create( query ), '_tab' );
break;
case 'blank':
window.open( wgServer + wgScriptPath + '/index.php?' + QueryString.create( query ), '_blank', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
break;
case 'window':
default :
window.open( wgServer + wgScriptPath + '/index.php?' + QueryString.create( query ), 'twinklewarnwindow', 'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
break;
}
document.getElementById('globalWrapper').appendChild( twinklespeedy.form )
twinklespeedy.form.submit();
}