User:Gregbard/twinklespeedy.js

// If TwinkleConfig aint exist. if( typeof( TwinkleConfig ) == 'undefined' ) { TwinkleConfig = {}; }

/** TwinkleConfig.summaryAd (string) If ad should be added or not to summary, default TWINKLE */ if( typeof( TwinkleConfig.summaryAd ) == 'undefined' ) { TwinkleConfig.summaryAd = " using TW"; }

/** TwinkleConfig.deletionSummaryAd (string) If ad should be added or not to deletion summary, default TWINKLE */ if( typeof( TwinkleConfig.deletionSummaryAd ) == 'undefined' ) { TwinkleConfig.deletionSummaryAd = " using TW"; }

/** TwinkleConfig.watchSpeedyPages (array) What types of actions that should result in forced addition to watchlist */ if( typeof( TwinkleConfig.watchSpeedyPages ) == 'undefined' ) { TwinkleConfig.watchSpeedyPages = [ 'g3', 'g5', 'g10', 'g11', 'g12' ]; }

/** 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 = [ 'g1', 'g2', 'g10', 'g11', 'g12', 'a1', 'a7', 'i3', 'i4', 'i5', 'i6', 'i7', 'u3', 't1' ]; }

/** 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 = 'window'; }

/** 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 = []; }

/** TwinkleConfig.orphanNormalPagesOnSpeedyDelete (hash) Defines if all backlinks to a page should be removed. property 'exclude' defined actions not to orphan */ if( typeof( TwinkleConfig.orphanBacklinksOnSpeedyDelete ) == 'undefined' ) { TwinkleConfig.orphanBacklinksOnSpeedyDelete = { exclude: ['g6'], orphan:true }; }

function twinkleSpeedyDelete { if( wgNamespaceNumber < 0 || wgCurRevisionId == false ) { return; }   if( userIsInGroup( 'sysop' ) ) { mw.util.addPortletLink( 'p-cactions', "javascript:twinklespeedy", "csd", "tw-csd", "Speedy delete according to WP:CSD", ""); } else { mw.util.addPortletLink( 'p-cactions', "javascript:twinklespeedy", "csd", "tw-csd", "Request speedy deletion according to WP:CSD", ""); }   } $(twinkleSpeedyDelete);

