r98840 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r98839‎ | r98840 | r98841 >
Date:00:31, 4 October 2011
Author:raindrift
Status:ok (Comments)
Tags:
Comment:
added support for multi-file selection
fixed a bug in FormData transport's progress bar method
Modified paths:
  • /trunk/extensions/UploadWizard/resources/mw.ApiUploadFormDataHandler.js (modified) (history)
  • /trunk/extensions/UploadWizard/resources/mw.FormDataTransport.js (modified) (history)
  • /trunk/extensions/UploadWizard/resources/mw.UploadWizard.js (modified) (history)
  • /trunk/extensions/UploadWizard/resources/mw.UploadWizardUpload.js (modified) (history)
  • /trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js (modified) (history)

Diff [purge]

Index: trunk/extensions/UploadWizard/resources/mw.ApiUploadFormDataHandler.js
@@ -6,6 +6,7 @@
77 mw.ApiUploadFormDataHandler = function( upload, api ) {
88 this.upload = upload;
99 this.api = api;
 10+
1011 this.$form = $j( this.upload.ui.form );
1112 this.formData = {
1213 action: 'upload',
@@ -15,8 +16,9 @@
1617
1718 var _this = this;
1819 this.transport = new mw.FormDataTransport(
19 - this.$form,
 20+ this.$form[0].action,
2021 this.formData,
 22+ this.upload,
2123 function( fraction ) {
2224 _this.upload.setTransportProgress( fraction );
2325 },
Index: trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js
@@ -2,25 +2,27 @@
33 * Create an interface fragment corresponding to a file input, suitable for Upload Wizard.
44 * @param upload
55 * @param div to insert file interface
6 - * @param addInterface interface to add a new one (assumed that we start out there)
 6+ * @param providedFile a File object that this ui component should use (optional)
77 */
8 -mw.UploadWizardUploadInterface = function( upload, filesDiv ) {
 8+mw.UploadWizardUploadInterface = function( upload, filesDiv, providedFile ) {
99 var _this = this;
1010
1111 _this.upload = upload;
1212
 13+ _this.providedFile = providedFile;
 14+
1315 // may need to collaborate with the particular upload type sometimes
1416 // for the interface, as well as the uploadwizard. OY.
1517 _this.div = $j('<div class="mwe-upwiz-file"></div>').get(0);
1618 _this.isFilled = false;
1719
18 - _this.$fileInputCtrl = $j('<input size="1" class="mwe-upwiz-file-input" name="file" type="file"/>');
 20+ _this.$fileInputCtrl = $j('<input size="1" class="mwe-upwiz-file-input" name="file" type="file" multiple="1"/>');
1921
2022 _this.initFileInputCtrl();
2123
2224 _this.$indicator = $j( '<div class="mwe-upwiz-file-indicator"></div>' );
2325
24 - visibleFilenameDiv = $j('<div class="mwe-upwiz-visible-file"></div>')
 26+ var visibleFilenameDiv = $j('<div class="mwe-upwiz-visible-file"></div>')
2527 .append( _this.$indicator )
2628 .append( '<div class="mwe-upwiz-visible-file-filename">'
2729 + '<div class="mwe-upwiz-file-preview"/>'
@@ -92,6 +94,11 @@
9395 true
9496 );
9597
 98+ if( providedFile ) {
 99+ // if a file is already present, trigger the change event immediately.
 100+ _this.$fileInputCtrl.change();
 101+ }
 102+
96103 };
97104
98105
@@ -225,15 +232,41 @@
226233 var _this = this;
227234 _this.$fileInputCtrl.change( function() {
228235 _this.clearErrors();
229 - _this.upload.checkFile(
230 - this, // the file input, different from _this
 236+
 237+ _this.upload.checkFile(
 238+ _this.getFilename(),
 239+ _this.getFiles(),
231240 function() { _this.fileChangedOk(); },
232241 function( code, info ) { _this.fileChangedError( code, info ); }
233242 );
234243 } );
235244 },
236245
 246+ /**
 247+ * Get a list of the files, defaulting to the value from the input form
 248+ * @return Array of file objects
 249+ */
 250+ getFiles: function() {
 251+ var files = [];
 252+ if( this.providedFile && ! this.$fileInputCtrl.get(0).value ) { // default to the fileinput if it's defined.
 253+ files[0] = this.providedFile;
 254+ } else {
 255+ $j.each( this.$fileInputCtrl.get(0).files, function( i, file ) {
 256+ files.push( file );
 257+ } );
 258+ }
 259+ return files;
 260+ },
237261
 262+ // get just the filename.
 263+ getFilename: function() {
 264+ if( this.providedFile && ! this.$fileInputCtrl.get(0).value ) { // default to the fileinput if it's defined.
 265+ return this.providedFile.fileName;
 266+ } else {
 267+ return this.$fileInputCtrl.get(0).value;
 268+ }
 269+ },
 270+
238271 /**
239272 * Run this when the value of the file input has changed and we know it's acceptable -- this
240273 * will update interface to show as much info as possible, including preview.
@@ -272,7 +305,7 @@
273306 },
274307
275308 fileChangedError: function( code, info ) {
276 - var filename = this.$fileInputCtrl.get(0).value;
 309+ var filename = this.getFilename();
277310
278311 // ok we now have a fileInputCtrl with a "bad" file in it
279312 // you cannot blank a file input ctrl in all browsers, so we
@@ -281,6 +314,10 @@
282315 this.$fileInputCtrl.replaceWith( $newFileInput );
283316 this.$fileInputCtrl = $newFileInput;
284317 this.initFileInputCtrl();
 318+
 319+ if( this.providedFile ) {
 320+ this.providedFile = null;
 321+ }
285322
286323 if ( code === 'ext' ) {
287324 this.showBadExtensionError( filename, info );
@@ -395,7 +432,7 @@
396433 */
397434 updateFilename: function() {
398435 var _this = this;
399 - var path = _this.$fileInputCtrl.val();
 436+ var path = this.getFilename();
400437 // get basename of file; some browsers do this C:\fakepath\something
401438 path = path.replace(/\w:.*\\(.*)$/,'$1');
402439
Index: trunk/extensions/UploadWizard/resources/mw.UploadWizard.js
@@ -397,13 +397,13 @@
398398 * we don't yet add it to the list of uploads; that only happens when it gets a real file.
399399 * @return the new upload
400400 */
401 - newUpload: function() {
 401+ newUpload: function( file ) {
402402 var _this = this;
403403 if ( _this.uploads.length == _this.maxUploads ) {
404404 return false;
405405 }
406406
407 - var upload = new mw.UploadWizardUpload( _this, '#mwe-upwiz-filelist' );
 407+ var upload = new mw.UploadWizardUpload( _this, '#mwe-upwiz-filelist', file );
408408 _this.uploadToAdd = upload;
409409
410410 // we explicitly move the file input to cover the upload button
@@ -419,8 +419,7 @@
420420 e.stopPropagation();
421421 } );
422422 // XXX bind to some error state
423 -
424 -
 423+
425424 return upload;
426425 },
427426
@@ -482,7 +481,7 @@
483482 */
484483 removeEmptyUploads: function() {
485484 this.removeMatchingUploads( function( upload ) {
486 - return mw.isEmpty( upload.ui.$fileInputCtrl.val() );
 485+ return mw.isEmpty( upload.filename );
487486 } );
488487 },
489488
Index: trunk/extensions/UploadWizard/resources/mw.FormDataTransport.js
@@ -8,13 +8,13 @@
99 */
1010
1111
12 -mw.FormDataTransport = function( $form, formData, progressCb, transportedCb ) {
13 - this.$form = $form;
 12+mw.FormDataTransport = function( postUrl, formData, uploadObject, progressCb, transportedCb ) {
1413 this.formData = formData;
1514 this.progressCb = progressCb;
1615 this.transportedCb = transportedCb;
 16+ this.uploadObject = uploadObject;
1717
18 - this.postUrl = this.$form[0].action;
 18+ this.postUrl = postUrl;
1919 this.chunkSize = 1 * 1024 * 1024; //1Mb
2020 this.maxRetries = 2;
2121 this.retries = 0;
@@ -28,7 +28,9 @@
2929 mw.FormDataTransport.prototype = {
3030 upload: function() {
3131 var _this = this,
32 - file = this.$form.find('input[name=file]')[0].files[0];
 32+ file = this.uploadObject.file;
 33+ var bytesAvailable = file.size;
 34+
3335 if(file.size > this.chunkSize) {
3436 this.uploadChunk(0);
3537 } else {
@@ -79,15 +81,16 @@
8082 $j.each(this.formData, function(key, value) {
8183 formData.append(key, value);
8284 });
83 - formData.append('filename', file.name);
84 - formData.append('file', file);
 85+ formData.append('filename', file.name);
 86+ formData.append('file', file);
 87+
8588 this.xhr.open("POST", _this.postUrl, true);
8689 this.xhr.send(formData);
8790 }
8891 },
8992 uploadChunk: function(offset) {
9093 var _this = this,
91 - file = this.$form.find('input[name=file]')[0].files[0],
 94+ file = this.uploadObject.file,
9295 bytesAvailable = file.size,
9396 chunk;
9497
Index: trunk/extensions/UploadWizard/resources/mw.UploadWizardUpload.js
@@ -7,7 +7,7 @@
88 */
99 ( function( $j ) {
1010
11 -mw.UploadWizardUpload = function( wizard, filesDiv ) {
 11+mw.UploadWizardUpload = function( wizard, filesDiv, providedFile ) {
1212
1313 this.index = mw.UploadWizardUpload.prototype.count;
1414 mw.UploadWizardUpload.prototype.count++;
@@ -22,6 +22,8 @@
2323 this.mimetype = undefined;
2424 this.extension = undefined;
2525 this.filename = undefined;
 26+ this.providedFile = providedFile;
 27+ this.file = undefined;
2628
2729 this.fileKey = undefined;
2830
@@ -30,7 +32,7 @@
3133 this.detailsWeight = 1; // default all same
3234
3335 // details
34 - this.ui = new mw.UploadWizardUploadInterface( this, filesDiv );
 36+ this.ui = new mw.UploadWizardUploadInterface( this, filesDiv, providedFile );
3537
3638 // handler -- usually ApiUploadHandler
3739 // this.handler = new ( mw.UploadWizard.config[ 'uploadHandlerClass' ] )( this );
@@ -258,18 +260,18 @@
259261 * Checks for file validity, then extracts metadata.
260262 * Error out if filename or its contents are determined to be unacceptable
261263 * Proceed to thumbnail extraction and image info if acceptable
262 - * @param {HTMLFileInput} file input field
 264+ * @param {string} the filename
 265+ * @param {Array} the list of files. usually one, can be more for multi-file select.
263266 * @param {Function()} callback when ok, and upload object is ready
264267 * @param {Function(String, Mixed)} callback when filename or contents in error. Signature of string code, mixed info
265268 */
266 - checkFile: function( fileInput, fileNameOk, fileNameErr ) {
 269+ checkFile: function( filename, files, fileNameOk, fileNameErr ) {
267270 // check if local file is acceptable
268271
269272 var _this = this;
270273
271274 // Check if filename is acceptable
272275 // TODO sanitize filename
273 - var filename = fileInput.value;
274276 var basename = mw.UploadWizardUtil.getBasename( filename );
275277
276278
@@ -301,13 +303,23 @@
302304 if ( $j.inArray( extension.toLowerCase(), mw.UploadWizard.config[ 'fileExtensions' ] ) === -1 ) {
303305 fileNameErr( 'ext', extension );
304306 } else {
305 -
306307 // extract more info via fileAPI
307308 if ( mw.fileApi.isAvailable() ) {
308 - if ( fileInput.files && fileInput.files.length ) {
309 - // TODO multiple files in an input
310 - this.file = fileInput.files[0];
311 - }
 309+
 310+ // An UploadWizardUpload object already exists (us) when we add a file.
 311+ // So, when multiple files are provided (via select multiple), add the first file to this UploadWizardUpload
 312+ // and create new UploadWizardUpload objects and corresponding interfaces for the rest.
 313+ //
 314+ // don't process the very first file, since that's this instance's job.
 315+ $j.each( files.slice(1), function( i, file ) {
 316+ //_this.wizard.setUploadFilled( _this.wizard.newUpload( file ) );
 317+ _this.wizard.newUpload( file );
 318+ } );
 319+ _this.wizard.updateFileCounts();
 320+
 321+ // this input will use the last one.
 322+ this.file = files[0];
 323+
312324 // TODO check max upload size, alert user if too big
313325 this.transportWeight = this.file.size;
314326 if ( !mw.isDefined( this.imageinfo ) ) {
@@ -559,10 +571,7 @@
560572 */
561573 getUploadHandler: function(){
562574 if( !this.uploadHandler ){
563 - if( mw.UploadWizard.config[ 'enableFirefogg' ]
564 - &&
565 - typeof( Firefogg ) != 'undefined'
566 - ) {
 575+ if( mw.UploadWizard.config[ 'enableFirefogg' ] && typeof( Firefogg ) != 'undefined' ) {
567576 mw.log("mw.UploadWizard::getUploadHandler> FirefoggHandler");
568577 this.uploadHandler = new mw.FirefoggHandler( this, this.api );
569578 } else if( mw.UploadWizard.config[ 'enableFormData' ] &&

Comments

#Comment by NeilK (talk | contribs)   01:16, 4 October 2011

Paired with Ian for most of this, so marking it ok. On review, there are a few comments we could remove, will followup.

#Comment by Raymond (talk | contribs)   19:25, 4 October 2011

This is bug 26502.

Status & tagging log