WordPress.org

Make WordPress Core

Opened 2 years ago

Closed 4 months ago

Last modified 3 months ago

#19845 closed task (blessed) (fixed)

Drag and drop files into the Visual Editor

Reported by: kovshenin Owned by: azaozz
Milestone: 3.9 Priority: normal
Severity: normal Version:
Component: Media Keywords: needs-testing has-patch
Focuses: javascript Cc:

Description

Hi there!

I recently thought that it would be nice if we could insert images into posts and pages, simply by dragging and dropping them into the editor. This could be a real time saver when composing. I made a really simple video to demonstrate how this might work, of course really really draft. I hope that we can consider this as proof of concept. I think that with this little upgrade we might fill in a hole in UX as when people are used to drag and drop in their text and document editors, like Google Docs, Microsoft Word and so on.

There are quite a lot of decisions to be made though, like what would be the size of the dropped image, how will the UI look to show upload progress, are multiple files allowed, how error messages are shown and so on.

I'll attach a little (very poorly written) plugin that does this together with a small patch to plupload, if you'd like to give it a spin. Please let me know your thoughts!

Thanks,
Konstantin

Idea: http://wordpress.org/extend/ideas/topic/drag-and-drop-files-into-the-visual-editor
Video: http://www.youtube.com/watch?v=Mqs4_g-7SCU
Ref: http://kovshenin.com/2012/01/dear-wordpress-i-want-to-drop-files-here-in-the-visual-editor-3790/

Attachments (13)

drag-drop-visual-editor.zip (1.9 KB) - added by kovshenin 2 years ago.
The plugin file, will not work without patching Plupload
drag-drop-visual-editor-2.zip (13.4 KB) - added by azaozz 2 years ago.
drag-drop-visual-editor-3.zip (15.2 KB) - added by azaozz 23 months ago.
drag-drop-visual-editor-4.zip (15.1 KB) - added by azaozz 23 months ago.
19845.diff (5.8 KB) - added by kovshenin 5 months ago.
19845.2.diff (419 bytes) - added by jorbin 4 months ago.
19845.3.diff (701 bytes) - added by kovshenin 4 months ago.
19845.4.diff (3.4 KB) - added by kovshenin 4 months ago.
19845.5.diff (4.4 KB) - added by azaozz 4 months ago.
19845.6.diff (3.3 KB) - added by kovshenin 4 months ago.
19845.7.diff (1.5 KB) - added by kovshenin 4 months ago.
19845.8.diff (3.5 KB) - added by azaozz 4 months ago.
19845.9.diff (3.0 KB) - added by kovshenin 4 months ago.

Download all attachments as: .zip

Change History (70)

kovshenin2 years ago

The plugin file, will not work without patching Plupload

comment:1 follow-up: kovshenin2 years ago

Okay plugin's attached. Now in order to grab the visual editor in the DOM we need to go through an iframe, so the getDocumentById for drop_element will not work. To get the plugin working you will need to:

  • Open wp-includes/js/plupload/plupload.html5.js
  • Search for drop_element and remove the call to k.getElementById that surrounds it so that it says var r=(p.settings.drop_element);
  • Save and preview in an HTML5 enabled browser, preferably Chrome

There are two places in plupload.html5.js to replace but replacing the first occurrence should be enough. Make sure that you backup the file first, although for some reason this doesn't seem to break the existing drag and drop :)

Let me know if you have any questions, thanks!

comment:2 scribu2 years ago

Dragging images directly into the visual editor is certainly an interesting idea.

A related plugin exists which allows you to drag images from the media library into the visual editor:

http://wordpress.org/extend/plugins/image-pro-wordpress-image-media-management-and-resizing-done-right/

comment:3 sabreuse2 years ago

  • Cc sabreuse@… added

comment:4 DrewAPicture2 years ago

  • Cc xoodrew@… added

comment:5 jayarjo2 years ago

  • Cc jayarjo added

comment:6 soulseekah2 years ago

  • Cc soulseekah added

comment:7 merty2 years ago

  • Cc merty92@… added

comment:8 ungestaltbar2 years ago

  • Cc ungestaltbar added

comment:9 hd-J2 years ago

  • Cc jeremy@… added

comment:10 ocean902 years ago

  • Cc ocean90 added

comment:11 in reply to: ↑ 1 azaozz2 years ago

Replying to kovshenin:

