草庐IT

JavaScript 剪贴板 Clipboard 的那些事儿!

CTO安东尼 2023-03-28 原文
减轻阅读负担,启发创作心智,轻松学习 JavaScript 技巧,日拱一卒,jym,冲~

本篇带来 —— JavaScript 剪贴板 Clipboard 的那些事儿!


复制粘贴就是互联网最伟大的发明,无论是使用快捷键 ctrl c 、ctrl v,还是鼠标选中右键复制再粘贴,Copy 操作都是非常简单的。

然而要注意的是,你的剪贴板 Clipboard 或许在被有些软件无时无刻的监听着,有时候在知乎上搜的东西,最终出现在了京东商品的推荐页里,让人不禁打个冷战,疑问道:它怎么知道我想买这个东西的?

在 JavaScript 中 ​​navigator.clipboard​​ 全局对象就是来处理剪贴板的,它有以下方法:

  • readText: 读文本
  • read: 读任何类型的数据,除文本外还有图片这些;
  • writeText: 写文本
  • write: 写任何数据;
接下来我们实战来看看 ​​navigator.clipboard​​ 的代码应用:

写入

原生 JS 实现将数据写入剪贴板:

<html>
<head>
<script >
async function copyText() {
let textArea = document.getElementById("myText")

const permission = await navigator.permissions.query({ name: 'clipboard-write' });
if (permission.state === 'denied') {
return console.error("Damn, we don't have permissions to do this")
}
try {
await navigator.clipboard.writeText(textArea.value) // 写入文本
console.log("done!")
} catch (e) {
console.error("Error while copying text!")
console.error(e.message)
}

}
</script>
</head>
<body>
<textarea rows="5" cols="89" id="myText"></textarea>
<button onclick="copyText()">Share!</button>
</body>
</html>
这里要注意的是,在我们写入之前要访问 ​​navigator.permissions.query({ name: 'clipboard-write' });​​ 用于提前判断我们是否有权限去做写入操作。

除了写入文本,还可以写入图片:

<html>
<head>
<script >
async function copyImg() {
const type = "image/png";

let myImg = document.getElementById("myImage")

let img = await fetch(myImg.getAttribute("src"))

var blob = new Blob([await img.blob()], { type });
var data = [new ClipboardItem({ [type]: blob })];

try {
await navigator.clipboard.write(data)
console.log("The image was copied")
} catch (e) {
console.error("There was a problem copying the imagge")
console.error(e)
}
}
</script>
</head>
<body>
<img src="./img.png" width="300" id="myImage" />
<button onclick="copyImg()">Share!</button>
</body>
</html>
与文本稍有不同的是我们要包装一个 ClipboardItem 数组;

读取

与写入数据对应的就是读取数据:

<html>
<head>
<script >
async function pasteImage() {
let destinationImage = document.getElementById("myImage")
const permission = await navigator.permissions.query({ name: 'clipboard-read' });
if (permission.state === 'denied') {
throw new Error('Not allowed to read clipboard.');
}
const clipboardContents = await navigator.clipboard.read();
for (const item of clipboardContents) {
if (!item.types.includes('image/png')) {
throw new Error('Clipboard contains non-image data.');
}
const blob = await item.getType('image/png');
destinationImage.src = URL.createObjectURL(blob);
}
}

</script>
</head>
<body>
<img width="300" id="myImage" />
<button onclick="pasteImage()">Get Image!</button>
</body>
</html>
同样需要先确认是否有权限读取:​​navigator.permissions.query({ name: 'clipboard-read' })​

读取图片要用到:​​URL.createObjectURL​​ 方法。

混淆剪贴内容

这里再提供一个小技巧:假设我们不想自己的文本内容被复制,除了禁止复制以外,还可以用 JS 脚本设置给它赋值一个内容混淆过的内容。

代码如下:

<html>
<head>
<script >
function setUpEvent() {
let mainContent = document.getElementById("main-content")

mainContent.addEventListener('copy', function(evt) {
let selectedText = document.getSelection()
selectedText = selectedText
.toString()
.split("") //turn it into an array of characters
.sort((a,b) => Math.random() > 0.5?1:-1) //shuffle the array
.join("") //join it back into a single string
evt.clipboardData.setData("text/plain", selectedText) //set the clipboard's data
evt.preventDefault()
})
}

</script>
</head>
<body onload="setUpEvent()">
<p id="main-content">
For this example, I'm using the HTML IMG tag just to get the src atttribute, since I can't really use the element directly. The API needs me to turn the image into a Blob (which is essentially a way of saying "It's a big chunk of I don't know exactly"). And since the DOM API doesn't have any methods I can use, I'm fetching the actual image and the calling the blob method on the response object (line 11).
The rest is as expected, I create a one-element array with a ClipboardItem containing the blob, and the I write the array into the clipboard.
You can use the above example to extrapolate how you would go about copying something else, like an XLS file. You need to fetch it, blob it, and make sure you used the right mime-type, which is the string I have on the type variable. If you don't know what's the mime-type for your file, just Google "mime-type for <your file's extension here>" and you'll have it.
</p>
</body>
</html>
我们可以在 ​​https://www.runoob.com/runcode​​ 即时运行这段代码看看混淆后的剪贴板的内容:

粘贴出来是这样的:

主要用到了随机数去打乱内容。

挺有意思的,不是让人不能复制,而是让人复制一个乱序的结果,Clipboard 也能这样玩儿~~

OK,以上便是本篇分享。点赞关注评论,为好文助力?

