JavaScript. Work with clipboard, Ctrl+C Ctrl+V
Tags: webdev, javascript, programming, html
Published: 2023-03-27 05:51:58

How to write an image to the clipboard. What data types can be written to the clipboard. Custom types support. How to make custom copy/paste buttons.


![Pic 1. Copy between tabs and Google Docs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/domlm4p1ke3s3fxg7vip.gif)_Pic 1. Copy between tabs and Google Docs_

 
## Task
Create a copy function for the [dgrm.net](https://dgrm.net/) flowchart editor.

- Copy-paste between tabs
- Paste to Word/Google docs -> diagram is inserted as a picture.
- Hot keys support: Ctrl+C, Ctrl+V, Ctrl+X
- Custom copy/paste buttons for work with mouse
- Mobile device support

 
## Clipboard APIs

### document.execCommand('copy') don’t work
This API is deprecated and doesn’t work. Don’t try to use it to bypass restrictions of other APIs.

### 'copy', 'paste', 'cut' event handlers
```js
document.addEventListener('copy', evt => {
 evt.preventDefault();
 evt.clipboardData.setData('text/plain', 'text to clipboard');
});

// Listing 1. Wright to clipboard on ‘copy’ event
```

In this option, there is no way to make your own ‘copy’ button, the user must press Ctrl + C.

### navigator.clipboard.read/wright
```js
btn.addEventListener('click', async _ => 
 await navigator.clipboard.writeText('text to clipboard')
);

// Listing 2. Write to clipboard on button click
```

You can make a custom “copy” button. Works in all browsers and on mobile devices.

Safari has a limitation: This API cannot be used in callbacks. This does not work in Safari:
```js
btn.addEventListener('click', async _ => 
 // create png from svg
 svgToPng(
  svg,
  // callback
  async png => await navigator.clipboard.write(...))
);

// Listing 3. Don’t work in Safari.
// navigator.clipboard is not allowed in callbacks.
// How to write an image to clipboard in the next part
```

This is a security limitation: it is not clear when the callback comes, the user may already have changed his mind about copying.

You can do this: first write the string to the clipboard, if the browser allows -> write the image.

```js
// guaranteed clipboard write
await navigator.clipboard.writeText('text to clipboard');

// try to write img
// if ok -> clipboard will be overwritten
try {
 // create png from svg
 svgToPng(
  svg,
  // callback
  async png => await navigator.clipboard.write(...));
} catch { }

// Listing 4. Write text to clipboard,
// if the browser allows -> write the image
```

## How to write an image to the clipboard
```js
await navigator.clipboard.write([new window.ClipboardItem({
 'image/png': Promise.resolve(png), // png is Blob
 'text/plain': Promise.resolve(new Blob(['text to clipboard'], { type: 'text/plain' }))
})]);

// Listing 5. Write image and alternative text to the clipboard
```

You can write several data types to the clipboard at the same time. For example image and text. If pasted into Word -> a picture is inserted, if into Notepad -> text is inserted.

You can write to clipboard this types:
- text/plain
- text/html
- image/png

Some browsers allow more types. These three are allowed everywhere.

You can write to the clipboard only PNG. Other image formats are not allowed.
When copying, the browser “cleanses” the png. To be safe, the browser removes metadata from png.
Trouble for dgrm.net. Dgrm.net stores a schema description in metadata. Thanks to metadata, you can open the picture for editing — Pic. 2.


![Pic 2. dgrm.net can open diagrams from PNG images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6xvaj858nxug5s9pe699.gif)_Pic 2. dgrm.net can open diagrams from PNG images_

## Custom data types in clipboard
‘text/plain’ from the clipboard can be pasted anywhere. It’s good to use a custom data type that only your application reads. For example ‘text/dgrm’.

For security, the browser associates custom type with domain. Thus, a third-party site will not read your data type from the clipboard.

Not all browsers support custom types. In Chrome, from some version you can use custom types, they must be prefixed with ‘web ‘ -> ‘web text/dgrm’.

Not all browsers allow writing non-’text/plain’ type to the clipboard using navigator.clipboard.**write**. They allow use of navigator.clipboard.write only in ‘copy’, ‘cut’ event handlers. Those. you can’t make your own “copy” button.

As a result you may prefer to use navigator.clipboard.**writeText**, it works everywhere.

## Read from clipboard
Reading from the clipboard is even more dangerous than writing. Even more restrictions. In FireFox, you can only read in the ‘paste’ event handler. You cannot make a custom“insert” button, you need the user to press Ctrl V.

```js
document.addEventListener('paste', evt => {
 const txt = evt.clipboardData.getData('text/plain');
});

// Listing 6. Read from clipboard on ‘paste’ event
```
Other browsers allow us to use the navigator.clipboard API.
```js
btn.addEventListener('click', async _ => 
 await navigator.clipboard.readText()
);

// Listing 7. Read from clipboard on button click
```
The browser will ask for the user’s permission. iOS Safari will ask every time navigator.clipboard.readText is called.

## About dgrm.net flowchart editor
[Dgrm.net](https://dgrm.net/) is a quick editor without extra buttons.

I am developing the editor. I write announcements in https://twitter.com/boyko_tech.

Try it, write what you like / don’t like. I keep a list of proposals.