Javascriptボタンクリックによるテキストのコピー処理
API
Clipboard
copy
ブラウザ上のテキストをコピーする際に、
いつもはキーボード操作(cmd or Ctrl + c)もしくは右クリックからのコピーでおこなっていると思います。
しかしながら、ソースコードをコピペする際にブラウザのテキストをコピーすると無駄な記述が入っていたりしないでしょうか。
ソースコード表示の右肩に用意されているコピー用のボタンはどのような実装がなされているかを解説していきます。
Clipboard API
こちらの機能を実装するにあたって必要な技術は Clipboard APIになります。
MDN クリップボード APIの詳細はこちらから。
モダンブラウザに実装されているこのAPIを使ってPCのクリップボードにデータを送り込むことで、
ペースト(cmd or Ctrl + v)ができるようになります。
Clipboard API の注意点
この機能を使う上でいくつかの注意点があります。
注意点その1
ブラウザの接続がHTTPS接続(安全なコンテキスト)であること。
安全なコンテキストについてはこちらを参照してください。
MDN Web Docs 安全なコンテキスト
例外として
http://127.0.0.1、http://localhost、file://は安全なコンテキストと見なされているようです。
注意点その2
ユーザーの許可が必要となること。
今回使用するwriteText メソッドもしくはwrite メソッドは、
ブラウザのタブがアクティブ(ページが表示され操作の対象とされている)時に自動で権限が付与されるので、
ユーザー許可を求められるポップアップがURLの箇所に表示されることはないですが、
read系のメソッドである、read メソッド、readText メソッドでは、
ユーザー許可を求められます。
Clipboard API を使ってコピー機能の実装
どのように実装するか実際のソースを記載します。
navigator.clipboard.writeText('コピーしたいテキスト')
.then(() => {
// コピーに成功した時の処理
console.log('success')
})
.catch(() => {
// コピーに失敗した時の処理
console.log('failed')
})
copyボタンをクリックすることで、
上記のソースコードをでコピーすることができ、
cmd or Ctrl + v を行うことで貼り付けることができます。
しかしながら、
開発者ツールのConsoleにそのまま貼り付けて実行しても、
failed と表示されてしまう点に注意してください。
というのも、
注意点その2の内容で
ブラウザのタブがアクティブ(ページが表示され操作の対象とされている)時にという旨を記載していました。
貼り付けてそのまま実行してしまうと、
アクティブなのは開発者ツールになっているため失敗してしまいます。
では、開発者ツールで実行して試すためのソースコードは以下になります。
setTimeout(() => {
navigator.clipboard.writeText('コピーしたいテキスト')
.then(() => {
// コピーに成功した時の処理
console.log('success')
})
.catch(() => {
// コピーに失敗した時の処理
console.log('failed')
})
}, 3000)
しかしながら、ソースコードを貼り付けて3秒待っただけでは,
先ほどと一緒の結果(failed)になってしまうので、
3秒以内に開発者ツールの内容であるwebページをアクティブにすることで、
成功の結果(success)が得られるようになります。
本サイト(whyisthis.dev)のコピー機能
本サイトでは、
ソースコードのコピー機能を実装しています。
ただコピーするだけでは、
コピーが成功したのか、失敗したのかわからないため、
成功した際に 「Copied」 と表示する機能も一緒に実装しています。
実際の処理手順
- コピーするテキストを取得する。
- コピーしたテキストを writeText に読み込ませる。
- 読み込みが成功したら Copied のテキストを表示する。
- タイマーを起動して表示終了を通知する。
- Copied のテキストを非表示にする。
上記の処理手順に沿ったコードを記載します。
copyBtn.addEventListener('click', (evt) => {
// コピーするテキストを含む要素を取得する
const copyTxtIncludedElement = document.querySelector('targetCodeElement')
// コピー元の要素からテキストを抽出
const copyTxt = copyTxtIncludedElement.textContent
// クリップボードにテキストを読み込ませる
navigator.clipboard.writeText(copyTxt)
.then(() => {
// Copied のテキストを表示する処理
// 本サイトはクラス名を追加して :before に対して css の content で表示
copyTxtIncludedElement.classList.add('is-copied')
// タイマーを起動: 1秒後にタイマーの終了を通知(resolve)
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, 1000)
})
})
.then(() => {
// タイマーの終了通知を受けて
// Copied のテキストを非表示にする処理
copyTxtIncludedElement.classList.remove('is-copied')
})
})
上記のソースコードはコピーするという機能の記述方法に対してあくまで一例に過ぎません。
Typescriptを使用するとこれとはまた別の書き方が必要になるかもしれません。
ですが基本となる処理の部分は大きく変わらないかと思うので、
参考にしていただけたら幸いです。