使用execCommand(Javascript)将隐藏文本复制到剪贴板

61

我正在尝试在不使用Flash的情况下复制到剪贴板,如果浏览器不兼容JavaScript方法,我计划通过ZeroClipboard来回退到Flash。

我为按钮添加了一个onClick监听器,代码如下:

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

并且有一个如下所示的输入字段:

<input type="text" name="Element To Be Copied" id="inputContainingTextToBeCopied" value="foo"/>

目前这个功能可以正常工作,但是设计要求包含被复制文本的字段不可见。我尝试过设置type="hidden"style="display: none",但都没有成功。两者都导致按钮选择整个页面并将所有内容复制到用户的剪贴板中。
相对自信地说,原因不是基于浏览器的,但以防万一,我正在测试使用Chrome(版本43.0.2357.134(64位))在Mac OS X 10.10.4上。

是否有一种方式可以在隐藏它时保持< input>可见的功能?或者,如果没有备选路线可以采取?


我知道有类似的问题,但没有一个能解决我的问题,要么太老,不实际使用Javascript,或者不符合特定的情况。 这里有一个好答案,适用于任何遇到类似但不那么具体问题的人。


9
你尝试过 opacity: 0 吗? - DavidDomain
@DavidDomain 我刚尝试了一下,它确实能够工作,这太棒了,谢谢你!但不幸的是,它仍然会留下透明的 div 并且改变了设计,如果没有更好的解决方案,我将采用这个方法并将输入框设置为 1px x 1px。如果您想回答,如果没有更好的解决方案,我将非常乐意接受。再次感谢! - Aaron Critchley
2
如果您使用jQuery来show()输入内容,然后调用copy,然后立即再次hide()它会怎样? - pokkanome
1
@pokkanome 我走了非常类似的路线,我很快就会发布答案,谢谢! - Aaron Critchley
我使用 style="position: absolute; top: -999px; left: -999px"。 - Adrian Hum
14个回答

107

这是我不使用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>


1
它对我有用,谢谢你,丹。我搜索了两个多小时的许多代码,但没有一个能为我工作。但是你的代码很棒,小而有效。再次感谢。 - Brij
很棒的解决方案,对我也起作用了,这个需要置顶。 - samir
3
如果你需要保留换行符,一种增强的方法是创建一个“textarea”而不是一个“input”,在我的情况下,值来自于一个隐藏的<pre>标签(因此换行符被保留)。 - jpw
1
哦,我的天啊,非常感谢。这个完美地集成到了我的代码中,而且非常紧凑! - thefailagent
在桌面端运行得非常好,但不幸的是在移动设备上无法正常工作。 - Tarquin
显示剩余5条评论

60

2019年 - 仍在寻找没有屏幕外内容的答案。

我所做的是首先将输入文本字段更改为type =“text”,复制文本,然后将其更改回type =“hidden”。 这很有效。

<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>

1
这绝对是最简单和最好的解决方案。 - therealrootuser
这是最简单和最好的解决方案。 - Bindas Samuel
很棒的解决方案,伙计。 - Santosh Singh
我们获得了胜利者。谢谢。 - Toucouleur
对我来说可以工作。然而最好的方法是移除元素,而不是隐藏它。否则,这是一个非常优秀的解决方案。 - Robert

41

--更新--

Document.execCommand()

[1] 在 Firefox 41 之前,需要在 user.js 首选项文件中启用剪贴板功能。有关更多信息,请参见Mozilla 首选项的简要指南。如果未支持或启用该命令,则 execCommand 会引发异常而不是返回 false。从 Firefox 41 开始,在能够弹出窗口的任何事件处理程序中默认启用剪贴板功能(半信任脚本)。

自从Firefox 41版本以来,Document.execCommand() 可以正常工作,因此不再需要使用备用方案。


由于浏览器在剪贴板访问方面的行为似乎存在差异,我花了一些时间才明白它。

这与您的解决方案非常相似,但不同之处在于创建一个临时元素并将其填充到输入值中。这样,我们可以保持输入的display属性设置为none。

对于IE,还有一种解决方法是使用window.clipboardData

Firefox根本不允许我访问剪贴板。所以我不得不添加一个提示,让用户手动复制输入值。确实,prompt很丑陋,但您可以像窗口一样使用模态框,这将达到同样的效果。

由于这似乎是一个棘手的问题,因此我在Win7(64位)上测试了:

Chrome - Version 43.0.2357.134 m

IE - Version 11.0.9600.17914

而Firefox无关紧要,因为它根本不允许我访问它。

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>


2
这很巨大,只需将元素移出屏幕并使用execCommand函数进行复制即可...请查看我在底部的答案。 - Mister SirCode

20

在 @DavidDomain 的帮助下,我找到了一个有点hacky但是可行的方法。

