那些被忽略但很好用的 Web API / Clipboard

CTRL + C & CTRL + V,两个指令就能让你成为工程师。

Selection API 掌管着网页中的「反白」,Clipboard API 则是掌管着网页中的「复制」,不管是做报告、分享文章或是写 code,都时常会参考、借监网页中的内容,这时候我们就会执行「复制」,将文本内容暂时放在电脑里的记忆体中,而这项动作只要是发生在我们网页中,我们就可以利用 Clipboard API 来动一些手脚。


Clipboard

Clipboard 指的是浏览器中的系统剪贴簿,我们可以透过一些指令来访问它,进而执行读写的动作,不过由於使用者可能会将一些机敏性的资料存放在剪贴簿中,所以为了避免个资外泄,除非使用者允许授权,不然浏览器都会限制网页读取使用者的剪贴簿,不过写入的部分就没有限制了。

https://ithelp.ithome.com.tw/upload/images/20210925/20125431SR4OG5meln.png

如果使用者拒绝了授权,只能透过使用者主动调整授权才能够开启功能,所以记得透过 Permissions.query() 来确认授权状态,并提醒使用者。

# Navigator.clipboard

要取得浏览器的 Clipboard 物件,只要访问 navigator 底下的 clipboard 属性即可:

const board = navigator.clipboard;
console.log(board) // Clipboard 物件

 

# Clipboard.readText

取得 Clipboard 物件後,我们就可以使用它自身的 method 来读写剪贴簿了,而 readText 就是让我们可以读取剪贴板目前储存的文本内容,呼叫它後会回传一个 Promise,需要用 then 来串接并取得文本:

<button>Get Clipboard</button>
<script>
  const button = document.querySelector('button');
  button.addEventListener('click', function() {
    navigator.clipboard.readText().then(text => {
      console.log(text) // 剪贴簿中的文本内容
    });
  });
</script>

你该注意:

  1. 有些浏览器可能会阻止「直接命令」剪贴簿,最好是透过使用者点击按钮或监听事件来处理。
  2. navigator.clipboard 取得的是当下视窗的系统剪贴簿,所以如果你是透过 Console 面板执行的话有可能会报错,因为它是在「开发者工具」视窗下执行的。

 

# Clipboard.writeText

知道怎麽「读」之後,就要来看看怎麽「写」了,writeText 可以让我们修改目前使用者储存在剪贴簿的内容,只要将指定内容当作参数传入即可,另外在执行後依然会回传 Promise,当修改成功後便可以执行 then 中的 Callback,或是在失败後进行 Error Handle。

<button>Set Clipboard</button>
<script>
  const button = document.querySelector('button');
  button.addEventListener('click', function() {
    const text = "你复制的东西被我变成这段文字了";
    navigator.clipboard.writeText(text)
      .then(() => alert("success"))
      .catch(() => alert("fail"))
  });
</script>

 

ClipboardEvent

除了可以主动操作 Clipboard 物件以外,浏览器还提供了一些剪贴簿的相关事件让我们监听,当使用者执行 cutcopypaste 的操作时,便能透过事件 Callback 执行指定动作,且 Callback 所获得的 Event 物件当中还会多一个 clipboardData 属性,该属性也会有自身的 method 可以使用。

# Event.clipboardData.getData

getData 可以让我们取得剪贴簿中的资料,它有一个必传的参数是资料格式,一般来说都是使用 "text/plain" 来指定「纯文字资料」。

它和前面提到的 Clipboard.readText 功能基本一样,但要注意这两者所属的物件是不同的。

// 让整个网页可以进行编辑,这样才能触发贴上事件
document.designMode = "on"
// getData 通常搭配 paste 事件,在 cut、copy 事件中使用会拿不到东西
document.addEventListener('paste', function(e) {
  const clipboardText = e.clipboardData.getData('text/plain');
  console.log("使用者贴上了文字:" + clipboardText)
});

 

# Event.clipboardData.setData

不晓得各位有没有在他人部落格中复制程序码後,发现贴上後的内容多了几行作者的着作申明?其实这样的功能就是透过 setData 做到的,它可以让我们修改使用者剪贴簿内容。

它和前面提到的 Clipboard.writeText 功能基本一样,但要注意这两者所属的物件是不同的。

// setData 通常搭配 cut、copy 事件,在 paste 事件中使用会没有效果
document.addEventListener("copy", function(e) {
  // 利用昨天认识的 Selection API 取得使用者反白的文字
  const selectionText = window.getSelection().toString();
  const extraText = "\n注意:你复制的这段文字属於 Max";
  e.preventDefault(); // 阻止使用者本来要执行的「复制」动作
  e.clipboardData.setData("text/plain", selectionText + extraText);
});

其实在 Clipboard API 被广泛的被浏览器采用前,要处理剪贴簿都是透过 document.execCommand,但因为它有不少缺点,所以逐渐被取代,如果各位有兴趣知道的话,可以再去搜寻了解。

 

其实你有注意的话,今天的示范程序码中有出现 DesignMode 和 Selection 的身影,这三者其实常常一起使用,这也就是为什麽我会在前面的章节一直提到要等三个 Web API 一起介绍完後,再来实际做一个文章编辑器的应用。到了今天我们终於把它们通通习得了,就准备明天动手写吧!


<<:  Day#10 初始专案...again (+版本控制)

>>:  Day12:全端工程师的生活常态

[Day22] JavaScript - Fetch API

第18篇有提到过Fetch的用法(连结),这篇要实际使用Fetch来做简单的Api串接。 首先介绍一...

Day3 风生水起,观元辰宫的火

在上一篇,除了水以外,这一篇就来讲火 五行中的火,除了"灶"以外,防火也是门学问...

Day 7-单元测试 NUnit 更多常用的特性-2 (基础-6)

如何撰写测试验证例外 — ExpectedExcetption 与 Assert.Throws(de...

[Day23] 如何让 Scrum Master 的经历为履历加分

这两年看过不少应徵工程师职缺的履历,会描述当过 Scrum Master 经历。在面试中,我如果针对...

[Day 13] - 初探永丰银行线上收款API - 丰收款 - 取得Nonce

取得Nonce 根据规格书的说明,每次呼叫api前都要先取得Nonce 要取得Nonce也满简单的,...