LoginSignup
2
0

More than 1 year has passed since last update.

Clipboard APIについて(JavaScript)

Last updated at Posted at 2023-03-04

この記事では、JavaScriptのClipborad APIを使って、クリップボードにテキストをコピーする方法と、その周辺についてまとめています。
主なターゲットとして

  • ボタンを押したらテキストをコピーできる機能を作りたい人
  • document.execCommand()(後述)を使っている人

を想定しています。

「ボタンを押す→テキストをコピー」

Atcoderなどの競プロサイトや、Qiitaなどの技術記事投稿サイトでよく見られる機能です。
Copy ボタンを押すことで、入力例やコードをクリップボードにコピーしています。

これを実現する方法はいくつか存在しています。

Atcoder

AtcoderではCommandline APIに用意されているcopy()関数を利用しています。

if (document.queryCommandSupported('copy') && (typeof PRINT === 'undefined')) {
...
}
$('.btn-copy').click(function() {
	window.getSelection().removeAllRanges();
	try {
		copy($('#'+$(this).data('target')).text()); // <- ここ!
        ...
	} catch (err) {
		console.log(err);
	}
	window.getSelection().removeAllRanges();
});

Commandline APIの関数が使用できるかを確かめるためにはdocument.queryCommandSupported(command)を利用します。

const flag = document.queryCommandSupported("SelectAll");
if(flag) {
  copy('Hello world!');
}

しかしこの機能は非推奨です。

非推奨: この機能は非推奨になりました。まだ対応しているブラウザーがあるかもしれませんが、すでに関連するウェブ標準から削除されているか、削除の手続き中であるか、互換性のためだけに残されている可能性があります。使用を避け、できれば既存のコードは更新してください。このページの下部にある互換性一覧表を見て判断してください。この機能は突然動作しなくなる可能性があることに注意してください。

記事執筆時点(2023年3月)において、全てのブラウザにおいて互換性がありますが、

この機能は、現在のどの仕様にも含まれていません。標準化される予定もありません。

当面この機能は使い続けられるだろうと思っていますが、これからクリップボードの操作を勉強しようと思っている人にはお勧めできません。

Qiita

Qiitaが使っている機能はAtcoderとは少し異なります。

HTML文書がdesignModeに切り替わっているときに利用できるexecCommandに用意されているcopyコマンドを利用しています。

...
const e = document.createRange();
e.selectNode(t);
const n = window.getSelection();
n && (n.removeAllRanges(),
n.addRange(e),
document.execCommand("copy"), // <- ここ!
...

Rangeインターフェースをクリップボードにコピーしています。

RangeDocument.createRange()で生成することができます。また、Selection.getRangeAt()document.caretRangeFromPoint()で選択することもできます。

しかし、これもまた非推奨です。

非推奨: この機能は非推奨になりました。まだ対応しているブラウザーがあるかもしれませんが、すでに関連するウェブ標準から削除されているか、削除の手続き中であるか、互換性のためだけに残されている可能性があります。使用を避け、できれば既存のコードは更新してください。このページの下部にある互換性一覧表を見て判断してください。この機能は突然動作しなくなる可能性があることに注意してください。

代替: Clipboard API

document.execCommand()ページには次のようなメモが書いてあります。

メモ: このメソッドは廃止されており、使用すべきではありません。特に、クリップボードを操作したい場合は Clipboard API の使用を検討してください。

これまで使われてきたCommandline APIやdocument.execCommand()の代替として提示されているのがClipboard APIです。

この API は、 document.execCommand() を使用したクリップボードへのアクセスを置き換えるように設計されています。

Clipboard APIには4つのメソッドがあります。

  • クリップボードへの書き込み系(write / writeText)
  • クリップボードの読み出し系(read / readText)

読み込み・読み出しでそれぞれ2つのメソッドが用意されていますが、writeText/readTexttext/plain専用であり、write/readは一般のblobに対して操作を行うことができます。

しかしClipboard APIにもいくつか問題点があります。

read/readTextはユーザーのクリップボードを覗くという性質上、Permissionが必要となります。

クリップボードからデータを読み込むには、権限 API の "clipboard-read" 権限を得る必要があります。

しかし現在存在する数多のAPIでは、Permissionの処理に一貫性がありません。そのため現在はPermission APIが開発中ですが、Firefoxなど複数のブラウザには互換性がない状態です。

今回はread/readTextを呼び出す際にPermmisionを得れば良いだけですが。

これとは別に、(たとえ間違ってでも)Permission Denyしてしまうと、Permissionを与え直すことが不便であるという問題も存在します。

パーミッションのプロンプトから位置を決して共有しないことを選択した場合(パーミッションを拒否した場合)、ブラウザーのメニューオプションを使用しないとパーミッションのプロンプトに戻ることはできません。

こればかりは避けては通れない課題ですね。

しかし、write/writeTextをするだけであれば構わないのでは?というのが正直なところ。

#clickbuttonを持つ要素がクリックされたときに、そのelement.textContentをクリップボードにコピーするコードは以下のようになります。

...
<div id="clickbutton">
    Here is the test content.
</div>
const clickClip = (e) => {
    const btn_content = e.target.textContent;
    navigator.clipboard.writeText(btn_content)
        .then(() => {
            console.log("Success!");
        },
        () => {
           console.log("Ops, something went wrong...");
        });
};

document.querySelector('#clickbutton').addEventListener('click', clickClip);

おわりに

最後までご覧いただきありがとうございます。
JavaScriptからクリップボードを使ってみたいと思って調べたところ、過渡期にあることがわかったので記事にしました。

普段はWeb開発をしています。
所属している研究室のWebサイトも作ったので是非みてください。

(近々、Clipboard APIを使ったデザインが登場する予定...楽しみ!)

それでは。

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0