JavaScriptでwebページのURLをクリップボードにコピーするボタンを設置

WebサイトやブログでのWebページのシェアはSNS等のボタンを設置することが多いですが、それだけでなく現在観覧しているページのURLを簡単にコピーできるボタンがあるととても便利です。
SNSだけでなくWebメールやFacebookのメッセンジャー、その他いろいろなアプリケーションでのやり取りでURLを簡単に貼り付けたいこともあるでしょう。
もちろん、パソコンですとマウス操作やスマートフォンでもコピー操作はありますが、もっと簡単にボタン1つクリックするアクションだけでクリップボードにコピーして共有したいところです。
そちらのほうがWebを観覧するユーザーにとっても楽だし都合がいいですよね。
親切にボタンを設置してあげましょう。
ここではjQueryやプラグインを使わず、JavaScriptで観覧しているWebページのURLをクリップボードにコピーするボタンを設置する方法をご紹介します。
PCでもスマートフォンでもどちらでもしっかり動くコピー機能のボタンを作成していきます。
ページのURLをコピーするボタンの作成
まずはコピーボタンをHTMLタグで構築していきます。
HTML
<button type="button" id="copy-page">
<span id="cAction">URLをコピー</span>
</button>
aタグなどで return false; でリンクを無効にしておいてボタンとして、onclickイベントハンドラでJavaScriptのイベントを発動させてもいいですが、スマートフォンでHTMLタグのonclick属性の挙動がおかしくしっかり作動しないことがあるので、今回はbuttonタグで作成していきます。
CSSでデザインするためにクラス名「copy-btn」を付けておきます。
クリックした後にコピーが完了したことを伝えるため、spanタグのid「cAction」の要素のテキストが変更できるように準備しておきます。
続いてCSSになります。
サンプルとしては以下のようにスタイルを効かせます。
ボタンのスタイルはご自身のWebサイトやブログに合わせてください。
CSS
#copy-page {
display: inline-block;
width: 160px;
padding: 0.5rem 0;
font-size: 1rem;
text-align: center;
color: #666;
border-radius: 6px;
background: #c7c7c7;
outline: none;
transition: all 0.5s ease;
&:hover {
cursor: pointer;
opacity: .7;
}
}
コピーボタンが構築できましたら、クリップボードへのコピー処理のプログラムをJavaScriptで実装していきます。
JavaScriptでイベント処理
クリップボードへのコピーは、navigator.clipboard.writeTextメソッドを利用します。
引数の中に、現在開いているWebページのURLを取得する location.href をセットすることで、直接クリップボードへ安全に文字を書き込むことができます。
今回ご紹介する方法は、要素を作ったり消したりしない仕様のため、スマートフォン(iOS/Android)や最新ブラウザでも非常に安定して動作させることができます。
また、今回は他のJavaScriptと変数名がバッティングしてサイトが壊れるのを防ぐために「即時関数」を、ボタンが連打されたときのタイマーバグを防ぐために「フラグ変数」を組み込んだ、より実用的なコードにしていきます。
それでは見ていきましょう。
まずは document.getElementById で対象のボタンのidをセット。そしてボタンがクリックしたときにイベントが発生するよう onclickイベントでの関数を定義していきます。
JavaScript
document.getElementById("copy-page").onclick = (() => {
const txt = document.getElementById("cAction");
let isTicking = false;
return () => {
if (isTicking) return;
isTicking = true;
navigator.clipboard.writeText(location.href)
.then(() => {
txt.textContent = "コピーしました";
setTimeout(() => {
txt.textContent = "URLをコピー";
isTicking = false;
}, 2000);
})
.catch(err => {
console.error("コピーに失敗しました: ", err);
txt.textContent = "コピー失敗";
isTicking = false;
});
};
})();
関数の処理の内容としては、
まず document.getElementById で対象のボタン要素を取得し、そのonclickイベントに対して即時関数を定義してイベントハンドラー(クリック時の処理)をセットします。
即時関数の中では、始めに変数 txt に文字の書き換え対象である cAction の要素を格納し、あわせて連打防止用のフラグ変数 isTicking を false(初期状態)で定義しておきます。このように関数の外側(初期化時)で要素や変数をあらかじめ取得・定義しておくことで、ボタンがクリックされるたびに毎回要素を探しにいく無駄な処理が発生せず、パフォーマンスを高めることができます。さらに、これらの変数はこの処理の中に完全に閉じ込められるため、他のJavaScriptと変数名がバッティングしてサイトが壊れる心配もありません。
そして、クリック時に実際に実行される関数を return で返します。
クリックされた際の処理としては、まず if (isTicking) return; で現在処理中(ロック状態)であるかを確認します。もし処理中であればその後の処理をすべて無視し、そうでなければ isTicking = true; に書き換えて処理をロックします。
これにより、ユーザーがボタンを連打したときにタイマーの挙動がおかしくなるのを防ぎます。
次に、本題であるクリップボードへのコピー処理を行います。
今回のクリップボードへのコピーは、ブラウザ機能である navigator.clipboard.writeTextメソッドを利用します。
引数の中に、現在開いているWebページのURLを取得する location.href をセットすることで、従来のやり方のようにわざわざ見えない textarea を生成して範囲選択するような複雑な処理を一切挟むことなく、ブラウザが直接クリップボードへ安全に文字を書き込んでくれます。要素を作ったり消したりしない仕様のため、スマートフォン(iOS/Android)や最新ブラウザでも非常に安定して動作させることができます。
writeTextメソッドによるコピーは非同期処理(Promise)で行われるため、処理が成功した後の挙動を .thenメソッドの中に記述していきます。
無事にコピーが完了したら、ユーザーに完了したことが伝わるように、あらかじめ格納しておいた変数 txt の textContent を利用してボタンのテキストを「コピーしました」に変更します。 その後、setTimeout関数を利用して2秒(2000ミリ秒)のタイマーを設定します。2秒が経過したらボタンのテキストを元の「URLをコピー」に戻し、最後に isTicking = false; とすることで連打防止のロックを解除し、再びボタンがクリックできる状態に戻します。
また、万が一ブラウザの権限設定などでコピーが拒否された場合に備え、.catchメソッドでエラーをキャッチし、コンソールにログを出力しつつ、画面上の文字を「コピー失敗」に変更してロックを解除する処理も合わせて記述しています。
ここまでで、バッティングや連打に強い最新のクリップボードへのコピー処理が完了となります。
注意:本番環境ではHTTPS(SSL化)が必須です
今回使用している Clipboard API は、セキュリティ上の理由から https:// から始まる安全なページでのみ動作する仕組みになっています。
自身のPCでテストする http://localhost などのローカル環境では、例外的に動作する場合もありますが、本番環境のサーバーへアップする際は、サイトのSSL化が必要になりますのでご注意ください。
まとめ
このブログでもJavaScriptで実装したURLがコピーできるボタンを設置しています。あとはちょっとアイコンも付けちゃってコピーボタンとわかりやすいデザインにしています。
人気のSNSのシェアボタンだけでもいいですが、現在観覧しているページのURLのコピーを簡単にできるようにしたほうが臨機応変に対応できるので、一緒にボタンを設置しておいた方が良いのではないでしょうか。
今回ご紹介した方法はPCでもスマートフォンでもどちらでも動く仕様となっていますので是非、親切に自分のデザインでコピーボタンを設置してみてください。