Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
mw.loader.load( 'ext.gadget.VisualFileChange' );

/*global mw, $, importScript*/
/*jshint curly:false, scripturl:true, strict:true */

var ns = mw.config.get('wgNamespaceNumber'), //  global [[Bugzilla:33837]] <nowiki>
	ul = mw.config.get('wgUserLanguage'),
	pn = mw.config.get('wgPageName'),
	un = mw.config.get('wgUserName'),
	ac = mw.config.get('wgAction'),
	ti = mw.config.get('wgTitle'),
	cun = "", // (optional) CUSTOM username
	convertToSVGTypes = "geology, meteorology, road sign, text logo",
	GlobalReplaceDefaultReason = '',
	ext, bSVG,
	AjaxDeleteExtraButtons = [];
window.delReqGlobalUsage = 1; // AQD DelReqHandler

function prefillDupe(e) { // hack for AjaxDeleteExtraButtons duplicate
	"use strict";
	if (!e) return;
	var talk_summary, talk_tag;
	if (e.target && e.target.parentNode.id) {
		talk_tag = '{{subst:Speedynote|1=%FILE%|2={{subst:int:File-exists-duplicate|}} [[:File:%PARAMETER%]].}}';
		talk_summary = 'Duplicate notification';
	}
	AjaxQuickDelete.insertTagOnPage(
		"{{duplicate|1=%PARAMETER%|user=%USER%}}",
		"Tagging as duplicate of [[File:%PARAMETER%]]",
		talk_tag,
		talk_summary,
		"Which file is this a duplicate of?"
	);
	setTimeout(function () {  // cleanup prefix / namespace "File:"
		var $t = $('#AjaxQuestion0');
		$t.val($('#mw-imagepage-section-duplicates ul a').eq(0).attr('title')).focusout(function (e) {
			e.preventDefault();
			return $t.val($.trim($t.val()).replace(/^[Ff]ile\:/, ''));
		});
	}, 200);
}
	
