JavaScript: implement copy paste cut function

js implements copy and paste function

Method 1: Copy, paste and cut in a native way (not recommended)

Use the built-in browser document.execCommand('copy')to implement copying, document.execCommand('paste')pasting, document.execCommand('cut')and cutting. The return values ​​of these three methods are Boolean types, which are used to determine whether these methods can be used in the current browser. True means that the method can be used, and false means that the method cannot be used. , currently, because of document.execCommand('paste')security issues, the document.execCommand('paste') operation has been banned for security reasons.
As a supplementary note, at present, the official method is not recommended to use the native method for copy and paste operations, and these methods may be deleted at any time

code show as below

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input type="text" id="input" value="123" />
    <button onclick="copy1()">复制(复制可编辑的标签中的内容)</button>
    <button onclick="copy2('这是复制的内容')">复制(将可编辑的标签隐藏)</button>
    <button onclick="cut()">剪切</button>
    <button onclick="paste()">粘贴</button>
    <input type="text" id="output">
    <script>
        // 复制可编辑标签中的value值得内容
      function copy1() {
      
      
        const inputEle = document.querySelector("#input");
        inputEle.select(); // 鼠标选择的内容
        document.execCommand("copy"); // 复制
      }

      /**
       * 如果想使用 execCommand 方法,又不想页面中出现可编辑区域,可以用下述办法取巧
       * @content 是要复制的内容
      */
      function copy2(content) {
      
      
        const dom = document.createElement("input");
        dom.value = content;
        document.body.appendChild(dom);
        dom.select();
        document.execCommand("copy");
        document.body.removeChild(dom);
      }

      // 剪切功能
      function cut(){
      
      
        console.log("cut");
        document.execCommand("cut")
      }

      // 粘贴功能:注意,只会在光标所在位置进行粘贴
      // function paste(){
      
      
      //   const pasteText = document.querySelector("#output")
      //   pasteText.focus() // 让光标聚焦到output标识的输入框上
      //   document.execCommand("paste"); // 截至目前该方法涉及到安全问题已失效
      // }
    </script>
  </body>
</html>

Using the execCommand command has the following defects:
(1) Not flexible enough . Only input, textarea or elements with contenteditable attributes can be operated
(2) execCommand is a synchronous operation , if copy/paste a large amount of data, the page will freeze.
(3) Some browsers will also pop up a prompt box to ask the user for permission . At this time, the page will lose response before the user makes a choice.
(4) It can only copy the selected content to the clipboard, but cannot arbitrarily write content to the clipboard

Method 2: The browser comes with clipboard API to realize copy and paste (recommended)

Introduction

ClipboardAPI is a next-generation clipboard operation method, which is more powerful and more reasonable than traditional document.execCommand()methods.

features

(1) All its operations are performed asynchronously , returning a promise object, which will not cause the page to freeze.
(2) It can put any content (such as pictures) into the clipboard .
(3) Security . Return the Clipboard object through navigator.clipboardthe property, and all operations are performed through this object. If navigator.clipboardthe property returns undefined, it means that the current browser does not support this API .

1) Sometimes users may put sensitive data (such as passwords) on the clipboard to allow scripts to read it arbitrarily, which will cause risks, and judging through the Clipboard object can avoid this risk well.
2) In addition, some browsers stipulate (such as Chrome) that only pages with the HTTPS protocol (or development environment, local environment) can use this API. Since Chrome 76, the Clipboard API will no longer be allowed in a non-encrypted environment (i.e. plain HTTP) using . This is because in the HTTP environment, network transmission is in clear text, which is easy to be eavesdropped and tampered with, thus introducing security risks.
3) Secondly, the copy permission is granted by the user by default, while the paste permission needs to be manually agreed by the user. For example, the script can be automatically completed when writing to the clipboard, but when reading the clipboard, the browser will pop up a dialog box to consult Whether the user agrees to read.

