]> scripts.mit.edu Git - autoinstalls/wordpress.git/blobdiff - wp-includes/js/plupload/wp-plupload.js
WordPress 4.1.4-scripts
[autoinstalls/wordpress.git] / wp-includes / js / plupload / wp-plupload.js
index dc91674930fc4d2c81577921899af0517a6c8701..09a37ceff248eaeb7b286d0da5b563e3c84e9f27 100644 (file)
@@ -1,27 +1,32 @@
+/* global pluploadL10n, plupload, _wpPluploadSettings */
+
 window.wp = window.wp || {};
 
-(function( exports, $ ) {
+( function( exports, $ ) {
        var Uploader;
 
-       if ( typeof _wpPluploadSettings === 'undefined' )
+       if ( typeof _wpPluploadSettings === 'undefined' ) {
                return;
+       }
 
-       /*
-        * An object that helps create a WordPress uploader using plupload.
+       /**
+        * A WordPress uploader.
         *
-        * @param options - object - The options passed to the new plupload instance.
-        *    Accepts the following parameters:
-        *    - container - The id of uploader container.
-        *    - browser   - The id of button to trigger the file select.
-        *    - dropzone  - The id of file drop target.
-        *    - plupload  - An object of parameters to pass to the plupload instance.
-        *    - params    - An object of parameters to pass to $_POST when uploading the file.
-        *                  Extends this.plupload.multipart_params under the hood.
+        * The Plupload library provides cross-browser uploader UI integration.
+        * This object bridges the Plupload API to integrate uploads into the
+        * WordPress back-end and the WordPress media experience.
         *
-        * @param attributes - object - Attributes and methods for this specific instance.
+        * @param {object} options           The options passed to the new plupload instance.
+        * @param {object} options.container The id of uploader container.
+        * @param {object} options.browser   The id of button to trigger the file select.
+        * @param {object} options.dropzone  The id of file drop target.
+        * @param {object} options.plupload  An object of parameters to pass to the plupload instance.
+        * @param {object} options.params    An object of parameters to pass to $_POST when uploading the file.
+        *                                   Extends this.plupload.multipart_params under the hood.
         */
        Uploader = function( options ) {
                var self = this,
+                       isIE = navigator.userAgent.indexOf('Trident/') != -1 || navigator.userAgent.indexOf('MSIE ') != -1,
                        elements = {
                                container: 'container',
                                browser:   'browse_button',
@@ -35,14 +40,16 @@ window.wp = window.wp || {};
 
                this.supported = this.supports.upload;
 
-               if ( ! this.supported )
+               if ( ! this.supported ) {
                        return;
+               }
 
+               // Arguments to send to pluplad.Uploader().
                // Use deep extend to ensure that multipart_params and other objects are cloned.
                this.plupload = $.extend( true, { multipart_params: {} }, Uploader.defaults );
                this.container = document.body; // Set default container.
 
-               // Extend the instance with options
+               // Extend the instance with options.
                //
                // Use deep extend to allow options.plupload to override individual
                // default plupload keys.
@@ -50,15 +57,17 @@ window.wp = window.wp || {};
 
                // Proxy all methods so this always refers to the current instance.
                for ( key in this ) {
-                       if ( $.isFunction( this[ key ] ) )
+                       if ( $.isFunction( this[ key ] ) ) {
                                this[ key ] = $.proxy( this[ key ], this );
+                       }
                }
 
-               // Ensure all elements are jQuery elements and have id attributes
-               // Then set the proper plupload arguments to the ids.
+               // Ensure all elements are jQuery elements and have id attributes,
+               // then set the proper plupload arguments to the ids.
                for ( key in elements ) {
-                       if ( ! this[ key ] )
+                       if ( ! this[ key ] ) {
                                continue;
+                       }
 
                        this[ key ] = $( this[ key ] ).first();
 
@@ -67,15 +76,27 @@ window.wp = window.wp || {};
                                continue;
                        }
 
-                       if ( ! this[ key ].prop('id') )
+                       if ( ! this[ key ].prop('id') ) {
                                this[ key ].prop( 'id', '__wp-uploader-id-' + Uploader.uuid++ );
+                       }
+
                        this.plupload[ elements[ key ] ] = this[ key ].prop('id');
                }
 
                // If the uploader has neither a browse button nor a dropzone, bail.
-               if ( ! ( this.browser && this.browser.length ) && ! ( this.dropzone && this.dropzone.length ) )
+               if ( ! ( this.browser && this.browser.length ) && ! ( this.dropzone && this.dropzone.length ) ) {
                        return;
+               }
+
+               // Make sure flash sends cookies (seems in IE it does without switching to urlstream mode)
+               if ( ! isIE && 'flash' === plupload.predictRuntime( this.plupload ) &&
+                       ( ! this.plupload.required_features || ! this.plupload.required_features.hasOwnProperty( 'send_binary_string' ) ) ) {
+
+                       this.plupload.required_features = this.plupload.required_features || {};
+                       this.plupload.required_features.send_binary_string = true;
+               }
 
+               // Initialize the plupload instance.
                this.uploader = new plupload.Uploader( this.plupload );
                delete this.plupload;
 
@@ -83,9 +104,20 @@ window.wp = window.wp || {};
                this.param( this.params || {} );
                delete this.params;
 
+               /**
+                * Custom error callback.
+                *
+                * Add a new error to the errors collection, so other modules can track
+                * and display errors. @see wp.Uploader.errors.
+                *
+                * @param  {string}        message
+                * @param  {object}        data
+                * @param  {plupload.File} file     File that was uploaded.
+                */
                error = function( message, data, file ) {
-                       if ( file.attachment )
+                       if ( file.attachment ) {
                                file.attachment.destroy();
+                       }
 
                        Uploader.errors.unshift({
                                message: message || pluploadL10n.default_error,
@@ -96,47 +128,59 @@ window.wp = window.wp || {};
                        self.error( message, data, file );
                };
 
-               this.uploader.init();
-
-               this.supports.dragdrop = this.uploader.features.dragdrop && ! Uploader.browser.mobile;
+               /**
+                * After the Uploader has been initialized, initialize some behaviors for the dropzone.
+                *
+                * @param {plupload.Uploader} uploader Uploader instance.
+                */
+               this.uploader.bind( 'init', function( uploader ) {
+                       var timer, active, dragdrop,
+                               dropzone = self.dropzone;
 
-               // Generate drag/drop helper classes.
-               (function( dropzone, supported ) {
-                       var timer, active;
+                       dragdrop = self.supports.dragdrop = uploader.features.dragdrop && ! Uploader.browser.mobile;
 
-                       if ( ! dropzone )
+                       // Generate drag/drop helper classes.
+                       if ( ! dropzone ) {
                                return;
+                       }
 
-                       dropzone.toggleClass( 'supports-drag-drop', !! supported );
+                       dropzone.toggleClass( 'supports-drag-drop', !! dragdrop );
 
-                       if ( ! supported )
+                       if ( ! dragdrop ) {
                                return dropzone.unbind('.wp-uploader');
+                       }
 
-                       // 'dragenter' doesn't fire correctly,
-                       // simulate it with a limited 'dragover'
-                       dropzone.bind( 'dragover.wp-uploader', function(){
-                               if ( timer )
+                       // 'dragenter' doesn't fire correctly, simulate it with a limited 'dragover'.
+                       dropzone.bind( 'dragover.wp-uploader', function() {
+                               if ( timer ) {
                                        clearTimeout( timer );
+                               }
 
-                               if ( active )
+                               if ( active ) {
                                        return;
+                               }
 
                                dropzone.trigger('dropzone:enter').addClass('drag-over');
                                active = true;
                        });
 
-                       dropzone.bind('dragleave.wp-uploader, drop.wp-uploader', function(){
+                       dropzone.bind('dragleave.wp-uploader, drop.wp-uploader', function() {
                                // Using an instant timer prevents the drag-over class from
                                // being quickly removed and re-added when elements inside the
                                // dropzone are repositioned.
                                //
-                               // See http://core.trac.wordpress.org/ticket/21705
+                               // @see https://core.trac.wordpress.org/ticket/21705
                                timer = setTimeout( function() {
                                        active = false;
                                        dropzone.trigger('dropzone:leave').removeClass('drag-over');
                                }, 0 );
                        });
-               }( this.dropzone, this.supports.dragdrop ));
+
+                       self.ready = true;
+                       $(self).trigger( 'uploader:ready' );
+               });
+
+               this.uploader.init();
 
                if ( this.browser ) {
                        this.browser.on( 'mouseenter', this.refresh );
@@ -146,13 +190,21 @@ window.wp = window.wp || {};
                        $('#' + this.uploader.id + '_html5_container').hide();
                }
 
+               /**
+                * After files were filtered and added to the queue, create a model for each.
+                *
+                * @event FilesAdded
+                * @param {plupload.Uploader} uploader Uploader instance.
+                * @param {Array}             files    Array of file objects that were added to queue by the user.
+                */
                this.uploader.bind( 'FilesAdded', function( up, files ) {
                        _.each( files, function( file ) {
                                var attributes, image;
 
                                // Ignore failed uploads.
-                               if ( plupload.FAILED === file.status )
+                               if ( plupload.FAILED === file.status ) {
                                        return;
+                               }
 
                                // Generate attributes for a new `Attachment` model.
                                attributes = _.extend({
@@ -167,7 +219,7 @@ window.wp = window.wp || {};
                                // Handle early mime type scanning for images.
                                image = /(?:jpe?g|png|gif)$/i.exec( file.name );
 
-                               // Did we find an image?
+                               // For images set the model's type and subtype attributes.
                                if ( image ) {
                                        attributes.type = 'image';
 
@@ -176,9 +228,9 @@ window.wp = window.wp || {};
                                        attributes.subtype = ( 'jpg' === image[0] ) ? 'jpeg' : image[0];
                                }
 
-                               // Create the `Attachment`.
+                               // Create a model for the attachment, and add it to the Upload queue collection
+                               // so listeners to the upload queue can track and display upload progress.
                                file.attachment = wp.media.model.Attachment.create( attributes );
-
                                Uploader.queue.add( file.attachment );
 
                                self.added( file.attachment );
@@ -193,6 +245,14 @@ window.wp = window.wp || {};
                        self.progress( file.attachment );
                });
 
+               /**
+                * After a file is successfully uploaded, update its model.
+                *
+                * @param {plupload.Uploader} uploader Uploader instance.
+                * @param {plupload.File}     file     File that was uploaded.
+                * @param {Object}            response Object with response properties.
+                * @return {mixed}
+                */
                this.uploader.bind( 'FileUploaded', function( up, file, response ) {
                        var complete;
 
@@ -224,6 +284,12 @@ window.wp = window.wp || {};
                        self.success( file.attachment );
                });
 
+               /**
+                * When plupload surfaces an error, send it to the error handler.
+                *
+                * @param {plupload.Uploader} uploader Uploader instance.
+                * @param {Object}            error    Contains code, message and sometimes file and other details.
+                */
                this.uploader.bind( 'Error', function( up, pluploadError ) {
                        var message = pluploadL10n.default_error,
                                key;
@@ -232,8 +298,11 @@ window.wp = window.wp || {};
                        for ( key in Uploader.errorMap ) {
                                if ( pluploadError.code === plupload[ key ] ) {
                                        message = Uploader.errorMap[ key ];
-                                       if ( _.isFunction( message ) )
+
+                                       if ( _.isFunction( message ) ) {
                                                message = message( pluploadError.file, pluploadError );
+                                       }
+
                                        break;
                                }
                        }
@@ -242,7 +311,9 @@ window.wp = window.wp || {};
                        up.refresh();
                });
 
-               this.init();
+               this.uploader.bind( 'PostInit', function() {
+                       self.init();
+               });
        };
 
        // Adds the 'defaults' and 'browser' properties.
@@ -250,6 +321,7 @@ window.wp = window.wp || {};
 
        Uploader.uuid = 0;
 
+       // Map Plupload error codes to user friendly error messages.
        Uploader.errorMap = {
                'FAILED':                 pluploadL10n.upload_failed,
                'FILE_EXTENSION_ERROR':   pluploadL10n.invalid_filetype,
@@ -280,8 +352,9 @@ window.wp = window.wp || {};
                 *    Sets values for a map of data.
                 */
                param: function( key, value ) {
-                       if ( arguments.length === 1 && typeof key === 'string' )
+                       if ( arguments.length === 1 && typeof key === 'string' ) {
                                return this.uploader.settings.multipart_params[ key ];
+                       }
 
                        if ( arguments.length > 1 ) {
                                this.uploader.settings.multipart_params[ key ] = value;
@@ -290,6 +363,10 @@ window.wp = window.wp || {};
                        }
                },
 
+               /**
+                * Make a few internal event callbacks available on the wp.Uploader object
+                * to change the Uploader internals if absolutely necessary.
+                */
                init:     function() {},
                error:    function() {},
                success:  function() {},
@@ -336,7 +413,11 @@ window.wp = window.wp || {};
                }
        });
 
+       // Create a collection of attachments in the upload queue,
+       // so that other modules can track and display upload progress.
        Uploader.queue = new wp.media.model.Attachments( [], { query: false });
+
+       // Create a collection to collect errors incurred while attempting upload.
        Uploader.errors = new Backbone.Collection();
 
        exports.Uploader = Uploader;