if (ns === 6) { /** Files only **/
	
	ext = ti.slice(-3).toUpperCase();
	bSVG = ( !ext.indexOf("SVG") );

	// importScript('MediaWiki:ExCommons.js');  // - copy files to individual Wikis before deleting them on Commons
	
	//importScript('User:Sreejithk2000/JustReplace.js');
	importScript('User:Perhelion/JustReplace+.js');
	importScript('User:Perhelion/cleanup.js'); // File desc. cleanup
	//importScript('User:Magog the Ogre/cleanup.js'); // File desc. cleanup
	//importScript('User:Rillke/bigChunkedUpload.js'); // [[Help:Chunked upload]]
	
	importScript('User:Rillke/LicenseReview.js');
	
	/*// AQD prefill move values
	if (!$('#AjaxRenameLink').length) // AQD prefill move values
		$('#mw-content-text').after($('<div>', {
				id: 'AjaxRenameLink',
				style: 'visibility:hidden'
			}).append([
					$('<span>', {
						id: 'AjaxRenameDestination',
						text: "OOjs UI icon "
					}),
					$('<span>', {
						id: 'AjaxRenameReason',
						text: "[[COM:MOVE#cite_ref-2|move criteria #2]] (+more meaningful)"
					})
				]));*/
	
	if ( bSVG ) { /** SVG only **/
		
		// simple SVG edit (beta)
		importScript('User:Rillke/SVGedit.js');
		
		// W3C-Validator check-link for every SVG (by [[User: Perhelion]] fixed also now for admins); + detailed byte-size
		importScript('User:Perhelion/simpleSVGcheck.js');
		
		AjaxDeleteExtraButtons.push({
			'label' : 'PoorSVG', // TracedSVG
			'tag' : '{{PoorSVG|1=%PARAMETER%}}', // Raster file
			'img_summary' : 'This SVG contains poor traced elements, please revectorize',
			'talk_tag' : '{{subst:TracedSVG/notify|1=%FILE%|2=%PARAMETER%}}',
			'talk_summary' : 'Poor SVG note',
			'prompt_text' : 'Which file is the original of?'
		}, {
			'label' : 'PoorSVG tag only', // TracedSVG
			'tag' : '{{PoorSVG|1=%PARAMETER%}}', // Raster file
			'img_summary' : 'This SVG contains poor traced elements, please revectorize',
			'prompt_text' : 'Which file is the original of?'
		}, {
			'label' : 'BadSVG',
			'tag' : '{{BadSVG}}',
			'img_summary' : 'This file contains raster graphics that should be removed',
			'talk_tag' : '{{subst:BadSVG/notification|1=%FILE%}}',
			'talk_summary' : 'Bad SVG note',
			'prompt_text' : 'Please remove embedded raster graphics?'
		}, {
			'label' : 'BadSVG tag only',
			'tag' : '{{BadSVG}}',
			'img_summary' : 'This file contains raster graphics that should be removed',
			'prompt_text' : 'Please remove embedded raster graphics?'
		}, {
			'label' : 'SVGbug', // SVGbug
			'tag' : '{{SVGbug|1=%PARAMETER%}}', // Raster file
			'img_summary' : 'This SVG contains one or more libRSVG bugs',
			'prompt_text' : 'Description of the bug or a link?'
		});
	} else {
		AjaxDeleteExtraButtons.push({
			'label' : 'ToSVG notify',
			'tag' : '{{Convert to SVG|%PARAMETER%}}',
			'img_summary' : 'This file should be better a SVG',
			'talk_tag' : '{{subst:Please use SVG|1=%FILE%}}',
			'talk_summary' : 'Use SVG note',
			'prompt_text' : 'Please use SVG insteed of raster graphics. Which type?'
		});
		GlobalReplaceDefaultReason = ext + ' → SVG';
	}
	
	// [[Help:QuickDelete]]
	//To watch user talk pages, to which you add tags
	var AjaxDeleteWatchUserTalk = true;
	//To watch file pages, to which you add tags
	var AjaxDeleteWatchFile = true;
	// adding more buttons :
	AjaxDeleteExtraButtons.push( {
                  'label': 'DW',
                  'tag': '{'+'{copyvio|[[COM:DW|Derivative work]]}}',
                  'img_summary': 'This is a [[COM:DW|derivative work]]',
                  'talk_tag': '{'+'{subst:derivativenote|1=%FILE%}}',
                  'talk_summary': '%FILE% is a [[COM:DW|derivative work]]',
                }, {
                  'label': 'Flickr copyvio',
                  'tag': '{'+'{copyvio|[[COM:FW|Flickr-washing]] file}}',
                  'img_summary': 'This is a [[COM:FW|Flickr-washing]] file',
                  'talk_tag': '{'+'{subst:Flickrvionote|1=%FILE%}}',
                  'talk_summary': '%FILE% is a [[COM:FW|Flickr-washing]] file',
                }, {
                  'label': 'Logo',
                  'tag': '{'+'{logo}}',
                  'img_summary': 'This is a non-simple logo, which is not allowed on Commons',
                  'talk_tag': '{'+'{subst:copyvionote|%FILE%}}',
                  'talk_summary': 'Non-simple logos, such as %FILE%, are not allowed on Commons',
                }, {
                  'label': 'Copyvio (www)',
                  'tag': '{'+'{copyvio|1=[[COM:NETCOPYRIGHT|Found elsewhere on the web and unlikely to be own work]]: [https://www.google.com/searchbyimage?image_url={{filepath:{'+'{subst:BASEPAGENAME}}}} Google search].}}',
                  'img_summary': 'speedy deletion: possible copyvio',
                  'talk_tag': '{'+'{subst:copyvionote|1=%FILE%|2=[[COM:NETCOPYRIGHT|Found elsewhere on the web and unlikely to be own work]]: [https://www.google.com/searchbyimage?image_url={{filepath:{'+'{subst:BASEPAGENAME}}}} Google search].}}',
                  'talk_summary': 'Notification of possible copyright violation for %FILE% because it is [[COM:NETCOPYRIGHT|Found elsewhere on the web and unlikely to be own work]].',
                }, {
                  'label': 'Copyvio (source)',
                  'tag': '{'+'{copyvio|1=[[COM:CSD#F4]], License review NOT passed: No evidence of a free license at the claimed source.}}',
                  'img_summary': 'speedy deletion: possible copyvio',
                  'talk_tag': '{'+'{subst:copyvionote|1=%FILE%|2=[[COM:CSD#F4]], License review NOT passed: No evidence of a free license at the claimed source.}}',
                  'talk_summary': 'Notification of possible copyright violation for %FILE% because license review NOT passed: No evidence of a free license at the claimed source.',
                }, {
                  'label': 'Copyvio (fb)',
                  'tag': '{'+'{copyvio|1=[[COM:CSD#F4]], License review NOT passed: Came via Facebook; their [https://www.facebook.com/legal/terms Terms of Use] are incompatible with publishing here.}}',
                  'img_summary': 'speedy deletion: possible copyvio',
                  'talk_tag': '{'+'{subst:copyvionote|1=%FILE%|2=License review NOT passed: Came via Facebook; their [https://www.facebook.com/legal/terms Terms of Use] are incompatible with publishing here.}}',
                  'talk_summary': 'Notification of possible copyright violation for %FILE% because [[COM:CSD#F4]], license review NOT passed: Came via Facebook; their [https://www.facebook.com/legal/terms Terms of Use] are incompatible with publishing here.',
                }, {
                  'label': 'Copyvio (F4)',
                  'tag': '{'+'{copyvio|1=[[COM:CSD#F4]], insufficient permission.}}',
                  'img_summary': 'speedy deletion: [[COM:CSD#F4]], insufficient permission',
                  'talk_tag': '{'+'{subst:copyvionote|1=%FILE%|2=[[COM:CSD#F4]], insufficient permission.}}',
                  'talk_summary': 'Notification of possible copyright violation for %FILE% because [[COM:CSD#F4]], insufficient permission.',
                }, {
		'label' : 'DW No Source',
		'tag' : '{{subst:dw-nsd}}',
		'img_summary' : 'This is a [[COM:DW|derivative work]] and no source is provided',
		'talk_tag' : '{{subst:dw image source|1=%FILE%}}',
		'talk_summary' : 'Original source is missing for %FILE%'
	}, /*{ //notice talk_tag and talk_summary must be '' (void string) if uploader must not be notified
		'label' : 'Duplicate',
		'tag' : '{{duplicate|1=%PARAMETER%|user=%USER%}}',
		'img_summary' : 'Tagging as duplicate of [[File:%PARAMETER%]]', // FIXME!?: $.trim(%PARAMETER%).replace(/^(?:File|Image)\:/, '')
		'talk_tag' : '{{subst:Speedynote|1=%FILE%|2={{subst:int:File-exists-duplicate|}} [[:File:%PARAMETER%]].}}',
		'talk_summary' : 'Duplicate notification',
		'prompt_text' : 'Which file is this a duplicate of?'
		},  {
		'label' : 'Dupe tag only ',
		'tag' : '{{duplicate|1=%PARAMETER%|user=%USER%}}',
		'img_summary' : 'Tagging as duplicate of [[File:%PARAMETER%]]', // FIXME!?: $.trim(%PARAMETER%).replace(/^(?:File|Image)\:/, '')
		'prompt_text' : 'Which file is this a duplicate of?'
		}, */
	{
                    'label': 'Speedy Recreation DR',
                    'tag': '{'+'{speedy|1=[[COM:CSD#G4]], Recreation of content previously deleted per community consensus.}}',
                    'img_summary': 'Requesting speedy deletion because of [[COM:CSD#G4]], Recreation of content previously deleted per community consensus.',
                    'talk_tag': '{'+'{subst:speedynote|1=%FILE%|2=[[COM:CSD#G4]], Recreation of content previously deleted per community consensus.}}',
                    'talk_summary': 'Notification of possible speedy deletion for %FILE% due to [[COM:CSD#G4]], Recreation of content previously deleted per community consensus.',
    }, {
                    'label': 'Speedy G7',
                    'tag': '{'+'{speedy|1=[[COM:CSD#G7]], own work within a week per %PARAMETER%.}}',
                    'img_summary': 'Requesting speedy deletion because of [[COM:CSD#G7]], own work within a week per %PARAMETER%.',
                    'prompt_text': 'Why G7?',
                    'talk_tag': '{'+'{subst:speedynote|1=%FILE%|2=[[COM:CSD#G7]], own work within a week per %PARAMETER%.}}',
                    'talk_summary': 'Notification of possible speedy deletion for %FILE% due to [[COM:CSD#G7]], own work within a week.',
	}, {
                    'label': 'Speedy F10',
                    'tag': '{'+'{SD|F10}}',
                    'img_summary': 'Requesting speedy deletion because of [[COM:CSD#F10|CSD F10]] (personal photos of or by non-contributors)',
                    'talk_tag': '{'+'{subst:speedynote|1=%FILE%|2=[[COM:CSD#F10|CSD F10]] (personal photos of or by non-contributors)}}',
                    'talk_summary': 'Notification of possible speedy deletion for %FILE% due to [[COM:CSD#F10|CSD F10]] (personal photos of or by non-contributors)',
    }, {
                    'label': 'Speedy G10',
                    'tag': '{'+'{SD|G10}}',
                    'img_summary': 'Requesting speedy deletion because of [[COM:CSD#G10|CSD G10]] (files created as advertisements)',
                    'talk_tag': '{'+'{subst:speedynote|1=%FILE%|2=[[COM:CSD#G10|CSD G10]] (files created as advertisements)}}',
                    'talk_summary': 'Notification of possible speedy deletion for %FILE% due to [[COM:CSD#G10|CSD G10]] (files created as advertisements)',
	}, {
                    'label': 'Speedy F10 & G10 Combo',
                    'tag': '{'+'{speedy|1=[[COM:CSD#F10|CSD F10]] (personal photos of or by non-contributors)['+'[Category:Personal files for speedy deletion]] and [[COM:CSD#G10|CSD G10]] (files created as advertisements)['+'[Category:Advertisements for speedy deletion]]}}',
                    'img_summary': 'Requesting speedy deletion because of [[COM:CSD#F10|CSD F10]] (personal photos of or by non-contributors) and [[COM:CSD#G10|CSD G10]] (files created as advertisements)',
                    'talk_tag': '{'+'{subst:speedynote|1=%FILE%|2=[[COM:CSD#F10|CSD F10]] (personal photos of or by non-contributors) and [[COM:CSD#G10|CSD G10]] (files created as advertisements)}}',
                    'talk_summary': 'Notification of possible speedy deletion for %FILE% due to [[COM:CSD#F10|CSD F10]] (personal photos of or by non-contributors) and [[COM:CSD#G10|CSD G10]] (files created as advertisements)',
	}, {
                    'label': 'Speedy Vandalism',
                    'tag': '{'+'{speedy|1=[[COM:CSD#G3]], vandalism.}}',
                    'img_summary': 'Requesting speedy deletion because of [[COM:CSD#G3]], vandalism.',
                    'talk_tag': '{'+'{subst:speedynote|1=%FILE%|2=[[COM:CSD#G3]], vandalism.}}',
                    'talk_summary': 'Notification of possible speedy deletion for %FILE% due to [[COM:CSD#G3]], vandalism.',
	}, {
                    'label': 'Speedy',
                    'tag': '{'+'{speedy|1=%PARAMETER%}}',
                    'img_summary': 'Requesting speedy deletion because %PARAMETER%',
                    'prompt_text': 'Why speedy delete?',
                    'talk_tag': '{'+'{subst:speedynote|1=%FILE%|2=%PARAMETER%}}',
                    'talk_summary': 'Notification of possible speedy deletion for %FILE%',
	}, {
                    'label': 'Uncategorized',
                    'tag': '{{subst:unc}}',
                    'img_summary': 'This file is uncategorized',
                    'talk_tag': '{'+'{subst:Please link images|%FILE%}}',
                    'talk_summary': '%FILE% is a file needs categories',
	}, {
		'label' : 'Wrong License',
		'tag' : '{{wl|1=%PARAMETER%}}',
		'img_summary' : 'Tagging as wrongly licensed because: %PARAMETER%',
		'talk_tag' : '{{subst:Wrong license note|2=%PARAMETER%|1=%FILE%}}',
		'talk_summary' : 'Notification of possible wrong license',
		'prompt_text' : 'Incorrect license: reason?'
	}, {
		'label' : 'Thumbnail',
		'tag' : '{{Thumbnail}}',
		'img_summary' : 'Tagging as thumbnail',
		'talk_tag' : '{{subst:Do not upload thumbnails|1=%FILE%}}',
		'talk_summary' : 'Thumb note',
		'prompt_text' : 'Please re-upload the full resolution version?'
	}, {
		'label' : 'Watermark',
		'tag' : '{{Watermark|1=}}',
		'img_summary' : 'This file contains a watermark that should be removed',
		'talk_tag' : '{{subst:No watermarks|1=:%FILE%}}',
		'talk_summary' : 'Watermarks note',
		'prompt_text' : 'Please remove Watermarks?'
        }, {
                'label': 'Watermark (No User Notice)',
                'tag': '{'+'{watermark}}',
                'img_summary': 'There is a watermark and/or a timestamp on the image',
        }, {
                'label': 'Watermark Removed',
                'tag': '{'+'{Attribution metadata from licensed image}}',
                'img_summary': 'There was a watermark and/or a timestamp on the image',
	} );

	// [[MediaWiki:Gadget-AjaxQuickDelete.js]]
	$.when(mw.loader.using('mediawiki.util'), $.ready).done(function () {
		$(mw.util.addPortletLink('p-tb', null, "Duplicate", 't-dupe', null)).click(prefillDupe);
		$(mw.util.addPortletLink('p-tb', null, "Dupe tag only", null, null,'#t-dupe')).click(prefillDupe);
		mw.util.addPortletLink('p-cactions', 'https://tools.wmflabs.org/derivative/deri1.php?image=File:' + ti, "derivateFX", 't-derivate', null);
	});

	// make editing and adding descriptions easier
	// importScript('User:MarkTraceur/editDescriptions.js'); too beta
} // Files only end

