If I ask: Do you know about clipboards?
I’m afraid everyone knows. We don’t know how many times a day we’re going to copy and paste on our computers or phones. Every “copy”, “paste” behind, will use the “clipboard”.
According to Wikipedia:
The clipboard is a data buffer used for short-term data storage and/or data transfer between documents or applications used by cut, copy and paste operations and provided by the operating system.
Translation:
The clipboard is a data cache used to store or transfer short-term data between documents or applications. It is provided by the operating system when users perform cutting, copying, and pasting operations.
The most important point here is that the “clipboard” is “provided by the operating system,” so it is a software feature at the system level.
For front-end developers, if I ask: Do you know how to use the clipboard?
Many people’s first reaction might be: use clipboard.js…
The principle of the clipboard. Js
Clipboard.js (clipboardjs.com/) has more than 24,000 stars on Github, showing its popularity. As for the use of this library, you can see for yourself, we will mainly analyze the implementation principle, in order to understand the current mainstream technology to operate the clipboard.
In short, clipboard.js leverages two existing Web apis (the former is part of HTML5 and the latter is part of HTML Editing API) :
- HTMLInputElement.select()
- document.execCommand()
Accordingly, there are only two steps.
First, create a temporary Texterea element, hide it with CSS, assign the text to be copied to the text area, and select everything in the text area:
// https://github.com/zenorocha/clipboard.js/blob/master/src/clipboard-action.js /** * Creates a fake textarea element, sets its value from `text` property, */ / selectFake() // create a temporary Texterea element this.fakeelem = document.createElement('textarea'); / / hide the element this. FakeElem. Style. The position = 'absolute'; this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px'; // Assign the text to be copied to the text area and select all contents this.fakeem. value = this.text; this.selectedText = select(this.fakeElem); // Trigger copy this.copytext ();Copy the code
If the copy operation succeeds, text will be written to the clipboard, and events will be sent based on the execution result:
// https://github.com/zenorocha/clipboard.js/blob/master/src/clipboard-action.js /** * Executes the copy operation based on the current selection. */ // copyText() succeeded = document.execCommand(this.action); this.handleResult(succeeded); /** * Fires an event based on the copy operation result. * @param {Boolean} succeeded */ handleResult(succeeded) { this.emitter.emit(succeeded ? 'success' : 'error', { action: this.action, text: this.selectedText, trigger: this.trigger, clearSelection: this.clearSelection.bind(this) }); }Copy the code
As mentioned earlier, the clipboard is provided by the operating system and is system-level. For security and user experience, browser vendors only trust users to copy operations triggered by applications, documents, or scripts. Also, the source of the content copied to the clipboard must be an existing DOM element.
The result of the above copy operation is to write text content to the clipboard. To read the contents of the clipboard, you must register a paste event handler to get the contents of the clipboard through the e.clipboardData.getData() method. This allows you to pre-process the content on the clipboard before the user pastes it into the target input box. But that’s not the point of this article.
While clipboard.js uses a technique that is supported by almost all browsers, it has a number of drawbacks.
Defects in existing technology
What were the failings of previous technologies? In addition to the previous need to programmatically simulate the copy operation of the clipboard triggered by the user through execCommand, there are:
- ExecCommand’s original intention was to edit the DOM, and there are many differences between browser implementations
- The copy-and-paste operation is synchronous and blocks the main thread, making the page unresponsive
- If you then pop up to request authorization, you might annoy the user
- Correspondingly, it prevents harmless processing or transcoding of certain types of data, such as images
- Transcoding is sometimes necessary to avoid external exploitation
To overcome these problems, the W3C began to develop a standard: Clipboard API and Events (www.w3.org/TR/clipboar…). .
The Clipboard API and Events defines the Async Clipboard API, which adds clipboardChange events accordingly.
Async Clipboard API
In other words, to avoid blocking the main thread, this new standard introduces an asynchronous clipboard API based on Promise. Since the clipboard is a system-level software feature, the corresponding API is mounted on the Navigator:
navigator.clipboard
Copy the code
The Clipboard object has four methods:
Promise<DataTransfer> read();
Promise<DOMString> readText();
Promise<void> write(DataTransfer data);
Promise<void> writeText(DOMString data);
Copy the code
Two read clipboards, two write clipboards.
Supports reading and writing of the following data types:
- text/plain
- text/uri-list
- text/csv
- text/css
- text/html
- application/xhtml+xml
- image/png
- image/jpg, image/jpeg
- image/gif
- image/svg+xml
- application/xml, text/xml
- application/javascript
- application/json
- application/octet-stream
read()
navigator.clipboard.read().then(function(data) { for (var i = 0; i < data.items.length; i++) { if (data.items[i].type == "text/plain") { console.log("Your string: ", data.items[i].getAs("text/plain")); } else { console.error("No text/plain data on clipboard."); }}});Copy the code
readText()
navigator.clipboard.readText().then(function(data) {
console.log("Your string: ", data);
});
Copy the code
write(data)
var data = new DataTransfer(); data.items.add("text/plain", "Howdy, partner!" ); navigator.clipboard.write(data).then(function() { console.log("Copied to clipboard successfully!" ); }, function() { console.error("Unable to write to clipboard. :-("); });Copy the code
writeText(data)
navigator.clipboard.writeText("Howdy, partner!" ).then(function() { console.log("Copied to clipboard successfully!" ); }, function() { console.error("Unable to write to clipboard. :-("); });Copy the code
Matters needing attention
- Navigator.clipboard can only be used in a “security context”. What is a “security context”? Basically, locahost and HTTPS. (This can be obtained using the window.isSecureContext property.)
- Desktop browsers are currently supported only by Chrome, Firefox and Opera, but not Safari and IE/Edge. Also, Chrome only supports readText() and writeText().
Reference links:
- clipboardjs.com/
- www.w3.org/TR/clipboar…
- Developers.google.com/web/updates…
- The w3c. Making. IO/webappsec – s…