` element with id `target` where the canvas image will be pasted.
+
+```html
+
+
+
Paste here.
+```
+
+#### JavaScript
+
+First we define an `async` function to copy a canvas to a blob.
+This wraps the old callback-style {{domxref("HTMLCanvasElement.toBlob()")}} method into the more intuitive `Promise` based function.
+
+```js
+// Async/await method replacing toBlob() callback
+async function getBlobFromCanvas(canvas) {
+ return new Promise((resolve, reject) => {
+ canvas.toBlob((blob) => {
+ if (blob) {
+ resolve(blob);
+ } else {
+ reject(new Error("Canvas toBlob failed"));
+ }
+ });
+ });
+}
+```
+
+Next we set up our canvas and add an event listener for the `click` event.
+
+When you click the blue rectangle the code first checks if the clipboard supports data of type `"image/png"`.
+If so, the canvas displaying the rectangle is copied into a blob, and then the blob is added to a `ClipboardItem` and then written to the clipboard.
```js
-const target = document.getElementById("target");
const canvas = document.getElementById("canvas");
// Set up canvas
@@ -88,24 +120,33 @@ ctx.fillStyle = "cornflowerblue";
ctx.fillRect(0, 0, 100, 100);
canvas.addEventListener("click", copyCanvasContentsToClipboard);
+const target = document.getElementById("target");
-function copyCanvasContentsToClipboard() {
- return new Promise((resolve, reject) => {
+async function copyCanvasContentsToClipboard() {
+ if (ClipboardItem.supports("image/png")) {
// Copy canvas to blob
- canvas.toBlob(async (blob) => {
- try {
- // Create ClipboardItem with blob and its type, and add to an array
- const data = [new ClipboardItem({ [blob.type]: blob })];
- // Write the data to the clipboard
- await navigator.clipboard.write(data);
- resolve();
- } catch (e) {
- reject(e);
- }
- });
- });
+ try {
+ const blob = await getBlobFromCanvas(canvas);
+ // Create ClipboardItem with blob and it's type, and add to an array
+ const data = [new ClipboardItem({ [blob.type]: blob })];
+ // Write the data to the clipboard
+ await navigator.clipboard.write(data);
+ } catch (error) {
+ console.log(error);
+ }
+ } else {
+ console.log("image/png is not supported");
+ }
}
+```
+Note that clipboard support for PNG files is a mandatory part of the specification, so we don't actually need the check using {{domxref("ClipboardItem.supports_static", "ClipboardItem.supports()")}} above (it always returns `true`).
+The check would be more useful in cases where we're fetching an optional file type, or a resource where we don't know the type in advance.
+
+We then define an event listener for [`paste` events](/en-US/docs/Web/API/Element/paste_event) on then element where we want to display the clipboard contents as an image.
+The [FileReader API](/en-US/docs/Web/API/FileReader) allows us to read the blob using the [`readAsDataUrl`](/en-US/docs/Web/API/FileReader/readAsDataURL) method and create an `
` element with the canvas contents:
+
+```js
target.addEventListener("paste", (event) => {
const items = (event.clipboardData || window.clipboardData).items;
const blob = items[0].getAsFile();
@@ -132,14 +173,12 @@ body {
}
img {
margin: 0.5rem;
-}
```
-```html
-
+#### Result
-
Paste here.
-```
+The result is shown below.
+First click on the blue square, and then select the text "Paste here" and use your OS-specific keyboard combinatations to paste from the clipboard (such as `Ctrl+V` on Windows).
{{embedlivesample("write_canvas_contents_to_the_clipboard", "", "300")}}
diff --git a/files/en-us/web/api/clipboarditem/clipboarditem/index.md b/files/en-us/web/api/clipboarditem/clipboarditem/index.md
index 23e03b2ec95339e..d8797a5d4a5fa29 100644
--- a/files/en-us/web/api/clipboarditem/clipboarditem/index.md
+++ b/files/en-us/web/api/clipboarditem/clipboarditem/index.md
@@ -42,16 +42,19 @@ This item is then written to the clipboard, using the {{domxref("Clipboard.write
```js
async function writeClipImg() {
try {
- const imgURL = "/myimage.png";
- const data = await fetch(imgURL);
- const blob = await data.blob();
-
- await navigator.clipboard.write([
- new ClipboardItem({
- [blob.type]: blob,
- }),
- ]);
- console.log("Fetched image copied.");
+ if (ClipboardItem.supports("image/png")) {
+ const imgURL = "/myimage.png";
+ const data = await fetch(imgURL);
+ const blob = await data.blob();
+ await navigator.clipboard.write([
+ new ClipboardItem({
+ [blob.type]: blob,
+ }),
+ ]);
+ console.log("Fetched image copied.");
+ } else {
+ console.log("image png is not suported");
+ }
} catch (err) {
console.error(err.name, err.message);
}
diff --git a/files/en-us/web/api/clipboarditem/index.md b/files/en-us/web/api/clipboarditem/index.md
index 87a5aec9f08c697..b946316a768a64b 100644
--- a/files/en-us/web/api/clipboarditem/index.md
+++ b/files/en-us/web/api/clipboarditem/index.md
@@ -27,6 +27,13 @@ _This interface provides the following properties._
- {{domxref("ClipboardItem.presentationStyle", "presentationStyle")}} {{ReadOnlyInline}}
- : Returns one of the following: `"unspecified"`, `"inline"` or `"attachment"`.
+## Static methods
+
+_This interface defines the following methods._
+
+- {{domxref("ClipboardItem.supports_static", "ClipboardItem.supports()")}}
+ - : Checks whether a given {{Glossary("MIME type")}} is supported by the clipboard. This enables a website to detect whether a MIME type is supported by the clipboard before attempting to write data.
+
## Instance methods
_This interface defines the following methods._
@@ -38,21 +45,25 @@ _This interface defines the following methods._
### Writing to the clipboard
-Here we're writing a new {{domxref("ClipboardItem.ClipboardItem", "ClipboardItem()")}} to the system clipboard by requesting a PNG image using the {{domxref("Fetch API")}}, and in turn, the {{domxref("Response.blob()", "responses' blob()")}} method, to create the new `ClipboardItem`.
+Here we use {{domxref("ClipboardItem.supports_static", "supports()")}} to check whether the `image/svg+xml` MIME data type is supported.
+If it is, we fetch the image with the ["Fetch API"](/en-US/docs/Web/API/Fetch_API), and then read it into a {{domxref("Blob")}}, which we can use to create a `ClipboardItem` that is written to the clipboard.
```js
async function writeClipImg() {
try {
- const imgURL = "/myimage.png";
- const data = await fetch(imgURL);
- const blob = await data.blob();
-
- await navigator.clipboard.write([
- new ClipboardItem({
- [blob.type]: blob,
- }),
- ]);
- console.log("Fetched image copied.");
+ if (ClipboardItem.supports("image/svg+xml")) {
+ const imgURL = "/myimage.svg";
+ const data = await fetch(imgURL);
+ const blob = await data.blob();
+ await navigator.clipboard.write([
+ new ClipboardItem({
+ [blob.type]: blob,
+ }),
+ ]);
+ console.log("Fetched image copied.");
+ } else {
+ console.log("SVG images are not supported by the clipboard.");
+ }
} catch (err) {
console.error(err.name, err.message);
}
diff --git a/files/en-us/web/api/clipboarditem/supports_static/index.md b/files/en-us/web/api/clipboarditem/supports_static/index.md
new file mode 100644
index 000000000000000..c11ee175c2027b5
--- /dev/null
+++ b/files/en-us/web/api/clipboarditem/supports_static/index.md
@@ -0,0 +1,86 @@
+---
+title: "ClipboardItem: supports() static method"
+short-title: supports()
+slug: Web/API/ClipboardItem/supports_static
+page-type: web-api-static-method
+browser-compat: api.ClipboardItem.supports_static
+---
+
+{{APIRef("Clipboard API")}} {{securecontext_header}}
+
+The **`supports()`** static method of the {{domxref("ClipboardItem")}} interface returns `true` if the given {{Glossary("MIME type")}} is supported by the clipboard, and `false` otherwise.
+
+Note that the [Clipboard API](/en-US/docs/Web/API/Clipboard_API) mandates support for plain text, HTML and PNG files.
+The `supports()` method will always return `true` for these MIME types, so testing them is unnecessary .
+
+## Syntax
+
+```js-nolint
+supports(type)
+```
+
+### Parameters
+
+- `type`
+
+ - : A string, indicating the {{Glossary("MIME type")}} to test.
+
+ These MIME types are always supported:
+
+ - `text/plain`
+ - `text/html`
+ - `image/png`
+
+ These MIME types may be supported:
+
+ - `image/svg+xml`
+ - Custom MIME-type formats starting with `"web "`.
+ The custom type (without the `"web "` prefix), must have the correct formatting for a MIME type.
+
+### Return value
+
+`true` if the given {{Glossary("MIME type")}} is supported by the clipboard, `false` otherwise.
+
+## Examples
+
+### Writing an image to the clipboard
+
+The following example fetches an SVG image to a blob, and then writes it to the clipboard.
+
+We use `supports()` to check whether the `"image/svg+xml"` MIME type is supported by the clipboard before fetching the image and writing it using {{domxref("clipboard.write()")}}.
+We also wrap the whole function body in [`try..catch`](/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) statement to catch any other errors, such as `ClipboardItem` itself not being supported.
+
+```js
+async function writeClipImg() {
+ try {
+ if (ClipboardItem.supports("image/svg+xml")) {
+ const imgURL = "/myimage.svg";
+ const data = await fetch(imgURL);
+ const blob = await data.blob();
+ await navigator.clipboard.write([
+ new ClipboardItem({
+ [blob.type]: blob,
+ }),
+ ]);
+ console.log("Fetched image copied to clipboard.");
+ } else {
+ console.log("SVG image not supported by clipboard");
+ }
+ } catch (err) {
+ console.error(err.name, err.message);
+ }
+}
+```
+
+## Specifications
+
+{{Specifications}}
+
+## Browser compatibility
+
+{{Compat}}
+
+## See also
+
+- [Clipboard API](/en-US/docs/Web/API/Clipboard_API)
+- [Image support for Async Clipboard article](https://web.dev/articles/async-clipboard)