javascript剪切/复制/粘贴到剪贴板:谷歌是如何解决的
javascript cut/copy/paste to clipboard: how did Google solve it?
是的,这个问题已经被问了一次又一次:如何使用javascript从系统剪贴板复制和粘贴到系统剪贴板?到目前为止,我只找到了部分解决方案和技巧。过去人们之所以经常问这个问题,是因为仍然没有有效的解决方案。然而,我看到Google Docs现在实际上已经为键盘事件和按钮提供了一个有效的解决方案。所以,这是可能的,但他们是如何做到的?软件沙拉文章,用JavaScript访问系统剪贴板–圣杯,给出了一个很好的问题概述(但它已经有几年的历史了)。
简而言之:
-
您可以使用键盘事件ctrl+x、ctrl+c、ctrl+v从具有准备好的数据的隐藏文本区域复制文本,或者捕获隐藏字段中粘贴的文本,然后对其进行操作
-
您可以通过Flash或Java Applet使用一些破解来将某些内容复制到系统剪贴板,而无需用户批准。
-
您可以使用clipboardData.setData(IE)和execCommand(其他浏览器)的"真实"解决方案,这取决于用户的批准。
知道谷歌是如何解决剪贴板问题的吗?
我知道这个问题很久以前就发布了,但我需要检查谷歌是如何做到的,所以也许有人会觉得这很有用。
事实上,谷歌也使用系统剪贴板,但这有点棘手。如果您使用键盘快捷键,您可以在例如窗口上捕获复制/粘贴/剪切事件:
window.addEventListener('copy', function (ev) {
console.log('copy event');
// you can set clipboard data here, e.g.
ev.clipboardData.setData('text/plain', 'some text pushed to clipboard');
// you need to prevent default behaviour here, otherwise browser will overwrite your content with currently selected
ev.preventDefault();
});
键盘快捷键的实时示例:http://jsfiddle.net/tyk9U/
不幸的是,这只是键盘快捷方式的唯一解决方案,上下文菜单也有问题,因为如果没有本机(可信)复制/剪切/粘贴事件,您就无法访问剪贴板数据。但谷歌做了一个有趣的把戏。有API document.execCommand()
允许您为contenteditable元素运行命令,还有命令"副本",您可以通过document.execCommand('copy')
触发它。但当您在Chrome的控制台中尝试此操作时,它将返回false
。我花了一些时间调查,结果发现他们安装了Chrome扩展,名为"谷歌硬盘"(请访问chrome://apps/你可以在那里看到它),它允许域drive.google.com和docs.google.com的剪贴板访问。打开一些文档或电子表格,在控制台中键入document.execCommand('copy')
-它将返回true
。卸载扩展时,您将无法使用上下文菜单中的剪贴板操作。
您可以使用非常简单的清单文件为自己创建这样的应用程序(详细信息请点击此处https://developer.chrome.com/apps/first_app):
{
"manifest_version": 2,
"name": "App name",
"description": "App description",
"version": "1.0",
"app": {
"urls": [
"http://your.app.url.here/"
],
"launch": {
"web_url": "http://your.app.url.here/"
}
},
"icons": {
"128": "x-128.png"
},
"permissions": [
"clipboardRead",
"clipboardWrite"
]
}
此处的"权限"字段启用剪贴板操作。
现在,当您启用此功能时,您可以执行document.execCommand('copy')
,它将工作(将返回true
)。但这并不是全部——chrome中的document.execCommand('copy')
触发复制事件,您可以使用用于捕获键盘剪贴板快捷键的相同代码来捕获它。这是谷歌现在做的。
当然,此描述仅对Chrome有效。
注意:这个答案在编写时是准确的,并且正确地回答了OP的问题。然而,从那时起,技术就在发展;如果您有兴趣在web应用程序中支持复制和粘贴,请参阅本页上的其他最新答案。—ruakh]
然而,我看到Google Docs现在实际上已经为键盘事件和按钮提供了一个有效的解决方案。
不,不是。不是。对于键盘事件,谷歌文档什么都不做;它只是没有阻止浏览器的默认复制和粘贴功能;因此,用户可以自由复制和粘贴,而不会受到谷歌文档的阻碍。对于按钮,谷歌文档不支持系统剪贴板,但它自己的"网络剪贴板"完全在谷歌文档中。您不能使用工具栏按钮复制文本以粘贴到计算机上的其他程序中,也不能粘贴从计算机上的另一个程序复制的文本。
有关这方面的更多信息,请参阅"在谷歌文档中复制和粘贴"。(这是面向用户的,而不是面向开发人员的,但它很好地明确了什么是受支持的,什么是不受支持的。)
除了其他人已经在这个线程中发布的内容外,我还创建了一个完整的示例,演示了键盘快捷方式(在Mac OS X上为CTRL+C或CMD+C)以及触发复制操作的自定义按钮方法。
完整的演示可以在这里找到:http://jsfiddle.net/rve7d/
在尝试创建这个演示时,我发现Mateusz W的回答非常有用,但他没有考虑对IE的支持,IE的行为略有不同,并使用不同的数据类型作为第一个参数。
if(window.clipboardData) {
// use just 'Text' or 'Url' as a first param otherwise strange exception is thrown
window.clipboardData.setData('Text', 'Text that will be copied to CB');
} else if(ev.originalEvent.clipboardData) {
ev.originalEvent.clipboardData.setData('text/plain', 'Text that will be copied to CB');
} else {
alert('Clipboard Data are not supported in this browser. Sorry.');
}
附言:我需要这个功能用于我们的自定义电子表格视图组件,并在途中分析了谷歌电子表格的源代码,所以我的解决方案基本上符合他们的解决方案。
谷歌使用了一种非常简单但很酷的方法。通过使用firebug,您将知道加载的html代码有一个大小为1的文本区域。谷歌文档所做的是,当用户选择文本并按下ctrl+c时,它会捕获事件,并通过某种技术获取文档容器中选择的文本,并将文本区域的值设置为该内容。然后聚焦并选择文本区域。现在它释放ctrl+c事件。但现在文本是在文本区域中选择的,所以当事件发生时,浏览器会复制文本区域中的文本,因此我们会得到复制的文本
<p>COPY : </p>
<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" value="clipboard" >clipboard</button></p>
<textarea rows="10" cols = "12"></textarea>
<p>CUT: </p>
<p><textarea class="js-cuttextarea">Hello I'm some text</textarea></p>
<p><button class="js-textareacutbtn" disable>Cut Textarea</button></p>
<script>
//copy clipboard
var copyEmailBtn = document.querySelector('.js-emailcopybtn');
copyEmailBtn.addEventListener('click', function(event) {
// Выборка ссылки с электронной почтой
var emailLink = document.querySelector('.js-emaillink');
var range = document.createRange();
range.selectNode(emailLink);
window.getSelection().addRange(range);
try {
// Теперь, когда мы выбрали текст ссылки, выполним команду копирования
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');
}
// Снятие выделения - ВНИМАНИЕ: вы должны использовать
// removeRange(range) когда это возможно
window.getSelection().removeAllRanges();
});
//cut
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');
}
});
</script>
- 如何解决Yii中的页面刷新问题
- 测试Angular Service解决错误回调中的promise
- 如何解决Access Control Allow Origin错误
- 如何解决这种情况下的非法调用类型错误
- 简单的ES6承诺问题-交换解决和拒绝参数
- 可以转换显示属性吗?如果没有,什么'这是最好的解决方案
- iPad虚拟键盘-哪一个-javasctript解决方案
- 在ES6 Promise中,我应该在解决/拒绝之前使用return吗
- 如何解决“;错误所请求的URL返回500-内部服务器错误”;
- 如何逃离<脚本>jquery html()中的标记.我使用了innerHTML和outerHTML来解决这个
- 如何解决'窗口未定义'终端上的节点JS出错
- Angularjs:如何在使用'解决'在$routeProvider中
- 可以't解决Javascript错误
- AJAX HTTP基本身份验证解决方案
- 为什么不'我的窗口滚动事件根本没有启动.其他答案没有解决问题
- 如何解决此错误
- 在chrome web商店中打开时,是否有允许执行内容/后台脚本的解决方案
- CORS故障无法解决jquery,laravel5.2
- Imacros解决解决媒体验证码
- 如何解决/解决JQuery安全异常0x80530012