jenkins-bot has submitted this change and it was merged.

Change subject: Replace FDT callbacks with OOJS events
......................................................................


Replace FDT callbacks with OOJS events

I think this is much cleaner.

Bug: T77124
Change-Id: I8513b7360271300efd478db8e98292623d306aa8
---
M UploadWizard.php
M resources/mw.ApiUploadFormDataHandler.js
M resources/mw.FormDataTransport.js
3 files changed, 329 insertions(+), 309 deletions(-)

Approvals:
  Gilles: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/UploadWizard.php b/UploadWizard.php
index 0b49595..61d1e0d 100644
--- a/UploadWizard.php
+++ b/UploadWizard.php
@@ -99,6 +99,10 @@
 
 $wgResourceModules['ext.uploadWizard.formDataTransport'] = array(
        'scripts' => 'mw.FormDataTransport.js',
+
+       'dependencies' => array(
+               'oojs',
+       ),
 ) + $uploadWizardModuleInfo;
 
 $wgResourceModules['ext.uploadWizard.iFrameTransport'] = array(
diff --git a/resources/mw.ApiUploadFormDataHandler.js 
b/resources/mw.ApiUploadFormDataHandler.js
index 22a7aa5..eb2ff09 100644
--- a/resources/mw.ApiUploadFormDataHandler.js
+++ b/resources/mw.ApiUploadFormDataHandler.js
@@ -20,15 +20,12 @@
                this.transport = new mw.FormDataTransport(
                        this.$form[0].action,
                        this.formData,
-                       this.upload,
-                       function ( fraction ) {
-                               handler.upload.setTransportProgress( fraction );
-                       },
-                       function ( result ) {
-                               handler.upload.setTransported( result );
-                       }
-               );
-
+                       this.upload
+               ).on( 'progress', function ( fraction ) {
+                       handler.upload.setTransportProgress( fraction );
+               } ).on( 'transported', function ( result ) {
+                       handler.upload.setTransported( result );
+               } );
        };
 
        mw.ApiUploadFormDataHandler.prototype = {
diff --git a/resources/mw.FormDataTransport.js 
b/resources/mw.FormDataTransport.js
index d1121be..92c00a2 100644
--- a/resources/mw.FormDataTransport.js
+++ b/resources/mw.FormDataTransport.js
@@ -1,19 +1,22 @@
-( function ( mw, $ ) {
-       /**
-        * Represents a "transport" for files to upload; using html5 FormData.
-        *
-        * @param form            jQuery selector for HTML form with selected 
file
-        * @param formData        object with additinal form fields required 
for upload api call
-        * @param progressCb    callback to execute when we've started.
-        * @param transportedCb callback to execute when we've finished the 
upload
-        */
+( function ( mw, $, oo ) {
+       var FDTP;
 
-       mw.FormDataTransport = function ( postUrl, formData, uploadObject, 
progressCb, transportedCb ) {
+       /**
+        * @class mw.FormDataTransport
+        * Represents a "transport" for files to upload; using HTML5 FormData.
+        * @mixins oo.EventEmitter
+        *
+        * @constructor
+        * @param {string} postUrl URL to post to.
+        * @param {Object} formData Additional form fields required for upload 
api call
+        * @param {mw.UploadWizardUpload} uploadObject Stupidly included object 
that is controlling the upload details
+        */
+       mw.FormDataTransport = function ( postUrl, formData, uploadObject ) {
                var profile = $.client.profile();
 
+               oo.EventEmitter.call( this );
+
                this.formData = formData;
-               this.progressCb = progressCb;
-               this.transportedCb = transportedCb;
                this.uploadObject = uploadObject;
 
                this.postUrl = postUrl;
@@ -36,318 +39,334 @@
                this.insufficientFormDataSupport = profile.name === 'firefox' 
&& profile.versionNumber < 7;
        };
 
-       mw.FormDataTransport.prototype = {
-               upload: function () {
-                       var formData,
-                               transport = this,
-                               file = this.uploadObject.file;
+       oo.mixinClass( mw.FormDataTransport, oo.EventEmitter );
 
-                       // use timestamp + filename to avoid conflicts on server
-                       this.tempname = ( new Date() ).getTime().toString() + 
file.name;
-                       // remove unicode characters, tempname is only used 
during upload
-                       this.tempname = this.tempname.split('').map(function 
(c) {
-                               return c.charCodeAt(0) > 128 ? '_' : c;
-                       }).join('');
+       FDTP = mw.FormDataTransport.prototype;
 
-                       if ( mw.UploadWizard.config.enableChunked && file.size 
> this.chunkSize ) {
-                               this.uploadChunk(0);
-                       } else {
-                               this.xhr = new XMLHttpRequest();
-                               this.xhr.addEventListener('load', function 
(evt) {
-                                       transport.parseResponse(evt, 
transport.transportedCb);
-                               }, false);
-                               this.xhr.addEventListener('error', function 
(evt) {
-                                       transport.parseResponse(evt, 
transport.transportedCb);
-                               }, false);
-                               this.xhr.upload.addEventListener('progress', 
function (evt) {
-                                       if ( transport.uploadObject.state === 
'aborted' ) {
-                                               transport.xhr.abort();
-                                               return;
-                                       }
-                                       if (evt.lengthComputable) {
-                                               var progress = 
parseFloat(evt.loaded / evt.total );
-                                               transport.progressCb(progress);
-                                       }
-                               }, false);
-                               this.xhr.addEventListener('abort', function 
(evt) {
-                                       transport.parseResponse(evt, 
transport.transportedCb);
-                               }, false);
+       FDTP.upload = function () {
+               var formData,
+                       transport = this,
+                       file = this.uploadObject.file;
 
-                               formData = new FormData();
+               // use timestamp + filename to avoid conflicts on server
+               this.tempname = ( new Date() ).getTime().toString() + file.name;
+               // remove unicode characters, tempname is only used during 
upload
+               this.tempname = this.tempname.split('').map(function (c) {
+                       return c.charCodeAt(0) > 128 ? '_' : c;
+               }).join('');
 
-                               $.each(this.formData, function (key, value) {
-                                       formData.append(key, value);
-                               });
-                               formData.append('filename', this.tempname);
-                               formData.append('file', file);
-
-                               // ignorewarnings is turned on, since warnings 
are presented in a later step and this
-                               // transport doesn't know how to deal with 
them.  Also, it's important to allow people to
-                               // upload files with (for example) blacklisted 
names, and then rename them later in the
-                               // wizard.
-                               formData.append( 'ignorewarnings', true );
-
-                               this.xhr.open('POST', this.postUrl, true);
-                               this.xhr.send(formData);
-                       }
-               },
-               uploadChunk: function (offset) {
-                       var formData,
-                               transport = this,
-                               file = this.uploadObject.file,
-                               bytesAvailable = file.size,
-                               chunk;
-                       if ( this.uploadObject.state === 'aborted' ) {
-                               if ( this.xhr ) {
-                                       this.xhr.abort();
-                               }
-                               return;
-                       }
-                       //Slice API was changed and has vendor prefix for now
-                       //new version now require start/end and not start/length
-                       if (file.mozSlice) {
-                               chunk = file.mozSlice(offset, offset + 
this.chunkSize, file.type);
-                       } else if (file.webkitSlice) {
-                               chunk = file.webkitSlice(offset, offset + 
this.chunkSize, file.type);
-                       } else {
-                               chunk = file.slice(offset, offset + 
this.chunkSize, file.type);
-                       }
-
+               if ( mw.UploadWizard.config.enableChunked && file.size > 
this.chunkSize ) {
+                       this.uploadChunk(0);
+               } else {
                        this.xhr = new XMLHttpRequest();
                        this.xhr.addEventListener('load', function (evt) {
-                               transport.responseText = 
evt.target.responseText;
-                               transport.parseResponse(evt, function 
(response) {
-                                       if (response.upload && 
response.upload.filekey) {
-                                               transport.filekey = 
response.upload.filekey;
-                                       }
-                                       if (response.upload && 
response.upload.result === 'Success') {
-                                               //upload finished and can be 
unstashed later
-                                               
transport.transportedCb(response);
-                                       } else if (response.upload && 
response.upload.result === 'Poll') {
-                                               //Server not ready, wait for 3 
seconds
-                                               setTimeout(function () {
-                                                       transport.checkStatus();
-                                               }, 3000);
-                                       } else if (response.upload && 
response.upload.result === 'Continue') {
-                                               //reset retry counter
-                                               transport.retries = 0;
-                                               //start uploading next chunk
-                                               
transport.uploadChunk(response.upload.offset);
-                                       } else {
-                                               if ( 
transport.uploadObject.state === 'aborted' ) {
-                                                       return;
-                                               }
-                                               //failed to upload, try again 
in 3 seconds
-                                               transport.retries++;
-                                               if (transport.maxRetries > 0 && 
transport.retries >= transport.maxRetries) {
-                                                       mw.log.warn( 'Max 
retries exceeded on unknown response' );
-                                                       //upload failed, raise 
response
-                                                       
transport.transportedCb(response);
-                                               } else {
-                                                       mw.log( 'Retry #' + 
transport.retries + ' on unknown response' );
-                                                       setTimeout(function () {
-                                                               
transport.uploadChunk(offset);
-                                                       }, 3000);
-                                               }
-                                       }
-                               });
+                               transport.emitParsedResponse( evt );
                        }, false);
                        this.xhr.addEventListener('error', function (evt) {
-                               if ( transport.uploadObject.state === 'aborted' 
) {
-                                       return;
-                               }
-                               //failed to upload, try again in 3 second
-                               transport.retries++;
-                               if (transport.maxRetries > 0 && 
transport.retries >= transport.maxRetries) {
-                                       mw.log.warn( 'Max retries exceeded on 
error event' );
-                                       transport.parseResponse(evt, 
transport.transportedCb);
-                               } else {
-                                       mw.log( 'Retry #' + transport.retries + 
' on error event' );
-                                       setTimeout(function () {
-                                               transport.uploadChunk(offset);
-                                       }, 3000);
-                               }
+                               transport.emitParsedResponse( evt );
                        }, false);
-                       this.xhr.upload.addEventListener('progress', function 
(evt) {
+
+                       this.xhr.upload.addEventListener( 'progress', function 
( evt ) {
                                if ( transport.uploadObject.state === 'aborted' 
) {
                                        transport.xhr.abort();
+                                       return;
                                }
-                               if (evt.lengthComputable) {
-                                       var progress = parseFloat( offset + 
evt.loaded ) / bytesAvailable;
-                                       transport.progressCb(progress);
+
+                               if ( evt.lengthComputable ) {
+                                       var progress = parseFloat(evt.loaded / 
evt.total );
+                                       transport.emit( 'progress', progress );
                                }
                        }, false);
                        this.xhr.addEventListener('abort', function (evt) {
-                               transport.parseResponse(evt, 
transport.transportedCb);
+                               transport.emitParsedResponse( evt );
                        }, false);
 
-                       if (this.insufficientFormDataSupport) {
-                               formData = this.geckoFormData();
-                       } else {
-                               formData = new FormData();
-                       }
+                       formData = new FormData();
+
                        $.each(this.formData, function (key, value) {
                                formData.append(key, value);
                        });
-                       formData.append('offset', offset);
                        formData.append('filename', this.tempname);
+                       formData.append('file', file);
 
-                       // ignorewarnings is turned on intentionally, see the 
above comment to the same effect.
+                       // ignorewarnings is turned on, since warnings are 
presented in a later step and this
+                       // transport doesn't know how to deal with them.  Also, 
it's important to allow people to
+                       // upload files with (for example) blacklisted names, 
and then rename them later in the
+                       // wizard.
                        formData.append( 'ignorewarnings', true );
-                       // only enable async if file is larger 10Mb
-                       if ( bytesAvailable > 10 * 1024 * 1024 ) {
-                               formData.append( 'async', true );
-                       }
 
-                       if (this.filekey) {
-                               formData.append('filekey', this.filekey);
-                       }
-                       formData.append('filesize', bytesAvailable);
-                       if (this.insufficientFormDataSupport) {
-                               formData.appendBlob('chunk', chunk, 
'chunk.bin');
-                       } else {
-                               formData.append('chunk', chunk);
-                       }
                        this.xhr.open('POST', this.postUrl, true);
-                       if (this.insufficientFormDataSupport) {
-                               formData.send(this.xhr);
-                       } else {
-                               this.xhr.send(formData);
-                       }
-               },
-               checkStatus: function () {
-                       var transport = this,
-                               api = new mw.Api(),
-                               params = {};
-                       if ( this.uploadObject.state === 'aborted' ) {
-                               return;
-                       }
-                       if (!this.firstPoll) {
-                               this.firstPoll = ( new Date() ).getTime();
-                       }
-                       $.each(this.formData, function (key, value) {
-                               params[key] = value;
-                       });
-                       params.checkstatus =  true;
-                       params.filekey =  this.filekey;
-                       api.post( params )
-                               .done( function (response) {
-                                       if (response.upload && 
response.upload.result === 'Poll') {
-                                               //If concatenation takes longer 
than 10 minutes give up
-                                               if ( ( ( new Date() ).getTime() 
- transport.firstPoll ) > 10 * 60 * 1000 ) {
-                                                       
transport.transportedCb({
-                                                               code: 
'server-error',
-                                                               info: 'unknown 
server error'
-                                                       });
-                                               //Server not ready, wait for 3 
more seconds
-                                               } else {
-                                                       if ( 
response.upload.stage === undefined && window.console ) {
-                                                               
window.console.log( 'Unable to check file\'s status' );
-                                                       } else {
-                                                               //Statuses that 
can be returned:
-                                                               // 
*mwe-upwiz-queued
-                                                               // 
*mwe-upwiz-publish
-                                                               // 
*mwe-upwiz-assembling
-                                                               
transport.uploadObject.ui.setStatus( 'mwe-upwiz-' + response.upload.stage );
-                                                               
setTimeout(function () {
-                                                                       
transport.checkStatus();
-                                                               }, 3000);
-                                                       }
-                                               }
-                                       } else {
-                                               
transport.transportedCb(response);
-                                       }
-                               } )
-                               .fail( function (status, response) {
-                                       transport.transportedCb(response);
-                               } );
-               },
-               parseResponse: function (evt, callback) {
-                       var response;
-                       try {
-                               response = $.parseJSON(evt.target.responseText);
-                       } catch ( e ) {
-                               response = {
-                                       error: {
-                                               code: evt.target.code,
-                                               info: evt.target.responseText
-                                       }
-                               };
-                       }
-                       callback(response);
-               },
-               geckoFormData: function () {
-                       var formData, onload,
-                               boundary = '------XX' + Math.random(),
-                               dashdash = '--',
-                               crlf = '\r\n',
-                               builder = '', // Build RFC2388 string.
-                               chunksRemaining = 0;
-
-                       builder += dashdash + boundary + crlf;
-
-                       formData = {
-                               append: function (name, data) {
-                                       // Generate headers.
-                                       builder += 'Content-Disposition: 
form-data; name="' + name + '"';
-                                       builder += crlf;
-                                       builder += crlf;
-
-                                       // Write data.
-                                       builder += data;
-                                       builder += crlf;
-
-                                       // Write boundary.
-                                       builder += dashdash + boundary + crlf;
-                               },
-                               appendFile: function (name, data, type, 
filename) {
-                                       builder += 'Content-Disposition: 
form-data; name="' + name + '"';
-                                       builder += '; filename="' + filename + 
'"';
-                                       builder += crlf;
-                                       builder += 'Content-Type: ' + type;
-                                       builder += crlf;
-                                       builder += crlf;
-
-                                       // Write binary data.
-                                       builder += data;
-                                       builder += crlf;
-
-                                       // Write boundary.
-                                       builder += dashdash + boundary + crlf;
-                               },
-                               appendBlob: function (name, blob, filename) {
-                                       chunksRemaining++;
-                                       var reader = new FileReader();
-                                       reader.onload = function (e) {
-                                               formData.appendFile(name, 
e.target.result,
-                                                                               
        blob.type, filename);
-                                               // Call onload after last Blob
-                                               chunksRemaining--;
-                                               if (!chunksRemaining && 
formData.xhr) {
-                                                       onload();
-                                               }
-                                       };
-                                       reader.readAsBinaryString(blob);
-                               },
-                               send: function (xhr) {
-                                       formData.xhr = xhr;
-                                       if (!chunksRemaining) {
-                                               onload();
-                                       }
-                               }
-                       };
-                       onload = function () {
-                               // Mark end of the request.
-                               builder += dashdash + boundary + dashdash + 
crlf;
-
-                               // Send to server
-                               formData.xhr.setRequestHeader(
-                                       'Content-type',
-                                       'multipart/form-data; boundary=' + 
boundary
-                               );
-                               formData.xhr.sendAsBinary(builder);
-                       };
-                       return formData;
+                       this.xhr.send(formData);
                }
        };
-}( mediaWiki, jQuery ) );
+
+       FDTP.uploadChunk = function ( offset ) {
+               var formData,
+                       transport = this,
+                       file = this.uploadObject.file,
+                       bytesAvailable = file.size,
+                       chunk;
+               if ( this.uploadObject.state === 'aborted' ) {
+                       if ( this.xhr ) {
+                               this.xhr.abort();
+                       }
+                       return;
+               }
+               //Slice API was changed and has vendor prefix for now
+               //new version now require start/end and not start/length
+               if (file.mozSlice) {
+                       chunk = file.mozSlice(offset, offset + this.chunkSize, 
file.type);
+               } else if (file.webkitSlice) {
+                       chunk = file.webkitSlice(offset, offset + 
this.chunkSize, file.type);
+               } else {
+                       chunk = file.slice(offset, offset + this.chunkSize, 
file.type);
+               }
+
+               this.xhr = new XMLHttpRequest();
+               this.xhr.addEventListener('load', function (evt) {
+                       transport.responseText = evt.target.responseText;
+                       transport.parseResponse(evt, function (response) {
+                               if (response.upload && response.upload.filekey) 
{
+                                       transport.filekey = 
response.upload.filekey;
+                               }
+                               if (response.upload && response.upload.result 
=== 'Success') {
+                                       //upload finished and can be unstashed 
later
+                                       transport.emit( 'transported', response 
);
+                               } else if (response.upload && 
response.upload.result === 'Poll') {
+                                       //Server not ready, wait for 3 seconds
+                                       setTimeout(function () {
+                                               transport.checkStatus();
+                                       }, 3000);
+                               } else if (response.upload && 
response.upload.result === 'Continue') {
+                                       //reset retry counter
+                                       transport.retries = 0;
+                                       //start uploading next chunk
+                                       
transport.uploadChunk(response.upload.offset);
+                               } else {
+                                       //failed to upload, try again in 3 
seconds
+                                       transport.retries++;
+                                       if (transport.maxRetries > 0 && 
transport.retries >= transport.maxRetries) {
+                                               mw.log.warn( 'Max retries 
exceeded on unknown response' );
+                                               //upload failed, raise response
+                                               transport.emit( 'transported', 
response );
+                                       } else {
+                                               mw.log( 'Retry #' + 
transport.retries + ' on unknown response' );
+                                               setTimeout(function () {
+                                                       
transport.uploadChunk(offset);
+                                               }, 3000);
+                                       }
+                               }
+                       });
+               }, false);
+               this.xhr.addEventListener('error', function (evt) {
+                       //failed to upload, try again in 3 second
+                       transport.retries++;
+                       if (transport.maxRetries > 0 && transport.retries >= 
transport.maxRetries) {
+                               mw.log.warn( 'Max retries exceeded on error 
event' );
+                               transport.emitParsedResponse( evt );
+                       } else {
+                               mw.log( 'Retry #' + transport.retries + ' on 
error event' );
+                               setTimeout(function () {
+                                       transport.uploadChunk(offset);
+                               }, 3000);
+                       }
+               }, false);
+               this.xhr.upload.addEventListener( 'progress', function ( evt ) {
+                       if ( transport.uploadObject.state === 'aborted' ) {
+                               transport.xhr.abort();
+                       }
+                       if ( evt.lengthComputable ) {
+                               var progress = parseFloat( offset + evt.loaded 
) / bytesAvailable;
+                               transport.emit( 'progress', progress );
+                       }
+               }, false );
+               this.xhr.addEventListener('abort', function (evt) {
+                       transport.emitParsedResponse( evt );
+               }, false);
+
+               if (this.insufficientFormDataSupport) {
+                       formData = this.geckoFormData();
+               } else {
+                       formData = new FormData();
+               }
+               $.each(this.formData, function (key, value) {
+                       formData.append(key, value);
+               });
+               formData.append('offset', offset);
+               formData.append('filename', this.tempname);
+
+               // ignorewarnings is turned on intentionally, see the above 
comment to the same effect.
+               formData.append( 'ignorewarnings', true );
+               // only enable async if file is larger 10Mb
+               if ( bytesAvailable > 10 * 1024 * 1024 ) {
+                       formData.append( 'async', true );
+               }
+
+               if (this.filekey) {
+                       formData.append('filekey', this.filekey);
+               }
+               formData.append('filesize', bytesAvailable);
+               if (this.insufficientFormDataSupport) {
+                       formData.appendBlob('chunk', chunk, 'chunk.bin');
+               } else {
+                       formData.append('chunk', chunk);
+               }
+               this.xhr.open('POST', this.postUrl, true);
+               if (this.insufficientFormDataSupport) {
+                       formData.send(this.xhr);
+               } else {
+                       this.xhr.send(formData);
+               }
+       };
+
+       FDTP.checkStatus = function () {
+               var transport = this,
+                       api = new mw.Api(),
+                       params = {};
+               if ( this.uploadObject.state === 'aborted' ) {
+                       return;
+               }
+               if (!this.firstPoll) {
+                       this.firstPoll = ( new Date() ).getTime();
+               }
+               $.each(this.formData, function (key, value) {
+                       params[key] = value;
+               });
+               params.checkstatus =  true;
+               params.filekey =  this.filekey;
+               api.post( params )
+                       .done( function (response) {
+                               if (response.upload && response.upload.result 
=== 'Poll') {
+                                       //If concatenation takes longer than 10 
minutes give up
+                                       if ( ( ( new Date() ).getTime() - 
transport.firstPoll ) > 10 * 60 * 1000 ) {
+                                               transport.emit( 'transported', {
+                                                       code: 'server-error',
+                                                       info: 'unknown server 
error'
+                                               } );
+                                       //Server not ready, wait for 3 more 
seconds
+                                       } else {
+                                               if ( response.upload.stage === 
undefined && window.console ) {
+                                                       window.console.log( 
'Unable to check file\'s status' );
+                                               } else {
+                                                       //Statuses that can be 
returned:
+                                                       // *mwe-upwiz-queued
+                                                       // *mwe-upwiz-publish
+                                                       // *mwe-upwiz-assembling
+                                                       
transport.uploadObject.ui.setStatus( 'mwe-upwiz-' + response.upload.stage );
+                                                       setTimeout(function () {
+                                                               
transport.checkStatus();
+                                                       }, 3000);
+                                               }
+                                       }
+                               } else {
+                                       transport.emit( 'transported', response 
);
+                               }
+                       } )
+                       .fail( function (status, response) {
+                               transport.emit( 'transported', response );
+                       } );
+       };
+
+       FDTP.parseResponse = function ( evt, cb ) {
+               var response;
+               try {
+                       response = $.parseJSON(evt.target.responseText);
+               } catch ( e ) {
+                       response = {
+                               error: {
+                                       code: evt.target.code,
+                                       info: evt.target.responseText
+                               }
+                       };
+               }
+
+               cb( response );
+       };
+
+       /**
+        * Emits a 'transported' event with an object indicating status,
+        * parsed from JSON in the event body.
+        * @param {Event} evt The response event.
+        */
+       FDTP.emitParsedResponse = function ( evt ) {
+               var transport = this;
+
+               this.parseResponse( evt, function ( response ) {
+                       transport.emit( 'transported', response );
+               } );
+       };
+
+       FDTP.geckoFormData = function () {
+               var formData, onload,
+                       boundary = '------XX' + Math.random(),
+                       dashdash = '--',
+                       crlf = '\r\n',
+                       builder = '', // Build RFC2388 string.
+                       chunksRemaining = 0;
+
+               builder += dashdash + boundary + crlf;
+
+               formData = {
+                       append: function (name, data) {
+                               // Generate headers.
+                               builder += 'Content-Disposition: form-data; 
name="' + name + '"';
+                               builder += crlf;
+                               builder += crlf;
+
+                               // Write data.
+                               builder += data;
+                               builder += crlf;
+
+                               // Write boundary.
+                               builder += dashdash + boundary + crlf;
+                       },
+                       appendFile: function (name, data, type, filename) {
+                               builder += 'Content-Disposition: form-data; 
name="' + name + '"';
+                               builder += '; filename="' + filename + '"';
+                               builder += crlf;
+                               builder += 'Content-Type: ' + type;
+                               builder += crlf;
+                               builder += crlf;
+
+                               // Write binary data.
+                               builder += data;
+                               builder += crlf;
+
+                               // Write boundary.
+                               builder += dashdash + boundary + crlf;
+                       },
+                       appendBlob: function (name, blob, filename) {
+                               chunksRemaining++;
+                               var reader = new FileReader();
+                               reader.onload = function (e) {
+                                       formData.appendFile(name, 
e.target.result,
+                                                                               
blob.type, filename);
+                                       // Call onload after last Blob
+                                       chunksRemaining--;
+                                       if (!chunksRemaining && formData.xhr) {
+                                               onload();
+                                       }
+                               };
+                               reader.readAsBinaryString(blob);
+                       },
+                       send: function (xhr) {
+                               formData.xhr = xhr;
+                               if (!chunksRemaining) {
+                                       onload();
+                               }
+                       }
+               };
+               onload = function () {
+                       // Mark end of the request.
+                       builder += dashdash + boundary + dashdash + crlf;
+
+                       // Send to server
+                       formData.xhr.setRequestHeader(
+                               'Content-type',
+                               'multipart/form-data; boundary=' + boundary
+                       );
+                       formData.xhr.sendAsBinary(builder);
+               };
+               return formData;
+       };
+}( mediaWiki, jQuery, OO ) );

-- 
To view, visit https://gerrit.wikimedia.org/r/178207
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I8513b7360271300efd478db8e98292623d306aa8
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/UploadWizard
Gerrit-Branch: master
Gerrit-Owner: MarkTraceur <[email protected]>
Gerrit-Reviewer: Gilles <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to