function twinklespeedy { twinklespeedy.Window = new SimpleWindow( 800, 400 ); twinklespeedy.Window.setTitle( "Choose criteria for speedy deletion" );

var form = new QuickForm( userIsInGroup( 'sysop' ) ? twinklespeedy.csdSysopCallback : twinklespeedy.csdUserCallback, 'change' ); if( userIsInGroup( 'sysop' ) ) { form.append( {               type: 'checkbox',                name: 'tag_only',                list: [                    {                        label: 'Tag page only, don\'t delete',                        value: 'tag_only',                        tooltip: 'If you just want to tag the page, instead of deleting it now'                    }                ]            } ); }   if( wgNamespaceNumber ==  6 ) { form.append( {type:'header', label:'Images/Media' } ); form.append ( {               type: 'radio',                name: 'csd',                list: [                    {                         label: 'I1: Redundant image',                        value: 'redundantimage',                        tooltip: 'Any image that is a redundant copy, in the same image file format and same or lower resolution, of something else on Wikipedia. Likewise, other media that is a redundant copy, in the same format and of the same or lower quality. This does not apply to images duplicated on Wikimedia Commons, because of licence issues; these should be tagged with \{\{subst:ncd|Image:newname.ext\}\} or \{\{subst:ncd\}\} instead'                     },                    {                         label: 'I2: Corrupt or empty image',                        value: 'noimage',                         tooltip: 'Before deleting this type of image, verify that the MediaWiki engine cannot read it by previewing a resized thumbnail of it. This also includes empty (i.e., no content) image description pages for Commons images' },                   {                         label: 'I3: Improper license', value: 'noncom', tooltip: '"Images licensed as "for non-commercial use only", "non-derivative use" or "used with permission" that were uploaded on or after 2005-05-19, except where they have been shown to comply with the limited standards for the use of non-free content. This includes images licensed under a "Non-commercial Creative Commons License". Such images uploaded before 2005-05-19 may also be speedily deleted if they are not used in any articles'                   },                    {                        label: 'I4: Lack of licensing information',                         value: 'unksource',                        tooltip: 'Images in category "Images with unknown source", "Images with unknown copyright status", or "Images with no copyright tag" that have been tagged with a template that places them in the category for more than seven days, regardless of when uploaded. Note, users sometimes specify their source in the upload summary, so be sure to check the circumstances of the image' },                   {                        label: 'I5: Unused unfree copyrighted images', value: 'unfree', tooltip: 'Images and other media that are not under a free license or in the public domain that are not used in any article and that have been tagged with a template that places them in a dated subcategory of Category:Orphaned fairuse images for more than seven days. Reasonable exceptions may be made for images uploaded for an upcoming article. Use \{\{subst:orfud\}\} to tag images for forthcoming deletion' },                   {                        label: 'I6: Missing fair-use rationale', value: 'norat', tooltip: 'Any image or media without a fair use rationale may be deleted seven days after it is uploaded. Boilerplate fair use templates do not constitute a fair use rationale. Images and other media uploaded before 2006-05-04 should not be deleted immediately; instead, the uploader should be notified that a fair-use rationale is needed. Images or other media uploaded after 2006-05-04 can be tagged with \{\{subst:nrd\}\}, and the uploader notified with \{\{subst:missing rationale|Image:image name\}\}. Such images can be found in the dated subcategories of Category:Images with no fair use rationale' },                   {                         label: 'I7: Invalid fair-use claim', value: 'badfairuse', tooltip: 'Any image or media with a clearly invalid fair-use tag (such as a \{\{logo\}\} tag on a photograph of a mascot) may be deleted at any time. Media that fail any part of the non-free content criteria and were uploaded after 2006-07-13 may be deleted forty-eight hours after notification of the uploader. For media uploaded before 2006-07-13 or tagged with the \{\{Replaceable fair use\}\} template, the uploader will be given seven days to comply with this policy after being notified' },                   {                        label: 'I8: Images available as bit-for-bit identical copies on the Wikimedia Commons', value: 'nowcommons', tooltip: 'Provided the following conditions are met: 1: The image\'s license and source status is beyond reasonable doubt, and the license is undoubtedly accepted at Commons. 2: All information on the image description page is present on the Commons image description page. That includes the complete upload history with links to the uploader\'s local user pages. 3: The image is not protected, and the image description page does not contain a request not to move it to Commons. 4: The image has been marked with Template:NowCommons for at least one week. Waiting one week is not necessary if it was the uploader who moved the image and marked it. 5: If the image is available on Commons under a different name than locally, all local references to the image must be updated to point to the title used at Commons. 6: For \{\{c-uploaded\}\} images: They may be speedily deleted as soon as they are off the Main Page.' },               ]            } );    }

form.append( { type:'header', label:'General criteria' } ); form.append( {           type: 'radio',            name: 'csd',            list: [                {                     label: 'G1: Nonsense',                     value: 'nonsense',                     tooltip: 'Patent nonsense and gibberish, an unsalvageably incoherent page with no meaningful content. This does not include: poor writing, partisan screeds, obscene remarks, vandalism, fictional material, material not in English, badly translated material, implausible theories, or hoaxes' },                {                     label: 'G2: Test page',                    value: 'test',                    tooltip: 'e.g., "Can I really create a page here?"'                 },                {                     label: 'G3: Pure vandalism',                    value: 'vandalism',                    tooltip: 'Plain pure vandalism'                },                {                     label: 'G3: Pagemove', value: 'pagemove', tooltip: 'Nonsense redirects that are created from the cleanup of page move vandalism.' },               {                    label: 'G4: Recreation of deleted material', value: 'repost', tooltip: 'A copy, by any title, of a page that was deleted via an XfD process or Deletion review, provided that the copy is substantially identical to the deleted version and that any revisions made clearly do not address the reasons for which the page was deleted. This clause does not apply to content that has been "userfied", to content undeleted as a result of Deletion review, or if the prior deletions were proposed or speedy deletions, although in this last case, the previous speedy criterion, or other speedy deletion criteria, may apply.' },               {                    label: 'G5: Banned user', value: 'banned', tooltip: 'Pages created by banned users while they were banned' },               {                    label: 'G6: History merge', value: 'histmerge', tooltip: 'Temporarily deleting a page in order to merge page histories' },               {                    label: 'G6: Move', value: 'move', tooltip: 'Making way for a noncontroversial move like reversing a redirect' },               {                    label: 'G6: Afd', value: 'afd', tooltip: 'An admin has closed an Articles for deletion debate as a "delete".' },               {                    label: 'G6: Housekeeping', value: 'g6', tooltip: 'Other non-controversial "housekeeping" tasks' },               {                    label: 'G7: Author requests deletion', value: 'author', tooltip: 'Any page for which deletion is requested by the original author in good faith, provided the page\'s only substantial content was added by its author' },               {                    label: 'G7: Author blanked', value: 'blanked', tooltip: ' If the author blanks the page, this can be taken as a deletion request' },               {                    label: 'G8: Talk pages whose corresponding article does not exist', value: 'talk', tooltip: 'unless: It contains deletion discussion that is not logged elsewhere; It is a User Talk page; It is the Talk page for an image uploaded on the Wikimedia Commons; It is a Talk subpage (such as archived Talk pages) whose corresponding top-level article does exist' },               {                     label: 'G10: Attack page', value: 'attack', tooltip: 'Pages that serve no purpose but to disparage their subject or some other entity (e.g., "John Q. Doe is an imbecile"). This includes a biography of a living person that is negative in tone and unsourced, where there is no NPOV version in the history to revert to. Administrators deleting such pages should not quote the content of the page in the deletion summary!' },               {                     label: 'G11: Blatant advertising', value: 'spam', tooltip: 'Pages which exclusively promote a company, product, group, service, or person and which would need to be fundamentally rewritten in order to become encyclopedic. Note that simply having a company, product, group, service, or person as its subject does not qualify an article for this criterion; an article that is blatant advertising should have inappropriate content as well' },               {                     label: 'G12: Blatant copyright infringement', value: 'copyvio', tooltip: 'Either, 1: Material was copied from another website that does not have a license compatible with Wikipedia, or is photography from a stock photo seller (such as Getty Images or Corbis) or other commercial content provider; 2: There is no non-infringing content in the page history worth saving; or 3: The infringement was introduced at once by a single person rather than created organically on wiki and then copied by another website such as one of the many Wikipedia mirrors' }           ]        });

form.append( { type:'header', label:'Articles' } ); form.append( {           type: 'radio',            name: 'csd',            list: [                {                    label: 'A1: Little or no context',                    value: 'nocontext',                    tooltip: 'Very short articles providing little or no context (e.g., "He is a funny man that has created Factory and the Hacienda. And, by the way, his wife is great."). Limited content is not in itself a reason to delete if there is enough context for the article to qualify as a valid stub'                },                {                    label: 'A2: Foreign language articles that exist on another Wikimedia project',                    value: 'foreign',                    tooltip: 'If the article in question does not exist on another project, the template \{\{notenglish\}\} should be used instead. All articles in a non-English language that do not meet this criteria (and do not meet any other criteria for speedy deletion) should be listed at Pages Needing Translation (PNT) for review and possible translation' },               {                    label: 'A3: No content whatsoever', value: 'nocontent', tooltip: 'Any article consisting only of links elsewhere (including hyperlinks, category tags and "see also" sections), a rephrasing of the title, and/or attempts to correspond with the person or group named by its title. This does not include disambiguation pages' },               {                    label: 'A5: # Transwikied articles', value: 'transwiki', tooltip: 'Any article that has been discussed at Articles for Deletion (et al), where the outcome was to transwiki, and where the transwikification has been properly performed and the author information recorded. Alternately, any article that consists of only a dictionary definition, where the transwikification has been properly performed and the author information recorded' },               {                    label: 'A7: Unremarkable people, groups, companies and web content', value: 'bio', tooltip: 'An article about a real person, group of people, band, club, company, or web content that does not assert the importance or significance of its subject. If controversial, or if there has been a previous AfD that resulted in the article being kept, the article should be nominated for AfD instead' },               {                    label: 'A7: Unremarkable band', value: 'band', tooltip: 'Article about a band, singer, musician, or musical ensemble that does not assert the importance or significance of the subject.' },               {                    label: 'A7: Unremarkable club', value: 'club', tooltip: 'Article about a club that does not assert the importance or significance of the subject.' },               {                    label: 'A7: Unremarkable company', value: 'inc', tooltip: 'Article about a company or corporation that does not assert the importance or significance of the subject.' },               {                    label: 'A7: Unremarkable website', value: 'web', tooltip: '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.append( { type:'header', label: 'Redirects' } ); form.append( {           type: 'radio',            name: 'csd',            list: [                {                     label: 'R1: Redirects to nonexistent pages',                    value: 'redirnone'                },                {                     label: 'R2: Redirects to the Talk:, User: or User talk: namespace from the article space',                     value: 'rediruser',                     tooltip: '(this does not include the Wikipedia shortcut pseudo-namespaces). If this was the result of a page move, consider waiting a day or two before deleting the redirect'                },                {                     label: 'R3: Redirects as a result of an implausible typo that were recently created',                     value: 'redirtypo',                     tooltip: 'However, redirects from common misspellings or misnomers are generally useful, as are redirects in other languages' }           ]        } );

form.append( { type:'header', label: 'Categories' } ); form.append( {           type: 'radio',            name: 'csd',            list: [                {                     label: 'C1: Empty categories',                    value: 'catempty',                    tooltip: '(no articles or subcategories for at least four days) whose only content has consisted of links to parent categories. This does not apply to categories being discussed on WP:CFD or WP:SFD, or disambiguation categories. If the category isn\'t relatively new, it possibly contained articles earlier, and deeper investigation is needed'                },                {                    label: 'C3: Template categories',                    value: 'catfd',                    tooltip: 'If a category is solely populated from a template (e.g. Category:Wikipedia cleanup from \{\{ cleanup \}\}) and the template is deleted per deletion policy, the category can also be deleted without further discussion' }           ]        } );

form.append( { type:'header', label: 'User pages' } ); form.append( {           type: 'radio',            name: 'csd',            list: [                {                    label: 'U1: User request',                    value: 'userreq',                    tooltip: 'Personal subpages, upon request by their user. In some rare cases there may be administrative need to retain the page. Also, sometimes, main user pages may be deleted as well. See Wikipedia:User page for full instructions and guidelines'                },                {                    label: 'U2: Nonexistent user',                    value: 'nouser',                    tooltip: 'User pages of users that do not exist (Check Special:Listusers)'                },                {                    label: 'U3: Non-free galleries',                    value: 'u3',                    tooltip: 'Galleries in the userspace which consist mostly of "fair use" or non-free images. Wikipedia\'s non-free content policy forbids users from displaying non-free images, even ones they have uploaded themselves, in userspace. It is acceptable to have free images, GFDL-images, Creative Commons and similar licenses along with public domain material, but not "fair use" images' },           ]        } );

form.append( { type:'header', label: 'Templates' } ); form.append( {           type: 'radio',            name: 'csd',            list: [

{                    label: 'T1: Templates that are divisive and inflammatory', value: 'divisive' }           ]        } );    form.append( { type:'header', label: 'Portals' } );    form.append( { type: 'radio', name: 'csd', list: [ {                   label: 'P2: Underpopulated portal', value: 'emptyportal', tooltip: 'Any Portal based on a topic for which there is not a non-stub header article, and at least three non-stub articles detailing subject matter that would be appropriate to discuss under the title of that Portal' }           ]        } );

twinklespeedy.rendered = form.render; twinklespeedy.Window.setContent( twinklespeedy.rendered ); twinklespeedy.Window.display; }

twinklespeedy.normalizeHash = { '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', 'redundantimage': 'i1', 'noimage': 'i2', 'noncom': 'i3', 'unksource': 'i4', 'unfree': 'i5', 'norat': 'i6', 'badfairuse': 'i7', 'nowcommons': 'i8', 'catempty': 'c1', 'catfd': 'c3', 'userreq': 'u1', 'nouser': 'u2', 'u3': 'u3', 'divisive': 't1', 'emptyportal': 'p2' };

twinklespeedy.reasonHash = { 'nonsense': 'was patent nonsense: an unsalvageably incoherent page 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 XfD', 'banned': 'was a contribution 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 AfD 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 disparage its subject', 'spam': 'was blatant advertising, used only to promote someone or something', 'copyvio': 'was a blatant 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', 'redundantimage': 'a same or better image exists on Wikipedia', 'noimage': 'was a corrupt or empty image', 'noncom': 'was licensed as "for non-commercial use only", "non-derivative use" or "used with permission", uploaded on or after May 19, 2005, and no assertion of fair use was provided', 'unksource': 'was an image lacking sources or licensing information for more than seven days', 'unfree': 'was an unfree image that wasn\'t been used for more than seven days', 'norat': 'was an image with fair use tag but no fair use rationale for more than seven days', 'badfairuse': 'was an image with an invalid fair use rationale and the uploader was notified more than 48 hours ago', 'nowcommons': 'was an image available as a bit-for-bit identical copy on the Wikimedia Commons', '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', 'divisive': 'was an divisive and inflammatory template', 'emptyportal': 'was an underpopulated portal' };

twinklespeedy.csdSysopCallback = function(e) {

wgPageName = wgPageName.replace( /_/g, ' ' ); // for queen/king/whatever and country! if( e.target.value == 'tag_only' ) { return; }   var tag_only = e.target.form.tag_only.checked; if( tag_only ) { return twinklespeedy.csdUserCallback(e); }

var value = e.target.value; var normalized = twinklespeedy.normalizeHash[ value ]; twinklespeedy.normalized = normalized; twinklespeedy.watch = TwinkleConfig.watchSpeedyPages.indexOf( normalized ) != -1; twinklespeedy.usertalk = TwinkleConfig.openUserTalkPageOnSpeedyDelete.indexOf( normalized ) != -1;

var reason = twinklespeedy.reasonHash[ value ];

twinklespeedy.summary = "Speedy deleted per (CSD " + normalized + "), " + reason + "." + TwinkleConfig.deletionSummaryAd; Status.init( twinklespeedy.rendered );

Status.status( 'Grabbing page' );

xmlhttp = sajax_init_object; xmlhttp.query = { 'title': wgPageName, 'action': 'delete' };

xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'GET', wgServer + wgScriptPath + '/index.php?' + QueryString.create( xmlhttp.query ), true ); xmlhttp.onload = function {

if( this.responseText.indexOf( 'var wgCurRevisionId = false;' ) != -1 ) { Status.error( "It seems that the page doesn't exists, perhaps it has already been deleted" ); return; }

Status.status( 'Deleting page...' );

var form = this.responseXML.getElementById( 'deleteconfirm' );

if ( this.responseText.indexOf("var wgPageName = \"Image:") != -1 ) { Status.status( 'Deleting image page...' );        form = this.responseXML.getElementsByTagName('input');

Status.status( form[0].value ); var postData = { 'wpReason': twinklespeedy.summary, 'wpEditToken': form[0].value }

} else { var postData = { 'wpWatch': twinklespeedy.watch ? '' : form.wpWatch.checked ? '' : undefined, 'wpReason': twinklespeedy.summary, 'wpEditToken': form.wpEditToken.value }

}

var xmlhttp = sajax_init_object; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'POST', wgServer + wgScriptPath + '/index.php?' + QueryString.create( this.query ), true); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlhttp.onload = function { Status.info( 'Page/Image deleted, remember to wait until it\'s all done.' ) }; xmlhttp.send( QueryString.create( postData ) );

// Deleting talk page if requested if( TwinkleConfig.deleteTalkPageOnDelete && wgNamespaceNumber % 2 == 0 && document.getElementById( 'ca-talk' ).className != 'new' ) { Status.status( 'Deleting talk page' ); var talk_page = namespaces[ wgNamespaceNumber + 1 ] + ':' + wgTitle; xmlhttp = sajax_init_object; xmlhttp.query = { 'title': talk_page, 'action': 'delete' };           xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'GET', wgServer + wgScriptPath + '/index.php?' + QueryString.create( xmlhttp.query ), true ); xmlhttp.onload = function(e) {

var form = this.responseXML.getElementById( 'deleteconfirm' ); if( form ) { var postData = { 'wpWatch': twinklespeedy.watch ? '' : form.wpWatch.checked ? '' : undefined, 'wpReason': "Speedy deleted per (CSD g8), was a talk page of deleted page." + TwinkleConfig.deletionSummaryAd, 'wpEditToken': form.wpEditToken.value }

xmlhttp = sajax_init_object; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'POST', wgServer + wgScriptPath + '/index.php?' + QueryString.create( this.query ), false); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlhttp.onload = function { Status.info( "Talkpage deleted") } xmlhttp.send( QueryString.create( postData ) );

} else { Status.warn( 'No delete form for talk page found, won\'t try to delete talk page' ); }           }            xmlhttp.send( null ); }

// Open user talk page if requested 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' }           xmlhttp = sajax_init_object; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'GET', wgServer + wgScriptPath + '/api.php?' + QueryString.create( query ), true ); xmlhttp.onload = function { var user = this.responseXML.documentElement.getElementsByTagName('rev')[0].getAttribute('user'); // TODO -> xpath

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; }           }            xmlhttp.send( null ); }

