将没有丰富样式的纯文本复制到剪贴板而不会失去焦点?

时间:2017-09-18 09:28:17

标签: javascript html5 focus selection clipboard

我查看了this question,在那里要求提供一种简单地将文本复制为纯文本的方法。我想做到这一点,但还有一件事 - 不要把注意力放在当前元素上。

我需要这个Chrome扩展程序,所以我不会受到跨浏览器支持的困扰。当用户输入输入(或contenteditable)时,会出现带有选项的下拉列表。如果他选择其中一个,它将被复制到他的剪贴板中。我不希望元素失去焦点,因为某些网站可能已经实现了在元素的blur事件上运行的逻辑。

这是我尝试过的:

解决方案1 ​​

创建<input>元素并使用其select()方法:

function clipWithInput(text) {
    var input = document.createElement("input");
    document.body.appendChild(input);

    input.addEventListener("focus", function (e) {
        e.preventDefault();
        e.stopPropagation();
    });

    input.value = text;
    input.select();

    document.execCommand("copy");
    document.body.removeChild(input);
}

document.getElementById("choice").onmousedown = function (e) {
  e.preventDefault(); // prevents loss of focus when clicked
  clipWithInput("Hello");
};
#main {background: #eee;}
#choice {background: #fac;}
<div id="main" contenteditable="true">Focus this, click the div below and then paste here.</div>
<div id="choice">Click to add "Hello" to clipboard</div>

正如您所看到的,这很有效。文本被复制。但是,当您关注contenteditable并单击“选择”时,焦点将丢失。 choice元素在preventDefault()事件中有mousedown,导致它不会破坏焦点。虚拟<input>元素是此处的问题,即使其preventDefault()事件上有focus。我猜测这里的问题是,为时已晚 - 初始元素已经触发了blur,因此我的虚拟输入focus无关紧要。

解决方案2

使用虚拟文本节点和Selection API:

function clipWithSelection(text) {
    var node = document.createTextNode(text),
        selection = window.getSelection(),
        range = document.createRange(),
        clone = null;

    if (selection.rangeCount > 0) {
        clone = selection.getRangeAt(selection.rangeCount - 1).cloneRange();
    }

    document.body.appendChild(node);
    selection.removeAllRanges();
    range.selectNodeContents(node);
    selection.addRange(range);
    document.execCommand("copy");

    selection.removeAllRanges();
    document.body.removeChild(node);

    if (clone !== null) {
        selection.addRange(clone);
    }
}

document.getElementById("choice").onmousedown = function (e) {
  e.preventDefault(); // prevents loss of focus when clicked
  clipWithSelection("Hello");
};
#main {background: #eee;}
#choice {background: #fac;}
<div id="main" contenteditable="true">Focus this, click the div below and then paste here.</div>
<div id="choice">Click to add "Hello" to clipboard</div>

乍一看这完美无缺。文本被复制,没有焦点丢失,插入符号保持在同一位置。没有戏剧性。但是,当您将文字粘贴到contenteditable(例如Gmail的电子邮件编辑器)时,结果就是:

<span style="color: rgb(0, 0, 0); font-family: "Times New Roman"; font-size: medium;">Hello</span>

不是纯文本。

  • 我尝试在<head>中附加没有样式的元素 - 不。未选择文本,也不会复制任何内容。
  • 我尝试在<span>中附加文字节点,并将style.fontFamily等内容设置为inherit,以及fontSizecolor。仍然无法正常工作。我记录了虚拟元素,它正确地具有我的inherit样式。但是,粘贴的文本没有。

小结

我希望以编程方式使用无样式复制纯文本,同时保留焦点在当前活动元素上。

0 个答案:

没有答案