What you may not know is Copy — Js

!!!!!!!!! PC & client

PS: Do you ever get annoyed by being copied and pasted from pictures or text, Sparrow’s here to solve your lifelong disease, sign up now, limited staff, hungry Bro!

In fact, today’s theme is to be around the JS inside the “copy” this professional term to outline the full text.

"Introduction" PM: We are going to explain 1.6 client requirements, blah blah blah... Next time, we will add the function of "copy" pictures and text, and send you the function of dragging file pictures and text to the input box... My meng PM: oh yes, but also compatible with wechat and other paste pictures.... mmpmmpmmp

Is this less than a wick incense time, triggered the thinking, how to do how to do how to do? Paste is still have some answers to paste event To do deal with good, depending on the type of the inside of the towing line also drag me in send to you a background color come in time, but copy to do? Text seems to use ancient execCommand should be no problem, but ghost images are also compatible with wechat paste function and even WPS browser compatibility in various situations, why? Hear me come (three days and two nights and hundreds of hairs)

Overview

  • Paste picture format and rules
    • Wechat chat picture paste (Rule)
    • Wechat screenshot paste (Rule)
  • Drag and drop
  • copy
    • Copy the words
    • Copy the picture
  • Document.execCommand()
  • Clipboard API
  • Event.clipboardData

Paste picture format and rules

There will be different types and formats in the events monitored by pasting pictures, and pasting them in a certain software may follow the so-called rules for others to copy pictures internally. So far, I have only met this 78 on wechat (the view of passers-by).

Wechat chat picture paste (Rule)

This is wechat chat page inside the picture paste, (randomly in wechat to find a chat window with pictures, and then right click copy) and then… Lu code!

// Here I mainly use the rich text to achieve the normal operation of the input box
    <div
        class= {["el-textarea".this.changeInputBackground ? 'background' : ' ']}
        ref={'messageContent'}
        spellcheck="false"
        vScrollbar
        contentEditable="true"
        onInput={e= > this.messageInput(e)}
        on-keydown={(e) = > this.keydown(e)}
        placeholder=""
        on-focus={e= > this.keepLastIndex(e.target)}
        on-drop={e= > this.drop(e)}
        on-paste={e= > this.paste(e)}
        on-blur={e= > this.textareaBlur(e)}
        on-dragenter={e= > this.dragEnter(e)}
        on-dragleave={e= > this.dragLeave(e)}
        domPropsInnerHTML={this.vmodelMessage}
    ></div>