if( wgNamespaceNumber == 6 && twinklespeedy.normalized != 'i8' ) {

var statusIndicator = document.createElement( 'div' ); Status.status( [ statusIndicator ] ); statusIndicator.appendChild( document.createTextNode( 'Removing usage of image, status: ' ) ); statusIndicator.appendChild( document.createTextNode( '0%' ) ); // removing instances of the image var xmlhttp = sajax_init_object; xmlhttp.statusIndicator = statusIndicator; xmlhttp.query = { 'action': 'query', 'list': 'imageusage', 'titles': wgPageName, 'iulimit': 500, 'format': 'xml' };           xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'GET', wgServer + wgScriptPath + '/api.php?' + QueryString.create( xmlhttp.query ), true); xmlhttp.onload = function {

var xmlDoc = this.responseXML; var nsResolver = xmlDoc.createNSResolver( xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement); var count = xmlDoc.evaluate( 'count(//imageusage/iu)', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null );

var nofnodes = count.numberValue * 2;

counter = 0; updateCounter = function(obj, total) { obj.replaceChild( document.createTextNode( parseInt( 100 * ++counter/total ) + '%' ), obj.lastChild ); if( counter == total ) { Status.info( 'removal of instances completed.' );

}               }

var snapshot = xmlDoc.evaluate('//imageusage/iu/@title', xmlDoc, nsResolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );

for ( var i = 0; i < snapshot.snapshotLength; ++i ) { (function(title, total, obj) {                           var xmlhttp = sajax_init_object;                            xmlhttp.query = {                                'title': title,                                'action': 'submit'                            };                            xmlhttp.overrideMimeType('text/xml');                            xmlhttp.open( 'GET', wgServer + wgScriptPath + '/index.php?' + QueryString.create( xmlhttp.query ), true);                            xmlhttp.onload = function {

var form = this.responseXML.getElementById('editform'); var text = form.wpTextbox1.value; var old_text = text; var wikiPage = new Mediawiki.Page( text ); wikiPage.commentOutImage( wgTitle, 'Commented out because image was deleted' );

text = wikiPage.getText; updateCounter( obj, total ); if( text == old_text ) { // Nothing to do, return updateCounter( obj, total ); return; } else { var postData = { 'wpMinoredit': form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': 'Removing instance of image ' + wgTitle + " that has been speedily deleted per (CSD " + twinklespeedy.normalized.toUpperCase + ")" + "; " + TwinkleConfig.deletionSummaryAd, 'wpTextbox1': text };                                   var xmlhttp = sajax_init_object; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'POST', wgServer + wgScriptPath + '/index.php?' + QueryString.create( this.query ), true); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlhttp.onload = function { updateCounter( obj, total ); }                                   xmlhttp.send( QueryString.create( postData ) );

}

}                                           xmlhttp.send( null ); })( snapshot.snapshotItem(i).value, nofnodes, this.statusIndicator );

}

}           xmlhttp.send( null ); }        if( TwinkleConfig.orphanBacklinksOnSpeedyDelete.orphan && TwinkleConfig.orphanBacklinksOnSpeedyDelete.exclude.indexOf(twinklespeedy.normalized.toLowerCase) == -1 ) {

var statusIndicator = document.createElement( 'div' ); Status.status( [ statusIndicator ] ); statusIndicator.appendChild( document.createTextNode( 'Unlinking backlinks, status: ' ) ); statusIndicator.appendChild( document.createTextNode( '0%' ) ); // removing instances of the image var xmlhttp = sajax_init_object; xmlhttp.statusIndicator = statusIndicator; xmlhttp.query = { 'action': 'query', 'list': 'backlinks', 'bltitle': wgPageName, 'bllimit': 500, 'blnamespace': [0, 100], // Main namespace and portal namespace only, keep on talk pages. 'format': 'xml' };           xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'GET', wgServer + wgScriptPath + '/api.php?' + QueryString.create( xmlhttp.query ), true); xmlhttp.onload = function {

var xmlDoc = this.responseXML; var nsResolver = xmlDoc.createNSResolver( xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement); var count = xmlDoc.evaluate( 'count(//backlinks/bl)', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null );

var nofnodes = count.numberValue * 2;

blcounter = 0; updateCounter = function(obj, total) { obj.replaceChild( document.createTextNode( parseInt( 100 * ++blcounter/total ) + '%' ), obj.lastChild ); if( blcounter == total ) { Status.info( 'removal of backlinks completed.' );

}               }

var snapshot = xmlDoc.evaluate('//backlinks/bl/@title', xmlDoc, nsResolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null );

for ( var i = 0; i < snapshot.snapshotLength; ++i ) { (function(title, total, obj) {                           var xmlhttp = sajax_init_object;                            xmlhttp.query = {                                'title': title,                                'action': 'submit'                            };                            xmlhttp.overrideMimeType('text/xml');                            xmlhttp.open( 'GET', wgServer + wgScriptPath + '/index.php?' + QueryString.create( xmlhttp.query ), true);                            xmlhttp.onload = function {

var form = this.responseXML.getElementById('editform'); var text = form.wpTextbox1.value; var old_text = text; var wikiPage = new Mediawiki.Page( text ); wikiPage.removeLink( wgPageName );

text = wikiPage.getText; updateCounter( obj, total ); if( text == old_text ) { // Nothing to do, return updateCounter( obj, total ); return; } else { var postData = { 'wpMinoredit': form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': 'Removing backlinks to ' + wgPageName + " that has been speedily deleted per (CSD " + twinklespeedy.normalized.toUpperCase + ")" + "; " + TwinkleConfig.deletionSummaryAd, 'wpTextbox1': text };                                   var xmlhttp = sajax_init_object; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'POST', wgServer + wgScriptPath + '/index.php?' + QueryString.create( this.query ), true); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlhttp.onload = function { updateCounter( obj, total ); }                                   xmlhttp.send( QueryString.create( postData ) );

}                           }                                            xmlhttp.send( null ); })( snapshot.snapshotItem(i).value, nofnodes, this.statusIndicator );

}

}           xmlhttp.send( null ); }   };    xmlhttp.send( null ); }

