User:Rillke/bigChunkedUpload.js
Jump to navigation
Jump to search
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.
Documentation for this user script can be added at User:Rillke/bigChunkedUpload. |
// jshint valid
/*jshint curly:false*/
/*global jQuery:false, mediaWiki:false, MwJSBot:false*/
(function($, mw, undefined) {
'use strict';
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") );
$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"], { /*no styles*/
}, { /*no messages*/
});
mw.loader.using(['mediawiki.commons.MwJSBot', 'jquery.ui.dialog', 'jquery.ui.progressbar', 'jquery.ui.slider', '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 the beta version 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: 5120,
min: 500,
change: function(e, ui) {
$czlz.text(ui.value + ' KiB');
},
slide: function(e, ui) {
$czlz.text(ui.value + ' KiB');
}
}).slider('option', 'value', 4096).appendTo($czWrap),
$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("Summary or Reason: ").appendTo($sumWrap),
$sum = $('<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 $def = new MwJSBot().chunkedUpload({
maxChunkSize: $cz.slider('option', 'value') * 1024,
title: $fn.val().replace(/File:/, ''),
summary: $sum.val() +" (uploaded using [[User:Rillke/bigChunkedUpload.js|chunked upload script]])",
passToAPI: {
upload: {
ignorewarnings: 1
},
finish: {
ignorewarnings: 1
}
},
callbacks: {
loginRequired: _onLogInRequired
}
}, 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 = '';
// 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);
log(curIdPlus1 + '/' + l + '> ' + txt, ddiff, ('err' === type) ? '#E9D977' : '');
}).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).attr('disabled', 'disabled');
// 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();
};
mw.loader.using(['ext.gadget.editDropdown', 'mediawiki.util'], _install);
}(jQuery, mediaWiki));