JavaScript实现复制粘贴

96
前端小白简简
2017.05.01 23:15* 字数 802

有个很常见的生活场景是:我们在网页上阅读一篇文章,移动鼠标,框选一段文字,这个时候文字有了蓝色背景,点鼠标右键,选择复制,就可以把选中的文字复制到剪贴板中。 其实这一小小的行为在 JavaScript 中涉及到如下一些术语:

相关术语

  • 锚点(anchor)

锚点指的是一个选区的起始点,这里的锚点不同于HTML中的锚点链接。当我们使用鼠标框选一个区域的时候,锚点就是我们鼠标按下瞬间的那个点。在用户拖动鼠标时,锚点是不会变的。

  • 焦点(focus)

选区的焦点是该选区的终点,当您用鼠标框选一个选区的时候,焦点是你的鼠标松开瞬间所记录的那个点。随着用户拖动鼠标,焦点的位置会随着改变。

  • 范围(range)

范围俗称拖蓝,用来表示用户选中的文本区域,即从锚点到焦点的这一段文本区域。

HTMLInputElement 的三种方法

  • 选中文本域中的内容

HTMLInputElement.select() 

英文解释为:Selects the input text in the element, and focuses it so the user can subsequently replace the whole entry.
刚认识这个方法的时候,下意识的觉得应该会返回选中的文字才对,然而并没有,这个方法没有返回值,仅仅只是选中了文字而已。

  • 在文本域上设置焦点

HTMLInputElement.focus() 

英文解释为:Focus on input; keystrokes will subsequently go to this element.

  • 从文本域上移开焦点

HTMLInputElement.blur() 

英文解释为:Removes focus from input; keystrokes will subsequently go nowhere.

值得注意的是以上三种方法都只面向 <input> 和 <textarea> 结点,并且都没有返回值。

document.execCommand

文档对象的 execCommand方法允许运行命令来操纵可编辑区域的内容,具体可以查看这里. 下面仅介绍 copy 这个方法:

bool = document.execCommand(copy)

这个方法指拷贝当前选中内容到剪贴板,返回值为一个 bool 值, 如果返回值为 false 则表示操作不被支持或未被启用。
很遗憾的是这个方法的浏览器兼容性一般,IE 仅支持 8 以上的版本。

通过以上几个方法我们已经可以实现简单的复制粘贴功能了:

  <input type="text" class="box-text" value="choose me!" />
  <button class="bt-copy" >copy</button>

  <script>
    $('.bt-copy').click(function(){
      var copyTarget = $('.box-text');
      copyTarget.select();
      try {
        document.execCommand('copy');
      }
      catch (err) {
        alert('请使用CTRL+C,CTRL+V来复制粘贴~');
      }
      copyTarget.blur();
    })  
  </script>

短短几行代码就实现了复制粘贴的功能,但仍然有改进的地方:

  • 增加除 <input> 和 <textarea> 外的结点的支持,可以借鉴 select.js 的实现方法。
  • 对不支持 document.execCommand('copy') 的浏览器使用 ZeroClipboard 作为 fallback。

---------------------------------------- 2017/5/5日 更 ----------------------------------------

之前说过, .select() 方法仅支持 <input><textarea> 元素,发现一个更好的办法用于解决这个问题:

  • 用 js 生成一个隐藏的 <textarea> 元素,追加到 dom 里面。
  • 把需要复制的文本赋值给刚生成的 <textarea> 元素。
  • 使用原生的方法进行选中和复制的操作。
  • 最后记得在DOM中移除 <textarea> 元素。
var textArea = document.createElement('textarea');
textArea.style.position = 'fixed';
textArea.style.left = '-10000px';
textArea.style.top = '-10000px';
document.body.appendChild(textArea);
textArea.value = this.copyText;
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
JavaScript