Index: trunk/extensions/UploadWizard/resources/mw.ApiUploadFormDataHandler.js |
— | — | @@ -6,6 +6,7 @@ |
7 | 7 | mw.ApiUploadFormDataHandler = function( upload, api ) { |
8 | 8 | this.upload = upload; |
9 | 9 | this.api = api; |
| 10 | + |
10 | 11 | this.$form = $j( this.upload.ui.form ); |
11 | 12 | this.formData = { |
12 | 13 | action: 'upload', |
— | — | @@ -15,8 +16,9 @@ |
16 | 17 | |
17 | 18 | var _this = this; |
18 | 19 | this.transport = new mw.FormDataTransport( |
19 | | - this.$form, |
| 20 | + this.$form[0].action, |
20 | 21 | this.formData, |
| 22 | + this.upload, |
21 | 23 | function( fraction ) { |
22 | 24 | _this.upload.setTransportProgress( fraction ); |
23 | 25 | }, |
Index: trunk/extensions/UploadWizard/resources/mw.UploadWizardUploadInterface.js |
— | — | @@ -2,25 +2,27 @@ |
3 | 3 | * Create an interface fragment corresponding to a file input, suitable for Upload Wizard. |
4 | 4 | * @param upload |
5 | 5 | * @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) |
7 | 7 | */ |
8 | | -mw.UploadWizardUploadInterface = function( upload, filesDiv ) { |
| 8 | +mw.UploadWizardUploadInterface = function( upload, filesDiv, providedFile ) { |
9 | 9 | var _this = this; |
10 | 10 | |
11 | 11 | _this.upload = upload; |
12 | 12 | |
| 13 | + _this.providedFile = providedFile; |
| 14 | + |
13 | 15 | // may need to collaborate with the particular upload type sometimes |
14 | 16 | // for the interface, as well as the uploadwizard. OY. |
15 | 17 | _this.div = $j('<div class="mwe-upwiz-file"></div>').get(0); |
16 | 18 | _this.isFilled = false; |
17 | 19 | |
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"/>'); |
19 | 21 | |
20 | 22 | _this.initFileInputCtrl(); |
21 | 23 | |
22 | 24 | _this.$indicator = $j( '<div class="mwe-upwiz-file-indicator"></div>' ); |
23 | 25 | |
24 | | - visibleFilenameDiv = $j('<div class="mwe-upwiz-visible-file"></div>') |
| 26 | + var visibleFilenameDiv = $j('<div class="mwe-upwiz-visible-file"></div>') |
25 | 27 | .append( _this.$indicator ) |
26 | 28 | .append( '<div class="mwe-upwiz-visible-file-filename">' |
27 | 29 | + '<div class="mwe-upwiz-file-preview"/>' |
— | — | @@ -92,6 +94,11 @@ |
93 | 95 | true |
94 | 96 | ); |
95 | 97 | |
| 98 | + if( providedFile ) { |
| 99 | + // if a file is already present, trigger the change event immediately. |
| 100 | + _this.$fileInputCtrl.change(); |
| 101 | + } |
| 102 | + |
96 | 103 | }; |
97 | 104 | |
98 | 105 | |
— | — | @@ -225,15 +232,41 @@ |
226 | 233 | var _this = this; |
227 | 234 | _this.$fileInputCtrl.change( function() { |
228 | 235 | _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(), |
231 | 240 | function() { _this.fileChangedOk(); }, |
232 | 241 | function( code, info ) { _this.fileChangedError( code, info ); } |
233 | 242 | ); |
234 | 243 | } ); |
235 | 244 | }, |
236 | 245 | |
| 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 | + }, |
237 | 261 | |
| 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 | + |
238 | 271 | /** |
239 | 272 | * Run this when the value of the file input has changed and we know it's acceptable -- this |
240 | 273 | * will update interface to show as much info as possible, including preview. |
— | — | @@ -272,7 +305,7 @@ |
273 | 306 | }, |
274 | 307 | |
275 | 308 | fileChangedError: function( code, info ) { |
276 | | - var filename = this.$fileInputCtrl.get(0).value; |
| 309 | + var filename = this.getFilename(); |
277 | 310 | |
278 | 311 | // ok we now have a fileInputCtrl with a "bad" file in it |
279 | 312 | // you cannot blank a file input ctrl in all browsers, so we |
— | — | @@ -281,6 +314,10 @@ |
282 | 315 | this.$fileInputCtrl.replaceWith( $newFileInput ); |
283 | 316 | this.$fileInputCtrl = $newFileInput; |
284 | 317 | this.initFileInputCtrl(); |
| 318 | + |
| 319 | + if( this.providedFile ) { |
| 320 | + this.providedFile = null; |
| 321 | + } |
285 | 322 | |
286 | 323 | if ( code === 'ext' ) { |
287 | 324 | this.showBadExtensionError( filename, info ); |
— | — | @@ -395,7 +432,7 @@ |
396 | 433 | */ |
397 | 434 | updateFilename: function() { |
398 | 435 | var _this = this; |
399 | | - var path = _this.$fileInputCtrl.val(); |
| 436 | + var path = this.getFilename(); |
400 | 437 | // get basename of file; some browsers do this C:\fakepath\something |
401 | 438 | path = path.replace(/\w:.*\\(.*)$/,'$1'); |
402 | 439 | |
Index: trunk/extensions/UploadWizard/resources/mw.UploadWizard.js |
— | — | @@ -397,13 +397,13 @@ |
398 | 398 | * we don't yet add it to the list of uploads; that only happens when it gets a real file. |
399 | 399 | * @return the new upload |
400 | 400 | */ |
401 | | - newUpload: function() { |
| 401 | + newUpload: function( file ) { |
402 | 402 | var _this = this; |
403 | 403 | if ( _this.uploads.length == _this.maxUploads ) { |
404 | 404 | return false; |
405 | 405 | } |
406 | 406 | |
407 | | - var upload = new mw.UploadWizardUpload( _this, '#mwe-upwiz-filelist' ); |
| 407 | + var upload = new mw.UploadWizardUpload( _this, '#mwe-upwiz-filelist', file ); |
408 | 408 | _this.uploadToAdd = upload; |
409 | 409 | |
410 | 410 | // we explicitly move the file input to cover the upload button |
— | — | @@ -419,8 +419,7 @@ |
420 | 420 | e.stopPropagation(); |
421 | 421 | } ); |
422 | 422 | // XXX bind to some error state |
423 | | - |
424 | | - |
| 423 | + |
425 | 424 | return upload; |
426 | 425 | }, |
427 | 426 | |
— | — | @@ -482,7 +481,7 @@ |
483 | 482 | */ |
484 | 483 | removeEmptyUploads: function() { |
485 | 484 | this.removeMatchingUploads( function( upload ) { |
486 | | - return mw.isEmpty( upload.ui.$fileInputCtrl.val() ); |
| 485 | + return mw.isEmpty( upload.filename ); |
487 | 486 | } ); |
488 | 487 | }, |
489 | 488 | |
Index: trunk/extensions/UploadWizard/resources/mw.FormDataTransport.js |
— | — | @@ -8,13 +8,13 @@ |
9 | 9 | */ |
10 | 10 | |
11 | 11 | |
12 | | -mw.FormDataTransport = function( $form, formData, progressCb, transportedCb ) { |
13 | | - this.$form = $form; |
| 12 | +mw.FormDataTransport = function( postUrl, formData, uploadObject, progressCb, transportedCb ) { |
14 | 13 | this.formData = formData; |
15 | 14 | this.progressCb = progressCb; |
16 | 15 | this.transportedCb = transportedCb; |
| 16 | + this.uploadObject = uploadObject; |
17 | 17 | |
18 | | - this.postUrl = this.$form[0].action; |
| 18 | + this.postUrl = postUrl; |
19 | 19 | this.chunkSize = 1 * 1024 * 1024; //1Mb |
20 | 20 | this.maxRetries = 2; |
21 | 21 | this.retries = 0; |
— | — | @@ -28,7 +28,9 @@ |
29 | 29 | mw.FormDataTransport.prototype = { |
30 | 30 | upload: function() { |
31 | 31 | 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 | + |
33 | 35 | if(file.size > this.chunkSize) { |
34 | 36 | this.uploadChunk(0); |
35 | 37 | } else { |
— | — | @@ -79,15 +81,16 @@ |
80 | 82 | $j.each(this.formData, function(key, value) { |
81 | 83 | formData.append(key, value); |
82 | 84 | }); |
83 | | - formData.append('filename', file.name); |
84 | | - formData.append('file', file); |
| 85 | + formData.append('filename', file.name); |
| 86 | + formData.append('file', file); |
| 87 | + |
85 | 88 | this.xhr.open("POST", _this.postUrl, true); |
86 | 89 | this.xhr.send(formData); |
87 | 90 | } |
88 | 91 | }, |
89 | 92 | uploadChunk: function(offset) { |
90 | 93 | var _this = this, |
91 | | - file = this.$form.find('input[name=file]')[0].files[0], |
| 94 | + file = this.uploadObject.file, |
92 | 95 | bytesAvailable = file.size, |
93 | 96 | chunk; |
94 | 97 | |
Index: trunk/extensions/UploadWizard/resources/mw.UploadWizardUpload.js |
— | — | @@ -7,7 +7,7 @@ |
8 | 8 | */ |
9 | 9 | ( function( $j ) { |
10 | 10 | |
11 | | -mw.UploadWizardUpload = function( wizard, filesDiv ) { |
| 11 | +mw.UploadWizardUpload = function( wizard, filesDiv, providedFile ) { |
12 | 12 | |
13 | 13 | this.index = mw.UploadWizardUpload.prototype.count; |
14 | 14 | mw.UploadWizardUpload.prototype.count++; |
— | — | @@ -22,6 +22,8 @@ |
23 | 23 | this.mimetype = undefined; |
24 | 24 | this.extension = undefined; |
25 | 25 | this.filename = undefined; |
| 26 | + this.providedFile = providedFile; |
| 27 | + this.file = undefined; |
26 | 28 | |
27 | 29 | this.fileKey = undefined; |
28 | 30 | |
— | — | @@ -30,7 +32,7 @@ |
31 | 33 | this.detailsWeight = 1; // default all same |
32 | 34 | |
33 | 35 | // details |
34 | | - this.ui = new mw.UploadWizardUploadInterface( this, filesDiv ); |
| 36 | + this.ui = new mw.UploadWizardUploadInterface( this, filesDiv, providedFile ); |
35 | 37 | |
36 | 38 | // handler -- usually ApiUploadHandler |
37 | 39 | // this.handler = new ( mw.UploadWizard.config[ 'uploadHandlerClass' ] )( this ); |
— | — | @@ -258,18 +260,18 @@ |
259 | 261 | * Checks for file validity, then extracts metadata. |
260 | 262 | * Error out if filename or its contents are determined to be unacceptable |
261 | 263 | * 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. |
263 | 266 | * @param {Function()} callback when ok, and upload object is ready |
264 | 267 | * @param {Function(String, Mixed)} callback when filename or contents in error. Signature of string code, mixed info |
265 | 268 | */ |
266 | | - checkFile: function( fileInput, fileNameOk, fileNameErr ) { |
| 269 | + checkFile: function( filename, files, fileNameOk, fileNameErr ) { |
267 | 270 | // check if local file is acceptable |
268 | 271 | |
269 | 272 | var _this = this; |
270 | 273 | |
271 | 274 | // Check if filename is acceptable |
272 | 275 | // TODO sanitize filename |
273 | | - var filename = fileInput.value; |
274 | 276 | var basename = mw.UploadWizardUtil.getBasename( filename ); |
275 | 277 | |
276 | 278 | |
— | — | @@ -301,13 +303,23 @@ |
302 | 304 | if ( $j.inArray( extension.toLowerCase(), mw.UploadWizard.config[ 'fileExtensions' ] ) === -1 ) { |
303 | 305 | fileNameErr( 'ext', extension ); |
304 | 306 | } else { |
305 | | - |
306 | 307 | // extract more info via fileAPI |
307 | 308 | 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 | + |
312 | 324 | // TODO check max upload size, alert user if too big |
313 | 325 | this.transportWeight = this.file.size; |
314 | 326 | if ( !mw.isDefined( this.imageinfo ) ) { |
— | — | @@ -559,10 +571,7 @@ |
560 | 572 | */ |
561 | 573 | getUploadHandler: function(){ |
562 | 574 | if( !this.uploadHandler ){ |
563 | | - if( mw.UploadWizard.config[ 'enableFirefogg' ] |
564 | | - && |
565 | | - typeof( Firefogg ) != 'undefined' |
566 | | - ) { |
| 575 | + if( mw.UploadWizard.config[ 'enableFirefogg' ] && typeof( Firefogg ) != 'undefined' ) { |
567 | 576 | mw.log("mw.UploadWizard::getUploadHandler> FirefoggHandler"); |
568 | 577 | this.uploadHandler = new mw.FirefoggHandler( this, this.api ); |
569 | 578 | } else if( mw.UploadWizard.config[ 'enableFormData' ] && |