Recently I was contracted to develop a new plugin for FileField Sources to allow pasting from clipboard. The newer versions of Chrome have supported this for a while (per this GMail blog post) while Firefox has an interesting behavior when pasting into contentEditable HTML areas that allows you to intercept image files (it pastes files from clipboard as an IMG tag with a data:image/png src attribute).

Combined, we get pretty good browser coverage. The Chrome implementation is following the W3C draft specification for clipboards, so hopefully more browsers will be supported in the future.

Here's an initial patch which adds this functionality for Firefox and Chrome. It doesn't currently hide the field for IE versions, but it *should* notify the user that clipboard support is not available; which in many ways is better than mysteriously hiding the options entirely.

Comments

RandalK’s picture

StatusFileSize
new13.74 KB

Applying this patch gives me this error:

git apply filefield_sources_clipboard.patch
fatal: corrupt patch at line 378

I have worked around this by adding "\ No newline at end of file" to the end of the patch directly.

Upon selecting the "tab" and doing as instructed it fails if there is more then one item in the clipboard array e.g.:

items[0].type = 'text/html'
items[0].kind = 'string'
items[1].type = 'image/png'
items[1].kind = 'file'

Attached patch adds a loop that tries to find the first kind of file in the array.

quicksketch’s picture

I thought about adding a loop also, but that had the odd side effect when copy/pasting an actual file from the desktop, the first item is the file name (in text) and the second item is the *icon* of the file (not the file itself unfortunately). Considering this isn't expected behavior, I stuck with just keeping the first item. In what situation do you have a second item that is the file you want instead of it being the first item?

RandalK’s picture

I have just been copying files from another browser tab with right-click copy image, the first appears as the html that wraps the image and the second being the image as a file object.

quicksketch’s picture

Ah, nice! Well lets add the loop back in there then. Kind of unfortunate that Macs have the unfortunate effect of pasting the file icon. No idea how that's supposed to be helpful. :\

Otherwise though, sounds like the source works pretty well? Any further comments?

RandalK’s picture

Had a try in afew browsers now Chrome support is good.
Managed to upload a file on Firefox from a desktop copy, although there is a missing function Drupal.fileFieldSources.moveCaretToEnd.

In older browsers that have no support for the paste event do not show any indication that it failed might need a check for this:

if (!('onpaste' in document.createElement('div'))) {
  // Show message that this browser does not support Paste events
}

Not sure if this should support copying from the desktop, on linux you just get the file path "/home/username/Desktop/myfile.ext"

quicksketch’s picture

Thanks for testing! Yeah that moveCaretToEnd() function I had added at one point but it didn't work on the contentEditable we're using to capture pastes, so I took it out.

Regarding the check, most browsers have support for onPaste I believe (including IE): http://www.quirksmode.org/dom/events/cutcopypaste.html

We might need to do some testing to see if this testing is necessary and how accurately we can target it.

quicksketch’s picture

StatusFileSize
new19.13 KB

So, some real-world testing makes feature detection even more difficult:

- Safari supports onpaste events and event clipboardData at the event level, however it does not include DataTransfer objects that contain any files. Seems like support may be there entirely but disabled (which would make sense if it's built into core Webkit). I've added an extra check so that Safari won't accidentally attempt to access non-existent properties and the error reports properly.
- IE supports onpaste events, but *will not allow pasting of images*. The entire option to paste both from right-click and the Edit menu is simply grayed out.
- Opera doesn't seem to support onpaste events at all, doh. The option to paste is also disabled like it is in IE when the clipboard contains images.

So in IE and Opera don't even have the opportunity to report an error, since the paste event either isn't allowed or it's not supported.

We *could* simply check $.browser.msie and $.browser.opera and show a warning, but attempt to process the clipboard anyway. I personally am inclined just to put a note on the feature with a link to Drupal.org where we can update information as it becomes available.

Here's a revised patch that includes your for() loop, adds better error checking, removes that moveCaretToEnd call, and adds this warning.

quicksketch’s picture

StatusFileSize
new13.76 KB

That last patch had an unrelated file in it.

RandalK’s picture

Not had time to test this, hopefully I will over the weekend but just eyeing the patch this looks off:

+    // All browsers in the future (hopefully).
+    else if (e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.items) {
+      clipboardData = e.originalEvent;
+    }

I'd agree with browser support being sketchy the notice would probably be best.

quicksketch’s picture

So jQuery attempts to standardized the normal event (or "e") variable when it comes into an event handler, so e.originalEvent actually means the raw browser event with all the discrepancies between browsers. e.originalEvent.clipboardData is the check for event-level clipboardData support, which both Safari and Chrome match. However e.originalEvent.clipboardData.items is only populated by Chrome, which is where the actual contents of the clipboard are stored.

As you probably know, you can't just check e.originalEvent.clipboardData.items directly, because if e.originalEvent.clipboardData is not present, you get an unknown variable error when checking for the child property of a parent that doesn't exist.

That said, there may be a better set of properties to be checking, but I think it's all necessary, other than maybe the check for e.originalEvent, since we know jQuery is going to make that.

RandalK’s picture

Oh I understand why the check is there but what does not look right is this "clipboardData = e.originalEvent;" which looks like it should be "clipboardData = e.originalEvent.clipboardData;"

quicksketch’s picture

Oh, right you are. I'll take another look.

quicksketch’s picture

StatusFileSize
new13.77 KB

Updated patch. The change doesn't have any effect though, since no browsers currently actually use that event location (yet).

RandalK’s picture

Status: Needs review » Needs work

More testing in Windows browsers:

IE 9: no paste, message shown = good
Safari (win) 5.1: no paste, message shown = good
Chrome (win) 21.0: works
Firefox (win) 15.0: works, but if you click "Clipboard" then "Upload" then back to "Clipboard" and paste as to error the hint text copies into the div. This might happen because the event listeners get attached on click each time.

I don't own a Mac but we should probably test that platform also.

quicksketch’s picture

Thanks! I've done all my testing on Mac (except the IE browsers) with good results. I'll look into that Firefox issue.

quicksketch’s picture

Status: Needs work » Needs review
StatusFileSize
new6.28 KB

Sorry I rerolled this patch after restructuring the code in #1547356: Browse option for IMCE disapear after an image has been uploaded in another imce image field and accidentally introduced the double-binding in the process. Simply moving the .bind() events outside the click handler again makes everything work properly.

quicksketch’s picture

StatusFileSize
new13.8 KB

Gar, with the new clipboard.inc included.

quicksketch’s picture

Status: Needs review » Fixed

Committed #17 and it's in the 1.7 release (for Drupal 7 only).

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.