WebExtensions: 指定した文字列をクリップボードに格納する (コピーする)
概要
Firefox の自分用アドオンで、特定のウェブページを見ているときに、その一部から文字列を構成してクリップボードに格納したい。Content scripts で copy イベントのリスナを使った話。
追記: mdn/webextensions-examples の見てなかった方に例があるのでそちらを見ればよく、このブログは読まなくてよい。
1. manifest.json の permissions に "clipboardWrite" を指定する。2. document.addEventListener('copy', onCopy);
とする。3.(以下 onCopy の話) copy イベントから DataTransfer オブジェクトを取得する。4. setData() でクリップボードに文字列を格納する。
Firefox Developer Edition 54 と 57。なんとなく Google Chrome も試した。
やった
document.execCommand() でやれと述べられるができなかった
見ているウェブページの一部から文字列を構成してクリップボードに格納したい。文字列は選択せずに都合のよいように作りたい。
MDN: Addons: Browser Extensions にニーズそのものである Interact with the clipboard がある。document.execCommand("copy") しろというが、これは文字列を選択しないとコピーできない (ドキュメント)。github mdn/webextensions-examples の selection-to-clipboard もこれを使っている。
WebExtensions 以前はどうやったか。古い話だが、Add-on SDK には clipboard API があり、var clipboard = require('sdk/clipboard');
で利用できた。Comparison with the Add-on SDK の API 比較対照資料にこう書いてある。
document.execCommand without using select() and similar in the background page.
しかしできない。document.execCommand('copy', false, some_text)
とやったができなかった。ほしい文字列 (HTML には存在しない) を選択していることにできればいいが、window.setSelection(任意の文字列) はあるはずがない。
copy イベント経由でデータをセットする
npm モジュールにクリップボードとやり取りするものがあるだろうから (探していない)、それを webpack でバンドルして利用すればできるに決まっている。もっと言えばアドオンでやる必要はない。でもウェブページを見ながらブラウザ上でそのままやりたいしモジュールバンドルはもっとモジュールが明らかに必要な時にやる、ということで情報を探した。
結果 copy イベントがあると判ったので、Ctrl-C でコピーが発生したときのイベントリスナで処理させることにした。
document.addEventListener('copy', onCopy);
して次のようにした。できた。
function onCopy(ev) { //実際に何か選択してるときは動作させたくない if(window.getSelection().toString() === '') { //雑に作ったので構成した文字列をグローバル変数に収めている。あとで直せばいい setTextForCopy(); //HTML を解析して文字列を作って TO_CLIPBOARD に格納する if(TO_CLIPBOARD !== '') { ev.preventDefault(); let transfer = ev.clipboardData; transfer.setData('text/plain', TO_CLIPBOARD); TO_CLIPBOARD = ''; } } } document.addEventListener('copy', onCopy);
Ctrl-C ではなく Ctrl-Y 等別のキーでやりたいときはキー押し下げで document.execCommand("copy") でコピーを発生させればいいけど、このままでは何か選択してたらそれが Ctrl+Y でクリップボードにコピーされてしまう。まあいいか。
なお、Firefox ではなく Google Chrome にローカルフォルダからインストールして使っても動作した。Google Chrome は開発版のリロードが楽でいいですね、という感想を持った。