之前是在一些类似于www.bootcss.com类似的网站见到过复制按钮,点击之后一整行文字都可以复制,然后到指定的位置粘贴就可以了,也知道这个是依托flash来实现的,刚好最近有一个需求是需要复制一段文字到剪贴板,查了一下JS的实现方式,还是有些坑的。
能够实现复制功能的方法是document.execCommand('copy'),可以参考MDN document.execCommand, 同时推荐看一下copy事件的文档。
我们都知道平时我们进行的复制粘贴都是选中一部分文本,然后按住ctrl + c
来实现复制功能,那么复制功能也需要先选中,再执行复制动作。如果事先在剪贴板内已经有了内容,就不需要选中功能,直接执行粘贴动作即可。
我本来的需求其实是进入一个页面直接在用户没有任何操作的情况下直接执行,然后我做了一系列的实验……首先放出我的demo~
<input id='ipt' value="我是要copy或者cut的内容">
<button id="btn">点击</button>
<script>
var ipt = document.getElementById('ipt')
var btn = document.getElementById('btn')
</script>
//第一种模拟点击的方法是没有什么卵用的
ipt.select()
btn.onclick = function(){
document.execCommand("Copy")
console.log(document.execCommand("Copy") ) //返回false
}
btn.click() //这一步虽然可以选中文字 ,但是无法利用这个模拟点击去实现复制
//很显然,这样不行
//我自己去进行点击,得到真实点击动作,可以完成复制或剪切
ipt.select()
btn.onclick = function(){
document.execCommand("Copy")
console.log(document.execCommand("Copy") ) //返回false
}
//当我点击之后,控制台返回了一个true,手动操作是可以实现的
//试一下换成document.ready的时候复制,好像也不行耶……
ipt.select()
window.onload = function(){
document.execCommand("Copy")
console.log(document.execCommand("Copy") ) //返回false
}
//这样并不能实现复制
//最后,我很绝望,试试简单粗暴、直接写,看能不能执行
ipt.select()
document.execCommand("Copy")
console.log(document.execCommand("Copy")) //false
//事实证明,好像也不行
各种实验做下来,除非手动去点击按钮获取内容(不包含js模拟点击动作),否则无法实现复制功能(手机端使用touch相关的动作去实现也无效)。值得一提的是,我的html里面是input元素,如果这个input是个readonly或disabled的情况,或者是input的type值为hidden,又或是input的css{display: none}我们都是无法实现select,无法选中文字的。但是我们可以把input的透明度设置为0,这样做有个问题就是手机端容易暴露我们隐藏的内容,而且在用户无意中点击到input的时候有一些浏览器会提示用户谨慎输入自己的信息,以免造成不必要的损失之类的提示语。于是有了替代input的其他元素来进行选中,至于用什么标签,你开心就好啦:
<div id="aa">xxxxxxxxxxxxxx</div>
<button id="btn">dfhdddddd</button>
<script>
var btn = document.getElementById('btn')
function selectText(element) {
var text = document.getElementById(element);
if (document.body.createTextRange) {
//createTextRange是用在IE中的
var range = document.body.createTextRange();
range.moveToElementText(text);
range.select();
} else if (window.getSelection) {
var selection = window.getSelection();
var range = document.createRange();
range.selectNodeContents(text);
selection.removeAllRanges();
selection.addRange(range);
document.execCommand("Copy")
} else {
alert("none");
}
}
selectText("aa");
//这样在刚打开页面的时候就可以看到已经选中的文字了
</script>
在参考MDN的copy
事件的时候,发现了这个描述:
用户在浏览器界面进行复制行为的时候,会触发copy事件(例如:使用CTRL/Cmd+C快捷键或者在选中菜单栏点击"复制"命令)。copy事件会调用document.execCommand('copy')。当一个HTML文档切换到设计模式(designMode)时,文档对象暴露 execCommand方法,该方法允许运行命令来操纵可编辑区域的内容。大多数命令影响文档的选择(粗体,斜体等),而其他命令插入新元素(添加链接)或影响整行(缩进)。当使用 contentEditable时,调用 execCommand() 将影响当前活动的可编辑元素。"
在执行copy动作的时候其实我们可以直接定义他需要复制的内容,这样的话,即使用户什么也不选,那么我么也可以在他下次粘贴的时候粘贴的是我们规定好的内容:
document.addEventListener('copy', function(e){
e.clipboardData.setData('text/plain', 'Hello, world!');
e.preventDefault(); // We want our data, not data from any selection, to be written to the clipboard
});
//当我们在此页面有复制动作的时候,在执行粘贴动作,就会把hello,world
然后我的需求到现在还没有实现。。。我查了一些资料,stackoverflow上了解到:
大家的解释都是关于安全方面的考量,不允许直接进行复制,必须是人作为主体来进行操作才能真正的执行复制这个动作;如果权限过大可能会被利用来做一些有损使用者利益的事情。有关的回答大家可以参考这个网站:
https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript/30810322#30810322