Using execCommand (Javascript) to copy hidden text to clipboard

点点圈 提交于 2019-11-27 07:47:41

--Update--

Document.execCommand()

[1] Before Firefox 41, clipboard capability needed to be enabled in the user.js preference file. See A brief guide to Mozilla preferences for more information. If the command wasn't supported or enabled, execCommand was raising an exception instead of returning false.In Firefox 41 and later, clipboard capability are enabled by default in any event handler that is able to pop-up a window (semi-trusted scripts).

Since Firefox version 41 Document.execCommand() now works. So no need to use a fallback anymore.


Since browsers seem to behave differently when it comes to the clipboard access, it took me a while to get my head around it.

It's pretty similar to your solution, but the difference is to create a temporary element and fill it with the input value. That way we can keep the input's display property set to none.

There is also a workaround for IE which uses window.clipboardData.

Firefox would not let me access the clipboard at all. So i had to add a prompt to let users manually copy the input value. Sure a prompt is ugly, but you could just use a modal like window, which would do the same.

Since this seems to be a knotty thing, i am on Win7 (64 bit) and tested in

Chrome - Version 43.0.2357.134 m

IE - Version 11.0.9600.17914

and Firefox is irrelevant, because it would not let me access it anyway.

var copyBtn   = $("#copy-btn"),
    input     = $("#copy-me");

function copyToClipboardFF(text) {
  window.prompt ("Copy to clipboard: Ctrl C, Enter", text);
}

function copyToClipboard() {
  var success   = true,
      range     = document.createRange(),
      selection;

  // For IE.
  if (window.clipboardData) {
    window.clipboardData.setData("Text", input.val());        
  } else {
    // Create a temporary element off screen.
    var tmpElem = $('<div>');
    tmpElem.css({
      position: "absolute",
      left:     "-1000px",
      top:      "-1000px",
    });
    // Add the input value to the temp element.
    tmpElem.text(input.val());
    $("body").append(tmpElem);
    // Select temp element.
    range.selectNodeContents(tmpElem.get(0));
    selection = window.getSelection ();
    selection.removeAllRanges ();
    selection.addRange (range);
    // Lets copy.
    try { 
      success = document.execCommand ("copy", false, null);
    }
    catch (e) {
      copyToClipboardFF(input.val());
    }
    if (success) {
      alert ("The text is on the clipboard, try to paste it!");
      // remove temp element.
      tmpElem.remove();
    }
  }
}

copyBtn.on('click', copyToClipboard);
#copy-me {
    display:none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="Element To Be Copied" id="copy-me" value="foo loves bar"/>
<button id="copy-btn">Copy</button><br/><br/>
<textarea placeholder="paste here"></textarea>

Here's my solution that doesn't use jQuery:

function setClipboard(value) {
    var tempInput = document.createElement("input");
    tempInput.style = "position: absolute; left: -1000px; top: -1000px";
    tempInput.value = value;
    document.body.appendChild(tempInput);
    tempInput.select();
    document.execCommand("copy");
    document.body.removeChild(tempInput);
}
<!DOCTYPE html>
<html>
<head>
<title>Set Clipboard</title>
</head>
<body>
    <button onclick="setClipboard('foo loves bar')">Set Clipboard</button>
</body>
</html>

Thanks to the help of @DavidDomain, I found a somewhat hacky, but functional approach.

Firstly, I moved the input way off screen and modified some properties, resulting in this:

<input type="text" name="Element To Be Copied" id="inputContainingTextToBeCopied" value="foo" style="display:none; position: relative; left: -10000px;"/>

display:none was added after the following modifications to the js

After that, the comment from @Pokkanome let me into modifying the onClick function like so:

$(buttonWhereActionWillBeTriggered).click(function(){ 
    var copyDiv = document.getElementById(inputContainingTextToBeCopied);
    copyDiv.style.display = 'block';
    copyDiv.focus();
    document.execCommand('SelectAll');
    document.execCommand("Copy", false, null);
    copyDiv.style.display = 'none';
}

I'm unsure if it's possible to copy from a hidden div using this method, which would make sense in terms of browser security as giving unquestioned access to the clipboard is going to be somewhat risky. The approach taken had the same intended result though.

This question is very old, so I have a NEW less outdated Answer.

Using this script can copy your data. its much smaller than the past ones

All it does is hide your Input WAYYY off the side of the screen, hence making it hidden. While STILL keeping the ability to copy it (Unlike when you use Display: None;)

function copyFunc() {
  var copyText = document.getElementById("copyInp");
  copyText.select();
  document.execCommand("copy"); //this function copies the text of the input with ID "copyInp"
}
<input type="text" value="StuffYaWantCopied" id="copyInp" style="position:absolute;left:-1000px;top:-1000px;">
  <a onclick="copyFunc()" style="cursor:cell;">
     Click here to Copy!
  </a>

2019 - was still looking for an answer without offscreen stuff.

What I did is first change the input text field to type="text", copy the text and then change it back to type="hidden". That works well.

<input id="dummy" name="dummy" type="hidden">

<script>
var copyText = document.getElementById("dummy");
copyText.type = 'text';
copyText.select();
document.execCommand("copy");
copyText.type = 'hidden';
</script>

Here's an easy, though hacky answer to this that seems to work for me. Rather than using display: none; use this:

height: 0px;
width: 0px;
overflow: hidden;
position: absolute;

This allows for selection while still hiding the textarea and not affecting the design.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!