http://www.mediawiki.org/wiki/Special:Code/MediaWiki/98840
Revision: 98840 Author: raindrift Date: 2011-10-04 00:31:05 +0000 (Tue, 04 Oct 2011) Log Message: ----------- 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 trunk/extensions/UploadWizard/resources/mw.FormDataTransport.js trunk/extensions/UploadWizard/resources/mw.UploadWizard.js trunk/extensions/UploadWizard/resources/mw.UploadWizardUpload.js trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js Modified: trunk/extensions/UploadWizard/resources/mw.ApiUploadFormDataHandler.js =================================================================== --- trunk/extensions/UploadWizard/resources/mw.ApiUploadFormDataHandler.js 2011-10-04 00:12:09 UTC (rev 98839) +++ trunk/extensions/UploadWizard/resources/mw.ApiUploadFormDataHandler.js 2011-10-04 00:31:05 UTC (rev 98840) @@ -6,6 +6,7 @@ mw.ApiUploadFormDataHandler = function( upload, api ) { this.upload = upload; this.api = api; + this.$form = $j( this.upload.ui.form ); this.formData = { action: 'upload', @@ -15,8 +16,9 @@ var _this = this; this.transport = new mw.FormDataTransport( - this.$form, + this.$form[0].action, this.formData, + this.upload, function( fraction ) { _this.upload.setTransportProgress( fraction ); }, Modified: trunk/extensions/UploadWizard/resources/mw.FormDataTransport.js =================================================================== --- trunk/extensions/UploadWizard/resources/mw.FormDataTransport.js 2011-10-04 00:12:09 UTC (rev 98839) +++ trunk/extensions/UploadWizard/resources/mw.FormDataTransport.js 2011-10-04 00:31:05 UTC (rev 98840) @@ -8,13 +8,13 @@ */ -mw.FormDataTransport = function( $form, formData, progressCb, transportedCb ) { - this.$form = $form; +mw.FormDataTransport = function( postUrl, formData, uploadObject, progressCb, transportedCb ) { this.formData = formData; this.progressCb = progressCb; this.transportedCb = transportedCb; + this.uploadObject = uploadObject; - this.postUrl = this.$form[0].action; + this.postUrl = postUrl; this.chunkSize = 1 * 1024 * 1024; //1Mb this.maxRetries = 2; this.retries = 0; @@ -28,7 +28,9 @@ mw.FormDataTransport.prototype = { upload: function() { var _this = this, - file = this.$form.find('input[name=file]')[0].files[0]; + file = this.uploadObject.file; + var bytesAvailable = file.size; + if(file.size > this.chunkSize) { this.uploadChunk(0); } else { @@ -79,15 +81,16 @@ $j.each(this.formData, function(key, value) { formData.append(key, value); }); - formData.append('filename', file.name); - formData.append('file', file); + formData.append('filename', file.name); + formData.append('file', file); + this.xhr.open("POST", _this.postUrl, true); this.xhr.send(formData); } }, uploadChunk: function(offset) { var _this = this, - file = this.$form.find('input[name=file]')[0].files[0], + file = this.uploadObject.file, bytesAvailable = file.size, chunk; Modified: trunk/extensions/UploadWizard/resources/mw.UploadWizard.js =================================================================== --- trunk/extensions/UploadWizard/resources/mw.UploadWizard.js 2011-10-04 00:12:09 UTC (rev 98839) +++ trunk/extensions/UploadWizard/resources/mw.UploadWizard.js 2011-10-04 00:31:05 UTC (rev 98840) @@ -397,13 +397,13 @@ * we don't yet add it to the list of uploads; that only happens when it gets a real file. * @return the new upload */ - newUpload: function() { + newUpload: function( file ) { var _this = this; if ( _this.uploads.length == _this.maxUploads ) { return false; } - var upload = new mw.UploadWizardUpload( _this, '#mwe-upwiz-filelist' ); + var upload = new mw.UploadWizardUpload( _this, '#mwe-upwiz-filelist', file ); _this.uploadToAdd = upload; // we explicitly move the file input to cover the upload button @@ -419,8 +419,7 @@ e.stopPropagation(); } ); // XXX bind to some error state - - + return upload; }, @@ -482,7 +481,7 @@ */ removeEmptyUploads: function() { this.removeMatchingUploads( function( upload ) { - return mw.isEmpty( upload.ui.$fileInputCtrl.val() ); + return mw.isEmpty( upload.filename ); } ); }, Modified: trunk/extensions/UploadWizard/resources/mw.UploadWizardUpload.js =================================================================== --- trunk/extensions/UploadWizard/resources/mw.UploadWizardUpload.js 2011-10-04 00:12:09 UTC (rev 98839) +++ trunk/extensions/UploadWizard/resources/mw.UploadWizardUpload.js 2011-10-04 00:31:05 UTC (rev 98840) @@ -7,7 +7,7 @@ */ ( function( $j ) { -mw.UploadWizardUpload = function( wizard, filesDiv ) { +mw.UploadWizardUpload = function( wizard, filesDiv, providedFile ) { this.index = mw.UploadWizardUpload.prototype.count; mw.UploadWizardUpload.prototype.count++; @@ -22,6 +22,8 @@ this.mimetype = undefined; this.extension = undefined; this.filename = undefined; + this.providedFile = providedFile; + this.file = undefined; this.fileKey = undefined; @@ -30,7 +32,7 @@ this.detailsWeight = 1; // default all same // details - this.ui = new mw.UploadWizardUploadInterface( this, filesDiv ); + this.ui = new mw.UploadWizardUploadInterface( this, filesDiv, providedFile ); // handler -- usually ApiUploadHandler // this.handler = new ( mw.UploadWizard.config[ 'uploadHandlerClass' ] )( this ); @@ -258,18 +260,18 @@ * Checks for file validity, then extracts metadata. * Error out if filename or its contents are determined to be unacceptable * Proceed to thumbnail extraction and image info if acceptable - * @param {HTMLFileInput} file input field + * @param {string} the filename + * @param {Array} the list of files. usually one, can be more for multi-file select. * @param {Function()} callback when ok, and upload object is ready * @param {Function(String, Mixed)} callback when filename or contents in error. Signature of string code, mixed info */ - checkFile: function( fileInput, fileNameOk, fileNameErr ) { + checkFile: function( filename, files, fileNameOk, fileNameErr ) { // check if local file is acceptable var _this = this; // Check if filename is acceptable // TODO sanitize filename - var filename = fileInput.value; var basename = mw.UploadWizardUtil.getBasename( filename ); @@ -301,13 +303,23 @@ if ( $j.inArray( extension.toLowerCase(), mw.UploadWizard.config[ 'fileExtensions' ] ) === -1 ) { fileNameErr( 'ext', extension ); } else { - // extract more info via fileAPI if ( mw.fileApi.isAvailable() ) { - if ( fileInput.files && fileInput.files.length ) { - // TODO multiple files in an input - this.file = fileInput.files[0]; - } + + // An UploadWizardUpload object already exists (us) when we add a file. + // So, when multiple files are provided (via select multiple), add the first file to this UploadWizardUpload + // and create new UploadWizardUpload objects and corresponding interfaces for the rest. + // + // don't process the very first file, since that's this instance's job. + $j.each( files.slice(1), function( i, file ) { + //_this.wizard.setUploadFilled( _this.wizard.newUpload( file ) ); + _this.wizard.newUpload( file ); + } ); + _this.wizard.updateFileCounts(); + + // this input will use the last one. + this.file = files[0]; + // TODO check max upload size, alert user if too big this.transportWeight = this.file.size; if ( !mw.isDefined( this.imageinfo ) ) { @@ -559,10 +571,7 @@ */ getUploadHandler: function(){ if( !this.uploadHandler ){ - if( mw.UploadWizard.config[ 'enableFirefogg' ] - && - typeof( Firefogg ) != 'undefined' - ) { + if( mw.UploadWizard.config[ 'enableFirefogg' ] && typeof( Firefogg ) != 'undefined' ) { mw.log("mw.UploadWizard::getUploadHandler> FirefoggHandler"); this.uploadHandler = new mw.FirefoggHandler( this, this.api ); } else if( mw.UploadWizard.config[ 'enableFormData' ] && Modified: trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js =================================================================== --- trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js 2011-10-04 00:12:09 UTC (rev 98839) +++ trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js 2011-10-04 00:31:05 UTC (rev 98840) @@ -2,25 +2,27 @@ * Create an interface fragment corresponding to a file input, suitable for Upload Wizard. * @param upload * @param div to insert file interface - * @param addInterface interface to add a new one (assumed that we start out there) + * @param providedFile a File object that this ui component should use (optional) */ -mw.UploadWizardUploadInterface = function( upload, filesDiv ) { +mw.UploadWizardUploadInterface = function( upload, filesDiv, providedFile ) { var _this = this; _this.upload = upload; + _this.providedFile = providedFile; + // may need to collaborate with the particular upload type sometimes // for the interface, as well as the uploadwizard. OY. _this.div = $j('<div class="mwe-upwiz-file"></div>').get(0); _this.isFilled = false; - _this.$fileInputCtrl = $j('<input size="1" class="mwe-upwiz-file-input" name="file" type="file"/>'); + _this.$fileInputCtrl = $j('<input size="1" class="mwe-upwiz-file-input" name="file" type="file" multiple="1"/>'); _this.initFileInputCtrl(); _this.$indicator = $j( '<div class="mwe-upwiz-file-indicator"></div>' ); - visibleFilenameDiv = $j('<div class="mwe-upwiz-visible-file"></div>') + var visibleFilenameDiv = $j('<div class="mwe-upwiz-visible-file"></div>') .append( _this.$indicator ) .append( '<div class="mwe-upwiz-visible-file-filename">' + '<div class="mwe-upwiz-file-preview"/>' @@ -92,6 +94,11 @@ true ); + if( providedFile ) { + // if a file is already present, trigger the change event immediately. + _this.$fileInputCtrl.change(); + } + }; @@ -225,15 +232,41 @@ var _this = this; _this.$fileInputCtrl.change( function() { _this.clearErrors(); - _this.upload.checkFile( - this, // the file input, different from _this + + _this.upload.checkFile( + _this.getFilename(), + _this.getFiles(), function() { _this.fileChangedOk(); }, function( code, info ) { _this.fileChangedError( code, info ); } ); } ); }, + /** + * Get a list of the files, defaulting to the value from the input form + * @return Array of file objects + */ + getFiles: function() { + var files = []; + if( this.providedFile && ! this.$fileInputCtrl.get(0).value ) { // default to the fileinput if it's defined. + files[0] = this.providedFile; + } else { + $j.each( this.$fileInputCtrl.get(0).files, function( i, file ) { + files.push( file ); + } ); + } + return files; + }, + // get just the filename. + getFilename: function() { + if( this.providedFile && ! this.$fileInputCtrl.get(0).value ) { // default to the fileinput if it's defined. + return this.providedFile.fileName; + } else { + return this.$fileInputCtrl.get(0).value; + } + }, + /** * Run this when the value of the file input has changed and we know it's acceptable -- this * will update interface to show as much info as possible, including preview. @@ -272,7 +305,7 @@ }, fileChangedError: function( code, info ) { - var filename = this.$fileInputCtrl.get(0).value; + var filename = this.getFilename(); // ok we now have a fileInputCtrl with a "bad" file in it // you cannot blank a file input ctrl in all browsers, so we @@ -281,6 +314,10 @@ this.$fileInputCtrl.replaceWith( $newFileInput ); this.$fileInputCtrl = $newFileInput; this.initFileInputCtrl(); + + if( this.providedFile ) { + this.providedFile = null; + } if ( code === 'ext' ) { this.showBadExtensionError( filename, info ); @@ -395,7 +432,7 @@ */ updateFilename: function() { var _this = this; - var path = _this.$fileInputCtrl.val(); + var path = this.getFilename(); // get basename of file; some browsers do this C:\fakepath\something path = path.replace(/\w:.*\\(.*)$/,'$1'); _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs