User:Begoon/bigChunkedUpload.js

////////////////////////////////////// // See User:Begoon/bigChunkedUpload // //////////////////////////////////////

/*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 = $( '', {					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 $( '' ) .attr( {						href: mw.util.getUrl( t ),						target: '_blank',						title: t					} ) .text( text || t ); },			$dlg = $( ' ' ), w = Math.min( $( window )				.width, 1200 ), $logInRequired = $( ' ' ) .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 = $( ' ' ) .appendTo( $dlg ), $progBar = $( ' ' ) .css( {				width: '98%',				padding: '2px'			} ) .progressbar( {				value: 0			} ) .appendTo( $dlg ), $progConsole = $( ' ' ) .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 = $( ' ' ) .text( pad( '0', 5, time ) + ': ' + what ); if ( color ) $logline.css( 'color', color ); $lastLogLineEndSpan = $( ' ' ) .appendTo( $logline ); $progConsole.append( $logline ); $progConsole.clearQueue .animate( {						scrollTop: $progConsole.scrollTop + $logline.position							.top					}, 800 ); },			logInlineProgress = function( what ) { if ( $lastLogLineEndSpan ) $lastLogLineEndSpan.text( what ); },			$progTextDiv = $( ' ' ) .text( "Ready. Selecting a file will immediately start the upload." ) .appendTo( $progDiv ), $options = $( ' ' ) .appendTo( $dlg ), $optionsL = $( ' ' ) .text( "Upload options" ) .appendTo( $options ), $czWrap = $( ' ' ) .appendTo( $options ), $czl = $( '' ) .text( "Chunk size: " ) .appendTo( $czWrap ), $czlz = $( ' ' ) .appendTo( $czl ), $cz = $( '' ) .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 = $( ' ' ) .appendTo( $options ), $useStash = $( '' ) .appendTo( $useStashWrap ), $useStashL = $( '' ) .text( " use stash and async (recommended for large videos and photos)" ) .appendTo( $useStashWrap ), $fnWrap = $( ' ' ) .appendTo( $options ), $fnl = $( '' ) .text( "File name: " ) .appendTo( $fnWrap ), $fn = $( '' ) .val( mw.config.get( 'wgPageName' ) ) .appendTo( $fnWrap ), $sumWrap = $( ' ' ) .appendTo( $options ), $suml = $( '' ) .text( modeNewFile ? "File description" : "Summary or Reason: " ) .appendTo( $sumWrap ), $sum = ( modeNewFile ? $( '' )				.appendTo( $sumWrap ) : $( '' )				.appendTo( $sumWrap ) ), $fsel = $( '' ) .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( $( ' ' )								.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 ) );