if (ns === -1) 
	mw.loader.load( "https://de.wikipedia.org/w/index.php?title=MediaWiki:Gadget-DeepCat.js&action=raw&ctype=text/javascript" );
else
	mw.loader.load('//meta.wikimedia.org/w/index.php?title=User:Hoo_man/smart_rollback.js&action=raw&ctype=text/javascript');

// SORT CONVERT-TO-SVG TAGS:
if (ns === 14 || (ns === 6 /*&& ["edit", "submit"].indexOf(ac) !== -1*/ && !/SVG/i.test(ti.slice(-3))))
	importScript('User:Perhelion/fixconverttosvg.js');
if (ns === 14 && ac === "view") {
	importScript('User:TheDJ/wdcat.js');
	importScript('User:Perhelion/massrename.js'); 
}

/* Admin only */
if (ns % 2 === 1 && $( '.com-edit-request-admin-area' ) ) importScript( 'MediaWiki:FulfillEditRequest.js' );

// Insert a personalized Texttemplate into the Special:Upload edit box.
//  I upload mostly my own work; preload input form; adapted from [[User: Dschwen]]
$(function () {
	"use strict";
	if (pn === 'Special:Upload' && /&uselang=([^&]*)ownwork/.test(location.search)) {
		var re = RegExp.$1;
		//mw.loader.using('moment',function(){
		setTimeout(function () {
			$('#wpUploadDescription').val(
				'=={{int:filedesc}}==\n' +
				'{{Information\n' +
				'|description=\n{{en|1=}}\n' +
				((re) ? '{{' + re + '|1=}}\n' : '') +
				'|source={{own based|…}}\n' +
				'|date=' + '{{Originaluploaddate|}} {{vectorization}} {{Uploaddate|{{subst:CURRENTYEAR}}-{{subst:CURRENTMONTH}}-{{subst:CURRENTDAY2}}}}\n' + 
				//+ moment().format('YYYY-MM-DD') + '}}\n' +
				'|author={{AutVec||' + un + '}}\n' +
				'|permission=\n' +
				'|other_versions=\n' +
				'<gallery widths="100" heights="100" showfilename>\n\n</gallery>\n' +
				'|other_fields={{Igen|h|+|s=|u='+ un +'}}\n' +
				'}}\n\n' +
				'=={{int:license-header}}==\n' +
				'{{self|GFDL|cc-by-sa-4.0|author=I, [[User:' + un + '|' + cun + ']]}}');
		}, 100);
		//});
	} else
		$('#n-uploadbtn').children('a').attr('href', '//commons.wikimedia.org/w/index.php?title=Special:Upload&uselang=' +
			((ul === 'en') ? '' : ul) + 'ownwork');
	// [[Mediawiki:Edittools]] 	smaller (HACK)
	if (!['edit', 'submit'].indexOf(ac)) {
		$.when(mw.loader.using(['ext.wikiEditor', 'mediawiki.util']), $.ready).then(mw.util.addCSS(".page-Edittools1.page-characters {font-size:11px}"));
		// Autocomplete for links and templates, written by [[משתמש:ערן]]
		mw.loader.load('//he.wikipedia.org/w/load.php?modules=ext.gadget.autocomplete', 'text/javascript', false);
	}
});

