Blogger:リンクのコピー(5)Firefox QuantumではFoxy Gesturesを使う

2018-03-18

旧ブログ

t f B! P L
Make Linkでhtml/textのコピーがうまくできなくなったので、『Firefox 57.0 (Quantum)』で『FireGestures』と『Make Link』が使えなくなって途方に暮れたかと思ったけど、『Foxy Gestures』で代替できたので問題なかった - 紙とエンピツ_ブログ版で紹介されていたたFoxy Gesturesを使うことにしました。

前の関連記事:Blogger:リンクのコピー(4)url2clipboardでtext/htmlのリンクを作成


Foxy GesturesをFirefox Quantumにインストール


Firefox Quantumからツール→アドオン。

Foxy Gesturesで検索してでてきたFoxy Gesturesをインストールしました。

Foxy Gesturesに「タイトルとURLをコピー」するスクリプトを追加する


Firefox 57(Quantum)で動かなくなった「FireGestures」の代替に選ばれたのは、「Foxy Gestures」と往年の名ソフトでした。 | texst.net

これの「タイトルとURLをコピー」のスクリプトをコピーします。

Firefox Quantumのツール→アドオン。

Foxy Gesturesの「設定」をクリック。

User Scriptsタブをクリック。


他の人に勧められてここにコピペするのは危険がある、とか書いてあります。

これを理解したうえで「I accept the risks」をクリック。

「Add User Script」をクリック。

今度はこのスクリプトを起動する操作を登録します。

「Other Gesutures」タブをクリック。


Enable chord gesturesにチェックをつけてRight + Leftのリストボックスの中にあるUser Scripts欄から先ほど追加したスクリプトを選択します。

これでマウスの右ボタンを押したまま左ボタンを押すとクリックしたページのタイトルがクリップボードがコピーされます。


ページの右下に実行されたスクリプト名が表示されるので、スクリプトが実行されたことがわかります。

このスクリプトはページタイトルとURLを続けたものをコピーするだけなのでリンクのコピーにするためには改造が必要です。

Foxy GesturesのUser Scriptの作成方法の解説


User Scriptで使えるAPIの解説はUser Scripts · marklieberman/foxygestures Wiki · GitHubにありました。

User ScriptはJavaScriptで書きます。
executeInBackground(func, args);
この関数に実行させたい関数funcとその引数の配列argsを渡すとPromiseが返ってきます。

引数はJSONに直列化されるのでDOMは渡せません。

Promiseを使う - JavaScript | MDNにPromiseの解説があります。

Promiseのthen()メソッドの引数のコールバック関数にはfuncの戻り値が渡されます。

この他次の関数が紹介されています。

getCurrentWindow()

現在のウィンドウを引数に返すPromiseを返します。

getCurrentWindowTabs()

現在のタブの配列を引数に返すPromiseを返します。

getActiveTab(callback)

現在のタブを引数にとるコールバック関数を渡します。

Promiseとかコールバック関数の解説は言葉では説明しにくいので、Firefox 57(Quantum)で動かなくなった「FireGestures」の代替に選ばれたのは、「Foxy Gestures」と往年の名ソフトでした。 | texst.netにあるスクリプトの例がわかりやすいです。

すぐ確定できない変数を引数にする関数をPromiseに渡しておき、Promiseのthen()メソッドにそのPromiseに渡しておいた関数の戻り値を引数にする関数を渡しておきます。

変数が確定するとPromiseに渡しておいた関数が実行され、then()メソッドに渡した関数に引数が渡されて実行されます。

リンクをコピーするスクリプトの作成

executeInBackground(() => 
 getActiveTab(tab => '<a href="' + tab.url + '">' + tab.title + '</a>')
  , []
).then(txt => {
 const oncopy = (ev) => {
  ev.clipboardData.setData("text/plain", txt);  // textとしてペーストするとき。必須。これがないとクリップボードに何も渡されない。
  ev.clipboardData.setData("text/html", txt);  // htmlとしてペーストするとき。
  ev.preventDefault();  // デフォルトの動作を止める。そうしないとクリップボードに元の値が入ってしまう。
  ev.stopPropagation();  // これよりイベントの伝播を止める。
 };
 document.addEventListener("copy", oncopy, true);  // targetは何でもよいので、capture phase、つまりドキュメントから行きの伝播を捉える。
 document.execCommand("copy"); 
 document.removeEventListener("copy", oncopy, true);  // リスナーの除去。
});
試行錯誤のうえようやくこれで思った通りの動作が得られました。