我是掘金安东尼 ? 100 万人气前端技术博主 ? INFP 写作人格坚持 1000 日更文 ✍ 关注我,安东尼陪你一起度过漫长编程岁月 ?

有关JavaScript 剪贴板 Clipboard 的那些事儿!的更多相关文章

  1. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  2. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  3. javascript - jQuery 的 jquery-1.10.2.min.map 正在触发 404(未找到) - 2

    我看到有关未找到文件min.map的错误消息:GETjQuery'sjquery-1.10.2.min.mapistriggeringa404(NotFound)截图这是从哪里来的? 最佳答案 如果ChromeDevTools报告.map文件的404(可能是jquery-1.10.2.min.map、jquery.min.map或jquery-2.0.3.min.map,但任何事情都可能发生)首先要知道的是,这仅在使用DevTools时才会请求。您的用户不会遇到此404。现在您可以修复此问题或禁用sourcemap功能。修复:获取文

  4. ruby-on-rails - 我将 Rails3 与 tinymce 一起使用。如何呈现用户关闭浏览器javascript然后输入xss? - 2

    我有一个用Rails3编写的站点。我的帖子模型有一个名为“内容”的文本列。在帖子面板中,html表单使用tinymce将“content”列设置为textarea字段。在首页,因为使用了tinymce,post.html.erb的代码需要用这样的原始方法来实现。.好的,现在如果我关闭浏览器javascript,这个文本区域可以在没有tinymce的情况下输入,也许用户会输入任何xss,比如alert('xss');.我的前台会显示那个警告框。我尝试sanitize(@post.content)在posts_controller中,但sanitize方法将相互过滤tinymce样式。例如

  5. ruby - 使用 Selenium WebDriver 启用/禁用 javascript - 2

    出于某种原因,我必须为Firefox禁用javascript(手动,我们按照提到的步骤执行http://support.mozilla.org/en-US/kb/javascript-settings-for-interactive-web-pages#w_enabling-and-disabling-javascript)。使用Ruby的SeleniumWebDriver如何实现这一点? 最佳答案 是的,这是可能的。而是另一种方式。您首先需要查看链接Selenium::WebDriver::Firefox::Profile#[]=

  6. ruby - Watir-Webdriver 是否支持点击目标为 javascript 的链接? - 2

    我是Ruby和Watir-Webdriver的新手。我有一套用VBScript编写的站点自动化程序,我想将其转换为Ruby/Watir,因为我现在必须支持Firefox。我发现我真的很喜欢Ruby,而且我正在研究Watir,但我已经花了一周时间试图让Webdriver显示我的登录屏幕。该站点以带有“我同意”区域的“警告屏幕”开头。用户点击我同意并显示登录屏幕。我需要单击该区域以显示登录屏幕(这是同一页面,实际上是一个表单,只是隐藏了)。我整天都在用VBScript这样做:objExplorer.Document.GetElementsByTagName("area")(0).click

  7. 网页设计期末作业,基于HTML+CSS+JavaScript超酷超炫的汽车类企业网站(6页) - 2

    🎉精彩专栏推荐💭文末获取联系✍️作者简介:一个热爱把逻辑思维转变为代码的技术博主💂作者主页:【主页——🚀获取更多优质源码】🎓web前端期末大作业:【📚毕设项目精品实战案例(1000套)】🧡程序员有趣的告白方式:【💌HTML七夕情人节表白网页制作(110套)】🌎超炫酷的Echarts大屏可视化源码:【🔰Echarts大屏展示大数据平台可视化(150套)】🔖HTML+CSS+JS实例代码:【🗂️5000套HTML+CSS+JS实例代码(炫酷代码)继续更新中…】🎁免费且实用的WEB前端学习指南:【📂web前端零基础到高级学习视频教程120G干货分享】🥇关于作者:💬历任研发工程师,技术组长,教学总监;

  8. ruby-on-rails - 在页面的最底部包含 javascript 文件 - 2

    我有一个Rails应用程序。还有一个javascript(javascript1.js)文件必须包含在每个View的最底部。我把它放在/assets/javascripts文件夹中。Application.js包含以下代码//=requirejquery//=requirejquery_ujs//=someotherfiles//=require_directory.即使Application.js中不包含javascript1.js,它也会自动包含,不是吗?那么我怎样才能做我想做的事呢? 最佳答案 单独定义、包含和执行您的java

  9. WebSocket的那些事(1-概念篇) - 2

    目录一、什么是Websocket二、WebSocket部分header介绍三、HTTPVSWebSocket四、什么时候使用WebSockets五、关于SockJS和STOMP一、什么是Websocket根据RFC6455标准,Websocket协议提供了一种标准化的方式在客户端和服务端之间通过TCP连接建立全双工、双向通信渠道。它是一种不同于HTTP的TCP协议,但是被设计为在HTTP基础上运行。Websocket交互始于HTTP请求,该请求会通过HTTPUpgrade请求头去升级请求,进而切换到Websocket协议。请求报文如下:GET/spring-websocket-portfoli

  10. ruby-on-rails - 为 rails 中的 javascript 生成完整的 url(类似于 javascript_path,但是是 url) - 2

    如何生成指向javascript文件的绝对链接。我想应该有类似下面的东西(不幸的是它似乎不可用):javascript_url'main'#->'http://localhost:3000/javascripts/main.js'代替:javascript_path'main'#->'/javascripts/main.js'我需要绝对URL,因为该javascript文件将用于书签。另外我需要相同的css文件。谢谢,德米特里。 最佳答案 javascript和css文件的绝对URL现在在Rails4中可用ActionView::H

随机推荐