]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - resources/src/mediawiki/mediawiki.Upload.js
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / resources / src / mediawiki / mediawiki.Upload.js
1 ( function ( mw, $ ) {
2         var UP;
3
4         /**
5          * Used to represent an upload in progress on the frontend.
6          * Most of the functionality is implemented in mw.Api.plugin.upload,
7          * but this model class will tie it together as well as let you perform
8          * actions in a logical way.
9          *
10          * A simple example:
11          *
12          *     var file = new OO.ui.SelectFileWidget(),
13          *       button = new OO.ui.ButtonWidget( { label: 'Save' } ),
14          *       upload = new mw.Upload;
15          *
16          *     button.on( 'click', function () {
17          *       upload.setFile( file.getValue() );
18          *       upload.setFilename( file.getValue().name );
19          *       upload.upload();
20          *     } );
21          *
22          *     $( 'body' ).append( file.$element, button.$element );
23          *
24          * You can also choose to {@link #uploadToStash stash the upload} and
25          * {@link #finishStashUpload finalize} it later:
26          *
27          *     var file, // Some file object
28          *       upload = new mw.Upload,
29          *       stashPromise = $.Deferred();
30          *
31          *     upload.setFile( file );
32          *     upload.uploadToStash().then( function () {
33          *       stashPromise.resolve();
34          *     } );
35          *
36          *     stashPromise.then( function () {
37          *       upload.setFilename( 'foo' );
38          *       upload.setText( 'bar' );
39          *       upload.finishStashUpload().then( function () {
40          *         console.log( 'Done!' );
41          *       } );
42          *     } );
43          *
44          * @class mw.Upload
45          *
46          * @constructor
47          * @param {Object|mw.Api} [apiconfig] A mw.Api object (or subclass), or configuration
48          *     to pass to the constructor of mw.Api.
49          */
50         function Upload( apiconfig ) {
51                 this.api = ( apiconfig instanceof mw.Api ) ? apiconfig : new mw.Api( apiconfig );
52
53                 this.watchlist = false;
54                 this.text = '';
55                 this.comment = '';
56                 this.filename = null;
57                 this.file = null;
58                 this.setState( Upload.State.NEW );
59
60                 this.imageinfo = undefined;
61         }
62
63         UP = Upload.prototype;
64
65         /**
66          * Get the mw.Api instance used by this Upload object.
67          *
68          * @return {jQuery.Promise}
69          * @return {Function} return.done
70          * @return {mw.Api} return.done.api
71          */
72         UP.getApi = function () {
73                 return $.Deferred().resolve( this.api ).promise();
74         };
75
76         /**
77          * Set the text of the file page, to be created on file upload.
78          *
79          * @param {string} text
80          */
81         UP.setText = function ( text ) {
82                 this.text = text;
83         };
84
85         /**
86          * Set the filename, to be finalized on upload.
87          *
88          * @param {string} filename
89          */
90         UP.setFilename = function ( filename ) {
91                 this.filename = filename;
92         };
93
94         /**
95          * Set the stashed file to finish uploading.
96          *
97          * @param {string} filekey
98          */
99         UP.setFilekey = function ( filekey ) {
100                 var upload = this;
101
102                 this.setState( Upload.State.STASHED );
103                 this.stashPromise = $.Deferred().resolve( function ( data ) {
104                         return upload.api.uploadFromStash( filekey, data );
105                 } );
106         };
107
108         /**
109          * Sets the filename based on the filename as it was on the upload.
110          */
111         UP.setFilenameFromFile = function () {
112                 var file = this.getFile();
113                 if ( !file ) {
114                         return;
115                 }
116                 if ( file.nodeType && file.nodeType === Node.ELEMENT_NODE ) {
117                         // File input element, use getBasename to cut out the path
118                         this.setFilename( this.getBasename( file.value ) );
119                 } else if ( file.name ) {
120                         // HTML5 FileAPI File object, but use getBasename to be safe
121                         this.setFilename( this.getBasename( file.name ) );
122                 } else {
123                         // If we ever implement uploading files from clipboard, they might not have a name
124                         this.setFilename( '?' );
125                 }
126         };
127
128         /**
129          * Set the file to be uploaded.
130          *
131          * @param {HTMLInputElement|File|Blob} file
132          */
133         UP.setFile = function ( file ) {
134                 this.file = file;
135         };
136
137         /**
138          * Set whether the file should be watchlisted after upload.
139          *
140          * @param {boolean} watchlist
141          */
142         UP.setWatchlist = function ( watchlist ) {
143                 this.watchlist = watchlist;
144         };
145
146         /**
147          * Set the edit comment for the upload.
148          *
149          * @param {string} comment
150          */
151         UP.setComment = function ( comment ) {
152                 this.comment = comment;
153         };
154
155         /**
156          * Get the text of the file page, to be created on file upload.
157          *
158          * @return {string}
159          */
160         UP.getText = function () {
161                 return this.text;
162         };
163
164         /**
165          * Get the filename, to be finalized on upload.
166          *
167          * @return {string}
168          */
169         UP.getFilename = function () {
170                 return this.filename;
171         };
172
173         /**
174          * Get the file being uploaded.
175          *
176          * @return {HTMLInputElement|File|Blob}
177          */
178         UP.getFile = function () {
179                 return this.file;
180         };
181
182         /**
183          * Get the boolean for whether the file will be watchlisted after upload.
184          *
185          * @return {boolean}
186          */
187         UP.getWatchlist = function () {
188                 return this.watchlist;
189         };
190
191         /**
192          * Get the current value of the edit comment for the upload.
193          *
194          * @return {string}
195          */
196         UP.getComment = function () {
197                 return this.comment;
198         };
199
200         /**
201          * Gets the base filename from a path name.
202          *
203          * @param {string} path
204          * @return {string}
205          */
206         UP.getBasename = function ( path ) {
207                 if ( path === undefined || path === null ) {
208                         return '';
209                 }
210
211                 // Find the index of the last path separator in the
212                 // path, and add 1. Then, take the entire string after that.
213                 return path.slice(
214                         Math.max(
215                                 path.lastIndexOf( '/' ),
216                                 path.lastIndexOf( '\\' )
217                         ) + 1
218                 );
219         };
220
221         /**
222          * Sets the state and state details (if any) of the upload.
223          *
224          * @param {mw.Upload.State} state
225          * @param {Object} stateDetails
226          */
227         UP.setState = function ( state, stateDetails ) {
228                 this.state = state;
229                 this.stateDetails = stateDetails;
230         };
231
232         /**
233          * Gets the state of the upload.
234          *
235          * @return {mw.Upload.State}
236          */
237         UP.getState = function () {
238                 return this.state;
239         };
240
241         /**
242          * Gets details of the current state.
243          *
244          * @return {string}
245          */
246         UP.getStateDetails = function () {
247                 return this.stateDetails;
248         };
249
250         /**
251          * Get the imageinfo object for the finished upload.
252          * Only available once the upload is finished! Don't try to get it
253          * beforehand.
254          *
255          * @return {Object|undefined}
256          */
257         UP.getImageInfo = function () {
258                 return this.imageinfo;
259         };
260
261         /**
262          * Upload the file directly.
263          *
264          * @return {jQuery.Promise}
265          */
266         UP.upload = function () {
267                 var upload = this;
268
269                 if ( !this.getFile() ) {
270                         return $.Deferred().reject( 'No file to upload. Call setFile to add one.' );
271                 }
272
273                 if ( !this.getFilename() ) {
274                         return $.Deferred().reject( 'No filename set. Call setFilename to add one.' );
275                 }
276
277                 this.setState( Upload.State.UPLOADING );
278
279                 return this.api.chunkedUpload( this.getFile(), {
280                         watchlist: ( this.getWatchlist() ) ? 1 : undefined,
281                         comment: this.getComment(),
282                         filename: this.getFilename(),
283                         text: this.getText()
284                 } ).then( function ( result ) {
285                         upload.setState( Upload.State.UPLOADED );
286                         upload.imageinfo = result.upload.imageinfo;
287                         return result;
288                 }, function ( errorCode, result ) {
289                         if ( result && result.upload && result.upload.warnings ) {
290                                 upload.setState( Upload.State.WARNING, result );
291                         } else {
292                                 upload.setState( Upload.State.ERROR, result );
293                         }
294                         return $.Deferred().reject( errorCode, result );
295                 } );
296         };
297
298         /**
299          * Upload the file to the stash to be completed later.
300          *
301          * @return {jQuery.Promise}
302          */
303         UP.uploadToStash = function () {
304                 var upload = this;
305
306                 if ( !this.getFile() ) {
307                         return $.Deferred().reject( 'No file to upload. Call setFile to add one.' );
308                 }
309
310                 if ( !this.getFilename() ) {
311                         this.setFilenameFromFile();
312                 }
313
314                 this.setState( Upload.State.UPLOADING );
315
316                 this.stashPromise = this.api.chunkedUploadToStash( this.getFile(), {
317                         filename: this.getFilename()
318                 } ).then( function ( finishStash ) {
319                         upload.setState( Upload.State.STASHED );
320                         return finishStash;
321                 }, function ( errorCode, result ) {
322                         if ( result && result.upload && result.upload.warnings ) {
323                                 upload.setState( Upload.State.WARNING, result );
324                         } else {
325                                 upload.setState( Upload.State.ERROR, result );
326                         }
327                         return $.Deferred().reject( errorCode, result );
328                 } );
329
330                 return this.stashPromise;
331         };
332
333         /**
334          * Finish a stash upload.
335          *
336          * @return {jQuery.Promise}
337          */
338         UP.finishStashUpload = function () {
339                 var upload = this;
340
341                 if ( !this.stashPromise ) {
342                         return $.Deferred().reject( 'This upload has not been stashed, please upload it to the stash first.' );
343                 }
344
345                 return this.stashPromise.then( function ( finishStash ) {
346                         upload.setState( Upload.State.UPLOADING );
347
348                         return finishStash( {
349                                 watchlist: ( upload.getWatchlist() ) ? 1 : undefined,
350                                 comment: upload.getComment(),
351                                 filename: upload.getFilename(),
352                                 text: upload.getText()
353                         } ).then( function ( result ) {
354                                 upload.setState( Upload.State.UPLOADED );
355                                 upload.imageinfo = result.upload.imageinfo;
356                                 return result;
357                         }, function ( errorCode, result ) {
358                                 if ( result && result.upload && result.upload.warnings ) {
359                                         upload.setState( Upload.State.WARNING, result );
360                                 } else {
361                                         upload.setState( Upload.State.ERROR, result );
362                                 }
363                                 return $.Deferred().reject( errorCode, result );
364                         } );
365                 } );
366         };
367
368         /**
369          * @enum mw.Upload.State
370          * State of uploads represented in simple terms.
371          */
372         Upload.State = {
373                 /** Upload not yet started */
374                 NEW: 0,
375
376                 /** Upload finished, but there was a warning */
377                 WARNING: 1,
378
379                 /** Upload finished, but there was an error */
380                 ERROR: 2,
381
382                 /** Upload in progress */
383                 UPLOADING: 3,
384
385                 /** Upload finished, but not published, call #finishStashUpload */
386                 STASHED: 4,
387
388                 /** Upload finished and published */
389                 UPLOADED: 5
390         };
391
392         mw.Upload = Upload;
393 }( mediaWiki, jQuery ) );