////////// Cat-A-Lot user preferences //////////
window.catALotPrefs = {
	"watchlist" : "watch",
	"minor" : true,
	"editpages" : true,
	"docleanup" : true,
	"subcatcount" : 50
};

/* MediaWiki:Gadget-markAdmins.js configuration */
window.markAdminCfg = {
	groups: {
		'steward':			{ enabled: 1 },
		'vrt-permissions':		{ enabled: 1 },
		'image-reviewer':	{ enabled: 1 }
	}
};

//vFCProfil/////////////////////////////////////
/////// VISUAL FILE CHANGE CONFIGURATION ///////
///// DO NOT MODIFY BY HAND - FINGERS AWAY! ////
////////////////////////////////////////////////
window.vFC_Profiles = {"SVG":{"editInputs":{"mdDeleteReason":"","mdEditSummary":"→SVG","mdReplacePermission":false,"mdDeleteHeading":"Files in [[:Category:Diagrams in German]] ","mdTalkNote":"Yours sincerely,","mdRRegEx1":true,"mdRVar1":true,"mdMatchText1":"/Category:Charts in English/g","mdReplaceText1":"Category:SVG charts in English","mdRRegEx2":false,"mdRVar2":true,"mdMatchText2":"","mdReplaceText2":"","selPreserve":"secure","alsoPreserve":""},"action":"c_replace","objectMembers":{"queryParams":{"target":"Category:Charts in English","cmdir":"asc","cmsort":"sortkey","cmstartsortkey":"","cmcontinue":"file|57494b49534f555243452028454e2920464952535420313030302056414c49444154494f4e532e504e47|25826615"},"startInput":{"mode":"Category","modeCat":true,"modeUser":false,"modePage":false,"target":"Category:Charts in English","loadThumbs":true,"loadWikitext":true,"startDate":"","startFile":""}},"proceedAt":{"vals":["file|454c454354524f4e4943204348454154494e4720504152454e54532050455243455054494f4e532e504e47|17574410","file|57494b49534f555243452028454e2920464952535420313030302056414c49444154494f4e532e504e47|25826615"],"setVals":["cmcontinue"]},"time":"2015-07-21T16:50:16.750Z"}};
//////////////////////////////////vFCProfilEnd//
//</nowiki>

