UNPKG

10.3 kBMarkdownView Raw
1![Logo for clipboard-polyfill: an icon of a clipboard fading into a drafting paper grid.](clipboard-polyfill-logo.svg)
2
3# `clipboard-polyfill`
4
5Makes copying on the web as easy as:
6
7 clipboard.writeText("hello world");
8
9This library is a polyfill for the modern `Promise`-based [asynchronous clipboard API](https://www.w3.org/TR/clipboard-apis/#async-clipboard-api).
10
11Note: As of late June 2020, you can use `navigator.clipboard.writeText("hello world);` in the stable versions of all major browsers (see below for compatibility). This library will only be useful to you if you 1) need to copy `text/html`, or 2) need to target older browsers.
12
13## Usage
14
15If you use `npm`, install:
16
17```shell
18npm install clipboard-polyfill
19```
20
21Sample app that copies text to the clipboard:
22
23```js
24// Using the `clipboard/text` build saves code size.
25// This is recommended if you only need to copy text.
26import * as clipboard from "clipboard-polyfill/text";
27
28function handler() {
29 clipboard.writeText("This text is plain.").then(
30 function () {
31 console.log("success!");
32 },
33 function () {
34 console.log("error!");
35 }
36 );
37}
38
39window.addEventListener("DOMContentLoaded", function () {
40 const button = document.body.appendChild(document.createElement("button"));
41 button.textContent = "Copy";
42 button.addEventListener("click", handler);
43});
44```
45
46Notes:
47
48- You need to call a clipboard operation in response to a user gesture (e.g. the event handler for a `button` click).
49 - Some browsers may only allow one clipboard operation per gesture.
50
51## `async`/`await` syntax
52
53```js
54import * as clipboard from "clipboard-polyfill/text";
55
56async function handler() {
57 console.log("Previous clipboard text:", await clipboard.readText());
58
59 await clipboard.writeText("This text is plain.");
60}
61
62window.addEventListener("DOMContentLoaded", function () {
63 const button = document.body.appendChild(document.createElement("button"));
64 button.textContent = "Copy";
65 button.addEventListener("click", handler);
66});
67```
68
69## More MIME types (data types)
70
71```js
72import * as clipboard from "clipboard-polyfill";
73
74async function handler() {
75 console.log("Previous clipboard contents:", await clipboard.read());
76
77 const item = new clipboard.ClipboardItem({
78 "text/html": new Blob(
79 ["<i>Markup</i> <b>text</b>. Paste me into a rich text editor."],
80 { type: "text/html" }
81 ),
82 "text/plain": new Blob(
83 ["Fallback markup text. Paste me into a rich text editor."],
84 { type: "text/plain" }
85 ),
86 });
87 await clipboard.write([item]);
88}
89
90window.addEventListener("DOMContentLoaded", function () {
91 const button = document.body.appendChild(document.createElement("button"));
92 button.textContent = "Copy";
93 button.addEventListener("click", handler);
94});
95```
96
97Check [the Clipboard API specification](https://www.w3.org/TR/clipboard-apis/#clipboard-interface) for more details.
98
99Notes:
100
101- You'll need to use `async` functions for the `await` syntax.
102- Currently, `text/plain` and `text/html` are the only data types that can be written to the clipboard across most browsers.
103- If you try to copy unsupported data types, they may be silently dropped (e.g. Safari 13.1) or the call may throw an error (e.g. Chrome 83). In general, it is not possible to tell when data types are dropped.
104- In some current browsers, `read()` may only return a subset of supported data types, even if the clipboard contains more data types. There is no way to tell if there were more data types.
105
106### `overwrite-globals` version
107
108If you want the library to overwrite the global clipboard API with its implementations, import `clipboard-polyfill/overwrite-globals`. This will turn the library from a [ponyfill](https://ponyfill.com/) into a proper polyfill, so you can write code as if the async clipboard API were already implemented in your browser:
109
110```js
111import "clipboard-polyfill/overwrite-globals";
112
113async function handler() {
114 const item = new window.ClipboardItem({
115 "text/html": new Blob(
116 ["<i>Markup</i> <b>text</b>. Paste me into a rich text editor."],
117 { type: "text/html" }
118 ),
119 "text/plain": new Blob(
120 ["Fallback markup text. Paste me into a rich text editor."],
121 { type: "text/plain" }
122 ),
123 });
124
125 navigator.clipboard.write([item]);
126}
127
128window.addEventListener("DOMContentLoaded", function () {
129 const button = document.body.appendChild(document.createElement("button"));
130 button.textContent = "Copy";
131 button.addEventListener("click", handler);
132});
133```
134
135This approach is not recommended, because it may break any other code that interacts with the clipboard API globals, and may be incompatible with future browser implementations.
136
137### Flat-file version with `Promise` included
138
139If you need to grab a version that "just works", download [`clipboard-polyfill.promise.js`](https://github.com/lgarron/clipboard-polyfill/releases/latest/download/clipboard-polyfill.promise.js) and include it using a `<script>` tag:
140
141```html
142<script src="./clipboard-polyfill.promise.js"></script>
143<button onclick="copy()">Copy text!</button>
144<script>
145 // `clipboard` is defined on the global `window` object.
146 function copy() {
147 clipboard.writeText("hello world!");
148 }
149</script>
150```
151
152## Why `clipboard-polyfill`?
153
154Browsers have implemented several clipboard APIs over time, and writing to the clipboard without [triggering bugs in various old and current browsers](https://github.com/lgarron/clipboard-polyfill/blob/master/experiment/Conclusions.md) is fairly tricky. In every browser that supports copying to the clipboard in some way, `clipboard-polyfill` attempts to act as close as possible to the async clipboard API. (See above for disclaimers and limitations.)
155
156See [this presentation](https://docs.google.com/presentation/d/1Ix2rYi67hbZoIQsd85kspkUPLi8Q-PZopy_AtfafHW0) for for a longer history of clipboard access on the web.
157
158## Compatibility
159
160- ☑️: Browser has native async clipboard support.
161- ✅: `clipboard-polyfill` provides support.
162- ❌: Support is not possible.
163- **Bold browser names** indicate the latest functionality changes for stable versions of modern browsers.
164
165Write support by earliest browser version:
166
167| Browser | `writeText()` | `write()` (HTML) | `write()` (other formats) |
168| ------------------------------------------- | ------------- | ---------------- | ---------------------------------- |
169| **Safari 13.1** | ☑️ | ☑️ | ☑️ (`image/uri-list`, `image/png`) |
170| **Chrome 76**ᵃ / **Edge 79** | ☑️ | ✅ | ☑️ (`image/png`) |
171| Chrome 66ᵃ / **Firefox 63** | ☑️ | ✅ | ❌ |
172| Safari 10 / Chrome 42ᵃ / Edgeᵈ / Firefox 41 | ✅ | ✅ᵇ | ❌ |
173| IE 9 | ✅ᶜ | ❌ | ❌ |
174
175Read support:
176
177| Browser | `readText()` | `read()` (HTML) | `read()` (other formats) |
178| ----------------------------------------------------------------------------------- | ------------ | --------------- | ---------------------------------- |
179| **Safari 13.1** | ☑️ | ☑️ | ☑️ (`image/uri-list`, `image/png`) |
180| **Chrome [76](https://web.dev/image-support-for-async-clipboard/)** ᵃ / **Edge 79** | ☑️ | ❌ | ☑️ (`image/png`) |
181| Chrome [66](https://developers.google.com/web/updates/2018/03/clipboardapi)ᵃ | ☑️ | ❌ | ❌ |
182| IE 9 | ✅ᶜ | ❌ | ❌ |
183| **Firefox** | ❌ | ❌ | ❌ |
184
185- ᵃ Also includes versions of Edge, Opera, Brave, Vivaldi, etc. based on the corresponding version of Chrome.
186- ᵇ HTML did not work properly on mobile Safari in the first few releases of version 10.
187- ᶜ In Internet Explorer, you will need to polyfill `window.Promise` if you want the library to work.
188- ᵈ In older versions of Edge (Spartan):
189 - It may not be possible to tell if a copy operation succeeded ([Edge Bug #14110451](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/14110451/), [Edge Bug #14080262](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/14080262/)). `clipboard-polyfill` will always report success in this case.
190 - Only the _last_ data type you specify is copied to the clipboard ([Edge Bug #14080506](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/14080506/)). Consider placing the most important data type last in the object that you pass to the `ClipboardItem` constructor.
191 - The `text/html` data type is not written using the expected `CF_HTML` format. `clipboard-polyfill` does _not_ try to work around this, since 1) it would require fragile browser version sniffing, 2) users of Edge are not generally stuck on version < 17, and 3) the failure mode for other browsers would be that invalid clipboard HTML is copied. ([Edge Bug #14372529](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/14372529/), [#73](https://github.com/lgarron/clipboard-polyfill/issues/73))
192
193`clipboard-polyfill` uses a variety of heuristics to work around compatibility bugs. Please [let us know](https://github.com/lgarron/clipboard-polyfill/issues/new) if you are running into compatibility issues with any of the browsers listed above.
194
195## This is way too complicated!
196
197If you only need to copy text, try [this gist](https://gist.github.com/lgarron/d1dee380f4ed9d825ca7) for a simpler solution.
198
199Alternatively, if you wait until iOS 14 / macOS 11, `navigator.clipboard.writeText()` will be supported in the stable versions of all major modern browsers.
200
\No newline at end of file