insert image description here
(4) One thing needs special attention. The script reads the clipboard of the current page (note that I am talking about the clipboard in the browser, not the clipboard that comes with the computer operating system), which brings a problem , if you want to paste the relevant code into the developer tool and run it directly, an error may be reported, because the current page at this time is the window of the developer tool, not the web page.
For example: If you paste the following code into the developer tool and run it, an error will be reported.

(async () => {
    
    
  const text = await navigator.clipboard.readText();
  console.log(text);
})();

Because when the code is running, the developer tool window is the current page, and there is no DOM interface on this page that ClipboardAPI depends on.

The solution is to put the relevant code into setTimeout() to delay running, and quickly click on the page window of the browser before calling the function to turn it into the current page.

setTimeout(async () => {
    
    
  const text = await navigator.clipboard.readText();
  console.log(text);
}, 2000);

clipboard object and related API

The clipboard object provides four methods for reading and writing the clipboard. They are all asynchronous methods and return promise objects.

Clipboard.readText()

Clipboard.readText()The method is used to copy the text data in the clipboard ( that is, the paste function ).

This method returns a Promise object, so I provide two usage forms here

  • Form 1: implementation of promise callback
// 普通方法
function paste() {
    
    
  navigator.clipboard // 创建clipboard对象
    .readText() // 调用readText()方法
    .then((clipText) => {
    
    
      // 成功回调 
      console.log(clipText); // clipText是从剪贴板读取到的内容(也就是要粘贴的内容)
    })
    .catch((err) => console.log("粘贴失败!",err)); // 失败回调
}
  • Form 2: async function
// async 函数
async function paste(){
    
    
  try{
    
    
    // 创建clipboard对象并调用readText()方法读取剪贴板上的内容进行返回
    const text = await navigator.clipboard.readText() 
    console.log("要粘贴的内容为:",text); // 具体粘贴到哪你自己决定
  }catch(err){
    
    
    // catch捕获处理报错
    console.log("粘贴失败!",err);
  }
}

Note that if the user is not allowed to use this API for pasting operations, the script will report an error, then we can use the catch() method to process the error report.

Clipboard.read()

Clipboard.read()The method is used to copy the data in the clipboard ( that is, the paste function ), which can be text data or binary data (such as pictures). This method requires explicit permission from the user.

This method returns a Promise object . Once the state of the object becomes resolved, you can get an array , each array member is an instance of the ClipboardItem object .

Below we briefly introduce several object properties and methods used in the code
Traversing the array objects obtained through Clipboard.read()the successful callback of the method, and thus obtaining objects one by one ClipboardItem, representing a separate clipping item , each clipping item has ClipboardItem.types属性and ClipboardItem.getType()方法.

1. ClipboardItem.types属性Return an array whose members are the available MIME types of the clipping item . For example, a clipping item can be pasted in HTML format or plain text format, so it has two MIME types (text/html and text/plain).

2. ClipboardItem.getType(type)方法It is used to read the data of the clipped item and return a Promise object . This method accepts the MIME type of the scrap item as a parameter and returns data of this type. This parameter is required, otherwise an error will be reported.

The code example is as follows :

  • Form 1: promise callback implementation
// 粘贴任何类型的数据
function paste() {
    
    
  navigator.clipboard
    .read() // 调用read()方法从剪贴板读取数据进行粘贴操作
    .then((clipboardItems) => {
    
    
      console.log(clipboardItems,"clipboardItems =========");
      // clipboardItems是一个数组
      for (const clipboardItem of clipboardItems) {
    
    
        console.log(clipboardItem, "clipboardItem ========="); // clipboardItem是一个实例对象
        for (const type of clipboardItem.types) {
    
     // clipboardItem.types返回一个数组,存储的是每一段剪贴板的mine数据类型
          clipboardItem
            .getType(type) // 读取接收到的mine类型作为参数,返回该类型的数据
            .then((res) => console.log(res))
            .catch((err) => console.log(err));
        }
      }
    })
    .catch((err) => {
    
    
      console.log(err.name,err.message)
    });
}
  • Form 2: async function + await implementation
