Hatena::ブログ(Diary)

Griever Twitter

2011/07/02

メニューを拡張するスクリプト

Copy URL Lite+ を参考にメニューを拡張するスクリプトを書きました。

JS がよくわからなくてもそれなりに使えると思います。


説明が長くなりそうなので簡単に機能説明するとこんな感じです。

  • ページ、タブ、ツール、Firefox Button にメニューを追加できる
  • コピー、検索、URL を開く、外部アプリの起動ができる(JS を書けば何でもできる)
  • 追加したメニューに自動的にアイコンが付く…かも
  • リンクを対象にするメニューはリンク以外では自動で非表示になる
  • メニュー、サブメニューが作り放題
  • .uc.js を更新しやすいように設定は外部ファイル

サブメニューを足した時のスクリーンショット

f:id:Griever:20110701223316j:image:w640


DL はこちら


使い方

  • addMenu.uc.js を入れる
  • Chrome フォルダに _addmenu.js を置く

以上。

設定ファイルはツールメニューから再読み込みできます。


メニューの追加

設定ファイルに用意された変数を使って書きます。

書式は Copy URL Lite+ とほぼ一緒です。*1

JS 書ける人はゴリゴリ書いても OK です。

// ページの右クリックメニューに追加
page({
	label  : "リンクのテキストを検索",
	text   : "%LINK_TEXT%",
	keyword: "g",
	where  : "tab"
});

たったこれだけでメニューが追加でき、自動的に Google のアイコンが付き*2、リンク上でのみ表示され、実行するとリンクのテキストを Google で新しいタブで検索してくれます。

// 見ているページを IE で開く
page({
	label: "Internet Explorer で開く",
	text: "%u",
	exec: "C:\\Program Files\\Internet Explorer\\iexplore.exe",
	condition: "nolink"
});

たったこれだけで IE 起動できます。


// タブの右クリックメニューに追加
tab({
	label: "Favicon の URL をコピー",
	text: "%FAVICON%"
});

たったこれだけでタブの右クリックメニューに Favicon をコピーするメニューができます。


ページやタブ以外に、ツールメニューや Firefox Button のメニューにも追加できます。


var mMenus = [
	{
		//...
	},
	{
		//...
	}
];
page(mMenus);

配列にしてから一度に追加することも出来ます。

Copy URL Lite+ のコマンドをそのまま持ってきても使えます。


サブメニューの追加
var pagesub = PageMenu({ label: "サブメニュー" });
pagesub({
	label : "リンク先のソースを表示",
	url   : "view-source:%l",
	where : "tab"
});

たったこれだけでサブメニューができて、その中に "リンク先のソースを表示" メニューが出来ます。


簡単でしょ?これくらいなら JavaScript 書けなくても何とかなりますよね?


利用可能な変数

基本的に Copy URL Lite+ の変数はそのまま使えます。

大文字・小文字は区別しません。

%EOL%            改行(\r\n)
%TITLE%          ページタイトル
%URL%            URI
%SEL%            選択範囲の文字列
%RLINK%          リンクアンカー先の URL
%IMAGE_URL%      画像の URL
%IMAGE_ALT%      画像の alt 属性
%IMAGE_TITLE%    画像の title 属性
%LINK%           リンクアンカー先の URL
%LINK_TEXT%      リンクのテキスト
%RLINK_TEXT%     リンクのテキスト
%MEDIA_URL%      メディアの URL
%CLIPBOARD%      クリップボードの内容
%FAVICON%        Favicon の URL
%EMAIL%          リンク先の E-mail アドレス
%HOST%           ページのホスト(ドメイン)
%LINK_HOST%      リンクのホスト(ドメイン)
%RLINK_HOST%     リンクのホスト(ドメイン)

%XXX_HTMLIFIED%  HTML エンコードされた上記変数(XXX → TITLE などに読み替える)
%XXX_HTML%       HTML エンコードされた上記変数
%XXX_ENCODE%     URI  エンコードされた上記変数
簡易的な変数(↑を入力するのがダルい時)
%h               ページのホスト(ドメイン)
%i               画像の URL
%l               リンクの URL
%m               メディアの URL
%p               クリップボードの内容
%s               選択文字列
%t               ページのタイトル
%u               ページの URL

