Now browsing the SCRAPBLOG weblog archives.
[userChrome.js] 軽量マウスジェスチャ(モーダルダイアログに関する不具合修正)
これまでは、例えば「alert(“OK”);」のようなモーダルダイアログ(閉じないと親のウィンドウの操作ができないタイプのダイアログ)の表示をジェスチャに割り当てると、ダイアログを閉じたあとにコンテキストメニューが出てしまうバグがあった。やむを得ず、「setTimeout(function(){ alert(“OK”); }, 0);」のように時間差で処理を実行させるという策を講じていたが、さきほどコンテキストメニューが出てしまう原因を調べてみた。
すると、モーダルダイアログを表示することで一見親ウィンドウの処理が一時停止しているかのように見えるが、なぜかダイアログ上でマウスを動かすとmousemoveイベントが発生し、 mouseup→contextmenu というイベント発生の順序が崩れて mouseup→mousemove→contextmenu になり、結果的に不具合が生じることがわかった。
そこで、以下のように微修正。スクリプト全体はこちらにあります。
変更前:
... // [3] ジェスチャ終了~アクション実行 if (this._state == 1) { this._state = this._directionChain ? 2 : 3; // ジェスチャが認識されれば、この時点でthis._stateは2になる。 // _stopGestureメソッドが_performActionメソッドを呼び出し、 // 下記_stopGestureから呼ばれる_performActionメソッドの中でモーダルダイアログを表示すると… this._stopGesture(event); // ダイアログ上をマウスが通過した際に余計なmousemoveイベントが発生し、 // ここを通過するときにはthis._stateは0になってしまう。 } ...
変更後:
... // [3] ジェスチャ終了~アクション実行 if (this._state == 1) { var state = this._directionChain ? 2 : 3; this._stopGesture(event); this._state = state; } ...
この修正に伴い、
// プライバシー情報の消去 setTimeout(function(){ document.getElementById("Tools:Sanitize").doCommand(); }, 0); // オプション setTimeout(function(){ openPreferences(); }, 0);
はそれぞれ以下のようにしてもOKになります。
// プライバシー情報の消去 document.getElementById("Tools:Sanitize").doCommand(); // オプション openPreferences();
[userChrome.js] 軽量マウスジェスチャで利用可能なスクリプト集
[userChrome.js] 軽量マウスジェスチャで利用可能なスクリプト
「○○をジェスチャにしたいんだけど、userChrome.jsには何て書けばいいの」といった話題はこちらでコメントお願いします。
ナビゲーション
// 戻る document.getElementById("Browser:Back").doCommand();
// 進む document.getElementById("Browser:Forward").doCommand();
// 更新 document.getElementById("Browser:Reload").doCommand();
// 更新(キャッシュを無視) document.getElementById("Browser:ReloadSkipCache").doCommand();
// ホーム document.getElementById("Browser:Home").doCommand();
// 中止 document.getElementById("Browser:Stop").doCommand();
// 巻き戻し(履歴の先頭へ戻る) if (gBrowser.sessionHistory.index > 0) gBrowser.gotoIndex(0);
// 早送り(履歴の末尾へ進む) var nav = gBrowser.webNavigation; var hist = nav.sessionHistory; nav.gotoIndex(hist.count - 1);
ウィンドウ
// 新しいウィンドウ document.getElementById("cmd_newNavigator").doCommand();
// ウィンドウを閉じる document.getElementById("cmd_closeWindow").doCommand();
// ウィンドウの最小化 window.minimize();
// ウィンドウの最大化/元のサイズに戻す window.windowState == window.STATE_MAXIMIZED ? window.restore() : window.maximize();
// 全画面表示 document.getElementById("View:FullScreen").doCommand();
タブ
// 新しいタブ document.getElementById("cmd_newNavigatorTab").doCommand();
// タブを閉じる document.getElementById("cmd_close").doCommand();
// 閉じたタブを元に戻す document.getElementById("History:UndoCloseTab").doCommand();
// [Tab Mix Plus] 最後に閉じたタブを復元(TMP独自のセッションマネージャを利用している場合) gBrowser.undoRemoveTab();
// 前のタブへ gBrowser.mTabContainer.advanceSelectedTab(-1, true);
// 次のタブへ gBrowser.mTabContainer.advanceSelectedTab(+1, true);
// 文字を小さくする document.getElementById("cmd_textZoomReduce").doCommand();
// 文字を大きくする document.getElementById("cmd_textZoomEnlarge").doCommand();
// 標準の文字サイズ document.getElementById("cmd_textZoomReset").doCommand();
// タブの複製 openNewTabWith(gBrowser.currentURI.spec, null, null, null, false);
// 他のタブをすべて閉じる var browser = getBrowser(); browser.removeAllTabsBut(browser.mCurrentTab);
// すべてのタブを閉じる var browser = getBrowser(); var ctab = browser.addTab("about:blank"); browser.removeAllTabsBut(ctab);
// 左のタブをすべて閉じる var tabs = gBrowser.mTabContainer.childNodes; for (var i = tabs.length - 1; tabs[i] != gBrowser.mCurrentTab; i--){} for (i--; i >=0 ; i--){ gBrowser.removeTab(tabs[i]); }
// 右のタブをすべて閉じる var tabs = gBrowser.mTabContainer.childNodes; for (var i = tabs.length - 1; tabs[i] != gBrowser.selectedTab; i--) { gBrowser.removeTab(tabs[i]); }
// [Tab Mix Plus] タブを凍結 gBrowser.freezeTab(gBrowser.mCurrentTab);
// [Tab Mix Plus] タブを保護 gBrowser.protectTab(gBrowser.mCurrentTab);
// [Tab Mix Plus] タブをロック gBrowser.lockTab(gBrowser.mCurrentTab);
ページ
// 先頭へスクロール goDoCommand("cmd_scrollTop");
// 末尾へスクロール goDoCommand("cmd_scrollBottom");
// ページアップ goDoCommand("cmd_scrollPageUp");
// ページダウン goDoCommand("cmd_scrollPageDown");
// このページをブックマーク document.getElementById("Browser:AddBookmarkAs").doCommand();
// 名前を付けてページを保存 document.getElementById("Browser:SavePage").doCommand();
// ページのソースを表示 document.getElementById("View:PageSource").doCommand();
// ページの情報を表示 document.getElementById("View:PageInfo").doCommand();
// 印刷プレビュー document.getElementById("cmd_printPreview").doCommand();
// 印刷 document.getElementById("cmd_print").doCommand();
ツール
// ダウンロード document.getElementById("Tools:Downloads").doCommand();
// アドオン document.getElementById("Tools:Addons").doCommand();
// プライバシー情報の消去 setTimeout(function(){ document.getElementById("Tools:Sanitize").doCommand(); }, 0);
// エラーコンソール toJavaScriptConsole();
// オプション setTimeout(function(){ openPreferences(); }, 0);
// DOM Inspector inspectDOMDocument(content.document);
// 検索バーを開く/閉じる if ("isFindBarVisible" in gFindBar) gFindBar.isFindBarVisible() ? gFindBar.closeFindBar() : gFindBar.onFindCmd(); else gFindBar.hidden ? gFindBar.onFindCommand() : gFindBar.close();
// Web 検索ボックスのクリア document.getElementById("searchbar").value = "";
サイドバー
// ブックマークサイドバー toggleSidebar("viewBookmarksSidebar");
// 履歴サイドバー toggleSidebar("viewHistorySidebar");
// [Sage] サイドバー toggleSidebar("viewSageSidebar");
// [ScrapBook] サイドバー toggleSidebar("viewScrapBookSidebar");
// [Foxage2ch] サイドバー toggleSidebar("viewFoxage2chSidebar");
// サイドバーを閉じる var sidebarBox = document.getElementById("sidebar-box"); if (!sidebarBox.hidden) toggleSidebar(sidebarBox.getAttribute("sidebarcommand"));
特殊操作
// ひとつ上の階層へ移動 var uri = gBrowser.currentURI; if (uri.path == "/") return; var pathList = uri.path.split("/"); if (!pathList.pop()) pathList.pop(); loadURI(uri.prePath + pathList.join("/") + "/");
// 再起動 Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup) .quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
// [ScrapBook] ページの取り込み sbBrowserOverlay.execCapture(0, null, false , "urn:scrapbook:root");
// [ScrapBook] ページの詳細な取り込み sbBrowserOverlay.execCapture(0, null, true , "urn:scrapbook:root");
[userChrome.js] 軽量マウスジェスチャ(改良バージョン)
[userChrome.js] 軽量マウスジェスチャを少し改良しました。先日のバージョンでは、右クリックによる mousedown イベントが発生した後に続けて mousemove イベントが発生して初めてジェスチャが開始されたとみなすロジックであった。
- mousedown→mousemove(ジェスチャ開始)→mousemove(ジェスチャ継続)…→mouseup(ジェスチャ終了)
しかし、このロジックですと mousedown から1回目の mousemove までにどれだけ大きくマウスポインタの位置を動かしたとしてもそれはジェスチャとして認識されないという問題があります。実際のところ mousedown から1回目の mousemove までの時間は一瞬ですので、その間に大きくマウスを動かすことはかなり難しいですが、読み込み中のタブがあって動作が鈍くなっているときに↓のジェスチャでタブを閉じようとすると、なぜか認識されずにコンテキストメニューが出てしまうといったケースが時々見られました。
今回のバージョンでは mousedown をした時点でジェスチャ開始とみなすというシンプルなロジックにしています。これによって上記の問題は解決され、今のところ快調に動いているように感じられます。
- mousedown(ジェスチャ開始)→mousemove(ジェスチャ継続)…→mouseup(ジェスチャ終了)
[userChrome.js] 軽量マウスジェスチャ
マウスジェスチャ機能は欲しいけど、All-in-One Gestures や Optimoz Mouse Gestures は余計な機能が多すぎる。AiOGから不要な機能を取っ払ってスリム化させようと試みたが、ソースコードが複雑すぎてやる気が失せた。そこで自分で一から考えて作ってみた結果、200行にも満たない userChrome.js 用スクリプトとして実装することができた。
xuldev.org :: userChrome.js scripts » Mouse Gestures
特徴
- マウストレイル(軌跡の描画)は重くなる原因なのであきらめた。とはいえ AiOG から trails.js を借りてきて一工夫すれば実装可能です。
- ジェスチャによって実行される処理は、極力ブラウザ本体に実装されたコマンドを呼び出すようにしている。
- 設定用GUIは無いが、スクリプトを直接編集することで無駄なく柔軟にカスタマイズできる。詳しくは下記スクリプト内の _performAction 関数をご覧ください。
[userChrome.js] Mouse Gestures
I like mouse gestures, but All-in-One Gestures and Optimoz Mouse Gestures both have too much unwanted features for me. I tried to reduce unwanted parts from AiOG but I gave up since the original source codes was very complex.
And so, I made it by myself from scratch as a small user script for userChrome.js extension, which has only less than 200 lines.
xuldev.org :: userChrome.js scripts » Mouse Gestures
Major features
- No mouse trails. Because it would be one of a factor to be slow down the gesture. Nonetheless we can implement it by picking ‘trails.js’ from AiOG.
- As much as possible, it executes the ‘built-in’ commands of Firefox itself when we perform actions by gestures.
- No options dialog. But we can economically and flexibly customize by editing the script directly. For more details, please see ‘_performAction’ method in the script below.