如何将文本复制到剪贴板(多浏览器)?

相关:Trello如何访问用户的剪贴板?


当前回答

我最近写了一篇关于这个问题的技术博客文章(我在Lucidhart工作,最近我们在剪贴板上做了一次彻底的修改)。

将纯文本复制到剪贴板相对简单,假设您尝试在系统复制事件期间执行此操作(用户按下Ctrl+C或使用浏览器菜单)。

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie")    != -1 ||
            navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) {
    var textToPutOnClipboard = "This is some text";
    if (isIe) {
        window.clipboardData.setData('Text', textToPutOnClipboard);
    } else {
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    }
    e.preventDefault();
});

不在系统复制事件期间将文本放到剪贴板上要困难得多。看起来这些其他答案中的一些引用了通过Flash实现的方法,这是唯一的跨浏览器方式(据我所知)。

除此之外,还有一些基于浏览器的选项。

这是Internet Explorer中最简单的,您可以通过以下方式随时从JavaScript访问clipboardData对象:

window.clipboardData

(当您尝试在系统剪切、复制或粘贴事件之外执行此操作时,Internet Explorer将提示用户授予web应用程序剪贴板权限。)

在Chrome中,您可以创建一个Chrome扩展,它将为您提供剪贴板权限(这是我们为Lucidchart所做的)。然后,对于安装了扩展的用户,您只需要自己触发系统事件:

document.execCommand('copy');

看起来Firefox有一些选项,允许用户授予某些站点访问剪贴板的权限,但我没有亲自尝试过这些选项。

其他回答

这是Chase Seibert答案的扩展,其优点是它适用于IMAGE和TABLE元素,而不仅仅是Internet Explorer 9上的DIV。

if (document.createRange) {
    // Internet Explorer 9 and modern browsers
    var r = document.createRange();
    r.setStartBefore(to_copy);
    r.setEndAfter(to_copy);
    r.selectNode(to_copy);
    var sel = window.getSelection();
    sel.addRange(r);
    document.execCommand('Copy');  // Does nothing on Firefox
} else {
    // Internet Explorer 8 and earlier. This stuff won't work
    // on Internet Explorer 9.
    // (unless forced into a backward compatibility mode,
    // or selecting plain divs, not img or table).
    var r = document.body.createTextRange();
    r.moveToElementText(to_copy);
    r.select()
    r.execCommand('Copy');
}

我找到了以下解决方案:

按下键处理程序创建一个“pre”标记。我们设置要复制到此标记的内容,然后在此标记上进行选择并在处理程序中返回true。这将调用Chrome的标准处理程序并复制选定的文本。

如果需要,您可以为恢复先前选择的函数设置超时。我在MooTools上的实现:

function EnybyClipboard() {
    this.saveSelection = false;
    this.callback = false;
    this.pastedText = false;

    this.restoreSelection = function() {
        if (this.saveSelection) {
            window.getSelection().removeAllRanges();
            for (var i = 0; i < this.saveSelection.length; i++) {
                window.getSelection().addRange(this.saveSelection[i]);
            }
            this.saveSelection = false;
        }
    };

    this.copyText = function(text) {
        var div = $('special_copy');
        if (!div) {
            div = new Element('pre', {
                'id': 'special_copy',
                'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
            });
            div.injectInside(document.body);
        }
        div.set('text', text);
        if (document.createRange) {
            var rng = document.createRange();
            rng.selectNodeContents(div);
            this.saveSelection = [];
            var selection = window.getSelection();
            for (var i = 0; i < selection.rangeCount; i++) {
                this.saveSelection[i] = selection.getRangeAt(i);
            }
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(rng);
            setTimeout(this.restoreSelection.bind(this), 100);
        } else return alert('Copy did not work. :(');
    };

    this.getPastedText = function() {
        if (!this.pastedText) alert('Nothing to paste. :(');
        return this.pastedText;
    };

    this.pasteText = function(callback) {
        var div = $('special_paste');
        if (!div) {
            div = new Element('textarea', {
                'id': 'special_paste',
                'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
            });
            div.injectInside(document.body);
            div.addEvent('keyup', function() {
                if (this.callback) {
                    this.pastedText = $('special_paste').get('value');
                    this.callback.call(null, this.pastedText);
                    this.callback = false;
                    this.pastedText = false;
                    setTimeout(this.restoreSelection.bind(this), 100);
                }
            }.bind(this));
        }
        div.set('value', '');
        if (document.createRange) {
            var rng = document.createRange();
            rng.selectNodeContents(div);
            this.saveSelection = [];
            var selection = window.getSelection();
            for (var i = 0; i < selection.rangeCount; i++) {
                this.saveSelection[i] = selection.getRangeAt(i);
            }
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(rng);
            div.focus();
            this.callback = callback;
        } else return alert('Failed to paste. :(');
    };
}

