明けましておめでとうございます。
Webページに時折配置されている「このページのURLをコピーする」ボタンですが、あると結構便利でして、たまに仕事でも設置を依頼されます。
ですがこのボタン、意外とややこしい。
早速結論
私は優秀なので結論から書きますね、以下のコードをコピペすれば完成です。
(クリックイベントの対象は適宜変更して下さい、aタグでもbuttonタグでも問題無いです)
$('#copy-url').click(function () { const url = window.location.href; if (navigator.clipboard) { navigator.clipboard.writeText(url) .then(() => { console.log('URL copied successfully'); }) .catch(err => { console.error('Failed to copy URL: ', err); }); } else { // Clipboard APIがサポートされていない場合の代替手段 const tempInput = document.createElement('input'); tempInput.value = url; document.body.appendChild(tempInput); tempInput.select(); document.execCommand('copy'); document.body.removeChild(tempInput); console.log('URL copied successfully'); } });
さて解説
さて、表題のボタンを作ろうとした場合、方法は「document.execCommand(‘copy’)」を使う方法と「navigator.clipboard.writeText()」を使う方法の2つがあります。
前者は比較的古い手法で非推奨になっており、後者は新しい手法だが未対応のブラウザがあるかも、といった具合です。
2つの違いをChatGPTさんに説明してもらいました↓
・サポート範囲:
document.execCommand(‘copy’)は比較的古い方法であり、ほとんどの主要なブラウザでサポートされていますが、古いブラウザや一部の環境では正しく動作しないことがあります。
navigator.clipboard.writeText()は比較的新しいAPIであり、モダンなブラウザでサポートされていますが、古いブラウザではサポートされていないことがあります。
・セキュリティ:
document.execCommand(‘copy’)は、ページがクリップボードにアクセスできるように許可されている場合に限り、クリップボードにアクセスできます。
しかし、この方法はセキュリティ上の懸念があります。
なぜなら、ページがクリップボードに何かをコピーすることができるだけでなく、ページがユーザーのクリップボードから情報を読み取ることもできるからです。
navigator.clipboard.writeText()は、ブラウザのセキュリティ上の制約に従い、ユーザーが明示的に許可した場合にのみクリップボードにアクセスできます。
そのため、より安全な方法と見なされます。
したがって、セキュリティ上の理由や古いブラウザへの対応が必要な場合は、document.execCommand(‘copy’)を使用することが適切です。
一方、モダンなブラウザのみを対象とし、セキュリティを重視する場合はnavigator.clipboard.writeText()を使用することをお勧めします。
現在ではほとんどのモダンブラウザが対応済みのようです。
参考サイト↓
https://developer.mozilla.org/ja/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard
navigator.clipboard.writeText()に軍配
これを考慮すると、navigator.clipboard.writeText()を使うのが良さそうです。
ただ1点懸念がありまして、navigator.clipboard.writeText()は「HTTP://(非SSL)環境」だと動かないのです。
「今どきどこもhttps対応してるだろ」と思うかもしれませんが、案件によってはテスト環境のみ未対応、みたいなことがありまして。。
なので、「未対応のブラウザがある」「http環境だと動作しない」の2点を考慮して出来たのが最初のコードです。
「navigator.clipboard」が対応していたらそっちで、未対応ならexecCommandを使うよう分岐しています。
なのでどっちのパターンでもバッチリ!って寸法ですわ。
おまけ:コピー成功したメッセージを出したい場合
もし「URLをコピーしました」みたいなメッセージを表示したい場合は、以下のようにフェードイン&フェードアウトすれば良いでしょう。
(navigator.clipboard.writeTextの呼び出しは非同期処理なのでthenの中に記述する必要があります)
$('#copy-url').click(function () { const url = window.location.href; if (navigator.clipboard) { navigator.clipboard.writeText(url) .then(() => { console.log('URL copied successfully'); $('#msg').fadeIn('slow', function () { $(this).delay(1000).fadeOut('slow'); }); }) .catch(err => { console.error('Failed to copy URL: ', err); }); } else { // Clipboard APIがサポートされていない場合の代替手段 const tempInput = document.createElement('input'); tempInput.value = url; document.body.appendChild(tempInput); tempInput.select(); document.execCommand('copy'); document.body.removeChild(tempInput); console.log('URL copied successfully'); $('#msg').fadeIn('slow', function () { $(this).delay(1000).fadeOut('slow'); }); } });
余談:検索して「非推奨」って出ると「うわぁめんどくさいよぅ」ってなりますよね。。