首先,我将输入框移出了屏幕并修改了一些属性,得到了以下代码:

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

在进行以下js修改后,添加了display:none:

之后,@Pokkanome的评论让我修改了onClick函数,如下所示:

$(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';
}

我不确定是否可以使用此方法从隐藏的 div 中复制,从浏览器安全性来看,这是有道理的,因为直接访问剪贴板会存在一定的风险。但所采取的方法具有相同的预期结果。


9
我有一个更新的解决方案:
使用这个脚本,你可以复制你的数据。与过去提供的脚本相比,它要小得多。
脚本使用一个输入框,该输入框可以通过CSS或内联样式在屏幕侧面隐藏,然后快速选择并运行复制命令。

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>

对于奖金,我制作了一个小的剪贴板API,它可以动态选择元素并使用Contenteditable Divs和动态变量从中检索文本: https://codepen.io/SkylerSpark/pen/OJJqxWX

此外,请查看Ciprians下面的答案,了解如何使用新的权限API直接将文本发送到剪贴板,并获得用户允许的权限,它在最新的浏览器中可用(我知道它实际上现在在chrome中可以工作,但我还没有测试其他浏览器):https://dev59.com/2lwZ5IYBdhLWcg3wVO5U#58099014


和我的想法相同,只需使用CSS在屏幕上隐藏输入元素 :) - aldrien.h
1
@aldrien.h 你应该知道,如果你使用 display: hidden 或类似的属性隐藏一个元素,那么这个元素将无法被选中。希望你已经了解这一点。所以,除非你想通过将元素的每个部分都设置为透明颜色来添加更多的 CSS 样式,否则你的想法是行不通的。 - Mister SirCode
我的意思是,使用CSS在屏幕上隐藏,就像上面的样式一样,绝对定位并使用负值到顶部和左侧,而不是display:none,execCommand无法在隐藏元素上工作。 :) - aldrien.h
1
直接复制@Dan Stevens的答案,只需将样式放入元素中而不是脚本中。 - VeenarM
1
@VeenarM 这是你需要学习的事情,就在stackoverflow上,如果信息更有价值,那么“相似”的代码并不重要...这里已经有数十亿份我添加的代码副本了,但说实话,我并不是一个追求声望的抄袭者,我是自己写的 :P此外,我的脚本比丹斯的要短得多,这不是为了竞争,而是事实。 - Mister SirCode
我还额外添加了一个基本的剪贴板API,VeenarM先生开心吗? :D在这里,尽量对人更加尊重。Stackoverflow不是关于愤怒和不尊重的,它是关于学习的 :) - Mister SirCode

7
你可以使用opacity:0.00000000000001隐藏输入框,然后使用JavaScript将隐藏的文本复制到剪贴板。

function myFunction() {
  var copyText = document.getElementById("myInput");
  copyText.select();
  copyText.setSelectionRange(0, 99999)
  document.execCommand("copy");
  alert("Text copied successfully");
}
<input type="text" value="===your text here===" id="myInput" style="opacity:0.00000000000001">
<button onclick="myFunction()">Copy</button>


Should you also make it have a width of 0 so it does not take up space? - Someone_who_likes_SE

7
一个在所有浏览器中都有效的替代方法是,不是隐藏元素,而是将其绝对定位并将其不透明度设置为0。
#copy-me {
    position: absolute;
    opacity: 0;
}

1
谢谢。对我来说更有用的是,使用absolute定位和-1000pxtopbottom解决方案为我创建了滚动条。 - SirSaleh

6
您可以使用window.navigator来实现此功能。
navigator.clipboard.writeText('this will be copied to the clipboard');

1
这是最好的和最现代化的解决方案。 - whatevermike
兼容性:https://developer.mozilla.org/zh-CN/docs/Web/API/Clipboard_API#browser_compatibility - C.Evenhuis

2

对我来说有效的方法是:

最初的回答
<div>
  <a class="copyBtn">Copy</a>
  <input class="d-none" value="teste">
</div>

并且:

$('.copyBtn').on('click', function(e) {
  e.preventDefault();
  var input = $(this).parent().find(".dirVal");
  $(input).removeClass("d-none");
  input.select();

  document.execCommand('copy');
  $(input).addClass("d-none");
  callNotify("Parabéns!", "Caminho copiado para área de transferência!", "success");
});

1

就是这样!

.blind {
    overflow: hidden;
    position: absolute;
    clip: rect(0 0 0 0);
    width: 1px;
    height: 1px;
    margin: -1px;
}

<textarea id="copy" class="blind">
your copy text here!
</textarea>

copyClipboard(document.getElementById('copy'));

function copyClipboard(el) {
  el.select();
  window.document.execCommand('copy');
}

https://gist.github.com/seunggabi/7ae53c100d647cb19c48047cff9b7019


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接