用法:

enyby_clip = new EnybyClipboard(); // Init

enyby_clip.copyText('some_text'); // Place this in the Ctrl+C handler and return true;

enyby_clip.pasteText(function callback(pasted_text) {
    alert(pasted_text);
}); // Place this in Ctrl+V handler and return true;

在粘贴时,它会创建一个文本区域,并以相同的方式工作。

PS:也许这个解决方案可以用于创建没有Flash的完整跨浏览器解决方案。它适用于Firefox和Chrome。

由于Chrome 42+和Firefox 41+现在支持document.execCommand('copy')命令,我结合Tim Down的旧答案和Google Developer的答案,创建了两个跨浏览器复制到剪贴板的功能:

函数selectElementContents(el){//复制textarea、pre、div等。if(document.body.createTextRange){//Internet Explorervar textRange=document.body.createTextRange();text范围.移动到元素文本(el);text范围.选择();textRange.execCommand(“复制”);}否则如果(window.getSelection&&document.createRange){//非Internet Explorervar range=document.createRange();range.selectNodeContents(el);var sel=window.getSelection();sel.removeAllRanges();sel.addRange(范围);尝试{var success=document.execCommand('copy');var msg=成功?'success':'不成功';console.log('复制命令为'+msg);}捕获(错误){console.log(“糟糕,无法复制”);}}}//结束函数selectElementContents(el)函数make_copy_button(el){var copy_btn=document.createElement('input');copy_btn.type=“按钮”;el.parentNode.insertBefore(copy_btn,el.nexSibling);copy_btn.onclick=函数(){selectElementContents(el);};if(document.queryCommandSupported(“copy”)||parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 42) {//复制适用于Internet Explorer 4+、Chrome 42+、Firefox 41+、Opera 29+copy_btn.value=“复制到剪贴板”;}其他{//仅适用于Safari和旧版Chrome、Firefox和Operacopy_btn.value=“全选(然后按Ctrl+C复制)”;}}/*注意:document.queryCommandSupported(“copy”)在支持复制的浏览器上应返回“true”,但Chrome版本42到47中存在一个错误,使其返回“false”。所以在那些版本的Chrome功能检测不起作用!看见https://code.google.com/p/chromium/issues/detail?id=476508*/make_copy_button(document.getElementById(“标记”));<pre-id=“markup”>可以通过跨浏览器支持复制或选择的文本。</pre>

我把我认为最好的东西放在一起了。

使用cssText避免Internet Explorer中的异常,而不是直接使用样式。如果有选择,则恢复选择设置为只读,以便移动设备上不会出现键盘有一个适用于iOS的解决方案,因此它实际上可以像通常阻止execCommand一样工作。

这里是:

const copyToClipboard = (function initClipboardText() {
  const textarea = document.createElement('textarea');

  // Move it off-screen.
  textarea.style.cssText = 'position: absolute; left: -99999em';

  // Set to readonly to prevent mobile devices opening a keyboard when
  // text is .select()'ed.
  textarea.setAttribute('readonly', true);

  document.body.appendChild(textarea);

  return function setClipboardText(text) {
    textarea.value = text;

    // Check if there is any content selected previously.
    const selected = document.getSelection().rangeCount > 0 ?
      document.getSelection().getRangeAt(0) : false;

    // iOS Safari blocks programmatic execCommand copying normally, without this hack.
    // https://stackoverflow.com/questions/34045777/copy-to-clipboard-using-javascript-in-ios
    if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
      const editable = textarea.contentEditable;
      textarea.contentEditable = true;
      const range = document.createRange();
      range.selectNodeContents(textarea);
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
      textarea.setSelectionRange(0, 999999);
      textarea.contentEditable = editable;
    }
    else {
      textarea.select();
    }

    try {
      const result = document.execCommand('copy');

      // Restore previous selection.
      if (selected) {
        document.getSelection().removeAllRanges();
        document.getSelection().addRange(selected);
      }

      return result;
    }
    catch (err) {
      console.error(err);
      return false;
    }
  };
})();

用法:复制到剪贴板(“部分文本”)

JavaScript/TypeScript中最简单的方法是使用此命令

navigator.clipboard.writeText(textExample);

只需在textExample中传递要复制到剪贴板的值