Think there may be more straightforward methods for passing the drop event to the parent window when something was dropped in TinyMCE (don't particularly like using jQuery inside the iframe). Would still need a way to get Plupload to "see" the event and start uploading.

comment:12 follow-up: azaozz2 years ago

Tweaked a bit the testing plugin. Now it includes the patched plupload.html5.js file and replaces the original, and inserts the image with the user's preferred settings (size, align, etc.).

comment:13 in reply to: ↑ 12 ; follow-up: kovshenin2 years ago

Replying to azaozz:

Looks great, thanks! I'm thinking about the best way to create a second drop zone with Plupload, since we should probably allow dropping images to the HTML textarea too. I don't see Plupload supporting multiple drop zones, however having a second Plupload instance doing the very same thing only with a different drop zone may be overkill. There might be a third drop zone for the featured image section too, so I think Plupload needs another patch.

comment:14 in reply to: ↑ 13 ; follow-up: azaozz2 years ago

Replying to kovshenin:

I'm thinking about the best way to create a second drop zone with Plupload, since we should probably allow dropping images to the HTML textarea too. I don't see Plupload supporting multiple drop zones...

Tried that too. Plupload can have several drop zones. Easiest would be to pass an array of element IDs or DOM elements. Will make a patch and see if they would accept/merge it.

comment:15 in reply to: ↑ 14 ; follow-up: kovshenin2 years ago

Replying to azaozz:

Will make a patch and see if they would accept/merge it.

Awesome, that's what I was asking, thanks!

Easiest would be to pass an array of element IDs or DOM elements.

For the sake of backwards compatibility I think the following should work: string, element, array of strings or elements.

comment:16 in reply to: ↑ 15 azaozz2 years ago

Replying to kovshenin:

For the sake of backwards compatibility I think the following should work: string, element, array of strings or elements.

Yes, exactly. That's how many API methods work in TinyMCE too.

comment:17 nacin2 years ago

  • Milestone changed from Awaiting Review to 3.5

This remains a feature request (not a task), but is something that we can look into in 3.5.

comment:18 azizur2 years ago

  • Cc azizur added

comment:19 foxinni23 months ago

  • Cc foxinni@… added

comment:20 azaozz23 months ago

Updated the test plugin, has all the basic code (tested in Firefox and Chrome, needs testing in IE10):

  • When an image is dropped in the visual editor, it is "cloned" and displayed straight away (with progress bar as overlay), then uploaded in the background and when done, the preview is replaced with a "real" <img> tag.
  • Supports non-image files, inserts a link to the file after the upload is complete.
  • Supports uploading of multiple images/files.
  • To-do: add "Cancel" button on the overlay, refine the styling, add error display, decide how to handle errors (what happens with the preview after we display an error).

comment:21 ocean9023 months ago

Note:
Since the admin_enqueue_scripts is hooked into admin_footer-post.php it only works if you edit a post.

comment:22 azaozz23 months ago

In drag-drop-visual-editor-4.zip fixed the enqueue for post-new.php. Also changed loading of the JS on editor init (instead of using a filter from PHP).

comment:23 DrewAPicture21 months ago

  • Keywords punt added

comment:24 helenyhou21 months ago

  • Keywords punt removed
  • Milestone changed from 3.5 to Future Release

A lack of recent activity, the amount of overturn in media and TinyMCE in the meantime, and our firm arrival in the beta period all point to a punt of this feature request.

comment:25 azaozz21 months ago

Been thinking/testing different approaches for the last couple of weeks. This is a nice-to-have, "flashy" feature but when using it for a while there are few things that aren't very good:

  • Works only in Firefox, WebKit and IE10+. That excludes about 30% of the users. It is possible to make it work for single file in older IE and Opera but is too hacky: need to overlay the editor iframe with an <input type=file /> that is in a separate form on dragenter, then submit that form on change. Of course there will be no progress bar then.
  • It is somewhat awkward to use. For the users to be able to drag files from the desktop to the browser window to the editor, they would need to resize the browser window to look for the files under it or to open another OS window containing the files that will overlay the browser. In both cases the users would "loose" their previous working area.

When using the standard uploader that's not as bad since the only purpose there is uploading. When typing a post/using the editor this doesn't feel right.

  • When a file is dragged to the editor iframe there is an indication (the caret is shown) of where the file would be dropped. However the caret position is actually not changed, so after dropping the file it is inserted at the previous caret location. Tried to find a workaround but seems impossible.

In that terms I'm 50/50 on whether this should be in core or implemented by a plugin.

comment:26 adamsilverstein18 months ago

  • Cc ADAMSILVERSTEIN@… added

comment:27 jkudish17 months ago

  • Cc jkudish added

comment:28 beaulebens17 months ago

  • Cc beau@… added

comment:29 sabreuse13 months ago

#24527 was marked as a duplicate.

kovshenin5 months ago

comment:30 kovshenin5 months ago

  • Focuses javascript added
  • Keywords has-patch added

Alternative approach in 19845.diff. Requires the latest Plupload 2.1.1 patch from #25663.

comment:31 azaozz4 months ago

19845.diff looks good. Will need to expose containerDragover() so it can be called from TinyMCE when the file(s) are dragged directly over the editor.

Was also thinking about a different workflow:

  • User drops file(s) on the editor (Visual or Text).
  • Instead of opening the media modal and forcing the user to wait for the file(s) to be uploaded, we show a small bar in the right or left bottom corner of the window that shows the total progress.
  • After the uploading is done, we could notify the user, perhaps by changing the color of the progress bar, etc.

This way we won't interrupt the user while the files are being uploaded, i.e. asynchronous uploading.

Last edited 4 months ago by azaozz (previous) (diff)

comment:32 nacin4 months ago

  • Milestone changed from Future Release to 3.9

The alternative workflow is something we should experiment with in the future, but the new approach from kovshenin is great for 3.9.

I can reproduce the issue with a direct drag to TinyMCE.

One enhancement would be for it to work on all editor instances (in the admin). To add one:

add_action( 'edit_form_advanced', function( $post ) {
	wp_editor( '', 'content_2' );
} );

I'm going to commit this and then we can iterate.

comment:33 nacin4 months ago

In 27343:

Add the ability to drag and drop files directly onto the editor.

The file will then begin to upload and the media manager will open.

props kovshenin.
see #19845.

jorbin4 months ago

comment:34 jorbin4 months ago

[27343] includes an extra comma at the end of an object. This will make IE sad and cry. :'(

27343.2.diff fixes that.

This was discovered and fixed at WordCamp Lancaster Contributor day.

comment:35 SergeyBiryukov4 months ago

In 27352:

Remove extra comma. props jorbin. see #19845.

kovshenin4 months ago

comment:36 kovshenin4 months ago

In 19845.3.diff: propagate the dragover event to the iframe container, at which point it's bubbled up to document which the uploader view handles successfully, or at least in Chrome, Firefox and Safari on OS X :)

comment:37 nacin4 months ago

In 27372:

TinyMCE: Propagate the dragover event outside the editor so drag-and-drop uploads can catch it.

props kovshenin.
see #19845.

kovshenin4 months ago

comment:38 kovshenin4 months ago

In 19845.4.diff: Add support for multiple editor instances on a single page.

comment:39 nacin4 months ago

In 27378:

Support multiple editor instances when drag-and-drop-uploading onto them.

Also reduces z-index to below the toolbar, and adds a comment.

props kovshenin.
see #19845.

comment:40 nacin4 months ago

  • Keywords needs-testing close added; has-patch removed
  • Type changed from feature request to task (blessed)

Looks like we may be done here? Great work, kovshenin.

comment:41 kovshenin4 months ago

  • Keywords close removed

Thanks! Before we close this let me do one last pass in various browsers and also patch up DFW for a fullscreen dropzone.

comment:42 azaozz4 months ago

We still have to handle cases where selected text is dragged in the Text editor and image/text is dragged in TinyMCE. Seems we can use dragstart and skip all other drag events until the dragend (both are not fired when dragging from the OS into the browser window).

Last edited 4 months ago by azaozz (previous) (diff)

azaozz4 months ago

comment:43 azaozz4 months ago

In 19845.5.diff: don't trigger for "local" dragging, i.e. when dragstart was fired.

To-do, needs fixing for IE:

  • In IE10 the blue overlay is shown only when the cursor is at the edge of the editor container and reverts back to gray overlay (non-dropzone) when cursor is above the editor. Dropping at the edge works.
  • In IE9, same as IE10 but dropping at the edge throws an error. Wondering if we should disable it in IE8 and 9 as they don't fully support the w3c drag/drop events.

kovshenin4 months ago

comment:44 follow-up: kovshenin4 months ago

  • Keywords has-patch added

In 19845.6.diff:

  • Use event propagation and $.closest() instead of pointer-events, which are not supported by many browsers, this should now work in IE10 and above
  • Add a fullscreen dropzone in DFW mode
  • Check the current browser for DnD and File API support before binding events

Still not sure about non-file dragging but I think we can come up with something cleaner than .5.diff.

comment:45 azaozz4 months ago

In 27464:

Limit the drag/drop upload only to newer browsers (IE10+), add a fullscreen dropzone in DFW mode, props kovshenin, see #19845

comment:46 in reply to: ↑ 44 ; follow-up: azaozz4 months ago

Replying to kovshenin:

Still not sure about non-file dragging but I think we can come up with something cleaner than .5.diff.

As far as I see this is the cleanest/most straightforward way to detect when a drag has started inside the browser window. Any other way would be more complicated and probably buggier.

Also it would be good to add a bail-out "close on click" to the overlay, just in case the user gets stuck with blocked editors. Was able to do that couple of times when dragging very fast in and out of the window for long time (browser slowdown/memory leak?).

Last edited 4 months ago by azaozz (previous) (diff)

kovshenin4 months ago

comment:47 in reply to: ↑ 46 kovshenin4 months ago

Replying to azaozz: I was thinking of simply checking whether the event contains a file when dragging. If it does, show the dropzones, see 19845.7.diff. The original dropzone in the media modal can benefit from a similar approach.

The "close on click" idea sounds neat. I've been able to reproduce it in Safari a couple of times when a file is dropped but fails to init an upload for some reason, and not only on the editor but also in the media modal.

comment:48 azaozz4 months ago

I was thinking of simply checking whether the event contains a file when dragging.

This works too. When dragging an image in TinyMCE, you're actually dragging the HTML <img> tag, not the file. So it doesn't trigger. Breaks the "drag directly over the editor" hack though, will have to bypass that somehow.

comment:49 azaozz4 months ago

Scratch that. In Firefox when dragging an image in contentEditable, you're dragging both the text (the <img> tag) and the image file. Need to fix that too.

azaozz4 months ago

comment:50 azaozz4 months ago

19845.8.diff fixes it to work in Firefox by excluding dragover when there is 'text/plain' in event.dataTransfer.types. Also adds "close on click" for the overlay and bypasses the event.dataTransfer.types check when triggering from TinyMCE.

Still thinking that using dragstart and dragend is somewhat more robust when checking for "local" dragging. They are designed not to fire when dragging from the OS into the browser, and that's what we want to detect.

comment:51 kovshenin4 months ago

I don't have a strong opinion, both approaches look fine. 5.diff might be more performant than what I proposed since dragging is such a high frequency event. I will leave the decision up to you :)

kovshenin4 months ago

comment:52 kovshenin4 months ago

I tested .5.diff and now I like it better than checking for files on high-frequency events. Here are some notes:

  • When starting a local drag in the editor and leaving while dragging, EditorUploader gets the regular dragover and shows the dropzone. I think we can simply add dragstart and dragend to the list of bubbled events and have only EditorUploader deal with local vs. file.
  • The dragend event is fired when dropping text, but not when dropping an image. Removing localDrag on drop could be an easy fix for this.
  • In Safari you can no longer drag text or other stuff around, this is a regression from 3.8.1 and I don't think it's related no d&d.

Updated patch in 19845.9.diff.

comment:53 follow-up: kovshenin4 months ago

In Safari you can no longer drag text or other stuff around, this is a regression from 3.8.1 and I don't think it's related no d&d.

This is fixed in TinyMCE 4.0.19.

comment:54 azaozz4 months ago

  • Owner set to azaozz
  • Resolution set to fixed
  • Status changed from new to closed

In 27531:

Drag/drop upload: don't trigger on "local" dragging, hide the overlay on click. Props kovshenin, fixes #19845

comment:55 in reply to: ↑ 53 azaozz4 months ago

Replying to kovshenin: Yes, was a TinyMCE bug in Safari.

This is done. If any bugs, please open new tickets.

Last edited 4 months ago by azaozz (previous) (diff)

comment:56 nacin3 months ago

#27375 was marked as a duplicate.

comment:57 ircbot3 months ago

This ticket was mentioned in IRC in #wordpress-dev by nacin. View the logs.

Note: See TracTickets for help on using tickets.