web/wp-includes/js/plupload/wp-plupload.js
changeset 204 09a1c134465b
parent 194 32102edaa81b
equal deleted inserted replaced
203:f507feede89a 204:09a1c134465b
     1 if(typeof wp==="undefined"){var wp={}}(function(a,b){var c;if(typeof _wpPluploadSettings==="undefined"){return}c=function(e){var d=this,g={container:"container",browser:"browse_button",dropzone:"drop_element"},f;this.supports={upload:c.browser.supported};this.supported=this.supports.upload;if(!this.supported){return}this.plupload=b.extend(true,{multipart_params:{}},c.defaults);this.container=document.body;b.extend(true,this,e);for(f in this){if(b.isFunction(this[f])){this[f]=b.proxy(this[f],this)}}for(f in g){if(!this[f]){continue}this[f]=b(this[f]).first();if(!this[f].length){delete this[f];continue}if(!this[f].prop("id")){this[f].prop("id","__wp-uploader-id-"+c.uuid++)}this.plupload[g[f]]=this[f].prop("id")}if(!(this.browser&&this.browser.length)&&!(this.dropzone&&this.dropzone.length)){return}this.uploader=new plupload.Uploader(this.plupload);delete this.plupload;this.param(this.params||{});delete this.params;this.uploader.init();this.supports.dragdrop=this.uploader.features.dragdrop&&!c.browser.mobile;(function(j,h){var i=50,k;if(!j){return}j.toggleClass("supports-drag-drop",!!h);if(!h){return j.unbind(".wp-uploader")}j.bind("dragover.wp-uploader",function(){if(k){return}j.addClass("drag-over");k=true});j.bind("dragleave.wp-uploader, drop.wp-uploader",function(){k=false;j.removeClass("drag-over")})}(this.dropzone,this.supports.dragdrop));if(this.browser){this.browser.on("mouseenter",this.refresh)}else{this.uploader.disableBrowse(true);b("#"+this.uploader.id+"_html5_container").hide()}this.uploader.bind("UploadProgress",this.progress);this.uploader.bind("FileUploaded",function(h,j,i){try{i=JSON.parse(i.response)}catch(k){return d.error(pluploadL10n.default_error,k)}if(!i||!i.type||!i.data){return d.error(pluploadL10n.default_error)}if("error"===i.type){return d.error(i.data.message,i.data)}if("success"===i.type){return d.success(i.data)}});this.uploader.bind("Error",function(h,i){var k=pluploadL10n.default_error,j;for(j in c.errorMap){if(i.code===plupload[j]){k=c.errorMap[j];break}}d.error(k,i);h.refresh()});this.uploader.bind("FilesAdded",function(h,i){b.each(i,function(){d.added(this)});h.refresh();h.start()});this.init()};b.extend(c,_wpPluploadSettings);c.uuid=0;c.errorMap={FAILED:pluploadL10n.upload_failed,FILE_EXTENSION_ERROR:pluploadL10n.invalid_filetype,IMAGE_FORMAT_ERROR:pluploadL10n.not_an_image,IMAGE_MEMORY_ERROR:pluploadL10n.image_memory_exceeded,IMAGE_DIMENSIONS_ERROR:pluploadL10n.image_dimensions_exceeded,GENERIC_ERROR:pluploadL10n.upload_failed,IO_ERROR:pluploadL10n.io_error,HTTP_ERROR:pluploadL10n.http_error,SECURITY_ERROR:pluploadL10n.security_error};b.extend(c.prototype,{param:function(d,e){if(arguments.length===1&&typeof d==="string"){return this.uploader.settings.multipart_params[d]}if(arguments.length>1){this.uploader.settings.multipart_params[d]=e}else{b.extend(this.uploader.settings.multipart_params,d)}},init:function(){},error:function(){},success:function(){},added:function(){},progress:function(){},complete:function(){},refresh:function(){this.uploader.refresh()}});a.Uploader=c})(wp,jQuery);
     1 window.wp = window.wp || {};
       
     2 
       
     3 (function( exports, $ ) {
       
     4 	var Uploader;
       
     5 
       
     6 	if ( typeof _wpPluploadSettings === 'undefined' )
       
     7 		return;
       
     8 
       
     9 	/*
       
    10 	 * An object that helps create a WordPress uploader using plupload.
       
    11 	 *
       
    12 	 * @param options - object - The options passed to the new plupload instance.
       
    13 	 *    Accepts the following parameters:
       
    14 	 *    - container - The id of uploader container.
       
    15 	 *    - browser   - The id of button to trigger the file select.
       
    16 	 *    - dropzone  - The id of file drop target.
       
    17 	 *    - plupload  - An object of parameters to pass to the plupload instance.
       
    18 	 *    - params    - An object of parameters to pass to $_POST when uploading the file.
       
    19 	 *                  Extends this.plupload.multipart_params under the hood.
       
    20 	 *
       
    21 	 * @param attributes - object - Attributes and methods for this specific instance.
       
    22 	 */
       
    23 	Uploader = function( options ) {
       
    24 		var self = this,
       
    25 			elements = {
       
    26 				container: 'container',
       
    27 				browser:   'browse_button',
       
    28 				dropzone:  'drop_element'
       
    29 			},
       
    30 			key, error;
       
    31 
       
    32 		this.supports = {
       
    33 			upload: Uploader.browser.supported
       
    34 		};
       
    35 
       
    36 		this.supported = this.supports.upload;
       
    37 
       
    38 		if ( ! this.supported )
       
    39 			return;
       
    40 
       
    41 		// Use deep extend to ensure that multipart_params and other objects are cloned.
       
    42 		this.plupload = $.extend( true, { multipart_params: {} }, Uploader.defaults );
       
    43 		this.container = document.body; // Set default container.
       
    44 
       
    45 		// Extend the instance with options
       
    46 		//
       
    47 		// Use deep extend to allow options.plupload to override individual
       
    48 		// default plupload keys.
       
    49 		$.extend( true, this, options );
       
    50 
       
    51 		// Proxy all methods so this always refers to the current instance.
       
    52 		for ( key in this ) {
       
    53 			if ( $.isFunction( this[ key ] ) )
       
    54 				this[ key ] = $.proxy( this[ key ], this );
       
    55 		}
       
    56 
       
    57 		// Ensure all elements are jQuery elements and have id attributes
       
    58 		// Then set the proper plupload arguments to the ids.
       
    59 		for ( key in elements ) {
       
    60 			if ( ! this[ key ] )
       
    61 				continue;
       
    62 
       
    63 			this[ key ] = $( this[ key ] ).first();
       
    64 
       
    65 			if ( ! this[ key ].length ) {
       
    66 				delete this[ key ];
       
    67 				continue;
       
    68 			}
       
    69 
       
    70 			if ( ! this[ key ].prop('id') )
       
    71 				this[ key ].prop( 'id', '__wp-uploader-id-' + Uploader.uuid++ );
       
    72 			this.plupload[ elements[ key ] ] = this[ key ].prop('id');
       
    73 		}
       
    74 
       
    75 		// If the uploader has neither a browse button nor a dropzone, bail.
       
    76 		if ( ! ( this.browser && this.browser.length ) && ! ( this.dropzone && this.dropzone.length ) )
       
    77 			return;
       
    78 
       
    79 		this.uploader = new plupload.Uploader( this.plupload );
       
    80 		delete this.plupload;
       
    81 
       
    82 		// Set default params and remove this.params alias.
       
    83 		this.param( this.params || {} );
       
    84 		delete this.params;
       
    85 
       
    86 		error = function( message, data, file ) {
       
    87 			if ( file.attachment )
       
    88 				file.attachment.destroy();
       
    89 
       
    90 			Uploader.errors.unshift({
       
    91 				message: message || pluploadL10n.default_error,
       
    92 				data:    data,
       
    93 				file:    file
       
    94 			});
       
    95 
       
    96 			self.error( message, data, file );
       
    97 		};
       
    98 
       
    99 		this.uploader.init();
       
   100 
       
   101 		this.supports.dragdrop = this.uploader.features.dragdrop && ! Uploader.browser.mobile;
       
   102 
       
   103 		// Generate drag/drop helper classes.
       
   104 		(function( dropzone, supported ) {
       
   105 			var timer, active;
       
   106 
       
   107 			if ( ! dropzone )
       
   108 				return;
       
   109 
       
   110 			dropzone.toggleClass( 'supports-drag-drop', !! supported );
       
   111 
       
   112 			if ( ! supported )
       
   113 				return dropzone.unbind('.wp-uploader');
       
   114 
       
   115 			// 'dragenter' doesn't fire correctly,
       
   116 			// simulate it with a limited 'dragover'
       
   117 			dropzone.bind( 'dragover.wp-uploader', function(){
       
   118 				if ( timer )
       
   119 					clearTimeout( timer );
       
   120 
       
   121 				if ( active )
       
   122 					return;
       
   123 
       
   124 				dropzone.trigger('dropzone:enter').addClass('drag-over');
       
   125 				active = true;
       
   126 			});
       
   127 
       
   128 			dropzone.bind('dragleave.wp-uploader, drop.wp-uploader', function(){
       
   129 				// Using an instant timer prevents the drag-over class from
       
   130 				// being quickly removed and re-added when elements inside the
       
   131 				// dropzone are repositioned.
       
   132 				//
       
   133 				// See http://core.trac.wordpress.org/ticket/21705
       
   134 				timer = setTimeout( function() {
       
   135 					active = false;
       
   136 					dropzone.trigger('dropzone:leave').removeClass('drag-over');
       
   137 				}, 0 );
       
   138 			});
       
   139 		}( this.dropzone, this.supports.dragdrop ));
       
   140 
       
   141 		if ( this.browser ) {
       
   142 			this.browser.on( 'mouseenter', this.refresh );
       
   143 		} else {
       
   144 			this.uploader.disableBrowse( true );
       
   145 			// If HTML5 mode, hide the auto-created file container.
       
   146 			$('#' + this.uploader.id + '_html5_container').hide();
       
   147 		}
       
   148 
       
   149 		this.uploader.bind( 'FilesAdded', function( up, files ) {
       
   150 			_.each( files, function( file ) {
       
   151 				var attributes, image;
       
   152 
       
   153 				// Ignore failed uploads.
       
   154 				if ( plupload.FAILED === file.status )
       
   155 					return;
       
   156 
       
   157 				// Generate attributes for a new `Attachment` model.
       
   158 				attributes = _.extend({
       
   159 					file:      file,
       
   160 					uploading: true,
       
   161 					date:      new Date(),
       
   162 					filename:  file.name,
       
   163 					menuOrder: 0,
       
   164 					uploadedTo: wp.media.model.settings.post.id
       
   165 				}, _.pick( file, 'loaded', 'size', 'percent' ) );
       
   166 
       
   167 				// Handle early mime type scanning for images.
       
   168 				image = /(?:jpe?g|png|gif)$/i.exec( file.name );
       
   169 
       
   170 				// Did we find an image?
       
   171 				if ( image ) {
       
   172 					attributes.type = 'image';
       
   173 
       
   174 					// `jpeg`, `png` and `gif` are valid subtypes.
       
   175 					// `jpg` is not, so map it to `jpeg`.
       
   176 					attributes.subtype = ( 'jpg' === image[0] ) ? 'jpeg' : image[0];
       
   177 				}
       
   178 
       
   179 				// Create the `Attachment`.
       
   180 				file.attachment = wp.media.model.Attachment.create( attributes );
       
   181 
       
   182 				Uploader.queue.add( file.attachment );
       
   183 
       
   184 				self.added( file.attachment );
       
   185 			});
       
   186 
       
   187 			up.refresh();
       
   188 			up.start();
       
   189 		});
       
   190 
       
   191 		this.uploader.bind( 'UploadProgress', function( up, file ) {
       
   192 			file.attachment.set( _.pick( file, 'loaded', 'percent' ) );
       
   193 			self.progress( file.attachment );
       
   194 		});
       
   195 
       
   196 		this.uploader.bind( 'FileUploaded', function( up, file, response ) {
       
   197 			var complete;
       
   198 
       
   199 			try {
       
   200 				response = JSON.parse( response.response );
       
   201 			} catch ( e ) {
       
   202 				return error( pluploadL10n.default_error, e, file );
       
   203 			}
       
   204 
       
   205 			if ( ! _.isObject( response ) || _.isUndefined( response.success ) )
       
   206 				return error( pluploadL10n.default_error, null, file );
       
   207 			else if ( ! response.success )
       
   208 				return error( response.data && response.data.message, response.data, file );
       
   209 
       
   210 			_.each(['file','loaded','size','percent'], function( key ) {
       
   211 				file.attachment.unset( key );
       
   212 			});
       
   213 
       
   214 			file.attachment.set( _.extend( response.data, { uploading: false }) );
       
   215 			wp.media.model.Attachment.get( response.data.id, file.attachment );
       
   216 
       
   217 			complete = Uploader.queue.all( function( attachment ) {
       
   218 				return ! attachment.get('uploading');
       
   219 			});
       
   220 
       
   221 			if ( complete )
       
   222 				Uploader.queue.reset();
       
   223 
       
   224 			self.success( file.attachment );
       
   225 		});
       
   226 
       
   227 		this.uploader.bind( 'Error', function( up, pluploadError ) {
       
   228 			var message = pluploadL10n.default_error,
       
   229 				key;
       
   230 
       
   231 			// Check for plupload errors.
       
   232 			for ( key in Uploader.errorMap ) {
       
   233 				if ( pluploadError.code === plupload[ key ] ) {
       
   234 					message = Uploader.errorMap[ key ];
       
   235 					if ( _.isFunction( message ) )
       
   236 						message = message( pluploadError.file, pluploadError );
       
   237 					break;
       
   238 				}
       
   239 			}
       
   240 
       
   241 			error( message, pluploadError, pluploadError.file );
       
   242 			up.refresh();
       
   243 		});
       
   244 
       
   245 		this.init();
       
   246 	};
       
   247 
       
   248 	// Adds the 'defaults' and 'browser' properties.
       
   249 	$.extend( Uploader, _wpPluploadSettings );
       
   250 
       
   251 	Uploader.uuid = 0;
       
   252 
       
   253 	Uploader.errorMap = {
       
   254 		'FAILED':                 pluploadL10n.upload_failed,
       
   255 		'FILE_EXTENSION_ERROR':   pluploadL10n.invalid_filetype,
       
   256 		'IMAGE_FORMAT_ERROR':     pluploadL10n.not_an_image,
       
   257 		'IMAGE_MEMORY_ERROR':     pluploadL10n.image_memory_exceeded,
       
   258 		'IMAGE_DIMENSIONS_ERROR': pluploadL10n.image_dimensions_exceeded,
       
   259 		'GENERIC_ERROR':          pluploadL10n.upload_failed,
       
   260 		'IO_ERROR':               pluploadL10n.io_error,
       
   261 		'HTTP_ERROR':             pluploadL10n.http_error,
       
   262 		'SECURITY_ERROR':         pluploadL10n.security_error,
       
   263 
       
   264 		'FILE_SIZE_ERROR': function( file ) {
       
   265 			return pluploadL10n.file_exceeds_size_limit.replace('%s', file.name);
       
   266 		}
       
   267 	};
       
   268 
       
   269 	$.extend( Uploader.prototype, {
       
   270 		/**
       
   271 		 * Acts as a shortcut to extending the uploader's multipart_params object.
       
   272 		 *
       
   273 		 * param( key )
       
   274 		 *    Returns the value of the key.
       
   275 		 *
       
   276 		 * param( key, value )
       
   277 		 *    Sets the value of a key.
       
   278 		 *
       
   279 		 * param( map )
       
   280 		 *    Sets values for a map of data.
       
   281 		 */
       
   282 		param: function( key, value ) {
       
   283 			if ( arguments.length === 1 && typeof key === 'string' )
       
   284 				return this.uploader.settings.multipart_params[ key ];
       
   285 
       
   286 			if ( arguments.length > 1 ) {
       
   287 				this.uploader.settings.multipart_params[ key ] = value;
       
   288 			} else {
       
   289 				$.extend( this.uploader.settings.multipart_params, key );
       
   290 			}
       
   291 		},
       
   292 
       
   293 		init:     function() {},
       
   294 		error:    function() {},
       
   295 		success:  function() {},
       
   296 		added:    function() {},
       
   297 		progress: function() {},
       
   298 		complete: function() {},
       
   299 		refresh:  function() {
       
   300 			var node, attached, container, id;
       
   301 
       
   302 			if ( this.browser ) {
       
   303 				node = this.browser[0];
       
   304 
       
   305 				// Check if the browser node is in the DOM.
       
   306 				while ( node ) {
       
   307 					if ( node === document.body ) {
       
   308 						attached = true;
       
   309 						break;
       
   310 					}
       
   311 					node = node.parentNode;
       
   312 				}
       
   313 
       
   314 				// If the browser node is not attached to the DOM, use a
       
   315 				// temporary container to house it, as the browser button
       
   316 				// shims require the button to exist in the DOM at all times.
       
   317 				if ( ! attached ) {
       
   318 					id = 'wp-uploader-browser-' + this.uploader.id;
       
   319 
       
   320 					container = $( '#' + id );
       
   321 					if ( ! container.length ) {
       
   322 						container = $('<div class="wp-uploader-browser" />').css({
       
   323 							position: 'fixed',
       
   324 							top: '-1000px',
       
   325 							left: '-1000px',
       
   326 							height: 0,
       
   327 							width: 0
       
   328 						}).attr( 'id', 'wp-uploader-browser-' + this.uploader.id ).appendTo('body');
       
   329 					}
       
   330 
       
   331 					container.append( this.browser );
       
   332 				}
       
   333 			}
       
   334 
       
   335 			this.uploader.refresh();
       
   336 		}
       
   337 	});
       
   338 
       
   339 	Uploader.queue = new wp.media.model.Attachments( [], { query: false });
       
   340 	Uploader.errors = new Backbone.Collection();
       
   341 
       
   342 	exports.Uploader = Uploader;
       
   343 })( wp, jQuery );