MZhou's blog

网页上的复制与剪切

这篇文章翻译自HTML5ROCKS的Cut and Copy Commands

IE 10及以上的版本修改了Document.execCommand()方法,增加了对剪切和复制的支持。Chrome从43版本开始也支持了这项特性。

当选中了浏览器中的任意文本,只要执行这个方法就可以剪切或拷贝这段文字。有了这个API后,选中一段文字并拷贝会变的非常简单。

这个API和Selection API一起使用时将会变的特别有用。你可以决定哪些文本被复制到剪切版。之后我们会详细阐述。

一个简单的例子

让我们来增加一个按钮,点击这个按钮会拷贝一个email地址到用户的剪切版。

我们在网页里面添加一个email地址和一个按钮,点击按钮会拷贝email地址:

<p>Email me at <a class="js-emaillink" href="mailto:matt@example.co.uk">matt@example.co.uk</a></p>
<p><button class="js-emailcopybtn"><img src="./images/copy-icon.png" /></button></p>

接下来在Javascript中,我们增加一个click事件监听器到按钮上。在事件监听器中我们通过class js-emaillink选中email地址,然后执行拷贝命令,然后用户的剪切版里面就会有email地址了。然后我们取消选中email地址,这样用户就不会见到文本被选中。

var copyEmailBtn = document.querySelector('.js-emailcopybtn');
copyEmailBtn.addEventListener('click', function(event) {
    // Select the email link anchor text
    var emailLink = document.querySelector('.js-emaillink');
    var range = document.createRange();
    range.selectNode(emailLink);
    window.getSelection().addRange(range);

    try {
        // Now that we've selected the anchor text, execute the copy command
        var successful = document.execCommand('copy');
        var msg = successful ? 'successful' : 'unsuccessful';
        console.log('Copy email command was ' + msg);
    } catch(err) {
        console.log('Oops, unable to copy');
    }

    // Remove the selections - NOTE: Should use
    // removeRange(range) when it is supported
    window.getSelection().removeAllRanges();
});

如上代码中使用了Selection APIwindow.getSelection()方法选中链接的文本。在document.execCommand()方法后,我们可以通过调用window.getSelection().removeAllRanges()方法来移除选中。如果你想检查拷贝是否成功,那么你可以checkdocument.execCommand();的返回值。如果返回false那么表示不支持拷贝或者不能使用(没有选中文本)。我们将execCommand()放到try catch里面执行是为了确保一些极端情况下浏览器会抛出错误

剪切命令可以在文本框中使用。你可以移除文本输入框中的文字并放到剪切版中使用。

在HTML中添加一个textarea和一个按钮:

<p><textarea class="js-cuttextarea">Hello I'm some text</textarea></p>
<p><button class="js-textareacutbtn" disable>Cut Textarea</button></p>

我们可以这么写js:

var cutTextareaBtn = document.querySelector('.js-textareacutbtn');
cutTextareaBtn.addEventListener('click', function(event) {
    var cutTextarea = document.querySelector('.js-cuttextarea');
    cutTextarea.select();

    try {
        var successful = document.execCommand('cut');
        var msg = successful ? 'successful' : 'unsuccessful';
        console.log('Cutting text command was ' + msg);
    } catch(err) {
        console.log('Oops, unable to cut');
    }
});

queryCommandSupported和queryCommandEnabled

在调用 document.execCommand() 之前你应该确认这个API是否被所在浏览器支持。这时候你可以用 document.queryCommandSupported() 方法来确认是否支持。在上面的例子中,我们可以在浏览器不支持时将按钮设置为disabled。具体代码如下:

copyEmailBtn.disabled = !document.queryCommandSupported('copy');

document.queryCommandSupported())和document.queryCommandEnabled())的区别是:前者检测浏览器是否支持剪切或拷贝,后者检测是否有选中的文本用于剪切或拷贝。这在让用户选中文本的情况(不用Selection API)下比较有用。如果没有选中的文本,你可以显示一个消息给用户,这样更加友好~

浏览器支持情况

IE 10+、Chrome 43+和Opera 29+ 已经支持了这些命令。

Firefox虽然已经支持了这些命令,但是需要修改下首选项(具体看这里。如果没有修改首选项,那么Firefox会抛出一个错误。

Safari目前不支持这些命令。

已知问题

直接用js代码调用 queryCommandSupported() 会一定会返回false,除非将其放在用户操作的回调函数中执行。这导致了你不能在浏览器不支持时禁用按钮。

在devtools中调用 queryCommandSupported() 一定会返回false。

目前剪切命令只在你用js选中文本时起作用。

MZhou's blog - Taste of life.

zmmbreeze / @zhoumm