async function paste(){
    
    
 try {
    
    
  const clipboardItems = await navigator.clipboard.read()
  for(const clipboardItem of clipboardItems){
    
    
    for(const type of clipboardItem.types){
    
    
      const result = await clipboardItem.getType(type)
      console.log(result);
    }
  }
 } catch (err) {
    
    
  console.log(err.name,err.message);
 }
}

Obviously using the second way to implement the code is simpler.

Clipboard.writeText()

Clipboard.writeText()The method is used to write the text content to the clipboard (that is, the copy function) , and this method also returns a Promise object.
The code example is as follows:
The function of the following code is: by clicking the page, copy the data to the clipboard.

document.body.addEventListener('click',async (e) => {
    
    
    await navigator.clipboard.writeText('Yo') // 参数是要写入的文本
  }
)

Of course you can trigger the copy operation by clicking a button, a tab, etc.

Clipboard.write()

Clipboard.write()The method is used to write arbitrary data to the clipboard, which can be text data or binary data .

This method accepts a ClipboardItem instance as a parameter, representing the data written to the clipboard.

  • Code example
    Copy an image type
async function copy1() {
    
    
  try {
    
    
  	// 图片地址
    const imgURL = "https://dummyimage.com/300.png"; 
    // 获取图片
    const data = await fetch(imgURL); 
    // 将图片转为blob类型
    const blob = await data.blob(); 
    // 将数据写入(复制)到剪贴板
    await navigator.clipboard.write([ 
      // 创建Clipboard实例对象,对象的键名是数据的 MIME 类型,键值就是数据本身
      new ClipboardItem({
    
     
        [blob.type]: blob,
      }),
    ]);
    console.log("Image copied.");
  } catch (err) {
    
    
    console.error(err.name, err.message);
  }
}

ClipboardItem()It is a constructor provided natively by the browser to generate a ClipboardItem instance . It receives an object as a parameter. The key name of the object is the MIME type of the data, and the key value is the data itself.

Note that the Chrome browser currently only supports writing images in PNG format.

In addition, the write() method can also write the values ​​of multiple formats of a clipping item to the clipboard, one is text data, and the other is binary data, which can be used for pasting in different occasions.

function copy() {
    
    
  const image = await fetch('kitten.png'); // 获取图片类型的数据
  const text = new Blob(['Cute sleeping kitten'], {
    
    type: 'text/plain'}); // 获取文字类型的数据并转为blob实例对象
  const item = new ClipboardItem({
    
    
    'text/plain': text,
    'image/png': image
  });
  await navigator.clipboard.write([item]);
}

That is, the clipping items in the clipboard have two types of data. When you want a picture, I will paste the data in the clipboard in the form of a picture for you to use. If you want to use text, I will paste the text for you.

Method 3: clipboard.js plug-in library to realize copy and cut (recommended)

It is a lightweight plug-in that can copy or cut text to the clipboard without Flash (note that there is no paste)

Official website: clipboard.js

Install import

# node安装
npm install clipboard --save
<!-- html文件中可以使用CDN引入 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/clipboard.min.js"></script>
// js文件中可以通过ES6语法的import或者commonjs进行引入或者使用其他引入方式

This library depends on both Selectionand execCommandapi. All browsers support the first, while the following browsers support the second.chrome42+,Edge12+,Firefox41+,IE9+,Opera2+,Safari0+

basic use

