Modernizr/Modernizr — pull request #659 by fivetanley (2012-08-18 07:44:56+00:00)
Title: fixes #605: Clipboard API feature-detection

Specification: http://www.w3.org/TR/clipboard-apis/
DataTransfer Interface: http://www.w3.org/TR/html5/dnd.html#the-datatransfer-interface
Event Interfaces: http://www.w3.org/TR/DOM-Level-3-Events/#event-interfaces

**tl;dr: It's pretty much impossible, I think, to fakeout a real `paste` event from the user's clipboard, because the spec does not allow it. We can't check for a `clipboardData` on the `paste` event because of this. So, we need to check for the ClipboardEvents constructor (which is spec'd), then we can check for the existence of `clipboardData` on a new `Event` (non-standard/not in spec).**

The best way to test this feature would to do it manually by hand:

1. Attach some event listeners for a 'paste' event to a DOM element
2. Paste something by hand into that DOM element.
3. Capture the event, and see if its 'clipboardData' propertyexists AND implements the `DataTransfer` Interface:

Old Interface:

* `setData` (function)
* `getData` (function)
* `clearData` (function)

And/or the new one, which looks like it is meant for drag/drop only?

* `setDragImage` (function)
* `addElement` (function)

The best check would be a `for in` check for those properties, because they may be on the prototype chain (most likely native code). The spec for DataTransfer seems to be designed for Drag/Drop events, so the `setDragImage` function probably shouldn't *have* to implemented. `addElement` is questionable.

Chrome 21 and Safari 5.1 support the old interface, so we could test that.

Why manually test? The specification allows for synthetic `ClipboardEvent`s, but, **does not allow for those synthetic events to read/write from the clipboard**. They may only pass `data` and `dataType` properties on the passed `Event` object to the event listeners. So, even if we manually dispatched events using `document.createEvent` and other methods, we couldn't mock the behavior to check for `clipboardData` on the passed `Event` object because:

* No browsers currently implement the `ClipboardEvent` constructor anyway.
* Using the `ClipboardEvent` constructor wouldn't pass the `clipboardData` property on the event, or would probably throw an exception depending on implementation. The spec doesn't want these synthesized events to be able to read or modify clipboard data (for good reason).
* Creating a `paste` event on an object doesn't create a `clipboardData` property, and creating that property on an event would make the detection work in browsers it shouldn't.

Link to Clipboard Event Interfaces:
http://www.w3.org/TR/clipboard-apis/#clipboard-event-interfaces

Link to test: http://jsbin.com/igitud/14/edit

Using the test above, these browsers have been tested and found to
implement the Clipboard API:

* Chrome 21
* Safari 5.1

These browsers have been tested and found to NOT implement Clipboard API:

* Firefox 14
* Firefox Aurora ( 15 ) ( [It may land soon...](https://bugzilla.mozilla.org/show_bug.cgi?id=407983) )

The test I comitted basically checks for the existence of a `ClipboardEvent` constructor, as per the spec. Next, it checks to see if creating a new `Event` creates a `clipboardData` property on the created object; This may be a WebKit-specific detail, because the spec does not require a `clipboardData` property for the `Event` interface.