preface

When copying articles from some websites, it is common to find that the copied content comes with a “little tail” attached with copyright information.

Such as:

Source: author: CoderLeiShuo links: https://juejin.cn/user/4160207732875736 the nuggets copyright owned by the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.Copy the code

In this article, try to achieve this effect.

The general principle is that when users copy, get the content selected by the user to copy, and then add the copyright information.

window.getSelection()methods

How do you get what the user copied? We can do this with the window.getSelection() method, which returns a **Selection object ** representing the range of text or the current position of the cursor selected by the user. Of course, you can also use Document.getSelection, which is equivalent.

For example, place the cursor in the search box shown above and type window.getSelection() on the console. The returned Selection object looks like the following:

👉 For details about Selection, click here

What we end up getting is plain text for the selected region, not a Seletion object. So you need to convert the Selection object to a String, either by concatenating an empty String or using the string.toString () method.

let selObj = window.getSelection();
let selectedTxt = selObj + ' ';
/ / or
let selectedTxt = selObj.toString();
Copy the code

Let’s try it on the web:

As shown in the image above, we select a portion of the web page, enter the relevant code in the console, and see if we can get the plain text of the selection correctly

As you can see, we have retrieved the selected content.

Window.getselection () is not supported on IE8 and below

element.oncopyThe event

In the previous step, we successfully retrieved the text content of the selection. Now we are ready to implement the effect of adding information to the copied content when we copy it.

So we need to bind the function to the element. onCopy event.

The onCopy property is used to get or set the event handler for the current element’s copy event. Note that the onCopy property can be set for other elements, so don’t assume it can only be set for window or document just because we usually set it for them.

Let’s start with an example on MDN:

<html>
<head>
<title>Oncopy example demonstration</title>

<script>
  function log(txt)
  {
    // Create a text node with the TXT value as a child node to append to the textarea element
    document.getElementById("log").appendChild(document.createTextNode(txt + "\n"));
  }
</script>
</head>

<body>
<div oncopy="Log (' Replication blocked! '); return false;">Try to copy this sentence!</div>

<h3>Log</h3>
<textarea rows="15" cols="80" id="log" readonly="true"></textarea>
</body>
</html>
Copy the code

When you try to copy “Try to copy this sentence! In the onCopy () function, a text node is created from the value of the TXT passed in, which is appended to the textarea element as a child node. Therefore, the textarea will display the words’ copying blocked ‘!

And since return false; Statement cancels the default behavior of copying, so no copied content is returned.

First implementation

So we can take our first stab at this. Get the selected content with the window.selection() method, and bind a custom event to onCopy that concatenates the selected content with our “little tail” information.

The code is as follows:

<! -- first implementation -->
<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>

<body>
    <p>In JavaScript, when an object is passed to a function that expects a string as an argument (such as window.alert or document.write), the object's toString() method is called and the return value is passed to the function.</p>
    <p>The implementation is simple: after the default replication is disabled, the main thing is to add information to the copied content and then write the information to the clipboard according to the setData() method of clipboardData</p>
    <script>
        document.oncopy = function () {
            let selObj = window.getSelection();
            // IE8 and earlier did not support window.getSelection
            if (typeof selObj == 'undefined') return;
            let selectedText = selObj + ' ';

            // If the selected text contains less than 30 characters, no operation is performed
            if (selectedText.length < 30) return;

            let copytext = selectedText + 'CoderLeiShuo';
            console.log(copytext);
        }
    </script>
</body>

</html>
Copy the code

As you can see, by binding a custom event to onCopy, after the event code executes, it outputs the selection text and the concatenated string of ‘CoderLeiShuo’.

So, if we send copytext back, can we do that?

So, return copytext; Statements. Take a look at the results:

Unfortunately, the pasted content still contains the selected text, which is not the concatenated string we need

There are two reasons:

  1. tooncopyIn the bound function, we returncontextIs of no use and should be returnedfalseRepresents the default behavior for canceling replication. Otherwise, no matter what you splice, the clipboard will still only have what you copied.
  2. However, when you cancel the default behavior of the copy event, the clipboard cannot get the copied content, which requires us to manually write the concatenated string to the clipboard.

clipboardDataobject

Canceling the default copy behavior is easy, so let’s take a closer look at the clipboard.

ClipboardData object: Used to access and modify data in the clipboard

In Internet Explorer, this object is a property of the Window object. In Chrome, Safari, and Firefox, this object is a property of the corresponding Event object. So when we use it, we need to do the following compatibility

document.oncopy = e= > {
    let clipboardData = e.clipboardData || window.clipboardData;
    // Get clipboardData object + do something
}
Copy the code

Object methods

This object has three methods: getData(), setData(), and clearData()

getData()methods

The getData() method takes a format argument, which is the format of the data to fetch. The data types are text/plain and text/uri-list.

setData()methods

The setData() method takes two arguments, the format argument, which represents the data type. The second parameter represents the content of the text to be placed on the clipboard. Here we can specify the format argument as text/plain, which stands for plain text.

clearData()methods

The clearData() method takes an optional argument, format, representing the data type to be deleted. If this parameter is an empty string or not provided, all types of data are deleted.

Second implementation

With that in mind, let’s try a second time. The specific code is as follows:

<! -- second implementation -->
<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <style>
        p {
            color: red;
            font-size: 20px;
        }
    </style>
</head>

<body>
    <p>In JavaScript, when an object is passed to a function that expects a string as an argument (such as window.alert or document.write), the object's toString() method is called and the return value is passed to the function.</p>
    <p>The implementation is simple: after the default replication is disabled, the main thing is to add information to the copied content and then write the information to the clipboard according to the setData() method of clipboardData</p>
    <script>
        document.oncopy = function (e) {
            // Get the selection object
            let selObj = window.getSelection();
            // IE8 and earlier did not support window.getSelection
            if (typeof selObj == 'undefined') return false;

            // Get the clipboardData object
            In Chrome\Safari\Firefox, this object is a property of the Event object
            // In Internet Explorer, it is an attribute of the Window object
            let clipboardData = e.clipboardData || window.clipboardData;

            // Get the selection text content
            let selectedText = selObj + ' ';

            let copytext;
            // If the selected text contains less than 30 characters, no operation is performed
            if (selectedText.length < 30) {
                copytext = selectedText;

            } else {
                copytext = selectedText +
                    '\n\n\n' +
                    '作者:CoderLeiShuo\n' +
                    'Link:' + location.href + '\n' +
                    'Source: Nuggets \n' +
                    The copyright belongs to the author. Commercial reprint please contact the author to obtain authorization, non-commercial reprint please indicate the source. ';
            }

            // setData(format,text) sets the contents of the clipboard
            clipboardData.setData('text/plain', copytext);
            
            // Cancel the default replication event
            return false;
            / / e.p reventDefault ()
            
        }
    </script>
</body>

</html>
Copy the code

Take a look at the results:

subsequent

At this point, we have implemented the basic functionality, but the current code is not compatible with lower versions of Internet Explorer and does not implement formatting copying. It will continue to be improved. My ability is limited, if the content of the article is wrong, please correct! Thank you very much!

Refer to the article

In the writing process of this article, I refer to the content of the following articles. It is on the shoulders of the predecessors that this article was created. Thank you!

Copy and paste in JavaScript

MDN element.oncopy

Method of automatically adding copyright information to copy web content (compatible with all versions of IE)