WebでHTMLをいい感じにコピーさせる
こんにちは id:mstssk です。
Webサービスを作っていると、何かしらをユーザーにコピーして使ってもらうというシチュエーションが出てきます。 WebページをシェアするためにURLのコピーボタンが置いてある、なんていうのはよく見かけますね。
しかし、ある程度複雑なコンテンツはHTML情報としてコピーさせたい事が稀にあります。 画像やリンクを含んだHTMLです。
そこで、もう少し欲張って、こういうことが出来ないか調べてみました。
3行まとめ
動作サンプル
以下、解説。
Webブラウザのクリップボード API
最近のWebブラウザにはPCのクリップボードを操作するAPIが標準搭載されており、JavaScriptを数行書くだけで任意のテキストをコピーさせられます。
// 「ほげほげ」というテキストをコピーする場合 copyButton.addEventListener("click", () => { navigator.clipboard.writeText("ほげほげ") .then(()=> console.log("copied!")); });
好き勝手にクリップボードを操作できるわけではなく制約があります。 ユーザーがボタンをクリックしたりとか何かしら操作を行った時だけクリップボードへのアクセスが許可されています。
このクリップボード APIはどのWebブラウザにもある機能ですが、2020年5月現在ではテキストまたは画像ファイルしかコピーさせられません。
2020/07/10 追記
Safari 13.1.1ではクリップボード APIでtext/htmlのコピーが行えるようです。
クリップボードAPIの制限については、執筆時点のものであり、またブラウザごとに対応状況も違っています。 この記事を参考にする前にクリップボードAPIの最新の実装状況を確認するのをおすすめします。
HTMLコピーを無理やり実現するやり方
Hackyなやり方ですが、Chrome, Safari, Firefoxで動く実装はあります。
document.execCommand("copy");
でコピー動作を直接呼び出す方法は、クリップボードAPIが登場する以前はずっと使われてきましたが、現在では非推奨とされています。
しかし、今回はクリップボードAPIで未対応のデータ(HTML)を扱うため致し方ありません。
実際の実装は以下の通り。 行っているのは、ユーザーがマウスでWebページ内を範囲選択してコピーしているのと同じ事をJavaScriptからやっているだけ。 ただし、プレーンテキストの情報も持たせるために一工夫しています。
const html = `<a href="https://example.com/"> <img src="https://github.com/viibar.png"> </a>`; copyButton.addEventListener("click", () => { // コピー対象にするダミー要素 const elem = document.createElement("span"); elem.style.height = "0px"; elem.style.width = "0px"; elem.innerHTML = html; // ダミー要素の中身が無いとSafariで動作しないので。 document.body.appendChild(elem); // ダミー要素を選択状態にする const range = document.createRange(); const selection = document.getSelection(); selection.removeAllRanges(); range.selectNodeContents(elem); selection.addRange(range); // コピーが行われたとき、コピーデータをすげ替える。ここが一工夫。 document.addEventListener("copy", function listener(event) { event.preventDefault(); event.clipboardData.setData("text/html", html); // for WYSIWYG event.clipboardData.setData("text/plain", html); document.removeEventListener("copy", listener); console.log("copied!", event); }); // コピー実行 document.execCommand("copy"); // 選択状態解除とダミー要素削除 selection.removeAllRanges(); document.body.removeChild(elem); });
実際に貼り付けてみた場合のスクリーンショット
WYSIWYGエディタやMS Wordなんかは、HTMLを解釈してそういうコンテンツとして貼り付けられます。
Gmailのメール作成画面(WYSIWYG) | MS Word |
---|---|
WYSIWYGエディタやWordにただのテキストとして貼り付けたいときは、右クリックメニューにオプションがあるはずです。
ただのテキストエディタでは、HTMLのソースコードをテキストとして貼り付けられます。
Visual Studio Code |
---|