使えるプロパティ

ここから中級編です。

page({ ... }) このオブジェクトのプロパティがそのままメニューの属性になります。

  • exec

外部アプリを起動します。

パラメータは text プロパティを利用します。

アプリのアイコンが自動で付きます。

ブックマーク検索エンジンのキーワードを指定します。

text プロパティがあればそれを利用して検索などをします。

検索エンジンなどのアイコンが自動で付きます。

  • text(変数が利用可能)

クリップボードにコピーしたい文字列を指定します。(Copy URL Lite+ 互換)

keyword, exec があればそれらの補助に使われます。

  • url(変数が利用可能)

開きたい URL を指定します。

内容によっては自動的にアイコンが付きます。

  • where

keyword, url でのページの開き方を指定できます(current, tab, tabshifted, window)

省略するとブックマークのように左クリックと中クリックを使い分けられます。

  • condition

メニューを表示する条件を指定します。(Copy URL Lite+ 互換)

省略すると url や text プロパティから自動的に表示/非表示が決まります。

select, link, mailto, image, media, input, noselect, nolink, nomailto, noimage, nomedia, noinput から組み合わせて使います。

※ページの右クリックメニュー以外では無効です。

  • oncommand, command

これらがある時は condition 以外の特殊なプロパティは無視されます。


メニューの挿入位置

