summaryrefslogtreecommitdiff
path: root/resources/src/mediawiki/mediawiki.Upload.js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/src/mediawiki/mediawiki.Upload.js')
-rw-r--r--resources/src/mediawiki/mediawiki.Upload.js368
1 files changed, 368 insertions, 0 deletions
diff --git a/resources/src/mediawiki/mediawiki.Upload.js b/resources/src/mediawiki/mediawiki.Upload.js
new file mode 100644
index 00000000..4f8789de
--- /dev/null
+++ b/resources/src/mediawiki/mediawiki.Upload.js
@@ -0,0 +1,368 @@
+( function ( mw, $ ) {
+ var UP;
+
+ /**
+ * @class mw.Upload
+ *
+ * Used to represent an upload in progress on the frontend.
+ * Most of the functionality is implemented in mw.Api.plugin.upload,
+ * but this model class will tie it together as well as let you perform
+ * actions in a logical way.
+ *
+ * A simple example:
+ *
+ * var file = new OO.ui.SelectFileWidget(),
+ * button = new OO.ui.ButtonWidget( { label: 'Save' } ),
+ * upload = new mw.Upload;
+ *
+ * button.on( 'click', function () {
+ * upload.setFile( file.getValue() );
+ * upload.setFilename( file.getValue().name );
+ * upload.upload();
+ * } );
+ *
+ * $( 'body' ).append( file.$element, button.$element );
+ *
+ * You can also choose to {@link #uploadToStash stash the upload} and
+ * {@link #finishStashUpload finalize} it later:
+ *
+ * var file, // Some file object
+ * upload = new mw.Upload,
+ * stashPromise = $.Deferred();
+ *
+ * upload.setFile( file );
+ * upload.uploadToStash().then( function () {
+ * stashPromise.resolve();
+ * } );
+ *
+ * stashPromise.then( function () {
+ * upload.setFilename( 'foo' );
+ * upload.setText( 'bar' );
+ * upload.finishStashUpload().then( function () {
+ * console.log( 'Done!' );
+ * } );
+ * } );
+ *
+ * @constructor
+ * @param {Object|mw.Api} [apiconfig] A mw.Api object (or subclass), or configuration
+ * to pass to the constructor of mw.Api.
+ */
+ function Upload( apiconfig ) {
+ this.api = ( apiconfig instanceof mw.Api ) ? apiconfig : new mw.Api( apiconfig );
+
+ this.watchlist = false;
+ this.text = '';
+ this.comment = '';
+ this.filename = null;
+ this.file = null;
+ this.setState( Upload.State.NEW );
+
+ this.imageinfo = undefined;
+ }
+
+ UP = Upload.prototype;
+
+ /**
+ * Set the text of the file page, to be created on file upload.
+ *
+ * @param {string} text
+ */
+ UP.setText = function ( text ) {
+ this.text = text;
+ };
+
+ /**
+ * Set the filename, to be finalized on upload.
+ *
+ * @param {string} filename
+ */
+ UP.setFilename = function ( filename ) {
+ this.filename = filename;
+ };
+
+ /**
+ * Sets the filename based on the filename as it was on the upload.
+ */
+ UP.setFilenameFromFile = function () {
+ var file = this.getFile();
+ if ( !file ) {
+ return;
+ }
+ if ( file.nodeType && file.nodeType === Node.ELEMENT_NODE ) {
+ // File input element, use getBasename to cut out the path
+ this.setFilename( this.getBasename( file.value ) );
+ } else if ( file.name ) {
+ // HTML5 FileAPI File object, but use getBasename to be safe
+ this.setFilename( this.getBasename( file.name ) );
+ } else {
+ // If we ever implement uploading files from clipboard, they might not have a name
+ this.setFilename( '?' );
+ }
+ };
+
+ /**
+ * Set the file to be uploaded.
+ *
+ * @param {HTMLInputElement|File} file
+ */
+ UP.setFile = function ( file ) {
+ this.file = file;
+ };
+
+ /**
+ * Set whether the file should be watchlisted after upload.
+ *
+ * @param {boolean} watchlist
+ */
+ UP.setWatchlist = function ( watchlist ) {
+ this.watchlist = watchlist;
+ };
+
+ /**
+ * Set the edit comment for the upload.
+ *
+ * @param {string} comment
+ */
+ UP.setComment = function ( comment ) {
+ this.comment = comment;
+ };
+
+ /**
+ * Get the text of the file page, to be created on file upload.
+ *
+ * @return {string}
+ */
+ UP.getText = function () {
+ return this.text;
+ };
+
+ /**
+ * Get the filename, to be finalized on upload.
+ *
+ * @return {string}
+ */
+ UP.getFilename = function () {
+ return this.filename;
+ };
+
+ /**
+ * Get the file being uploaded.
+ *
+ * @return {HTMLInputElement|File}
+ */
+ UP.getFile = function () {
+ return this.file;
+ };
+
+ /**
+ * Get the boolean for whether the file will be watchlisted after upload.
+ *
+ * @return {boolean}
+ */
+ UP.getWatchlist = function () {
+ return this.watchlist;
+ };
+
+ /**
+ * Get the current value of the edit comment for the upload.
+ *
+ * @return {string}
+ */
+ UP.getComment = function () {
+ return this.comment;
+ };
+
+ /**
+ * Gets the base filename from a path name.
+ *
+ * @param {string} path
+ * @return {string}
+ */
+ UP.getBasename = function ( path ) {
+ if ( path === undefined || path === null ) {
+ return '';
+ }
+
+ // Find the index of the last path separator in the
+ // path, and add 1. Then, take the entire string after that.
+ return path.slice(
+ Math.max(
+ path.lastIndexOf( '/' ),
+ path.lastIndexOf( '\\' )
+ ) + 1
+ );
+ };
+
+ /**
+ * Sets the state and state details (if any) of the upload.
+ *
+ * @param {mw.Upload.State} state
+ * @param {Object} stateDetails
+ */
+ UP.setState = function ( state, stateDetails ) {
+ this.state = state;
+ this.stateDetails = stateDetails;
+ };
+
+ /**
+ * Gets the state of the upload.
+ *
+ * @return {mw.Upload.State}
+ */
+ UP.getState = function () {
+ return this.state;
+ };
+
+ /**
+ * Gets details of the current state.
+ *
+ * @return {string}
+ */
+ UP.getStateDetails = function () {
+ return this.stateDetails;
+ };
+
+ /**
+ * Get the imageinfo object for the finished upload.
+ * Only available once the upload is finished! Don't try to get it
+ * beforehand.
+ *
+ * @return {Object|undefined}
+ */
+ UP.getImageInfo = function () {
+ return this.imageinfo;
+ };
+
+ /**
+ * Upload the file directly.
+ *
+ * @return {jQuery.Promise}
+ */
+ UP.upload = function () {
+ var upload = this;
+
+ if ( !this.getFile() ) {
+ return $.Deferred().reject( 'No file to upload. Call setFile to add one.' );
+ }
+
+ if ( !this.getFilename() ) {
+ return $.Deferred().reject( 'No filename set. Call setFilename to add one.' );
+ }
+
+ this.setState( Upload.State.UPLOADING );
+
+ return this.api.upload( this.getFile(), {
+ watchlist: ( this.getWatchlist() ) ? 1 : undefined,
+ comment: this.getComment(),
+ filename: this.getFilename(),
+ text: this.getText()
+ } ).then( function ( result ) {
+ upload.setState( Upload.State.UPLOADED );
+ upload.imageinfo = result.upload.imageinfo;
+ return result;
+ }, function ( errorCode, result ) {
+ if ( result && result.upload && result.upload.warnings ) {
+ upload.setState( Upload.State.WARNING, result );
+ } else {
+ upload.setState( Upload.State.ERROR, result );
+ }
+ return $.Deferred().reject( errorCode, result );
+ } );
+ };
+
+ /**
+ * Upload the file to the stash to be completed later.
+ *
+ * @return {jQuery.Promise}
+ */
+ UP.uploadToStash = function () {
+ var upload = this;
+
+ if ( !this.getFile() ) {
+ return $.Deferred().reject( 'No file to upload. Call setFile to add one.' );
+ }
+
+ if ( !this.getFilename() ) {
+ this.setFilenameFromFile();
+ }
+
+ this.setState( Upload.State.UPLOADING );
+
+ this.stashPromise = this.api.uploadToStash( this.getFile(), {
+ filename: this.getFilename()
+ } ).then( function ( finishStash ) {
+ upload.setState( Upload.State.STASHED );
+ return finishStash;
+ }, function ( errorCode, result ) {
+ if ( result && result.upload && result.upload.warnings ) {
+ upload.setState( Upload.State.WARNING, result );
+ } else {
+ upload.setState( Upload.State.ERROR, result );
+ }
+ return $.Deferred().reject( errorCode, result );
+ } );
+
+ return this.stashPromise;
+ };
+
+ /**
+ * Finish a stash upload.
+ *
+ * @return {jQuery.Promise}
+ */
+ UP.finishStashUpload = function () {
+ var upload = this;
+
+ if ( !this.stashPromise ) {
+ return $.Deferred().reject( 'This upload has not been stashed, please upload it to the stash first.' );
+ }
+
+ return this.stashPromise.then( function ( finishStash ) {
+ upload.setState( Upload.State.UPLOADING );
+
+ return finishStash( {
+ watchlist: ( upload.getWatchlist() ) ? 1 : undefined,
+ comment: upload.getComment(),
+ filename: upload.getFilename(),
+ text: upload.getText()
+ } ).then( function ( result ) {
+ upload.setState( Upload.State.UPLOADED );
+ upload.imageinfo = result.upload.imageinfo;
+ return result;
+ }, function ( errorCode, result ) {
+ if ( result && result.upload && result.upload.warnings ) {
+ upload.setState( Upload.State.WARNING, result );
+ } else {
+ upload.setState( Upload.State.ERROR, result );
+ }
+ return $.Deferred().reject( errorCode, result );
+ } );
+ } );
+ };
+
+ /**
+ * @enum mw.Upload.State
+ * State of uploads represented in simple terms.
+ */
+ Upload.State = {
+ /** Upload not yet started */
+ NEW: 0,
+
+ /** Upload finished, but there was a warning */
+ WARNING: 1,
+
+ /** Upload finished, but there was an error */
+ ERROR: 2,
+
+ /** Upload in progress */
+ UPLOADING: 3,
+
+ /** Upload finished, but not published, call #finishStashUpload */
+ STASHED: 4,
+
+ /** Upload finished and published */
+ UPLOADED: 5
+ };
+
+ mw.Upload = Upload;
+}( mediaWiki, jQuery ) );