ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

handlers.js (20282B)


      1 /* global plupload, pluploadL10n, ajaxurl, post_id, wpUploaderInit, deleteUserSetting, setUserSetting, getUserSetting, shortform */
      2 var topWin = window.dialogArguments || opener || parent || top, uploader, uploader_init;
      3 
      4 // Progress and success handlers for media multi uploads.
      5 function fileQueued( fileObj ) {
      6 	// Get rid of unused form.
      7 	jQuery( '.media-blank' ).remove();
      8 
      9 	var items = jQuery( '#media-items' ).children(), postid = post_id || 0;
     10 
     11 	// Collapse a single item.
     12 	if ( items.length == 1 ) {
     13 		items.removeClass( 'open' ).find( '.slidetoggle' ).slideUp( 200 );
     14 	}
     15 	// Create a progress bar containing the filename.
     16 	jQuery( '<div class="media-item">' )
     17 		.attr( 'id', 'media-item-' + fileObj.id )
     18 		.addClass( 'child-of-' + postid )
     19 		.append( '<div class="progress"><div class="percent">0%</div><div class="bar"></div></div>',
     20 			jQuery( '<div class="filename original">' ).text( ' ' + fileObj.name ) )
     21 		.appendTo( jQuery( '#media-items' ) );
     22 
     23 	// Disable submit.
     24 	jQuery( '#insert-gallery' ).prop( 'disabled', true );
     25 }
     26 
     27 function uploadStart() {
     28 	try {
     29 		if ( typeof topWin.tb_remove != 'undefined' )
     30 			topWin.jQuery( '#TB_overlay' ).unbind( 'click', topWin.tb_remove );
     31 	} catch( e ){}
     32 
     33 	return true;
     34 }
     35 
     36 function uploadProgress( up, file ) {
     37 	var item = jQuery( '#media-item-' + file.id );
     38 
     39 	jQuery( '.bar', item ).width( ( 200 * file.loaded ) / file.size );
     40 	jQuery( '.percent', item ).html( file.percent + '%' );
     41 }
     42 
     43 // Check to see if a large file failed to upload.
     44 function fileUploading( up, file ) {
     45 	var hundredmb = 100 * 1024 * 1024,
     46 		max = parseInt( up.settings.max_file_size, 10 );
     47 
     48 	if ( max > hundredmb && file.size > hundredmb ) {
     49 		setTimeout( function() {
     50 			if ( file.status < 3 && file.loaded === 0 ) { // Not uploading.
     51 				wpFileError( file, pluploadL10n.big_upload_failed.replace( '%1$s', '<a class="uploader-html" href="#">' ).replace( '%2$s', '</a>' ) );
     52 				up.stop();  // Stop the whole queue.
     53 				up.removeFile( file );
     54 				up.start(); // Restart the queue.
     55 			}
     56 		}, 10000 ); // Wait for 10 seconds for the file to start uploading.
     57 	}
     58 }
     59 
     60 function updateMediaForm() {
     61 	var items = jQuery( '#media-items' ).children();
     62 
     63 	// Just one file, no need for collapsible part.
     64 	if ( items.length == 1 ) {
     65 		items.addClass( 'open' ).find( '.slidetoggle' ).show();
     66 		jQuery( '.insert-gallery' ).hide();
     67 	} else if ( items.length > 1 ) {
     68 		items.removeClass( 'open' );
     69 		// Only show Gallery/Playlist buttons when there are at least two files.
     70 		jQuery( '.insert-gallery' ).show();
     71 	}
     72 
     73 	// Only show Save buttons when there is at least one file.
     74 	if ( items.not( '.media-blank' ).length > 0 )
     75 		jQuery( '.savebutton' ).show();
     76 	else
     77 		jQuery( '.savebutton' ).hide();
     78 }
     79 
     80 function uploadSuccess( fileObj, serverData ) {
     81 	var item = jQuery( '#media-item-' + fileObj.id );
     82 
     83 	// On success serverData should be numeric,
     84 	// fix bug in html4 runtime returning the serverData wrapped in a <pre> tag.
     85 	if ( typeof serverData === 'string' ) {
     86 		serverData = serverData.replace( /^<pre>(\d+)<\/pre>$/, '$1' );
     87 
     88 		// If async-upload returned an error message, place it in the media item div and return.
     89 		if ( /media-upload-error|error-div/.test( serverData ) ) {
     90 			item.html( serverData );
     91 			return;
     92 		}
     93 	}
     94 
     95 	item.find( '.percent' ).html( pluploadL10n.crunching );
     96 
     97 	prepareMediaItem( fileObj, serverData );
     98 	updateMediaForm();
     99 
    100 	// Increment the counter.
    101 	if ( post_id && item.hasClass( 'child-of-' + post_id ) ) {
    102 		jQuery( '#attachments-count' ).text( 1 * jQuery( '#attachments-count' ).text() + 1 );
    103 	}
    104 }
    105 
    106 function setResize( arg ) {
    107 	if ( arg ) {
    108 		if ( window.resize_width && window.resize_height ) {
    109 			uploader.settings.resize = {
    110 				enabled: true,
    111 				width: window.resize_width,
    112 				height: window.resize_height,
    113 				quality: 100
    114 			};
    115 		} else {
    116 			uploader.settings.multipart_params.image_resize = true;
    117 		}
    118 	} else {
    119 		delete( uploader.settings.multipart_params.image_resize );
    120 	}
    121 }
    122 
    123 function prepareMediaItem( fileObj, serverData ) {
    124 	var f = ( typeof shortform == 'undefined' ) ? 1 : 2, item = jQuery( '#media-item-' + fileObj.id );
    125 	if ( f == 2 && shortform > 2 )
    126 		f = shortform;
    127 
    128 	try {
    129 		if ( typeof topWin.tb_remove != 'undefined' )
    130 			topWin.jQuery( '#TB_overlay' ).click( topWin.tb_remove );
    131 	} catch( e ){}
    132 
    133 	if ( isNaN( serverData ) || !serverData ) {
    134 		// Old style: Append the HTML returned by the server -- thumbnail and form inputs.
    135 		item.append( serverData );
    136 		prepareMediaItemInit( fileObj );
    137 	} else {
    138 		// New style: server data is just the attachment ID, fetch the thumbnail and form html from the server.
    139 		item.load( 'async-upload.php', {attachment_id:serverData, fetch:f}, function(){prepareMediaItemInit( fileObj );updateMediaForm();});
    140 	}
    141 }
    142 
    143 function prepareMediaItemInit( fileObj ) {
    144 	var item = jQuery( '#media-item-' + fileObj.id );
    145 	// Clone the thumbnail as a "pinkynail" -- a tiny image to the left of the filename.
    146 	jQuery( '.thumbnail', item ).clone().attr( 'class', 'pinkynail toggle' ).prependTo( item );
    147 
    148 	// Replace the original filename with the new (unique) one assigned during upload.
    149 	jQuery( '.filename.original', item ).replaceWith( jQuery( '.filename.new', item ) );
    150 
    151 	// Bind Ajax to the new Delete button.
    152 	jQuery( 'a.delete', item ).click( function(){
    153 		// Tell the server to delete it. TODO: Handle exceptions.
    154 		jQuery.ajax({
    155 			url: ajaxurl,
    156 			type: 'post',
    157 			success: deleteSuccess,
    158 			error: deleteError,
    159 			id: fileObj.id,
    160 			data: {
    161 				id : this.id.replace(/[^0-9]/g, '' ),
    162 				action : 'trash-post',
    163 				_ajax_nonce : this.href.replace(/^.*wpnonce=/,'' )
    164 			}
    165 		});
    166 		return false;
    167 	});
    168 
    169 	// Bind Ajax to the new Undo button.
    170 	jQuery( 'a.undo', item ).click( function(){
    171 		// Tell the server to untrash it. TODO: Handle exceptions.
    172 		jQuery.ajax({
    173 			url: ajaxurl,
    174 			type: 'post',
    175 			id: fileObj.id,
    176 			data: {
    177 				id : this.id.replace(/[^0-9]/g,'' ),
    178 				action: 'untrash-post',
    179 				_ajax_nonce: this.href.replace(/^.*wpnonce=/,'' )
    180 			},
    181 			success: function( ){
    182 				var type,
    183 					item = jQuery( '#media-item-' + fileObj.id );
    184 
    185 				if ( type = jQuery( '#type-of-' + fileObj.id ).val() )
    186 					jQuery( '#' + type + '-counter' ).text( jQuery( '#' + type + '-counter' ).text()-0+1 );
    187 
    188 				if ( post_id && item.hasClass( 'child-of-'+post_id ) )
    189 					jQuery( '#attachments-count' ).text( jQuery( '#attachments-count' ).text()-0+1 );
    190 
    191 				jQuery( '.filename .trashnotice', item ).remove();
    192 				jQuery( '.filename .title', item ).css( 'font-weight','normal' );
    193 				jQuery( 'a.undo', item ).addClass( 'hidden' );
    194 				jQuery( '.menu_order_input', item ).show();
    195 				item.css( {backgroundColor:'#ceb'} ).animate( {backgroundColor: '#fff'}, { queue: false, duration: 500, complete: function(){ jQuery( this ).css({backgroundColor:''}); } }).removeClass( 'undo' );
    196 			}
    197 		});
    198 		return false;
    199 	});
    200 
    201 	// Open this item if it says to start open (e.g. to display an error).
    202 	jQuery( '#media-item-' + fileObj.id + '.startopen' ).removeClass( 'startopen' ).addClass( 'open' ).find( 'slidetoggle' ).fadeIn();
    203 }
    204 
    205 // Generic error message.
    206 function wpQueueError( message ) {
    207 	jQuery( '#media-upload-error' ).show().html( '<div class="error"><p>' + message + '</p></div>' );
    208 }
    209 
    210 // File-specific error messages.
    211 function wpFileError( fileObj, message ) {
    212 	itemAjaxError( fileObj.id, message );
    213 }
    214 
    215 function itemAjaxError( id, message ) {
    216 	var item = jQuery( '#media-item-' + id ), filename = item.find( '.filename' ).text(), last_err = item.data( 'last-err' );
    217 
    218 	if ( last_err == id ) // Prevent firing an error for the same file twice.
    219 		return;
    220 
    221 	item.html( '<div class="error-div">' +
    222 				'<a class="dismiss" href="#">' + pluploadL10n.dismiss + '</a>' +
    223 				'<strong>' + pluploadL10n.error_uploading.replace( '%s', jQuery.trim( filename )) + '</strong> ' +
    224 				message +
    225 				'</div>' ).data( 'last-err', id );
    226 }
    227 
    228 function deleteSuccess( data ) {
    229 	var type, id, item;
    230 	if ( data == '-1' )
    231 		return itemAjaxError( this.id, 'You do not have permission. Has your session expired?' );
    232 
    233 	if ( data == '0' )
    234 		return itemAjaxError( this.id, 'Could not be deleted. Has it been deleted already?' );
    235 
    236 	id = this.id;
    237 	item = jQuery( '#media-item-' + id );
    238 
    239 	// Decrement the counters.
    240 	if ( type = jQuery( '#type-of-' + id ).val() )
    241 		jQuery( '#' + type + '-counter' ).text( jQuery( '#' + type + '-counter' ).text() - 1 );
    242 
    243 	if ( post_id && item.hasClass( 'child-of-'+post_id ) )
    244 		jQuery( '#attachments-count' ).text( jQuery( '#attachments-count' ).text() - 1 );
    245 
    246 	if ( jQuery( 'form.type-form #media-items' ).children().length == 1 && jQuery( '.hidden', '#media-items' ).length > 0 ) {
    247 		jQuery( '.toggle' ).toggle();
    248 		jQuery( '.slidetoggle' ).slideUp( 200 ).siblings().removeClass( 'hidden' );
    249 	}
    250 
    251 	// Vanish it.
    252 	jQuery( '.toggle', item ).toggle();
    253 	jQuery( '.slidetoggle', item ).slideUp( 200 ).siblings().removeClass( 'hidden' );
    254 	item.css( {backgroundColor:'#faa'} ).animate( {backgroundColor:'#f4f4f4'}, {queue:false, duration:500} ).addClass( 'undo' );
    255 
    256 	jQuery( '.filename:empty', item ).remove();
    257 	jQuery( '.filename .title', item ).css( 'font-weight','bold' );
    258 	jQuery( '.filename', item ).append( '<span class="trashnotice"> ' + pluploadL10n.deleted + ' </span>' ).siblings( 'a.toggle' ).hide();
    259 	jQuery( '.filename', item ).append( jQuery( 'a.undo', item ).removeClass( 'hidden' ) );
    260 	jQuery( '.menu_order_input', item ).hide();
    261 
    262 	return;
    263 }
    264 
    265 function deleteError() {
    266 }
    267 
    268 function uploadComplete() {
    269 	jQuery( '#insert-gallery' ).prop( 'disabled', false );
    270 }
    271 
    272 function switchUploader( s ) {
    273 	if ( s ) {
    274 		deleteUserSetting( 'uploader' );
    275 		jQuery( '.media-upload-form' ).removeClass( 'html-uploader' );
    276 
    277 		if ( typeof( uploader ) == 'object' )
    278 			uploader.refresh();
    279 	} else {
    280 		setUserSetting( 'uploader', '1' ); // 1 == html uploader.
    281 		jQuery( '.media-upload-form' ).addClass( 'html-uploader' );
    282 	}
    283 }
    284 
    285 function uploadError( fileObj, errorCode, message, up ) {
    286 	var hundredmb = 100 * 1024 * 1024, max;
    287 
    288 	switch ( errorCode ) {
    289 		case plupload.FAILED:
    290 			wpFileError( fileObj, pluploadL10n.upload_failed );
    291 			break;
    292 		case plupload.FILE_EXTENSION_ERROR:
    293 			wpFileExtensionError( up, fileObj, pluploadL10n.invalid_filetype );
    294 			break;
    295 		case plupload.FILE_SIZE_ERROR:
    296 			uploadSizeError( up, fileObj );
    297 			break;
    298 		case plupload.IMAGE_FORMAT_ERROR:
    299 			wpFileError( fileObj, pluploadL10n.not_an_image );
    300 			break;
    301 		case plupload.IMAGE_MEMORY_ERROR:
    302 			wpFileError( fileObj, pluploadL10n.image_memory_exceeded );
    303 			break;
    304 		case plupload.IMAGE_DIMENSIONS_ERROR:
    305 			wpFileError( fileObj, pluploadL10n.image_dimensions_exceeded );
    306 			break;
    307 		case plupload.GENERIC_ERROR:
    308 			wpQueueError( pluploadL10n.upload_failed );
    309 			break;
    310 		case plupload.IO_ERROR:
    311 			max = parseInt( up.settings.filters.max_file_size, 10 );
    312 
    313 			if ( max > hundredmb && fileObj.size > hundredmb ) {
    314 				wpFileError( fileObj, pluploadL10n.big_upload_failed.replace( '%1$s', '<a class="uploader-html" href="#">' ).replace( '%2$s', '</a>' ) );
    315 			} else {
    316 				wpQueueError( pluploadL10n.io_error );
    317 			}
    318 
    319 			break;
    320 		case plupload.HTTP_ERROR:
    321 			wpQueueError( pluploadL10n.http_error );
    322 			break;
    323 		case plupload.INIT_ERROR:
    324 			jQuery( '.media-upload-form' ).addClass( 'html-uploader' );
    325 			break;
    326 		case plupload.SECURITY_ERROR:
    327 			wpQueueError( pluploadL10n.security_error );
    328 			break;
    329 /*		case plupload.UPLOAD_ERROR.UPLOAD_STOPPED:
    330 		case plupload.UPLOAD_ERROR.FILE_CANCELLED:
    331 			jQuery( '#media-item-' + fileObj.id ).remove();
    332 			break;*/
    333 		default:
    334 			wpFileError( fileObj, pluploadL10n.default_error );
    335 	}
    336 }
    337 
    338 function uploadSizeError( up, file ) {
    339 	var message, errorDiv;
    340 
    341 	message = pluploadL10n.file_exceeds_size_limit.replace( '%s', file.name );
    342 
    343 	// Construct the error div.
    344 	errorDiv = jQuery( '<div />' )
    345 		.attr( {
    346 			'id':    'media-item-' + file.id,
    347 			'class': 'media-item error'
    348 		} )
    349 		.append(
    350 			jQuery( '<p />' )
    351 				.text( message )
    352 		);
    353 
    354 	// Append the error.
    355 	jQuery( '#media-items' ).append( errorDiv );
    356 	up.removeFile( file );
    357 }
    358 
    359 function wpFileExtensionError( up, file, message ) {
    360 	jQuery( '#media-items' ).append( '<div id="media-item-' + file.id + '" class="media-item error"><p>' + message + '</p></div>' );
    361 	up.removeFile( file );
    362 }
    363 
    364 /**
    365  * Copies the attachment URL to the clipboard.
    366  *
    367  * @since 5.8.0
    368  *
    369  * @param {MouseEvent} event A click event.
    370  *
    371  * @return {void}
    372  */
    373 function copyAttachmentUploadURLClipboard() {
    374 	var clipboard = new ClipboardJS( '.copy-attachment-url' ),
    375 		successTimeout;
    376 
    377 	clipboard.on( 'success', function( event ) {
    378 		var triggerElement = jQuery( event.trigger ),
    379 			successElement = jQuery( '.success', triggerElement.closest( '.copy-to-clipboard-container' ) );
    380 
    381 		// Clear the selection and move focus back to the trigger.
    382 		event.clearSelection();
    383 		// Handle ClipboardJS focus bug, see https://github.com/zenorocha/clipboard.js/issues/680
    384 		triggerElement.trigger( 'focus' );
    385 		// Show success visual feedback.
    386 		clearTimeout( successTimeout );
    387 		successElement.removeClass( 'hidden' );
    388 		// Hide success visual feedback after 3 seconds since last success.
    389 		successTimeout = setTimeout( function() {
    390 			successElement.addClass( 'hidden' );
    391 		}, 3000 );
    392 		// Handle success audible feedback.
    393 		wp.a11y.speak( pluploadL10n.file_url_copied );
    394 	} );
    395 }
    396 
    397 jQuery( document ).ready( function( $ ) {
    398 	copyAttachmentUploadURLClipboard();
    399 	var tryAgainCount = {};
    400 	var tryAgain;
    401 
    402 	$( '.media-upload-form' ).bind( 'click.uploader', function( e ) {
    403 		var target = $( e.target ), tr, c;
    404 
    405 		if ( target.is( 'input[type="radio"]' ) ) { // Remember the last used image size and alignment.
    406 			tr = target.closest( 'tr' );
    407 
    408 			if ( tr.hasClass( 'align' ) )
    409 				setUserSetting( 'align', target.val() );
    410 			else if ( tr.hasClass( 'image-size' ) )
    411 				setUserSetting( 'imgsize', target.val() );
    412 
    413 		} else if ( target.is( 'button.button' ) ) { // Remember the last used image link url.
    414 			c = e.target.className || '';
    415 			c = c.match( /url([^ '"]+)/ );
    416 
    417 			if ( c && c[1] ) {
    418 				setUserSetting( 'urlbutton', c[1] );
    419 				target.siblings( '.urlfield' ).val( target.data( 'link-url' ) );
    420 			}
    421 		} else if ( target.is( 'a.dismiss' ) ) {
    422 			target.parents( '.media-item' ).fadeOut( 200, function() {
    423 				$( this ).remove();
    424 			} );
    425 		} else if ( target.is( '.upload-flash-bypass a' ) || target.is( 'a.uploader-html' ) ) { // Switch uploader to html4.
    426 			$( '#media-items, p.submit, span.big-file-warning' ).css( 'display', 'none' );
    427 			switchUploader( 0 );
    428 			e.preventDefault();
    429 		} else if ( target.is( '.upload-html-bypass a' ) ) { // Switch uploader to multi-file.
    430 			$( '#media-items, p.submit, span.big-file-warning' ).css( 'display', '' );
    431 			switchUploader( 1 );
    432 			e.preventDefault();
    433 		} else if ( target.is( 'a.describe-toggle-on' ) ) { // Show.
    434 			target.parent().addClass( 'open' );
    435 			target.siblings( '.slidetoggle' ).fadeIn( 250, function() {
    436 				var S = $( window ).scrollTop(),
    437 					H = $( window ).height(),
    438 					top = $( this ).offset().top,
    439 					h = $( this ).height(),
    440 					b,
    441 					B;
    442 
    443 				if ( H && top && h ) {
    444 					b = top + h;
    445 					B = S + H;
    446 
    447 					if ( b > B ) {
    448 						if ( b - B < top - S )
    449 							window.scrollBy( 0, ( b - B ) + 10 );
    450 						else
    451 							window.scrollBy( 0, top - S - 40 );
    452 					}
    453 				}
    454 			} );
    455 
    456 			e.preventDefault();
    457 		} else if ( target.is( 'a.describe-toggle-off' ) ) { // Hide.
    458 			target.siblings( '.slidetoggle' ).fadeOut( 250, function() {
    459 				target.parent().removeClass( 'open' );
    460 			} );
    461 
    462 			e.preventDefault();
    463 		}
    464 	});
    465 
    466 	// Attempt to create image sub-sizes when an image was uploaded successfully
    467 	// but the server responded with an HTTP 5xx error.
    468 	tryAgain = function( up, error ) {
    469 		var file = error.file;
    470 		var times;
    471 		var id;
    472 
    473 		if ( ! error || ! error.responseHeaders ) {
    474 			wpQueueError( pluploadL10n.http_error_image );
    475 			return;
    476 		}
    477 
    478 		id = error.responseHeaders.match( /x-wp-upload-attachment-id:\s*(\d+)/i );
    479 
    480 		if ( id && id[1] ) {
    481 			id = id[1];
    482 		} else {
    483 			wpQueueError( pluploadL10n.http_error_image );
    484 			return;
    485 		}
    486 
    487 		times = tryAgainCount[ file.id ];
    488 
    489 		if ( times && times > 4 ) {
    490 			/*
    491 			 * The file may have been uploaded and attachment post created,
    492 			 * but post-processing and resizing failed...
    493 			 * Do a cleanup then tell the user to scale down the image and upload it again.
    494 			 */
    495 			$.ajax({
    496 				type: 'post',
    497 				url: ajaxurl,
    498 				dataType: 'json',
    499 				data: {
    500 					action: 'media-create-image-subsizes',
    501 					_wpnonce: wpUploaderInit.multipart_params._wpnonce,
    502 					attachment_id: id,
    503 					_wp_upload_failed_cleanup: true,
    504 				}
    505 			});
    506 
    507 			if ( error.message && ( error.status < 500 || error.status >= 600 ) ) {
    508 				wpQueueError( error.message );
    509 			} else {
    510 				wpQueueError( pluploadL10n.http_error_image );
    511 			}
    512 
    513 			return;
    514 		}
    515 
    516 		if ( ! times ) {
    517 			tryAgainCount[ file.id ] = 1;
    518 		} else {
    519 			tryAgainCount[ file.id ] = ++times;
    520 		}
    521 
    522 		// Try to create the missing image sizes.
    523 		$.ajax({
    524 			type: 'post',
    525 			url: ajaxurl,
    526 			dataType: 'json',
    527 			data: {
    528 				action: 'media-create-image-subsizes',
    529 				_wpnonce: wpUploaderInit.multipart_params._wpnonce,
    530 				attachment_id: id,
    531 				_legacy_support: 'true',
    532 			}
    533 		}).done( function( response ) {
    534 			var message;
    535 
    536 			if ( response.success ) {
    537 				uploadSuccess( file, response.data.id );
    538 			} else {
    539 				if ( response.data && response.data.message ) {
    540 					message = response.data.message;
    541 				}
    542 
    543 				wpQueueError( message || pluploadL10n.http_error_image );
    544 			}
    545 		}).fail( function( jqXHR ) {
    546 			// If another HTTP 5xx error, try try again...
    547 			if ( jqXHR.status >= 500 && jqXHR.status < 600 ) {
    548 				tryAgain( up, error );
    549 				return;
    550 			}
    551 
    552 			wpQueueError( pluploadL10n.http_error_image );
    553 		});
    554 	}
    555 
    556 	// Init and set the uploader.
    557 	uploader_init = function() {
    558 		uploader = new plupload.Uploader( wpUploaderInit );
    559 
    560 		$( '#image_resize' ).bind( 'change', function() {
    561 			var arg = $( this ).prop( 'checked' );
    562 
    563 			setResize( arg );
    564 
    565 			if ( arg )
    566 				setUserSetting( 'upload_resize', '1' );
    567 			else
    568 				deleteUserSetting( 'upload_resize' );
    569 		});
    570 
    571 		uploader.bind( 'Init', function( up ) {
    572 			var uploaddiv = $( '#plupload-upload-ui' );
    573 
    574 			setResize( getUserSetting( 'upload_resize', false ) );
    575 
    576 			if ( up.features.dragdrop && ! $( document.body ).hasClass( 'mobile' ) ) {
    577 				uploaddiv.addClass( 'drag-drop' );
    578 
    579 				$( '#drag-drop-area' ).on( 'dragover.wp-uploader', function() { // dragenter doesn't fire right :(
    580 					uploaddiv.addClass( 'drag-over' );
    581 				}).on( 'dragleave.wp-uploader, drop.wp-uploader', function() {
    582 					uploaddiv.removeClass( 'drag-over' );
    583 				});
    584 			} else {
    585 				uploaddiv.removeClass( 'drag-drop' );
    586 				$( '#drag-drop-area' ).off( '.wp-uploader' );
    587 			}
    588 
    589 			if ( up.runtime === 'html4' ) {
    590 				$( '.upload-flash-bypass' ).hide();
    591 			}
    592 		});
    593 
    594 		uploader.bind( 'postinit', function( up ) {
    595 			up.refresh();
    596 		});
    597 
    598 		uploader.init();
    599 
    600 		uploader.bind( 'FilesAdded', function( up, files ) {
    601 			$( '#media-upload-error' ).empty();
    602 			uploadStart();
    603 
    604 			plupload.each( files, function( file ) {
    605 				if ( file.type === 'image/heic' && up.settings.heic_upload_error ) {
    606 					// Show error but do not block uploading.
    607 					wpQueueError( pluploadL10n.unsupported_image );
    608 				} else if ( file.type === 'image/webp' && up.settings.webp_upload_error ) {
    609 					// Disallow uploading of WebP images if the server cannot edit them.
    610 					wpQueueError( pluploadL10n.noneditable_image );
    611 					up.removeFile( file );
    612 					return;
    613 				}
    614 
    615 				fileQueued( file );
    616 			});
    617 
    618 			up.refresh();
    619 			up.start();
    620 		});
    621 
    622 		uploader.bind( 'UploadFile', function( up, file ) {
    623 			fileUploading( up, file );
    624 		});
    625 
    626 		uploader.bind( 'UploadProgress', function( up, file ) {
    627 			uploadProgress( up, file );
    628 		});
    629 
    630 		uploader.bind( 'Error', function( up, error ) {
    631 			var isImage = error.file && error.file.type && error.file.type.indexOf( 'image/' ) === 0;
    632 			var status  = error && error.status;
    633 
    634 			// If the file is an image and the error is HTTP 5xx try to create sub-sizes again.
    635 			if ( isImage && status >= 500 && status < 600 ) {
    636 				tryAgain( up, error );
    637 				return;
    638 			}
    639 
    640 			uploadError( error.file, error.code, error.message, up );
    641 			up.refresh();
    642 		});
    643 
    644 		uploader.bind( 'FileUploaded', function( up, file, response ) {
    645 			uploadSuccess( file, response.response );
    646 		});
    647 
    648 		uploader.bind( 'UploadComplete', function() {
    649 			uploadComplete();
    650 		});
    651 	};
    652 
    653 	if ( typeof( wpUploaderInit ) == 'object' ) {
    654 		uploader_init();
    655 	}
    656 
    657 });