ここから上級編です(ぇ

前述のプロパティの他にメニューの位置を決めるプロパティがあります。

  • insertBefore(指定した id の前に挿入)
  • insertAfter (指定した id の後に挿入)
  • position (指定した n 番目に挿入。最初に入れるなら "1")

XUL の overlay を真似ているのでわかる方にはすぐわかる仕様です。

insertBefore は id の複数指定に対応していなかったり、ファイルメニューなどに挿入できたりとちょっとぶっ飛んだ仕様です。

// ファイルメニューの終了の前に再起動メニューを追加
page({
	label: "再起動",
	oncommand: "Application.restart();",
	insertBefore: "menu_FileQuitItem"
});

こんな無茶も出来る

// Services を利用して検索エンジンの一欄を作る
var search = new PageMenu({
	label:"選択文字列を…",
	condition: "select"
});
Services.search.getEngines().forEach(function(engine){
	search({
		label: engine.name + " で検索",
		keyword: engine.alias,
		text: "%s",
		src: engine.iconURI? engine.iconURI.spec : ""
	});
});
PageMenu({
	label: "タブ一覧",
	position:"1",
	onpopupshowing: function(event) {
		var popup = event.target;
		Array.forEach(gBrowser.mTabs, function(tab){
			var menuitem = document.createElement("menuitem");
			menuitem.setAttribute("label", tab.getAttribute("label"));
			menuitem.setAttribute("src", tab.getAttribute("image"));
			menuitem.setAttribute("class", "menuitem-iconic");
			menuitem.setAttribute("oncommand", "gBrowser.mTabContainer.selectedIndex = " + tab._tPos);
			if (tab.selected)
				menuitem.style.fontWeight = "bold";
			popup.appendChild(menuitem);
		});
	},
	onpopuphidden: function(event) {
		var range = document.createRange();
		range.selectNodeContents(event.target);
		range.deleteContents();
		range.detach();
	}
});

作ってみて

あれもこれもできるように〜と思ったら結構大掛かりなスクリプトになっちゃって説明が足りてるかどうか分からない。。

どなたかサンプルや解説を書いてくれると助かるな〜とか言ってみる(ぇ

*1:色々追加されてますが、Copy URL Lite+ で使える機能は一通り使える

*2キーワード "g" に Google 検索が登録されていることが前提

かまどうまかまどうま 2011/07/02 18:37 こういうのを待ってた!
Operaみたいにコンテキストメニューをいじりたいと思いつつ拡張でもなかなか出来ないことをここまで簡単に出来るのは素晴らしい・・・。
ъ(゜Д゜)グッジョブ!!

通りすがり通りすがり 2011/07/05 17:27 メニューアイコンとメニューテキストが極端に近いといいますか、
アイコンとテキストを遮る縦のラインを無視して描画?されている次第です。
当方だけなのかもしれませんが、ぜひご確認のほどよろしくお願いします。

saburowsaburow 2011/07/06 03:31 素晴らしい!このようなスクリプトを求めてました。

一点質問です。
tab(***)で得られる変数(%URL%他)の中身ですが、該当タブの内容ではなく
現在アクティブなタブの情報となっていますが、こちら仕様でしょうか。

GrieverGriever 2011/07/06 20:15 > アイコンとテキストを遮る縦のラインを無視して描画?されている次第です。
私の環境(標準テーマ+XP)では SS のように縦のラインはありませんね。
アイコンは標準的な付け方をしているのでお使いのテーマや CSS で表示がずれたりしているのかもしれません。


> tab(***)で得られる変数(%URL%他)の中身ですが、該当タブの内容ではなく
> 現在アクティブなタブの情報となっていますが、こちら仕様でしょうか。
仕様です。
現在見ているページ(ページの右クリックメニューではそのフレーム)を対象にしています。

タブのメニューからはそのタブの情報が取れるので、そちらのほうが便利そうですね。
次のバージョンで右クリックしたタブの内容を取れるようにしておきます。

通りすがり通りすがり 2011/07/06 20:38 私はwindows7(標準テーマ)を使用しているので、OSによるものなのかもしれません。
新規プロファイルデフォルトテーマでも同じ現象を確認しまして。
Grieverさんと違う環境なのでCSSなどで個人で対応していきたいと思います。
ありがとうございました。

otooto 2011/07/12 17:40 いろいろ試してみたのですが、どうもうまく動作しないので質問させて下さい。
はてなブックマークを使えるということは、Evernoteも同じように使用できると思うのですが、動作しません。
もしよろしければ書き方を教えて頂けませんか?

あとFirefox Buttonにメニューを追加できるみたいですが、メニューバーの内容も追加で移動できるようにはできるのでしょうか?

お時間ある時にでも教えて頂けると嬉しいです。
よろしくお願いします。

GrieverGriever 2011/07/12 23:22 > はてなブックマークを使えるということは、Evernoteも同じように使用できると思うのですが、動作しません。
http://www.evernote.com/about/intl/jp/download/
↑にある「Web クリッパーブックマークレット」のことでしょうか?
これでしたらブックマークレットをお気に入りに入れて "evernote" とキーワードをつけて
page({
label: "Evernote Web クリッパー",
keyword: "evernote"
});
とすれば動きます。
0.0.2 にバグがあってこれが動かない可能性があります。0.0.3 にバージョンアップしてください。。

> あとFirefox Buttonにメニューを追加できるみたいですが、メニューバーの内容も追加で移動できるようにはできるのでしょうか?
"移動" はできません。
メニューバーの内容を自動的に取得する機能も無いので、手作業で同じメニューを作っていくしか無いですね。

otooto 2011/07/13 22:59 Evernote、ちゃんと動かすことが出来ました。
どうもありがとうございます!
Firefox Buttonのほうは地道に対応していきたいともいます。

okbtsnrokbtsnr 2012/08/15 08:01 最近、本スクリプトがあることを知り入れてみましたが、ツール>クリックした要素をDOMiで調査とaddMenuの再読み込みは出るのですがコンテキストメニューにサブメニューが表示されません。
何が原因でしょうか?
Win7(64) Firefox15.0β4
_addmenu.jsはサンプル通りです。

okbtsnrokbtsnr 2012/08/15 10:44 すみません。
新たなプロファイルでは動作しました。
アドオンが犯人みたいで、もう少し調べてみます。

okbtsnrokbtsnr 2012/08/15 10:59 CoolPreviews 3.5を無効にしたら動きました。
う〜ん、困った。

okbtsnrokbtsnr 2012/08/15 18:12 ごめん、CoolPreviewではなく、MenuEditorです。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/Griever/20110702/1309588302