7 * Used to represent an upload in progress on the frontend.
8 * Most of the functionality is implemented in mw.Api.plugin.upload,
9 * but this model class will tie it together as well as let you perform
10 * actions in a logical way.
14 * var file = new OO.ui.SelectFileWidget(),
15 * button = new OO.ui.ButtonWidget( { label: 'Save' } ),
16 * upload = new mw.Upload;
18 * button.on( 'click', function () {
19 * upload.setFile( file.getValue() );
20 * upload.setFilename( file.getValue().name );
24 * $( 'body' ).append( file.$element, button.$element );
26 * You can also choose to {@link #uploadToStash stash the upload} and
27 * {@link #finishStashUpload finalize} it later:
29 * var file, // Some file object
30 * upload = new mw.Upload,
31 * stashPromise = $.Deferred();
33 * upload.setFile( file );
34 * upload.uploadToStash().then( function () {
35 * stashPromise.resolve();
38 * stashPromise.then( function () {
39 * upload.setFilename( 'foo' );
40 * upload.setText( 'bar' );
41 * upload.finishStashUpload().then( function () {
42 * console.log( 'Done!' );
47 * @param {Object|mw.Api} [apiconfig] A mw.Api object (or subclass), or configuration
48 * to pass to the constructor of mw.Api.
50 function Upload( apiconfig
) {
51 this.api
= ( apiconfig
instanceof mw
.Api
) ? apiconfig
: new mw
.Api( apiconfig
);
53 this.watchlist
= false;
58 this.setState( Upload
.State
.NEW
);
60 this.imageinfo
= undefined;
63 UP
= Upload
.prototype;
66 * Set the text of the file page, to be created on file upload.
68 * @param {string} text
70 UP
.setText = function ( text
) {
75 * Set the filename, to be finalized on upload.
77 * @param {string} filename
79 UP
.setFilename = function ( filename
) {
80 this.filename
= filename
;
84 * Sets the filename based on the filename as it was on the upload.
86 UP
.setFilenameFromFile = function () {
87 var file
= this.getFile();
88 if ( file
.nodeType
&& file
.nodeType
=== Node
.ELEMENT_NODE
) {
89 // File input element, use getBasename to cut out the path
90 this.setFilename( this.getBasename( file
.value
) );
91 } else if ( file
.name
&& file
.lastModified
) {
92 // HTML5 FileAPI File object, but use getBasename to be safe
93 this.setFilename( this.getBasename( file
.name
) );
98 * Set the file to be uploaded.
100 * @param {HTMLInputElement|File} file
102 UP
.setFile = function ( file
) {
107 * Set whether the file should be watchlisted after upload.
109 * @param {boolean} watchlist
111 UP
.setWatchlist = function ( watchlist
) {
112 this.watchlist
= watchlist
;
116 * Set the edit comment for the upload.
118 * @param {string} comment
120 UP
.setComment = function ( comment
) {
121 this.comment
= comment
;
125 * Get the text of the file page, to be created on file upload.
129 UP
.getText = function () {
134 * Get the filename, to be finalized on upload.
138 UP
.getFilename = function () {
139 return this.filename
;
143 * Get the file being uploaded.
145 * @return {HTMLInputElement|File}
147 UP
.getFile = function () {
152 * Get the boolean for whether the file will be watchlisted after upload.
156 UP
.getWatchlist = function () {
157 return this.watchlist
;
161 * Get the current value of the edit comment for the upload.
165 UP
.getComment = function () {
170 * Gets the base filename from a path name.
172 * @param {string} path
175 UP
.getBasename = function ( path
) {
176 if ( path
=== undefined || path
=== null ) {
180 // Find the index of the last path separator in the
181 // path, and add 1. Then, take the entire string after that.
184 path
.lastIndexOf( '/' ),
185 path
.lastIndexOf( '\\' )
191 * Sets the state and state details (if any) of the upload.
193 * @param {mw.Upload.State} state
194 * @param {Object} stateDetails
196 UP
.setState = function ( state
, stateDetails
) {
198 this.stateDetails
= stateDetails
;
202 * Gets the state of the upload.
204 * @return {mw.Upload.State}
206 UP
.getState = function () {
211 * Gets details of the current state.
215 UP
.getStateDetails = function () {
216 return this.stateDetails
;
220 * Get the imageinfo object for the finished upload.
221 * Only available once the upload is finished! Don't try to get it
224 * @return {Object|undefined}
226 UP
.getImageInfo = function () {
227 return this.imageinfo
;
231 * Upload the file directly.
233 * @return {jQuery.Promise}
235 UP
.upload = function () {
238 if ( !this.getFile() ) {
239 return $.Deferred().reject( 'No file to upload. Call setFile to add one.' );
242 if ( !this.getFilename() ) {
243 return $.Deferred().reject( 'No filename set. Call setFilename to add one.' );
246 this.setState( Upload
.State
.UPLOADING
);
248 return this.api
.upload( this.getFile(), {
249 watchlist
: ( this.getWatchlist() ) ? 1 : undefined,
250 comment
: this.getComment(),
251 filename
: this.getFilename(),
253 } ).then( function ( result
) {
254 upload
.setState( Upload
.State
.UPLOADED
);
255 upload
.imageinfo
= result
.upload
.imageinfo
;
257 }, function ( errorCode
, result
) {
258 if ( result
&& result
.upload
&& result
.upload
.warnings
) {
259 upload
.setState( Upload
.State
.WARNING
, result
);
261 upload
.setState( Upload
.State
.ERROR
, result
);
263 return $.Deferred().reject( errorCode
, result
);
268 * Upload the file to the stash to be completed later.
270 * @return {jQuery.Promise}
272 UP
.uploadToStash = function () {
275 if ( !this.getFile() ) {
276 return $.Deferred().reject( 'No file to upload. Call setFile to add one.' );
279 if ( !this.getFilename() ) {
280 this.setFilenameFromFile();
283 this.setState( Upload
.State
.UPLOADING
);
285 this.stashPromise
= this.api
.uploadToStash( this.getFile(), {
286 filename
: this.getFilename()
287 } ).then( function ( finishStash
) {
288 upload
.setState( Upload
.State
.STASHED
);
290 }, function ( errorCode
, result
) {
291 if ( result
&& result
.upload
&& result
.upload
.warnings
) {
292 upload
.setState( Upload
.State
.WARNING
, result
);
294 upload
.setState( Upload
.State
.ERROR
, result
);
296 return $.Deferred().reject( errorCode
, result
);
299 return this.stashPromise
;
303 * Finish a stash upload.
305 * @return {jQuery.Promise}
307 UP
.finishStashUpload = function () {
310 if ( !this.stashPromise
) {
311 return $.Deferred().reject( 'This upload has not been stashed, please upload it to the stash first.' );
314 return this.stashPromise
.then( function ( finishStash
) {
315 upload
.setState( Upload
.State
.UPLOADING
);
317 return finishStash( {
318 watchlist
: ( upload
.getWatchlist() ) ? 1 : undefined,
319 comment
: upload
.getComment(),
320 filename
: upload
.getFilename(),
321 text
: upload
.getText()
322 } ).then( function ( result
) {
323 upload
.setState( Upload
.State
.UPLOADED
);
324 upload
.imageinfo
= result
.upload
.imageinfo
;
326 }, function ( errorCode
, result
) {
327 if ( result
&& result
.upload
&& result
.upload
.warnings
) {
328 upload
.setState( Upload
.State
.WARNING
, result
);
330 upload
.setState( Upload
.State
.ERROR
, result
);
332 return $.Deferred().reject( errorCode
, result
);
338 * @enum mw.Upload.State
339 * State of uploads represented in simple terms.
342 /** Upload not yet started */
345 /** Upload finished, but there was a warning */
348 /** Upload finished, but there was an error */
351 /** Upload in progress */
354 /** Upload finished, but not published, call #finishStashUpload */
357 /** Upload finished and published */
362 }( mediaWiki
, jQuery
) );