diff --git a/src/js/media/controllers/audio-details.js b/src/js/media/controllers/audio-details.js index 07fb99029f9a0..e53d381ebc412 100644 --- a/src/js/media/controllers/audio-details.js +++ b/src/js/media/controllers/audio-details.js @@ -21,6 +21,7 @@ AudioDetails = State.extend(/** @lends wp.media.controller.AudioDetails.prototyp content: 'audio-details', menu: 'audio-details', router: false, + uploader: false, priority: 60 }, diff --git a/src/js/media/controllers/cropper.js b/src/js/media/controllers/cropper.js index 0921839224eb0..cef778336816a 100644 --- a/src/js/media/controllers/cropper.js +++ b/src/js/media/controllers/cropper.js @@ -20,6 +20,7 @@ Cropper = wp.media.controller.State.extend(/** @lends wp.media.controller.Croppe toolbar: 'crop', content: 'crop', router: false, + uploader: false, canSkipCrop: false, // Default doCrop Ajax arguments to allow the Customizer (for example) to inject state. diff --git a/src/js/media/controllers/edit-image.js b/src/js/media/controllers/edit-image.js index 828cec6aaaa22..6e9859b34d3d9 100644 --- a/src/js/media/controllers/edit-image.js +++ b/src/js/media/controllers/edit-image.js @@ -28,7 +28,8 @@ EditImage = wp.media.controller.State.extend(/** @lends wp.media.controller.Edit menu: false, toolbar: 'edit-image', content: 'edit-image', - url: '' + url: '', + uploader: false }, /** diff --git a/src/js/media/controllers/embed.js b/src/js/media/controllers/embed.js index e485260cc5fe3..e2c243b9097e9 100644 --- a/src/js/media/controllers/embed.js +++ b/src/js/media/controllers/embed.js @@ -33,6 +33,7 @@ Embed = wp.media.controller.State.extend(/** @lends wp.media.controller.Embed.pr menu: 'default', toolbar: 'main-embed', priority: 120, + uploader: false, type: 'link', url: '', metadata: {} diff --git a/src/js/media/controllers/image-details.js b/src/js/media/controllers/image-details.js index e2bd41f47da0e..3ab4f7b7337a3 100644 --- a/src/js/media/controllers/image-details.js +++ b/src/js/media/controllers/image-details.js @@ -38,6 +38,7 @@ ImageDetails = State.extend(/** @lends wp.media.controller.ImageDetails.prototyp router: false, toolbar: 'image-details', editing: false, + uploader: false, priority: 60 }, Library.prototype.defaults ), diff --git a/src/js/media/controllers/video-details.js b/src/js/media/controllers/video-details.js index d54fcdbfa829b..5cc9f52121b69 100644 --- a/src/js/media/controllers/video-details.js +++ b/src/js/media/controllers/video-details.js @@ -21,6 +21,7 @@ VideoDetails = State.extend(/** @lends wp.media.controller.VideoDetails.prototyp content: 'video-details', menu: 'video-details', router: false, + uploader: false, priority: 60 }, diff --git a/src/js/media/views/uploader/window.js b/src/js/media/views/uploader/window.js index 0cd97f7c9dd76..24e904bcf1ec2 100644 --- a/src/js/media/views/uploader/window.js +++ b/src/js/media/views/uploader/window.js @@ -55,7 +55,7 @@ UploaderWindow = wp.media.View.extend(/** @lends wp.media.view.UploaderWindow.pr ready: function() { var postId = wp.media.view.settings.post.id, - dropzone; + dropzone, blockDrop; // If the uploader already exists, bail. if ( this.uploader ) { @@ -71,9 +71,46 @@ UploaderWindow = wp.media.View.extend(/** @lends wp.media.view.UploaderWindow.pr dropzone.on( 'dropzone:enter', _.bind( this.show, this ) ); dropzone.on( 'dropzone:leave', _.bind( this.hide, this ) ); + // Ignore files dragged onto states that don't support uploading, e.g. cropping. + // Listen in the capture phase to run before the uploader's own drag and drop handlers. + blockDrop = _.bind( this.blockDrop, this ); + dropzone.each( function() { + var element = this; + + _.each( [ 'dragenter', 'dragover', 'drop' ], function( type ) { + element.addEventListener( type, blockDrop, true ); + } ); + } ); + $( this.uploader ).on( 'uploader:ready', _.bind( this._ready, this ) ); }, + /** + * Prevents dropping files when the current state doesn't support uploading. + * + * States opt out of uploading by setting their `uploader` attribute to false. + * + * @since 7.2.0 + * + * @param {DragEvent} event The drag event. + */ + blockDrop: function( event ) { + var state = this.controller.state(); + + if ( ! state || false !== state.get( 'uploader' ) ) { + return; + } + + // Only block files; other content, such as text, can still be dragged. + if ( ! event.dataTransfer || -1 === _.indexOf( event.dataTransfer.types, 'Files' ) ) { + return; + } + + event.stopPropagation(); + event.preventDefault(); + event.dataTransfer.dropEffect = 'none'; + }, + _ready: function() { this.controller.trigger( 'uploader:ready' ); },