//catALot///////////////////////////////////////
////////// Cat-a-lot user preferences //////////
window.catALotPrefs = {"redir_category":"Category redirects","watchlist":"nochange","minor":true,"editpages":false,"docleanup":true,"subcatcount":50};
////////////////////////////////////catALotEnd//
function rollbackSummary() {
  var hasRollback = $("span.mw-rollback-link");
  if (hasRollback[0]) {
    mw.util.addPortletLink('p-cactions', 'javascript:setRollbackSummary()', "rollback summary", "ca-rollbacksummary", "Set rollback link edit summary");
  }
}
$(rollbackSummary);
function setRollbackSummary() {
  summary = prompt("Change the default rollback summary for rollback links on this page to:", "");
  if (!summary) {
    for (var i in document.links) {
      if (document.links[i].href.indexOf('summary=') != -1) {
        document.links[i].href = document.links[i].href.substring(0, document.links[i].href.indexOf('summary=')-1);
      }
    }
  }
  else {
  summary = "&summary=" + encodeURIComponent(summary);
    for (var i in document.links) {
      if (document.links[i].href.indexOf('action=rollback') != -1) {
        document.links[i].href += summary;
      }
    }
  }
}
/*jshint curly:false*/
/*global jQuery:false, mediaWiki:false, MwJSBot:false*/

