有个很常见的生活场景是:我们在网页上阅读一篇文章,移动鼠标,框选一段文字,这个时候文字有了蓝色背景,点鼠标右键,选择复制,就可以把选中的文字复制到剪贴板中。 其实这一小小的行为在 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);