There are two steps in total. The first step is to use the specified attribute in the specified html tag to bind. The second step is to create a Clipboard instance object and call the related event event. The operation is as follows:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 引入clipboard.js -->
    <script src="https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.11/clipboard.js"></script>
    <title>Document</title>
  </head>
  <body>
    <div>
      <!-- Target -->
      <input type="text" id="foo" value="要复制的内容" />

      <!-- Trigger -->
      <button class="btn" data-clipboard-target="#foo" data-clipboard-action="copy">复制</button>
      <!-- 
        有两个属性值:
        data-clipboard-target:取值是一个选择器对象,用来绑定要复制的标签,复制其内容
        data-clipboard-action:用来决定是复制还是粘贴,有两个取值:copy和cut
       -->
    </div>
    <script>
        // 创建一个实例对象,参数是一个选择器,绑定的是触发复制/剪切事件的标签
      var clipboard = new ClipboardJS(".btn");

      // 成功回调
      clipboard.on("success", function (e) {
      
      
        console.info("Action:", e.action); // 操作:copy或者cut
        console.info("Text:", e.text); // 复制/剪切的内容
        console.info("Trigger:", e.trigger); // 触发对象

        e.clearSelection();
      });

      // 失败回调
      clipboard.on("error", function (e) {
      
      
        console.error("Action:", e.action); // 操作:copy或者cut
        console.error("Trigger:", e.trigger); // 触发对象
      });
    </script>
  </body>
</html>

You can use ClipboardJS.isSupported()the method to determine whether the browser can use this library

advanced use

new ClipboardJS("选择器",{...})method, the second parameter is an object, you can pass a callback function into it, as follows

(1) Return the node target to be bound through the function

new ClipboardJS('.btn', {
    
    
    target: function(trigger) {
    
    
        return trigger.nextElementSibling;
    }
});

(2) Set the text content to be copied through the function text

new ClipboardJS('.btn', {
    
    
    text: function(trigger) {
    
    
        return trigger.getAttribute('aria-label');
    }
});

(3) When used in Bootstrap Modals or with any other library that changes focus, set the focused element to the container value

new ClipboardJS('.btn', {
    
    
    container: document.getElementById('modal')
});

(4) Destroy the copied and pasted instance object (if used in a single-page application, to manage the DOM life cycle more precisely, you can use the following method to clear the created event object)

var clipboard = new ClipboardJS('.btn');
clipboard.destroy();

It can be seen that the basic functions of this plug-in library are copy and cut, and no paste operation is involved. Therefore, it is usually used in conjunction with the browser's own clipboard API to implement copy and paste operations.

Supplement: copy and paste operation interception

Mainly used copy and paste events

copy

For example: when copying, convert the text put into the clipboard by the user to uppercase


const source = document.querySelector('.source');

source.addEventListener('copy', (event) => {
    
    
  const selection = document.getSelection();
  event.clipboardData.setData('text/plain', selection.toString().toUpperCase());
  event.preventDefault();
});

In the above example, the clipboardData property of the event object contains the clipboard data. It is an object with the following properties and methods.
Event.clipboardData.setData(type, data): To modify the clipboard data, the data type needs to be specified.
Event.clipboardData.getData(type): To get the clipboard data, the data type needs to be specified
Event.clipboardData.clearData([type]); to clear the clipboard data, the data type can be specified. If no type is specified, all types of data will be cleared.
Event.clipboardData.items: An array-like object containing all clipping items, but usually only one clipping item.

For example: intercept the user's copy operation and put the specified content into the clipboard

onst clipboardItems = [];

document.addEventListener('copy', async (e) => {
    
    
  e.preventDefault(); // 先使用该方法组织默认事件,然后由脚本接管复制操作
  try {
    
    
    let clipboardItems = [];
    for (const item of e.clipboardData.items) {
    
    
      if (!item.type.startsWith('image/')) {
    
    
        continue;
      }
      clipboardItems.push(
        new ClipboardItem({
    
    
          [item.type]: item,
        })
      );
      await navigator.clipboard.write(clipboardItems);
      console.log('Image copied.');
    }
  } catch (err) {
    
    
    console.error(err.name, err.message);
  }
});

paste

When the user uses the clipboard data to perform a paste operation, the paste event will be triggered

document.addEventListener('paste', async (e) => {
    
    
  e.preventDefault();
  const text = await navigator.clipboard.readText();
  console.log('Pasted text: ', text);
});

Guess you like

Origin blog.csdn.net/lalala_dxf/article/details/128374242