1

I'm trying to copy all the links of a web page to clipboard. I'm trying to join all the anchor tags into a string, putting that string into a input field and then copying it by document.execCommand("copy") but somehow document.execCommand("copy") only works in browser developer tools. I want it to work in a script loaded in web page. Kindly Help me, Thanks in advance.

var
body = document.querySelector("body"),
input = document.createElement("textarea"),
a = document.getElementsByTagName("a"),
list = [],
anchor = document.createElement("a");
for (let i = 0; i < a.length; i++){
    list.push(a[i]);
};
list = list.join("\r\n");
input.value = list;
input.setAttribute("readonly", "");
input.style = "position: absolute; left: -9999px;";
body.appendChild(input);
input.select();
document.execCommand('copy');
body.removeChild(input);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>test</title>
    </head>
<body>
    <a href="http://ali.com">sample link</a>
    <script src="script.js"></script>
</body>
</html>
Ali Raza
  • 21
  • 5

2 Answers2

2

Something to be aware of is that execCommand('copy') only reliably works in the context of a user invoked action. In other words, if you want to copy data to the clipboard, this should be done as a side effect of a user say, clicking a button.

You could for instance, revise your script as follows - bringing the call to execCommand() inside of a click event handler, to achieve the required copy to clipboard behaviour:

var
body = document.querySelector("body"),
input = document.createElement("textarea"),
a = document.getElementsByTagName("a"),
anchor = document.createElement("a");

input.setAttribute("readonly", "");

// Added a copy button for the purpose of this demonstration
var copyButton = document.createElement("button")
copyButton.innerText = 'Copy'

// The event in which the copy to clip board will occour
copyButton.addEventListener('click', () => {

    // This code is in the context of a user 'click' action 
    var list = []
    for (let i = 0; i < a.length; i++){
        list.push(a[i]);
    };
    list = list.join("\r\n");

    body.appendChild(input);
    input.value = list;
    input.focus();
    input.select();

    // exec copy command is now being called in the context of 
    // a user invoked interaction (ie click), so it should work
    // as expected
    if(document.execCommand('copy')) {
        console.log('copy success')
    }
    else {
        console.log('copy failed')
    }
    body.removeChild(input);
})

body.appendChild(copyButton);
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
  • What if I want to click the button automatically? – Ali Raza Jul 26 '18 at 02:41
  • I don't believe that will work - from past experience I have found reliable clip board interaction from js requires invocation to genuinely be from the user (ie not emulating user interaction ) – Dacre Denny Jul 26 '18 at 02:47
  • Basically I'm trying to create a chrome extension, so should I add two button saying copy to clipboard and download? What do you think will this script work in chrome extension? – Ali Raza Jul 26 '18 at 03:15
  • Yes I would recommend you add a button for the user to click, in order to copy your link data to the clipboard. That would be the most reliable way of achieving this - it should work in the context of your chrome extension – Dacre Denny Jul 26 '18 at 03:22
  • 1
    @AliRaza If you are writing a chrome extension, why didn't you say so in the question? That is an **important** information as you have access to far more powerful APIs than untrusted web APIs. For instance, to write to the clipboard, you have a permission field called `clipboardRead`. With this permission set, you won't face the user-gesture restriction. An other way from an extension would be to send the data to your background script and from there execute the copy to clipboard as [shown here](https://stackoverflow.com/a/25627634/3702797). – Kaiido Jul 26 '18 at 03:43
  • @Kaiido I'm totally a beginner. Don't know anything much about chrome extensions so that's why I didn't mention it. Firstly I just wanted this script to be working without extension. You are always welcome to tell me how can I make the desired extension? or you can give me any link to look at. – Ali Raza Jul 26 '18 at 04:19
  • @AliRaza if the answer has addressed the original question consider marking it as accepted, and then perhaps ask a new question that is more specific to your problem – Dacre Denny Jul 26 '18 at 04:30
0

You can execute your copy function with Javascript when the user clicks on the window. Copying to clipboard needs to be triggered by an action of the user i.e a click.

<a href="http://ali.com">sample link</a>
<script>
var copied = false
window.onclick = function(e){
  if(!copied){
   copy();
   copied = true;
   e.target.focus();//focus back on target of click to prevent constant blurring of first click
   }
}
function copy(){
  var
body = document.body,
input = document.createElement("textarea"),
a = document.getElementsByTagName("a"),
list = [],
anchor = document.createElement("a");
for (let i = 0; i < a.length; i++){
   list.push(a[i]);
};
list = list.join("\r\n");
input.value = list;
input.setAttribute("readonly", "true");
input.style = "position: absolute; left: -9999px;";
document.body.appendChild(input);
input.select();
document.execCommand('copy');
input.remove();
}
</script>
<button id="hidden" onClick="copy()" style="display: none;">
</button>
<br/>
<textarea placeholder="Paste the copied text"></textarea>
Unmitigated
  • 76,500
  • 11
  • 62
  • 80