X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/wordpress.git/blobdiff_plain/e08b42e8ad054ec67522d7ac1aaae5dc68cb3d01..caeaf8dc94b5e3f75dc98ec92dc7b76049cdddb6:/wp-includes/js/plupload/wp-plupload.js diff --git a/wp-includes/js/plupload/wp-plupload.js b/wp-includes/js/plupload/wp-plupload.js index 5751949b..09a37cef 100644 --- a/wp-includes/js/plupload/wp-plupload.js +++ b/wp-includes/js/plupload/wp-plupload.js @@ -2,28 +2,31 @@ 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', @@ -37,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. @@ -52,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(); @@ -69,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; @@ -85,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, @@ -98,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 ); @@ -148,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({ @@ -169,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'; @@ -178,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 ); @@ -195,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; @@ -226,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; @@ -234,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; } } @@ -244,7 +311,9 @@ window.wp = window.wp || {}; up.refresh(); }); - this.init(); + this.uploader.bind( 'PostInit', function() { + self.init(); + }); }; // Adds the 'defaults' and 'browser' properties. @@ -252,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, @@ -282,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; @@ -292,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() {}, @@ -338,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;