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()を使ったデモページ
コメントが承認されるまで時間がかかります。