Techvenience

Technology × Convenience - Vue / React / Next / Nuxt / ChatGPTなどのIT技術がもたらす便利さをお伝えします。最近はChatGPTなどのAI技術を使ってブログを書いています。

javascriptでクリップボードに文章をコピーする

javascriptでクリップボードに文章をコピーする

f:id:duo-taro100:20160218004611p:plain

今回はjavascriptでクリップボードに文章をコピーする方法を記載します。
いくつか方法を試しましたが、今回ご紹介する方法が最善かと思います。

textareaを作成してコピー??

今回ご紹介する方法以外に、 コピーしたいテキストを取り出して、createElementで作成したtextareaにその文章を入れ込み、選択させた状態にしてからコピーするというものがありました。
この方法でも動きましたが、iosのsafari??などで分岐が必要になったり、iosでコピーできない状況があったりしたので別の方法を探しました。

htmlの作成

まずはコピーしたい箇所のhtmlです

<p id="target">コピーしたい文章です!!</p>

javascriptの実装

今回ご紹介する方法は以下の通りです。
詳細解説は後述。

const ele = document.querySelector('#target');
const selected = window.getSelection();
const range = document.createRange();
range.selectNodeContents(ele);
selected.removeAllRanges();
selection.addRange(range);
const isSuccess = document.execCommand('copy');
selected.removeAllRanges();

解説

上記の実装を解説して行きます

要素の取得
// 対象の要素を取得
const ele = document.querySelector('#target');
selectionオブジェクトを取得

selectionオブジェクトを取得します。取得した選択文字列に対して処理を行うために必要です。
developer.mozilla.org

前述したtextareaやinputなどを使う方法でであれば、select()すればいいですが、今回のようにpタグなどを利用しており、select()が使えない場合にはSelectionが必要になります。

// seletionオブジェクト取得
const selection = window.getSelection();

このSelectionにコピー対象を渡してあげるという実装が必要になりますが、SelectionにはRangeオブジェクトしか渡すことができません。
なのでRangeオブジェクトを作成します。

Rangeオブジェクトの作成

Rangeオブジェクトを作成します。
rangeとは翻訳そのままですが、「範囲」を表すものです。
developer.mozilla.org

    // rangeオブジェクトの作成
    const range = document.createRange();
Rangeオブジェクトの範囲決定

指定した要素の内側を範囲とするための記述です。
今回であればidが「target」のpタグの内側が対象になります。

    // Rangeオブジェクトの範囲決定
    range.selectNodeContents(ele);
SelectionオブジェクトからRangeオブジェクトを削除

Selectionオブジェクトが別のRangeオブジェクトを有していることを考慮して削除しておきます。

    // SelectionオブジェクトからRangeオブジェクトを削除
    selection.removeAllRanges();
SelectionオブジェクトにRangeオブジェクトを追加

先ほど作成したRangeオブジェクトをSelectionオブジェクトに追加します。

    // RangeオブジェクトをSelectionオブジェクトに追加
    selection.addRange(range);
クリップボードにコピー

クリップボードへのコピーを実施します。
成功すればtrue、失敗すればfalseが返るのでそれによって挙動を変えましょう。

    // クリップボードにコピー
    const isSuccess = document.execCommand('copy');
再度SelectionオブジェクトからRangeオブジェクトを削除

初期化の意味を込めてRangeオブジェクトを削除します。

    // Rangeオブジェクトを削除
    selection.removeAllRanges();

最後にハマったことを書いて終わりにします。

preタグからコピーするとGmailに正しく貼り付けができない

最初に実装した時にpreタグを使用していました。

<pre id="target">コピーしたい文章です!!</pre>

この値をコピーしてからGmailに貼り付けようとしても、空白状態となってしまいました。
pタグやdivタグにしたら問題なく動きました。
ちなみにGmail以外のiPhoneメールアプリ、Yahooメールなどは問題ありませんでした。
ご注意ください。

以上。