|
| 1 | +# Explainer: [`InputEvent.dataTransfer`](https://w3c.github.io/input-events/#dom-inputevent-datatransfer) Feature For [`Contenteditable`](https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable) Host |
| 2 | + |
| 3 | + |
| 4 | +## Authors: |
| 5 | +- Pranav Modi (pranavmodi@microsoft.com) |
| 6 | + |
| 7 | +## Participate |
| 8 | +- Feature request: [InputEvent#dataTransfer is null for contenteditable host and insertFromPaste input](https://issues.chromium.org/issues/401593412) |
| 9 | +- Spec: [Input Event Types](https://w3c.github.io/input-events/#overview) |
| 10 | +- Issue Tracker: [Issue Tracker](https://issues.chromium.org/issues/401593412) |
| 11 | +- Open new issue: [Open New Issue](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/new?assignees=pranavmodi&labels=DataTransferForInputEvent&template=data-transfer-for-input-event.md&title=%5BData+Transfer+For+Input+Event%5D+%3CTITLE+HERE%3E) |
| 12 | + |
| 13 | +<!-- START doctoc generated TOC please keep comment here to allow auto update --> |
| 14 | +<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> |
| 15 | +## Table of Contents |
| 16 | + |
| 17 | +- [Introduction](#introduction) |
| 18 | +- [User-Facing Problem](#user-facing-problem) |
| 19 | +- [Goals](#goals) |
| 20 | +- [Non-goals](#non-goals) |
| 21 | +- [Motivation](#motivation) |
| 22 | + - [Code Example](#code-example) |
| 23 | + - [Before the Fix](#before-the-fix) |
| 24 | + - [After the Fix](#after-the-fix) |
| 25 | +- [Considered Alternatives](#considered-alternatives) |
| 26 | +- [Security and Privacy](#security-and-privacy) |
| 27 | +- [Performance Impact](#performance-impact) |
| 28 | +- [Interoperability](#interoperability) |
| 29 | +- [References and Acknowledgements](#references-and-acknowledgements) |
| 30 | + |
| 31 | +<!-- END doctoc generated TOC please keep comment here to allow auto update --> |
| 32 | + |
| 33 | + |
| 34 | +## Introduction |
| 35 | + |
| 36 | +Modern web applications rely heavily on rich text editing experiences, especially within [`contenteditable`](https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable) elements. [`InputEvent.dataTransfer`](https://w3c.github.io/input-events/#dom-inputevent-datatransfer) is a property that provides access to a [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) object during input events triggered by paste, drop, or replacement actions. It allows developers to inspect and handle the data being inserted. However, developers have long faced limitations when handling paste and drop operations due to the absence of the [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) property on [Input Event Types](https://w3c.github.io/input-events/#overview) objects. This explainer proposes that [`InputEvent.dataTransfer`](https://w3c.github.io/input-events/#dom-inputevent-datatransfer) be exposed for specific input types [`insertFromPaste`, `insertReplacementText`, and `insertFromDrop`](https://w3c.github.io/input-events/#overview) within [`contenteditable`](https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable) contexts. This change puts Chromium in alignment with the [`W3C spec`](https://www.w3.org/TR/input-events-2/). |
| 37 | + |
| 38 | +## User-Facing Problem |
| 39 | +A user pastes formatted content (e.g., bold text, lists, links) into a custom editor. The developers listening to the input event with inputType = "insertFromPaste" in the following example couldn’t access [`InputEvent.dataTransfer`](https://w3c.github.io/input-events/#dom-inputevent-datatransfer) — it was null. |
| 40 | + |
| 41 | +```html |
| 42 | +<p contenteditable="true"> |
| 43 | + Go on, try pasting some content into this editable paragraph and see what |
| 44 | + happens! |
| 45 | +</p> |
| 46 | + |
| 47 | +<p class="result"></p> |
| 48 | +``` |
| 49 | + |
| 50 | +```js |
| 51 | +const editable = document.querySelector("p[contenteditable]"); |
| 52 | +const result = document.querySelector(".result"); |
| 53 | +editor.addEventListener("input", (event) => { |
| 54 | + if (event.inputType === "insertFromPaste" && event.dataTransfer) { // fails on the second condition and lines below are not executed as event.dataTransfer is NULL. |
| 55 | + const html = event.dataTransfer.getData("text/html"); |
| 56 | + const text = event.dataTransfer.getData("text/plain"); |
| 57 | + // Use html/text for sanitization, logging, or formatting |
| 58 | + } |
| 59 | +}); |
| 60 | +``` |
| 61 | +When [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) was NULL, Users |
| 62 | + |
| 63 | +- Couldn’t access the actual content being pasted or dropped. |
| 64 | +- Couldn’t differentiate between rich and plain text. |
| 65 | +- Couldn’t intercept or sanitize HTML before it was rendered. |
| 66 | +- Couldn’t process dropped files without relying on separate drop event listeners. |
| 67 | +- Couldn’t build consistent logic across beforeinput, input, and drop events. |
| 68 | + |
| 69 | +After the fix, [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) is exposed on the input event. |
| 70 | + |
| 71 | +## Goals |
| 72 | +The goal of this feature is to expose the [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) property on [`InputEvent`](https://w3c.github.io/input-events/#interface-InputEvent) objects for specific input types [`insertFromPaste`, `insertReplacementText`, and `insertFromDrop`](https://w3c.github.io/input-events/#overview) in [`contenteditable`](https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable) contexts. This enables developers to access drag-and-drop and clipboard data during input events, improving support for rich text editors and other interactive content tools. |
| 73 | +What developers can do with [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) |
| 74 | +1. Access Rich Clipboard Data |
| 75 | + - Developers can inspect dataTransfer.getData("text/html") to: |
| 76 | + - Sanitize pasted HTML for security. |
| 77 | + - Preserve formatting in custom editors. |
| 78 | + |
| 79 | +2. Customize Paste/Drop Behavior |
| 80 | + - Developers can override default behavior based on: |
| 81 | + - MIME types in dataTransfer.items. |
| 82 | + - Source metadata (e.g., URLs, app-specific formats). |
| 83 | + - User intent (e.g., distinguish between plain text and rich content). |
| 84 | + |
| 85 | +3. Audit and Logging |
| 86 | + - Developers can log what was pasted or dropped for: |
| 87 | + - Accessibility tracking. |
| 88 | + - Undo/redo history. |
| 89 | + - Security audits. |
| 90 | + |
| 91 | +4. Improve Accessibility and UX |
| 92 | + - For spelling corrections (insertReplacementText), developers can: |
| 93 | + - Track automated vs manual changes. |
| 94 | + - Provide visual feedback or undo options. |
| 95 | + - Integrate with grammar tools or custom dictionaries. |
| 96 | + |
| 97 | +## Non-goals |
| 98 | +This feature does not: |
| 99 | +- Modify the behavior of form controls like [`<input>`](https://html.spec.whatwg.org/multipage/input.html#the-input-element) and [`<textarea>`](https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element). |
| 100 | +- Change the underlying drag-and-drop security model. |
| 101 | +- Introduce new input types or event interfaces. |
| 102 | + |
| 103 | +## Motivation |
| 104 | +The W3C Input Events Level 2 specification requires that [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) be available for certain input types. Prior to this feature, Chromium did not expose [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) on [`InputEvent`](https://w3c.github.io/input-events/#interface-InputEvent) for [`insertFromPaste`, `insertReplacementText`, and `insertFromDrop`](https://w3c.github.io/input-events/#overview), resulting in inconsistent behavior across browsers and limiting developer capabilities. |
| 105 | + |
| 106 | +This feature addresses: |
| 107 | +- Spec compliance. |
| 108 | +- Interoperability with Safari and Firefox. |
| 109 | +- Developer needs for accessing drag-and-drop and clipboard data in editable content. |
| 110 | + |
| 111 | +### Code Example |
| 112 | +#### Before the Fix |
| 113 | +```javascript |
| 114 | +editor.addEventListener("input", (event) => { |
| 115 | + console.log(event.inputType); // e.g., "insertFromDrop" |
| 116 | + console.log(event.dataTransfer); // null |
| 117 | +}); |
| 118 | +``` |
| 119 | + |
| 120 | +#### After the Fix |
| 121 | +```javascript |
| 122 | +editor.addEventListener("input", (event) => { |
| 123 | + console.log(event.inputType); // e.g., "insertFromDrop" |
| 124 | + console.log(event.dataTransfer); // non-null |
| 125 | + if (event.dataTransfer) { |
| 126 | + console.log("Dropped plain data:", event.dataTransfer.getData("text/plain")); |
| 127 | + console.log("Dropped html data:", event.dataTransfer.getData("text/html")); |
| 128 | + } |
| 129 | +}); |
| 130 | +``` |
| 131 | +In the implementation, [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) property is attached only when the target is a [`contenteditable`](https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable) element, excluding form controls ([`input`](https://html.spec.whatwg.org/multipage/input.html#the-input-element) or [`textarea`](https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element)). |
| 132 | + |
| 133 | +## Considered Alternatives |
| 134 | +- Keeping the current behavior: This would continue to violate the spec and limit developer capabilities (currently developers can get [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) only if they listen to [`beforeinput`](https://w3c.github.io/input-events/#event-type-beforeinput) event). |
| 135 | +- Exposing [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) for all elements: This was rejected to preserve existing behavior for form controls and avoid unintended side effects. |
| 136 | + |
| 137 | +## Security and Privacy |
| 138 | +This proposal has no known impact on accessibility or privacy and does not alter the permission or security model. The [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) property is exposed only when the browser determines it is appropriate based on the input event type and context. It is scoped to [`contenteditable`](https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable) elements and does not alter drag-and-drop security model. No new information is exposed to sites because the same information is also exposed during the [`beforeinput`](https://w3c.github.io/input-events/#event-type-beforeinput) event. |
| 139 | + |
| 140 | +## Performance Impact |
| 141 | +The feature introduces minimal overhead, as [`dataTransfer`](https://html.spec.whatwg.org/multipage/dnd.html#datatransfer) is conditionally attached only when relevant. No significant performance regressions were observed during testing. |
| 142 | + |
| 143 | +## Interoperability |
| 144 | +This feature aligns with the [`W3C Input Events Level 2 specification`](https://www.w3.org/TR/input-events-2/) and matches behavior in Safari and Firefox. It improves cross-browser consistency for developers. |
| 145 | + |
| 146 | +## References and Acknowledgements |
| 147 | +- [Spec: Input Events Level 2](https://w3c.github.io/input-events/#dom-inputevent-datatransfer) |
| 148 | +- [Bug: Chromium Issue 401593412](https://issues.chromium.org/issues/401593412) |
| 149 | +- [MDN: InputEvent.dataTransfer](https://developer.mozilla.org/en-US/docs/Web/API/InputEvent/dataTransfer) |
| 150 | + |
| 151 | +Many thanks for valuable feedback and advice from: |
| 152 | +- [Rohan Raja](https://github.com/roraja) |
| 153 | +- [Rakesh Goulikar](https://github.com/ragoulik) |
| 154 | +- [Samba Murthy Bandaru](https://github.com/sambandaru) |
| 155 | +- [Daniel Clark](https://github.com/dandclark) |
| 156 | +--- |
0 commit comments