Blogger:リンクのコピー(3)Format LinkでFirefox Quantumへ対応

ここで調べたCreate LinkとFormat Linkのやり方を参考にしました。

Create Linkではまずtextareaの要素を作成してそれを選択してコピーしていますが、そうしなくてもcopyイベントの引数から取得したclipboardDataにデータをセットすればペーストできました。

LibreOffice5(122)Javaの例: ClipboardをPythonにするでやったようにクリップボードには複数のMIMEタイプを指定できるので、text/html形式とtext/html形式の二つを指定しています。

text/html形式だけの指定だとテキストエディタではペーストメニューがでてこなくなります。

preventDefault()でデフォルトコピーイベントをキャンセルしないとクリップボードの内容が更新されませんでした。

stopPropagation()はなくても動作しますが、それ以上のイベントの伝播は無駄なのでここで止めています。

Blogger:ページ番号付ページナビ(9)Paginavi2_Bloggerモジュールの導入

イベントバブリングについてはここでやりました。

addEventListenerの第3引数の意味 | JavaScript プログラミング解説

addEventListener()の第3引数でtrueを渡してイベントフェーズのCapture Phaseでイベントを捉えるようにしています。

Promiseを使っているのでイベントリスナーを使わなくても行けそうなのですが、ClipboardEvent以外からのクリップボードの取得方法がわかりませんでした。

選択文字列があればページタイトルの代わりにコピーするスクリプト


Create LinkやFormat Linkと同様に文字列を選択しているときはその文字列をページタイトルの代わりにテキストノードにするようにします。
executeInBackground(() => getActiveTab(tab => tab), []  // then()メソッドの引数の関数の引数にtabをそのまま渡す。
).then(tab => {
 const oncopy = (ev) => {
  const txt = window.getSelection().toString() || tab.title;  // 選択文字列があるときはそれをテキストノードにする。
  const html = '<a href="' + tab.url + '">' + txt + '</a>';
  ev.clipboardData.setData("text/plain", html);  // textとしてペーストするとき。必須。これがないとクリップボードに何も渡されない。
  ev.clipboardData.setData("text/html", html);  // htmlとしてペーストするとき。
  ev.preventDefault();  // デフォルトの動作を止める。そうしないとクリップボードに元の値が入ってしまう。
  ev.stopPropagation();  // これよりイベントの伝播を止める。
 };  // イベントリスナー。
 document.addEventListener("copy", oncopy, true);  // targetは何でもよいので、capture phase、つまりドキュメントから行きの伝播を捉える。
 document.execCommand("copy");   // コピーイベントを発生させる。
 document.removeEventListener("copy", oncopy, true);  // リスナーの除去。
});
User ScriptにCopy Linkという名前でこのスクリプトを登録しました。


Right+LeftでこのCopy Linkが起動するようにしました。

これでマウスの右ボタンを押しながら左ボタンを押すとそのページのリンクがクリップボードに入るようになりました。

BloggerのエディタモードでペーストするとHTMLとしてペーストされます。

(2018.6.29追記。document.execCommand(‘cut’/‘copy’) はユーザー生成の短期的なイベントハンドラーの内部からの呼び出しでないため拒否されました。と言われて、clipboardWriteのパーミッションを有効にしないとスクリプトは機能しなくなっています。

パーミッションの変更は以下のようにしてできました。

ツール→アドオン→FoxyGestures→設定。

More Preferencesタブを選択。


Optional Permissionsの項目にある、Request "clipboardWrite" のボタンをクリックするとコピーできるようになります。)

参考にしたサイト


『Firefox 57.0 (Quantum)』で『FireGestures』と『Make Link』が使えなくなって途方に暮れたかと思ったけど、『Foxy Gestures』で代替できたので問題なかった - 紙とエンピツ_ブログ版
Make Linkに代わってFoxy Gesturesを使う方法。

Firefox 57(Quantum)で動かなくなった「FireGestures」の代替に選ばれたのは、「Foxy Gestures」と往年の名ソフトでした。 | texst.net
Foxy GesturesのUser Scriptの例がたくさんあります。

GitHub - marklieberman/foxygestures: Mouse gestures for Firefox
Foxy Gesturesのソース。

User Scripts · marklieberman/foxygestures Wiki · GitHub
Foxy GesturesのUser Scriptの解説。

Promiseを使う - JavaScript | MDN
Foxy GesturesのUser ScriptではPromiseを使います。

addEventListenerの第3引数の意味 | JavaScript プログラミング解説
イベントフェーズの解説。

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