/** * paste event */
    paste(event) {
        event.preventDefault()
        let * = this.$refs.messageContent // Input box content * arbitrary write
        var clipboardData = event.clipboardData || window.clipboardData
        const items = clipboardData.items
        const text = clipboardData.getData('text/plain') // Get the text
        let apptext = document.createTextNode(text)
        let i = 0, tl = items.length;
        let imagesblob = [] // There are several types of bolB encryption, base64, formData that can be negotiated with the server when uploading
        let imagesbase64 = [] 
        // var fd = new FormData(document.forms[0]);

        for (; i < tl;) {
            if (items[i].kind == 'file') {
                let file = items[i].getAsFile();
                if (file.type.indexOf('image') > -1) {
                    let blob = URL.createObjectURL(file) / / create bolb
                    let el = document.createElement('img')
                    el.title = file.name
                    el.src = blob
                    el.dataset.name = file.name
                    if (file.path.length == 0 && tl == 1) { // Shear board condition
                        var reader = new FileReader();
                        reader.onload = function (event) {
                            el.dataset.path = event.target.result
                            el.dataset.type = '2' // 2 is sent when there is no path
                        }
                        reader.readAsDataURL(file);
                        imagesblob.push(el)
                    } else {
                        if(file.path.length ! = =0) {
                            el.dataset.path = file.path
                            el.dataset.type = '1' // 1 is normally sent
                            imagesblob.push(el)
                        }
                    }
                    // var reader = new FileReader();
                    // reader.onload = function (event) {
                    // var base64_str = event.target.result;
                    // imagesbase64.push(base64_str);
                    // }
                    // reader.readAsDataURL(file);
                    // fd.append('file' + i, file)
                }
            }
            i++
        }
        *.append(apptext) // Add text
        if (imagesblob.length > 0) {
            for (let j = 0; j < imagesblob.length; j++) {
                *.append(imagesblob[j]) // Add images}}this.keepLastIndex(*) // Cursor lag
    },

Copy the code

In fact, this is fine, but you never know what kind of devil will appear. For example, when you copy the wechat input box, there will be two images, and the first image will have no path after parsing, and the second one will have path, so you will definitely determine that the image does not have path, and then process it

Wechat screenshot paste (Rule)

In another case, when you take a screenshot, you will find that the image is stored in binary and there is no path in the clipboard, it is just a string of gibberish, and then you will find that there is a conflict, a big conflict with the previous situation… The above code is solved and I forgot how to write it (I wrote it months ago).

Drag and drop

Submit a piece of junk code

    drop(event) {
        event.preventDefault()
        let imgTypeFn = file= > file.type.indexOf('image') > -1
        let items = event.dataTransfer.files // Get all files dragged
        / / event. DataTransfer. GetData (' text/plain ') / / drag in text
        let * = this.$refs.messageContent
        const text = event.dataTransfer.getData('text/plain')
        let apptext = document.createTextNode(text)
        let i = 0, tl = items.length;
        let imagesblob = []
        for (; i < tl;) {
            if (imgTypeFn(items[i])) {
                let blob = URL.createObjectURL(items[i])
                let el = document.createElement('img')
                el.title = items[i].name
                el.src = blob
                el.dataset.name = items[i].name
                el.dataset.path = items[i].path
                imagesblob.push(el)
            } 
            i++
        }
        *.append(apptext)
        if (imagesblob.length > 0) {
            for (let j = 0; j < imagesblob.length; j++) {
                *.append(imagesblob[j])
            }
        }
        this.keepLastIndex(*)
    },
Copy the code

All right, here we go

copy

In fact, before this, or check the various materials on the Internet, there are many good tool libraries to implement this function; Such as clipboard. Js; ExecCommand (‘copy’), event. ClipboardData (copy) (paste), Navigator. Clipboard Today I’m going to focus on the new one. PS: ACTUALLY, I would like to be more specific and do something, but the timing doesn’t allow me to do that, so… Rub your hands together and see… This is a new version of the Cut, copy, and Paste Clipboard API browser that allows JavaScript scripts to read and write to the clipboard and automatically copy and paste content. As a general rule, scripts should not alter the user’s clipboard in case it does not meet the user’s expectations. However, there are times when it does come in handy, such as the “one-click copy” feature, where a user clicks a button and the specified content automatically goes to the clipboard.

Document. ExecCommand () method (Ruan Yifeng teacher’s diary)

Document.execcommand () is a traditional way to manipulate the clipboard, supported by all browsers. It supports copy, cut, and paste.Copy the code
  • Document. ExecCommand (‘copy’)

      // Create input to assign content, select and copy
      const inputElement = document.querySelector('#input');
      inputElement.select();
      document.execCommand('copy');
    Copy the code
  • Document. ExecCommand (‘cut’) (Cut)

  • Document. ExecCommand (‘paste’)

    // Same principle
    const pasteText = document.querySelector('#output');
    pasteText.focus();
    document.execCommand('paste');
    Copy the code
  • Disadvantages The document.execcommand () method, while convenient, has some disadvantages. First, it can only copy selected content to the clipboard, not write anything to the clipboard. Second, it’s a synchronous operation, and pages can get stuck if you copy/paste a lot of data. Some browsers also pop up a box asking for permission, and the page stops responding before the user makes a choice.

To address these issues, browser vendors have proposed an asynchronous Clipboard API.

Clipboard API

The Clipboard API is the next generation of Clipboard manipulation methods that are more powerful and reasonable than the traditional document.execcommand () method; All of its operations are asynchronous, return Promise objects, and do not cause the page to stall. Moreover, it can put any content (such as pictures) into the clipboard; The navigator. Clipboard property returns the ClipBoard object through which all operations are performed;Copy the code

const clipboardObj = navigator.clipboard; If the navigator.clipboard property returns undefined, the current browser does not support this API. The Clipboard object provides the following methods:

  • read()

Reads data (such as an image) from the clipboard and returns a Promise object. The spectrum is retrieved When the data has been retrieved, the promise is resolved with a DataTransfer object that provides the data.

```js async function getClipboardContents() { try { const clipboardItems = await navigator.clipboard.read(); for (const clipboardItem of clipboardItems) { for (const type of clipboardItem.types) { const blob = await clipboardItem.getType(type); console.log(URL.createObjectURL(blob)); } } } catch (err) { console.error(err.name, err.message); }} ` ` `Copy the code
  • readText()

Read text from the operating system; Returns a Promise which is resolved with a DOMString containing the clipboard’s text once it’s available.

```javascript document.body.addEventListener( 'click', async (e) => { const text = await navigator.clipboard.readText();  console.log(text); }) ` ` `Copy the code
  • write()

Writes arbitrary data to the operating system clipboard. This asynchronous operation signals that it’s finished by resolving the returned Promise.

```js try { const imgURL = 'https://dummyimage.com/300.png'; const data = await fetch(imgURL); const blob = await data.blob(); await navigator.clipboard.write([ new ClipboardItem({ [blob.type]: blob }) ]); console.log('Image copied.'); } catch (err) { console.error(err.name, err.message); } ` ` `Copy the code
  • writeText()

Writes text to the operating system clipboard. Returning a Promise which is resolved once the text is fully copied into the clipboard.

```js
document.body.addEventListener(
'click',
    async (e) => {
        await navigator.clipboard.writeText('Yo')
    }
)
```
Copy the code

!!!!!!!!! When writing images using write, there may be some minor problems, such as bloB format not conforming to our expectations, For example :Cannot read properties of undefined (reading ‘substring’), Failed to read or decode Blob for clipboard item type image/png. The source of this error is that the image is not formatted correctly or is parsed to bloB format. The forehead.. Parse the image to base64, then to blob, then to ClipboardItem and then to write copy. well In this way

    // Start with base64
    function imageBase64(img) {
        var canvas = document.createElement("canvas");
        canvas.width = img.width;
        canvas.height = img.height;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0.0, img.width, img.height);
        var dataURL = canvas.toDataURL("image/png");
        return dataURL;
    }
    // Note that special symbols in base64 cannot be recognized in atOB.
    function base64ToBlob(b64Data, contentType, sliceSize) {
        contentType = contentType || ' ';
        sliceSize = sliceSize || 512;
        var byteCharacters = window.atob(b64Data);
        // var byteCharacters = b64Data;
        // This atOB function decodes the Base64-encoded string into a new string containing characters for each byte of binary data.
        var byteArrays = [];
        for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
            var slice = byteCharacters.slice(offset, offset + sliceSize);
            var byteNumbers = new Array(slice.length);
            // Apply it to create an array of byte values by using the.charcodeat method for each character in the string.
            for (var i = 0; i < slice.length; i++) {
                byteNumbers[i] = slice.charCodeAt(i);
            }
            // Convert this array of byte values to an array of bytes of the actual type by passing it to the Uint8Array constructor.
            var byteArray = new Uint8Array(byteNumbers);
            byteArrays.push(byteArray);
        }
        console.log(byteArrays)
        // Create a BLOb: a URL containing this data and display it to the user.
        var blob = new Blob(byteArrays, { type: contentType });
        return blob;
    }

    // Copy last
    copy_img.onclick = async_ = > {let base64 = imageBase64(img)
        let blob = base64ToBlob(base64.replace('data:image/png; base64,'.' '), 'image/png') 
        clipboardObj.write([
            new ClipboardItem({
                'image/png': blob
            })
        ])
    }
    // Nice
   
Copy the code

Event.clipboardData

  • Event. The clipboardData. SetData (type, data) : to modify the clipboard data, you need to specify the data type.
  • Event. The clipboardData. GetData (type) : obtain the clipboard data, you need to specify the data type.
  • Event. The clipboardData. ClearData ([type]) : clear clipboard data, you can specify a data type. If no type is specified, all types of data are cleared.
  • Event. The clipboardData. Items: a similar array of objects, includes all clip-book items, but usually only one clip.

References:
  • “Clipboard API Tutorial” by Ruan Yifeng
  • DataTransferItem
  • new File(…)
  • clipboard.js
  • clipboard-polyfill
  • About Blob
  • Navigator.Clipboard
  • Uint8Array
  • MIME-copy
  • Be sure to check out ClipboardItem
  • Use of document.execcommand () in Javascript
  • Async Clipboard API Image Demo