( function( $, mw, undefined ) {
	'use strict';

	var modeNewFile;

	function ucFirst( s ) {
		return s[ 0 ].toUpperCase() + s.slice( 1 );
	}

	var _install = function() {

		var $reuploadLink = $( '#mw-imagepage-reupload-link' )
			.find( 'a' ),
			$activationLinks;

		if ( $reuploadLink.length ) {
			$activationLinks = $( '<a>', {
					text: " (chunked upload)"
				} )
				.attr( {
					href: '#chunked upload'
				} )
				.insertAfter( $reuploadLink );

			$activationLinks = $activationLinks.add(
				mw.libs.commons.ui.addEditLink(
					'#chunked upload',
					"upload new version (chunked)",
					'e-chunkedupload-overwrite',
					"Overwrite file with another one using chunked uploading" ) );
		} else if ( mw.config.get( 'wgCanonicalNamespace' ) === 'File' ) {
			var title, validTitle;
			try {
				title = mw.config.get( 'wgTitle' );
				validTitle = new mw.Title( title );

				validTitle = validTitle.ext.length && !/(?:\/|\#|\:)/.test( title );
			} catch ( ex ) {}
			if ( validTitle ) {
				$activationLinks = $( mw.libs.commons.ui.addEditLink(
					'#chunked upload',
					"upload (chunked)",
					'e-chunkedupload-overwrite',
					"Create new file using chunked uploading" ) );
				modeNewFile = true;
			}
		}
		if ( $activationLinks ) $activationLinks.click( window.bigChunkedUpload );
		if ( mw.util.getParamValue( 'chunkedupload' ) ) window.bigChunkedUpload();
	};

	window.bigChunkedUpload = function( e ) {
		if ( e ) e.preventDefault();
		if ( null === mw.loader.getState( 'mediawiki.commons.MwJSBot' ) ) {
			mw.loader.implement( 'mediawiki.commons.MwJSBot', [
				"//commons.wikimedia.org/w/index.php?action=raw&ctype=text/javascript&title=User:Rillke/MwJSBot.js&_=2"
			], { /*no styles*/ }, { /*no messages*/ } );
		}
		mw.loader.using( [
			'mediawiki.commons.MwJSBot',
			'jquery.ui',
			'jquery.ui',
			'jquery.ui',
			'mediawiki.util' ], _bigChunkedUpload );
	};

	var _bigChunkedUpload = function() {
		var instanceId = 'i' + Math.round( Math.random() * 1073741824 ),
			start,
			makeWikiLink = function( t, text ) {
				return $( '<a>' )
					.attr( {
						href: mw.util.getUrl( t ),
						target: '_blank',
						title: t
					} )
					.text( text || t );
			},
			$dlg = $( '<div>' ),
			w = Math.min( $( window )
				.width(), 1200 ),
			$logInRequired = $( '<div class="ui-state-highlight" style="display:none; cursor:pointer">' )
			.text( "To continue uploading, please log in and click here after you did so. Script will try to resume. Error reported by server is: " )
			.appendTo( $dlg ),
			$progDiv = $( '<div>' )
			.appendTo( $dlg ),
			$progBar = $( '<div>' )
			.css( {
				width: '98%',
				padding: '2px'
			} )
			.progressbar( {
				value: 0
			} )
			.appendTo( $dlg ),
			$progConsole = $( '<div>' )
			.css( {
				'background': 'black',
				'color': 'white',
				'font-family': '\'Lucida Console\',Console,monospace',
				'overflow': 'auto',
				'width': '98%',
				'height': '200px',
				'border': '1px solid grey',
				'padding': '2px',
				'white-space': 'pre-wrap',
				'resize': 'both'
			} )
			.text( 'Hi, ' + mw.config.get( 'wgUserName' ) + '! Thank you for testing version 0.0.1 of ' )
			.append( makeWikiLink( 'User:Rillke/bigChunkedUpload.js' ), '.' )
			.appendTo( $dlg ),
			pad = function( digit, number, input ) {
				input += '';
				return new Array( Math.max( number + 1 - input.length, 1 ) )
					.join( digit ) + input;
			},
			$lastLogLineEndSpan,
			log = function( what, time, color ) {
				var $logline = $( '<div>' )
					.text( pad( '0', 5, time ) + ': ' + what );
				if ( color ) $logline.css( 'color', color );
				$lastLogLineEndSpan = $( '<span>' )
					.appendTo( $logline );
				$progConsole.append( $logline );
				$progConsole.clearQueue()
					.animate( {
						scrollTop: $progConsole.scrollTop() + $logline.position()
							.top
					}, 800 );
			},
			logInlineProgress = function( what ) {
				if ( $lastLogLineEndSpan ) $lastLogLineEndSpan.text( what );
			},
			$progTextDiv = $( '<div>' )
			.text( "Ready. Selecting a file will immediately start the upload." )
			.appendTo( $progDiv ),
			$options = $( '<fieldset>' )
			.appendTo( $dlg ),
			$optionsL = $( '<legend>' )
			.text( "Upload options" )
			.appendTo( $options ),
			$czWrap = $( '<div>' )
			.appendTo( $options ),
			$czl = $( '<label for="chunksize' + instanceId + '" style="display:block">' )
			.text( "Chunk size: " )
			.appendTo( $czWrap ),
			$czlz = $( '<span>' )
			.appendTo( $czl ),
			$cz = $( '<div id="chunksize' + instanceId + '">' )
			.css( {
				width: '98%'
			} )
			.slider( {
				max: 20480,
				min: 100,
				change: function( e, ui ) {
					$czlz.text( ui.value + ' KiB' );
				},
				slide: function( e, ui ) {
					$czlz.text( ui.value + ' KiB' );
				}
			} )
			.slider( 'option', 'value', 4096 )
			.appendTo( $czWrap ),
			$useStashWrap = $( '<div>' )
			.appendTo( $options ),
			$useStash = $( '<input type="checkbox" checked="checked" id="usestash' + instanceId + '" />' )
			.appendTo( $useStashWrap ),
			$useStashL = $( '<label for="usestash' + instanceId + '">' )
			.text( " use stash and async (recommended for large videos and photos)" )
			.appendTo( $useStashWrap ),
			$fnWrap = $( '<div>' )
			.appendTo( $options ),
			$fnl = $( '<label for="filename' + instanceId + '" style="display:block">' )
			.text( "File name: " )
			.appendTo( $fnWrap ),
			$fn = $( '<input type="text" style="width:98%" placeholder="File:Filename.ext" title="file name goes here" id="filename' + instanceId + '">' )
			.val( mw.config.get( 'wgPageName' ) )
			.appendTo( $fnWrap ),
			$sumWrap = $( '<div>' )
			.appendTo( $options ),
			$suml = $( '<label for="summary' + instanceId + '" style="display:block">' )
			.text( modeNewFile ? "File description" : "Summary or Reason: " )
			.appendTo( $sumWrap ),
			$sum = ( modeNewFile ? $( '<textarea style="width:98%; height: 7em;" placeholder="File description" title="file description goes here" id="summary' + instanceId + '">' )
				.appendTo( $sumWrap ) : $( '<input type="text" style="width:98%" placeholder="Reason/Summary" title="reason/summary go here" id="summary' + instanceId + '">' )
				.appendTo( $sumWrap ) ),
			$fsel = $( '<input type="file" id="files" name="file" style="width:98%">' )
			.appendTo( $options )
			.change( function( e ) {
				start = new Date();

				var lastdate,
					oldOnBeforeUnload = window.onbeforeunload,
					oldDocTitle = document.title,
					filename = ucFirst( $fn.val()
						.replace( /File:/, '' )
						.replace( /_/g, ' ' ) ),
					lastblink,
					_blink = function( $node ) {
						if ( lastblink ) clearTimeout( lastblink );
						$node.addClass( 'ui-state-error' );
						setTimeout( function() {
							$node.removeClass( 'ui-state-error' );
						}, 1000 );
					},
					_onLogInRequired = function( err, callWhenDone ) {
						var _onNodeClick = function() {
							$logInRequired.unbind( 'click', _onNodeClick )
								.hide();
							callWhenDone();
						};
						$logInRequired.find( 'span' )
							.first()
							.remove();
						$logInRequired.append( $( '<span>' )
								.text( err ) )
							.show()
							.click( _onNodeClick );
					},
					_onUploadProgress = function( progressCalculated, date ) {
						if ( !lastdate ) lastdate = start;
						if ( ( date - lastdate ) < 200 && progressCalculated !== 1 ) return;
						lastdate = date;
						progressCalculated = Math.round( progressCalculated, 1 );
						logInlineProgress( ' Upload: ' + progressCalculated + '%' );
					},
					_updateProgressBar = function( progressCalculated, date ) {
						if ( !lastdate ) lastdate = start;
						if ( ( date - lastdate ) < 200 && progressCalculated !== 100 ) return;
						$progBar.progressbar( 'option', 'value', progressCalculated );
						document.title = Math.round( progressCalculated ) + "% of " + filename + " uploaded  - Chunked upload - Wikimedia Commons";
					};

				if ( !filename ) return _blink( $fn );

				var params = {
					maxChunkSize: $cz.slider( 'option', 'value' ) * 1024,
					retry: {
						serverError: 250
					},
					title: $fn.val()
						.replace( /File:/, '' ),
					summary: '[[c:User:Rillke/bigChunkedUpload.js]]: ' + $sum.val(),
					useStash: $useStash.prop( 'checked' ),
					async: $useStash.prop( 'checked' ),
					passToAPI: {
						upload: {
							ignorewarnings: 1
						},
						finish: {
							ignorewarnings: 1
						}
					},
					callbacks: {
						loginRequired: _onLogInRequired
					}
				};
				if ( modeNewFile ) {
					params.text = $sum.val();
				}

				var $def = new MwJSBot()
					.chunkedUpload( params, this.files[ 0 ] )
					.progress( function( type, chunkinfo, txt ) {
						var cc = chunkinfo.currentchunk,
							idIsNumber = ( 'number' === typeof cc.id ),
							curIdPlus1 = idIsNumber ? ( cc.id + 1 ) : cc.id,
							curId = idIsNumber ? cc.id : 0,
							l = chunkinfo.length,
							progressCalculated = ( ( curId ) / l ) * 100 + ( cc.progress / l ),
							d = new Date(),
							ddiff = Math.round( ( d - start ) / 1000 ),
							prog = '',
							color = '';

						// second term respects progress of current chunk
						if ( idIsNumber ) _updateProgressBar( progressCalculated );

						// handle these often frequently occuring events differently
						if ( 'uploadstatus' === type ) {
							return _onUploadProgress( cc.progress, d );
						}

						txt = txt || cc.progressText;
						prog += "Uploaded part " + curIdPlus1 + " of " + l + ";";
						prog += " Time elapsed: " + ddiff + "s ;";
						prog += " Status: " + txt;
						$progTextDiv.text( prog );
						switch ( type ) {
							case 'err':
							case 'stuck':
								color = '#E9D977';
								break;
							default:
								break;
						}
						log( curIdPlus1 + '/' + l + '> ' + txt, ddiff, color );

					} )
					.done( function() {
						var txt = "DONE.",
							d = new Date(),
							ddiff = Math.round( ( d - start ) / 1000 );

						$progDiv.text( txt );
						log( txt, ddiff, '#77E9C7' );
						window.onbeforeunload = oldOnBeforeUnload;
						window.location.href = "/wiki/File:" + encodeURIComponent( $fn.val()
							.replace( /^File:/i, "" ) );
					} )
					.fail( function( txt ) {
						txt = "FAILED: " + txt;

						var d = new Date(),
							ddiff = Math.round( ( d - start ) / 1000 );

						$progDiv.text( txt );
						log( txt, ddiff, '#E977C7' );
						window.onbeforeunload = oldOnBeforeUnload;
						document.title = "FAILED! File upload failed - Chunked upload - Wikimedia Commons";
						setTimeout( function() {
							document.title = oldDocTitle;
						}, 10000 );
					} );

				$fn.add( $sum )
					.add( $fsel )
					.add( $useStash )
					.attr( 'disabled', 'disabled' );
				$cz.slider( 'option', 'disabled', true );

				// Prevent leaving the page accidentally
				window.onbeforeunload = function() {
					return "Upload seems to be still in progress. Do you really wish to quit?";
				};
			} );

		$dlg.dialog( {
			'title': "Overwrite existing files using Chunked Upload protocol",
			//'height': $(window).height(),
			'width': w
		} );

		// Set focus to summary-field
		$sum.focus();
	};

	// Register globally
	if ( $.inArray( mw.config.get( 'wgDBname' ), [ 'commonswiki', 'commonsarchivewiki' ] ) < 0 ) {
		// Register Commons RL modules
		mw.loader.addSource( { commonswiki: "//commons.wikimedia.org/w/load.php" } );
	
		mw.loader.register([
			[ "ext.gadget.editDropdown", "ver1_svg", [], null, "commonswiki" ],
			[ "ext.gadget.libAPI", "ver1_svg", [], null, "commonswiki" ]
		]);
	}

	mw.loader.using( [ 'ext.gadget.editDropdown', 'mediawiki.util', 'mediawiki.Title' ], _install );

}( jQuery, mediaWiki ) );
User:Kanonkas/rollbackSummary.js