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

IT技术 javascript jquery html clipboard
2021-01-17 20:27:34

我正在尝试在不使用 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"但都没有成功。两者都会导致按钮选择整个页面并将整个内容复制到用户的剪贴板。
我相对相信原因不是基于浏览器,但为了以防万一,我正在 Mac OS X 10.10.4 上的 Chrome(版本 43.0.2357.134(64 位))上进行测试。

有没有办法可以在隐藏 <input> 的同时保持其可见的功能?或者如果不是我可以选择的替代路线?


我知道类似的问题,但没有一个能解决我的问题,要么是太旧了,要么是没有实际使用 Javascript,要么是不适合特定场景。对于任何有类似的、不太具体的问题的人来说,这是一个很好的答案

6个回答

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

如果您需要保留换行符,一项改进是创建一个“textarea”而不是“input”,在我的情况下,该值来自隐藏的 <pre> (因此保留了换行符)
2021-03-14 20:27:34
我的代码段使用标准 Javascript,应该可以在现代 Web 浏览器中按原样工作。我会检查execComand目标浏览器功能的浏览器兼容性(大多数都支持):developer.mozilla.org/en-US/docs/Web/API/Document/...
2021-03-20 20:27:34
天啊,太谢谢你了。这完美地集成到我的代码中并且非常紧凑!
2021-03-20 20:27:34
它对我有用,丹,非常感谢。我在 2 个多小时内搜索了这么多代码,没有人为我工作。但你的代码很好。小而有效。再次感谢。
2021-03-21 20:27:34
您好,我刚刚遇到了这个问题,并且几个小时以来一直在寻找这样的解决方案。如果没有 jQuery 的代码很好,那么这个脚本的头部是否需要任何外部链接/调用?因为现在我在ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js 上使用 google jQuery 文件,我需要参考其他文件才能使用吗?谢谢!
2021-03-21 20:27:34

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>
我们赢了。谢谢
2021-03-17 20:27:34
优秀的解决方案伙计。
2021-03-19 20:27:34
这是迄今为止最简单和最好的解决方案。
2021-03-21 20:27:34
这是最简单和最好的解决方案。
2021-03-23 20:27:34

- 更新 -

文档.execCommand()

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

由于Firefox 版本 41 Document.execCommand() 现在可以工作。所以不需要再使用回退了。


由于浏览器在访问剪贴板时的行为似乎有所不同,因此我花了一些时间来理解它。

它与您的解决方案非常相似,但不同之处在于创建一个临时元素并用 input 填充它value这样我们就可以将输入的display属性设置为none

还有一种适用于IE的解决方法,它使用window.clipboardData.

Firefox根本不允许我访问剪贴板。所以我不得不添加一个prompt让用户手动复制输入值。当然 aprompt是丑陋的,但你可以只使用像窗口这样的模式,它会做同样的事情。

由于这似乎是一件棘手的事情,因此我在Win7(64 位)上进行了测试

铬 - 版本 43.0.2357.134 m

IE - 版本 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>

这是巨大的,只需将元素移出屏幕并使用 execCommand 函数复制它......检查我在底部的答案。
2021-03-24 20:27:34

感谢@DavidDomain 的帮助,我发现了一种有点笨拙但实用的方法。

首先,我将输入方式移出屏幕并修改了一些属性,结果如下:

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

display:none 是在对js进行以下修改后添加的

之后,@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 中复制,这在浏览器安全性方面是有意义的,因为毫无疑问地访问剪贴板会有一些风险。不过,所采取的方法具有相同的预期结果。

我这里有一个不太过时的解决方案:

使用此脚本,您可以复制数据。它比过去提供的脚本小得多。

脚本的作用是使用一个隐藏在屏幕侧面的输入,通过 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 答案,了解使用新的 Permissions API 将文本直接发送到具有用户允许的权限的剪贴板,它不完全受支持,但它在最新的浏览器中可用(我知道它现在实际上适用于 chrome,但我还没有测试过任何其他浏览器):https : //stackoverflow.com/a/58099014/11165703

与我的想法相同,只需使用 css 将输入元素隐藏在屏幕上:)
2021-03-15 20:27:34
@aldrien.h 你知道如果你用 display: hidden 或类似的东西隐藏一个元素,就不可能选择它吗?我希望你会。因此,除非您想通过使用透明颜色“隐藏”元素的每个部分来添加更多 CSS,否则您的想法将行不通。
2021-03-17 20:27:34
我的意思是,使用 css 隐藏在屏幕上,就像上面的样式一样,绝对位置的顶部和左侧为负值,而不是显示:无,execCommand不适用于隐藏元素。:)
2021-03-17 20:27:34
从字面上看,@Dan Stevens 答案的副本只是将样式放入元素而不是脚本中。
2021-03-22 20:27:34
@VeenarM 这是你需要学习的东西,在 stackoverflow 中,如果信息更可行,那么代码是否“相似”也没关系......我在这里添加的代码有数十亿份,但老实说,我不是代表嗅探复印机,我自己写的
2021-03-30 20:27:34