twinklespeedy.csdUserCallback = function(e) {

var value = e.target.value; var normalized = twinklespeedy.normalizeHash[ value ]; twinklespeedy.watch = TwinkleConfig.watchSpeedyPages.indexOf( normalized ) != -1; twinklespeedy.usertalk = TwinkleConfig.openUserTalkPageOnSpeedyDelete.indexOf( normalized ) != -1;

var reason = twinklespeedy.reasonHash[ value ];

twinklespeedy.summary = "Requesting speedy deletion (CSD " + normalized + ")." + TwinkleConfig.summaryAd; switch( normalized ) { case 'i8': var date = new Date; twinklespeedy.code = "\{\{NowCommons|month=" + date.getUTCMonthName + "|day=" + date.getUTCDate + "|year=" + date.getUTCFullYear + "|1=" + wgPageName.replace( '_', ' ' ) + "\}\}"; break; case 'g12': url = prompt( 'please enter url if available, including the http://' ); if( url == null ) { return; }       twinklespeedy.code = "\{\{db-" +  value + "|url=" + url + "\}\}"; break; case 'i1': img = prompt( 'enter the image this is redundant to, excluding the Image: prefix' ); if( img == null ) { return; }       twinklespeedy.code = "\{\{db-" +  value + "|1=" + img + "\}\}"; break; default: twinklespeedy.code = "\{\{db-" + value + "\}\}"; break; }

Status.init( twinklespeedy.rendered );

Status.status( 'Updating the page' );

xmlhttp = sajax_init_object; xmlhttp.query = { 'title': wgPageName, 'action': 'submit' }   xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'GET', wgServer + wgScriptPath + '/index.php?' + QueryString.create( xmlhttp.query ), true); xmlhttp.onload = function {

if( this.responseText.indexOf( 'var wgCurRevisionId = false;' ) != -1 ) { Status.error( "It seems that the page doesn't exists, perhaps it has already been deleted" ); return; }       form = this.responseXML.getElementById( 'editform' );

var text = form.wpTextbox1.value;

Status.status( 'Checking for tags on the page...' );

var tag = /(\{\{(?:db-?|delete)\|?.*?\}\})/.exec( text );

if( tag ) { Status.warn( [ htmlNode( 'strong', tag[0] ), " is alread placed on the page." ] ) return; }

var xfd = /(\{\{(?:[rsaitcm]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( 'Updating the page...' ); var postData = { 'wpMinoredit': TwinkleConfig.markSpeedyPagesAsMinor ? true : form.wpMinoredit.checked ? '' : undefined, 'wpWatchthis': twinklespeedy.watch ? true : form.wpWatchthis.checked ? '' : undefined, 'wpStarttime': form.wpStarttime.value, 'wpEdittime': form.wpEdittime.value, 'wpAutoSummary': form.wpAutoSummary.value, 'wpEditToken': form.wpEditToken.value, 'wpSummary': twinklespeedy.summary, 'wpTextbox1': twinklespeedy.code + "\n" + text };       var xmlhttp = sajax_init_object; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'POST', wgServer + wgScriptPath + '/index.php?' + QueryString.create( this.query ), true); xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded'); xmlhttp.onload = function { Status.info( 'Page tagged' ) }; xmlhttp.send( QueryString.create( postData ) ); }   xmlhttp.send( null );

// Open user talk page if requested 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' }       xmlhttp = sajax_init_object; xmlhttp.overrideMimeType('text/xml'); xmlhttp.open( 'GET', wgServer + wgScriptPath + '/api.php?' + QueryString.create( query ), true ); xmlhttp.onload = function { var user = this.responseXML.documentElement.getElementsByTagName('rev')[0].getAttribute('user'); // TODO -> xpath

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; }       }        xmlhttp.send( null ); } }