テキストをクリップボードにコピーする

inputやtextareaの内容をクリップボードにコピーする実装を行う機会があったので、その際に調べたことをメモ。

サンプルコード

ボタンをクリックした時に、任意のテキストをクリップボードにコピーするようにしてみます。

<button id="btn">クリップボードにコピー</button>

クリップボードへのコピーはClipboard APIを使います。

var btn = document.getElementById('btn');
btn.addEventListener('click', function(e) {
	copy_to_clipboard('ここの内容をコピーします。');
});

function copy_to_clipboard(value) {
	if(navigator.clipboard) {
		var copyText = value;
		navigator.clipboard.writeText(copyText).then(function() {
			alert('コピーしました。');
		});
	} else {
		alert('対応していません。');
	}
}

Clipboard APIでクリップボードにコピーするデモページ

これでクリップボードへのコピーが実装できましたが、この方法はIEやiOS13以下の端末など一部対応していません。
Clipboard APIの対応ブラウザはこちら

別の方法として、execCommand()を使用する方法があります。
Clipboard APIの場合はコピーするテキストを指定できましたが、execCommand()の場合はページ上で選択状態のテキストをコピーする形になるため、先ほどのデモと実装方法が少し異なります。

execCommand()を使う注意点として、execCommand()は既に廃止されており、execCommand()でのコピーに取って代わるようにClipboard APIが設計されています。

記事を作成した時点では動作しているようですが、将来的に動作しなくなる可能性が高いので、使用する場合はご注意ください。

execCommand()の例として、入力エリアにフォーカスを当てた際にクリップボードにコピーするようにしてみます。

<input type="text" class="js-copy-to-clipboard" value="https://cly7796.net/blog/">
<textarea class="js-copy-to-clipboard">
cly7796.net
https://cly7796.net/blog/
</textarea>

.js-copy-to-clipboardに対してコピーの処理が適用される措定です。
クリップボードへのコピーは、setSelectionRange()でテキストを選択状態にした上で、execCommand(‘copy’)を使って行います。

var copyArea = document.querySelectorAll('.js-copy-to-clipboard');
for (var i = 0; i < copyArea.length; i++) {
	copy_to_clipboard(copyArea[i]);
}

function copy_to_clipboard(target) {
	target.addEventListener('focus', function(e) {
		// 内容を全選択
		target.setSelectionRange(0, 999999);
		// クリップボードにコピー
		document.execCommand('copy');
	});
}

9行目のsetSelectionRange()は最初はselect()を使って全選択するようにしていたのですが、iOSの場合に上手く全選択されなかったためsetSelectionRange()を使用する形に変更しました。

これでフォーカスを当てた際にクリップボードにコピーされるようになりました。
execCommand()でクリップボードにコピーするデモページ

iOSでも対応する場合の補足として、iOSでコピーしたい場合は以下のような条件があるようです。

  • inputとtextareaからのみコピーが可能
  • form内にない場合はcontenteditable属性がtrueである必要がある
  • readonly属性がtrueの場合はコピーできない
  • コピーするテキストが選択されている状態である

参考記事はこちらで、各項目を全て確認はできていないですが、手持ちのiOS12の端末でform外のinput要素でcontenteditable属性がfalseの場合でもコピーできるようだったので、バージョンによって変わっている可能性がありそうです。

先ほどのデモでは入力エリアのテキストを全選択した上でコピーしていましたが、Clipboard APIの時のようにボタンをクリックした時に指定したテキストをコピーできるようにしてみます。

<button id="btn">クリップボードにコピー</button>

仕組み上ページ内にあるテキストが選択されている必要があるので、コピー用の仮のtextareaをコピー時のみ追加する形で実装してみます。

var btn = document.getElementById('btn');
btn.addEventListener('click', function(e) {
	copy_to_clipboard('ここの内容をコピーします。');
});

function copy_to_clipboard(value) {
	// コピー用のtextareaを生成
	var textarea = document.createElement('textarea');
	textarea.style.position ='absolute';
	textarea.style.opacity = 0;
	textarea.style.pointerEvents = 'none';
	textarea.value = value;

	// 一時的にtextareaをページに追加して、コピー後に削除
	document.body.appendChild(textarea);
	textarea.focus();
	textarea.setSelectionRange(0, 999999);
	document.execCommand('copy');
	textarea.parentNode.removeChild(textarea);
}

IEだとコピー時にアラートが表示されて一時的に処理が止まり、textareaが見えてしまうため、9~11行目のstyleで見えないようにしています。
execCommand()でクリップボードにコピーするデモページ2

これでexecCommand()を使ったコピーもできるようになったので、最初のClipboard APIのデモでClipboard APIに対応していなかった場合にexecCommand()を使う形にしてみます。

var btn = document.getElementById('btn');
btn.addEventListener('click', function(e) {
	copy_to_clipboard('ここの内容をコピーします。');
});

function copy_to_clipboard(value) {
	if(navigator.clipboard) {
		var copyText = value;
		navigator.clipboard.writeText(copyText).then(function() {
			alert('コピーしました。');
		});
	} else {
		copy_to_clipboard_for_old_browser(value);
	}
}

function copy_to_clipboard_for_old_browser(value) {
	// コピー用のtextareaを生成
	var textarea = document.createElement('textarea');
	textarea.style.position ='absolute';
	textarea.style.opacity = 0;
	textarea.style.pointerEvents = 'none';
	textarea.value = value;

	// 一時的にtextareaをページに追加して、コピー後に削除
	document.body.appendChild(textarea);
	textarea.focus();
	textarea.setSelectionRange(0, 999999);
	document.execCommand('copy');
	textarea.parentNode.removeChild(textarea);
}

これでClipboard APIに対応していない場合はexecCommand()を使ってコピーするようになりました。
Clipboard APIとexecCommand()を使ったデモページ

参考サイト

このエントリーをはてなブックマークに追加

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2021年9月
 1234
567891011
12131415161718
19202122232425
2627282930