Skip to content

Instantly share code, notes, and snippets.

@Griever
Created July 2, 2011 04:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Griever/1059720 to your computer and use it in GitHub Desktop.
Save Griever/1059720 to your computer and use it in GitHub Desktop.
メニューを拡張する userChromeJS 用のスクリプト
// ==UserScript==
// @name addMenu.uc.js
// @description メニューを拡張する userChromeJS 用のスクリプト
// @namespace http://d.hatena.ne.jp/Griever/
// @author Griever
// @include main
// @license MIT License
// @compatibility Firefox 5
// @charset UTF-8
// @version 0.0.3
// @note 0.0.3 keyword の新しい書式で古い書式が動かない場合があったのを修正
// @note %URL_HTMLIFIED%, %EOL_ENCODE% が変換できなかったミスを修正
// @note %LINK_OR_URL% 変数を作成(リンク URL がなければページの URL を返す)
// @note タブの右クリックメニューでは %URL% や %SEL% はそのタブのものを返すようにした
// @note keyword で "g %URL%" のような記述を可能にした
// @note ツールの再読み込みメニューの右クリックで設定ファイルを開くようにした
// ==/UserScript==
/***** 説明 *****
◆ これは何? ◆
メニューを拡張する userChromeJS 用のスクリプトです。
作成に当たっては Copy URL Lite+ を参考にさせていただきました。
・http://www.code-404.net/articles/browsers/copy-url-lite
◆ 使い方 ◆
設定ファイル(_addmenu.js)を chrome フォルダにおいてください。
.uc.js の方はどこでも構いません。
ブラウザ起動後に設定ファイルが読み込まれ、メニューが追加されます。
設定ファイルの再読み込みはツールメニューから行えます。
◆ 書式 ◆
page, tab, too, app 関数にメニューの素となるオブジェクトを渡す。
オブジェクトのプロパティがそのまま menuitem の属性になります。
○exec
外部アプリを起動します。
パラメータは text プロパティを利用します。
アプリのアイコンが自動で付きます。
○keyword
ブックマークや検索エンジンのキーワードを指定します。
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 以外の特殊なプロパティは無視されます。
◆ サブメニュー ◆
PageMenu, TabMenu, ToolMenu, AppMenu 関数を使って自由に追加できます。
◆ 利用可能な変数 ◆
%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% リンクのホスト(ドメイン)
%LINK_OR_URL% リンクの URL が取れなければページの URL
%RLINK_OR_URL% リンクの URL が取れなければページの URL
%XXX_HTMLIFIED% HTML エンコードされた上記変数(XXX → TITLE などに読み替える)
%XXX_HTML% HTML エンコードされた上記変数
%XXX_ENCODE% URI エンコードされた上記変数
◇ 簡易的な変数 ◇
%h ページのホスト(ドメイン)
%i 画像の URL
%l リンクの URL
%m メディアの URL
%p クリップボードの内容
%s 選択文字列
%t ページのタイトル
%u ページの URL
基本的に Copy URL Lite+ の変数はそのまま使えます。
大文字・小文字は区別しません。
*/
(function(css){
let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
if (window.addMenu) {
window.addMenu.destroy();
delete window.addMenu;
}
window.addMenu = {
get prefs() {
delete this.prefs;
return this.prefs = Services.prefs.getBranch("addMenu.")
},
get FILE() {
let aFile;
try {
// addMenu.FILE_PATH があればそれを使う
aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile)
aFile.initWithPath(this.prefs.getCharPref("FILE_PATH"));
} catch (e) {
aFile = Services.dirsvc.get("UChrm", Ci.nsILocalFile);
aFile.appendRelativePath("_addmenu.js");
}
//if (!aFile.exists() || !aFile.isFile()) {
return aFile;
//}
//delete this.FILE;
//return this.FILE = aFile;
},
get focusedWindow() {
return gContextMenu ? gContextMenu.target.ownerDocument.defaultView : content;
//var win = document.commandDispatcher.focusedWindow;
//return (!win || win == window)? content : win;
},
init: function() {
let he = "(?:_HTML(?:IFIED)?|_ENCODE)?";
let rTITLE = "%TITLE"+ he +"%|%t\\b";
let rURL = "%(?:R?LINK_OR_)?URL"+ he +"%|%u\\b";
let rHOST = "%HOST"+ he +"%|%h\\b";
let rSEL = "%SEL"+ he +"%|%s\\b";
let rLINK = "%R?LINK(?:_TEXT|_HOST)?"+ he +"%|%l\\b";
let rIMAGE = "%IMAGE(?:_URL|_ALT|_TITLE)"+ he +"%|%i\\b";
let rMEDIA = "%MEDIA_URL"+ he +"%|%m\\b";
let rCLIPBOARD = "%CLIPBOARD"+ he +"%|%p\\b";
let rFAVICON = "%FAVICON"+ he +"%";
let rEMAIL = "%EMAIL"+ he +"%";
let rExt = "%EOL"+ he +"%";
this.rTITLE = new RegExp(rTITLE, "i");
this.rURL = new RegExp(rURL, "i");
this.rHOST = new RegExp(rHOST, "i");
this.rSEL = new RegExp(rSEL, "i");
this.rLINK = new RegExp(rLINK, "i");
this.rIMAGE = new RegExp(rIMAGE, "i");
this.rMEDIA = new RegExp(rMEDIA, "i");
this.rCLIPBOARD = new RegExp(rCLIPBOARD, "i");
this.rFAVICON = new RegExp(rFAVICON, "i");
this.rEMAIL = new RegExp(rEMAIL, "i");
this.rExt = new RegExp(rExt, "i");
this.regexp = new RegExp(
[rTITLE, rURL, rHOST, rSEL, rLINK, rIMAGE, rMEDIA, rCLIPBOARD, rFAVICON, rEMAIL, rExt].join("|"), "ig");
var ins;
ins = $("context-viewinfo");
ins.parentNode.insertBefore($E(<menuseparator id="addMenu-page-insertpoint" class="addMenu-insert-point" />), ins.nextSibling);
ins = $("context_closeTab");
ins.parentNode.insertBefore($E(<menuseparator id="addMenu-tab-insertpoint" class="addMenu-insert-point" />), ins.nextSibling);
ins = $("prefSep");
ins.parentNode.insertBefore($E(<menuseparator id="addMenu-tool-insertpoint" class="addMenu-insert-point" />), ins.nextSibling);
ins = $("appmenu-quit");
ins.parentNode.insertBefore($E(<menuseparator id="addMenu-app-insertpoint" class="addMenu-insert-point" />), ins);
ins = $("devToolsSeparator");
ins.parentNode.insertBefore($E(
<menuitem id="addMenu-rebuild"
label={U("addMenu の再読み込み")}
oncommand="setTimeout(function(){ addMenu.rebuild(true); }, 10);"
onclick="if (event.button == 2) { event.preventDefault(); addMenu.edit(addMenu.FILE); }" />
), ins);
$("contentAreaContextMenu").addEventListener("popupshowing", this, false);
this.style = addStyle(css);
this.rebuild();
},
uninit: function() {
$("contentAreaContextMenu").removeEventListener("popupshowing", this, false);
},
destroy: function() {
this.uninit();
this.removeMenuitem();
$$('menuseparator.addMenu-insert-point').forEach(function(e) e.parentNode.removeChild(e));
var ids = ["addMenu-rebuild"];
for (let [i, id] in Iterator(ids)) {
let e = $(id);
if (e) e.parentNode.removeChild(e);
}
if (this.style && this.style.parentNode) this.style.parentNode.removeChild(this.style);
},
handleEvent: function(event) {
switch(event.type){
case "popupshowing":
if (event.target != event.currentTarget) return;
var state = [];
if (gContextMenu.onTextInput)
state.push("input");
if (gContextMenu.isTextSelected ||
gContextMenu.onTextInput && this.getInputSelection(gContextMenu.target))
state.push("select");
if (gContextMenu.onLink) {
state.push("link");
if (gContextMenu.onMailtoLink)
state.push("mailto");
}
if (gContextMenu.onImage)
state.push("image");
if (gContextMenu.onVideo || gContextMenu.onAudio)
state.push("media")
event.currentTarget.setAttribute("addMenu", state.join(" "));
break;
}
},
onCommand: function(event) {
var menuitem = event.target;
var text = menuitem.getAttribute("text") || "";
var keyword = menuitem.getAttribute("keyword") || "";
var url = menuitem.getAttribute("url") || "";
var where = menuitem.getAttribute("where") || "";
var exec = menuitem.getAttribute("exec") || "";
if (keyword) {
let kw = keyword + (text? " " + (text = this.convertText(text)) : "");
let newurl = getShortcutOrURI(kw);
if (newurl == kw && text)
return this.log(U("キーワードが見つかりません: ") + keyword);
this.openCommand(event, newurl, where);
}
else if (url)
this.openCommand(event, this.convertText(url), where);
else if (exec)
this.exec(exec, this.convertText(text));
else if (text)
this.copy(this.convertText(text));
},
openCommand: function(event, url, where) {
var uri;
try {
uri = Services.io.newURI(url, null, null);
} catch (e) {
return this.log(U("URL が不正です: ") + url);
}
if (uri.scheme === "javascript")
loadURI(url);
else if (where)
openUILinkIn(uri.spec, where);
else if (event.button == 1)
openNewTabWith(uri.spec);
else openUILink(uri.spec, event);
},
exec: function(path, arg){
var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
try {
var a = (typeof arg == 'string' || arg instanceof String) ? arg.split(/\s+/) : [arg];
file.initWithPath(path);
process.init(file);
process.run(false, a, a.length);
} catch(e) {
throw e;
}
},
rebuild: function(isAlert) {
var aFile = this.FILE;
if (!aFile || !aFile.exists() || !aFile.isFile()) {
this.log(aFile? aFile.path : U("設定ファイル") + U(" が見つかりません"));
return;
}
var aiueo = [
{ current: "page", submenu: "PageMenu", insertId: "addMenu-page-insertpoint" },
{ current: "tab" , submenu: "TabMenu" , insertId: "addMenu-tab-insertpoint" },
{ current: "tool", submenu: "ToolMenu", insertId: "addMenu-tool-insertpoint" },
{ current: "app" , submenu: "AppMenu" , insertId: "addMenu-app-insertpoint" }
];
var data = loadText(aFile);
var sandbox = new Cu.Sandbox( new XPCNativeWrapper(window) );
sandbox.Components = Components;
sandbox.Cc = Cc;
sandbox.Ci = Ci;
sandbox.Cr = Cr;
sandbox.Cu = Cu;
sandbox.Services = Services;
sandbox.locale = Services.prefs.getCharPref("general.useragent.locale");
sandbox.include = function(aLeafName) {
try {
let aFile = addMenu.FILE.parent;
aFile.QueryInterface(Ci.nsILocalFile);
aFile.appendRelativePath(aLeafName);
if (!aFile.exists() || !aFile.isFile())
throw U(aLeafName + " が見つかりません");
let fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(aFile);
return Services.scriptloader.loadSubScript(fileURL, sandbox, "UTF-8");
} catch (e) {
Cu.reportError(e);
}
};
aiueo.forEach(function({ current, submenu }){
sandbox["_" + current] = [];
sandbox[current] = function(itemObj) {
ps(itemObj, sandbox["_" + current]);
}
sandbox[submenu] = function(menuObj) {
menuObj._items = []
sandbox["_" + current].push(menuObj);
return function(itemObj) {
ps(itemObj, menuObj._items);
}
}
}, this);
function ps(item, array) {
("join" in item && "unshift" in item) ?
[].push.apply(array, item) :
array.push(item);
}
try {
var result = Cu.evalInSandbox(data, sandbox, "1.8");
} catch (e) {
throw e;
}
this.removeMenuitem();
aiueo.forEach(function({ current, submenu, insertId }){
if (!sandbox["_" + current] || sandbox["_" + current].length == 0) return;
let insertPoint = $(insertId);
this.createMenuitem(sandbox["_" + current], insertPoint);
}, this);
if (isAlert) this.alert(U("設定を再読み込みしました"));
},
newMenu: function(menuObj) {
var menu = document.createElement("menu");
var popup = menu.appendChild(document.createElement("menupopup"));
for (let [key, val] in Iterator(menuObj)) {
if (key === "_items") continue;
if (typeof val == "function")
menuObj[key] = val = val.toSource() + ".call(this, event);"
menu.setAttribute(key, val);
}
let cls = menu.classList;
cls.add("addMenu");
// 表示 / 非表示の設定
if (menuObj.condition)
this.setCondition(menu, menuObj.condition);
this.setIcon(menu, menuObj);
menuObj._items.forEach(function(obj) {
popup.appendChild(this.newMenuitem(obj));
}, this);
return menu;
},
newMenuitem: function(obj) {
// label == separator か必要なプロパティが足りない場合は区切りとみなす
if (obj.label === "separator" ||
(!obj.label && !obj.text && !obj.keyword && !obj.url && !obj.oncommand && !obj.command)) {
var menuitem = document.createElement("menuseparator");
} else if (obj.oncommand || obj.command) {
var menuitem = document.createElement("menuitem");
if (!obj.label)
obj.label = obj.oncommand || obj.command;
} else {
var menuitem = document.createElement("menuitem");
// property fix
if (!obj.label)
obj.label = obj.exec || obj.keyword || obj.url || obj.text;
if (obj.keyword && !obj.text) {
let index = obj.keyword.search(/\s+/);
if (index > 0) {
obj.text = obj.keyword.substr(index).trim();
obj.keyword = obj.keyword.substr(0, index);
}
}
if (obj.where && /\b(tab|tabshifted|window|current)\b/i.test(obj.where))
obj.where = RegExp.$1.toLowerCase();
if (obj.where && !("acceltext" in obj))
obj.acceltext = obj.where;
if (!obj.condition && (obj.url || obj.text)) {
// 表示 / 非表示の自動設定
let condition = "";
if (this.rSEL.test(obj.url || obj.text)) condition += " select";
if (this.rLINK.test(obj.url || obj.text)) condition += " link";
if (this.rEMAIL.test(obj.url || obj.text)) condition += " mailto";
if (this.rIMAGE.test(obj.url || obj.text)) condition += " image";
if (this.rMEDIA.test(obj.url || obj.text)) condition += " media";
if (condition)
obj.condition = condition;
}
}
// obj を属性にする
for (let [key, val] in Iterator(obj)) {
if (typeof val == "function")
obj[key] = val = val.toSource() + ".call(this, event);";
menuitem.setAttribute(key, val);
}
var cls = menuitem.classList;
cls.add("addMenu");
// 表示 / 非表示の設定
if (obj.condition)
this.setCondition(menuitem, obj.condition);
// separator はここで終了
if (menuitem.localName == "menuseparator")
return menuitem;
// oncommand, command はここで終了
if (obj.oncommand || obj.command)
return menuitem;
if (!obj.onclick)
menuitem.setAttribute("onclick", "checkForMiddleClick(this, event)");
menuitem.setAttribute("oncommand", "addMenu.onCommand(event);");
// 可能ならばアイコンを付ける
this.setIcon(menuitem, obj);
return menuitem;
},
createMenuitem: function(itemArray, insertPoint) {
var chldren = $A(insertPoint.parentNode.children);
for (let [, obj] in Iterator(itemArray)) {
let menuitem = obj._items ? this.newMenu(obj) : this.newMenuitem(obj);
let ins;
if (obj.insertAfter && (ins = $(obj.insertAfter))) {
ins.parentNode.insertBefore(menuitem, ins.nextSibling);
continue;
}
if (obj.insertBefore && (ins = $(obj.insertBefore))) {
ins.parentNode.insertBefore(menuitem, ins);
continue;
}
if (obj.position && parseInt(obj.position, 10) > 0) {
(ins = chldren[parseInt(obj.position, 10)-1]) ?
ins.parentNode.insertBefore(menuitem, ins):
insertPoint.parentNode.appendChild(menuitem);
continue;
}
insertPoint.parentNode.insertBefore(menuitem, insertPoint);
}
},
removeMenuitem: function() {
$$('menu.addMenu').forEach(function(e) e.parentNode.removeChild(e) );
$$('.addMenu').forEach(function(e) e.parentNode.removeChild(e) );
},
setIcon: function(menu, obj) {
if (menu.hasAttribute("src") && menu.hasAttribute("image"))
return;
if (obj.exec) {
var aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
try {
aFile.initWithPath(obj.exec);
} catch (e) {
return;
}
if (!aFile.exists() || !aFile.isExecutable()) {
menu.setAttribute("disabled", "true");
} else {
let fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromFile(aFile);
menu.setAttribute("src", "moz-icon://" + fileURL + "?size=16");
}
return;
}
if (obj.keyword) {
let engine = Services.search.getEngineByAlias(obj.keyword);
if (engine && engine.iconURI) {
menu.setAttribute("src", engine.iconURI.spec);
return;
}
}
let url = obj.keyword ? getShortcutOrURI(obj.keyword) : obj.url ? obj.url.replace(this.regexp, "") : "";
if (!url) return;
let uri, iconURI;
try {
uri = Services.io.newURI(url, null, null);
} catch (e) { }
if (!uri) return;
menu.setAttribute("scheme", uri.scheme);
try {
iconURI = PlacesUtils.favicons.getFaviconForPage(uri);
} catch (e) { }
try {
// javascript: URI の host にアクセスするとエラー
menu.setAttribute("src", iconURI && iconURI.spec?
"moz-anno:favicon:" + iconURI.spec:
"moz-anno:favicon:" + uri.scheme + "://" + uri.host + "/favicon.ico");
} catch (e) { }
},
setCondition: function(menu, condition) {
if (/\bnormal\b/i.test(condition)) {
menu.setAttribute("condition", "normal");
} else {
let match = condition.toLowerCase().match(/\b(?:no)?(?:select|link|mailto|image|media|input)\b/ig);
if (!match || !match[0])
return;
match = match.filter(function(c,i,a) a.indexOf(c) === i);
menu.setAttribute("condition", match.join(" "));
}
},
convertText: function(text) {
var that = this;
var context = gContextMenu || { // とりあえずエラーにならないようにオブジェクトをでっち上げる
link: { href: "", host: "" },
target: { alt: "", title: "" },
__noSuchMethod__: function(id, args) "",
};
var tab = document.popupNode && document.popupNode.localName == "tab" ? document.popupNode : null;
var win = tab ? tab.linkedBrowser.contentWindow : this.focusedWindow;
return text.replace(this.regexp, function(str){
str = str.toUpperCase().replace("%LINK", "%RLINK");
if (str.indexOf("_HTMLIFIED") >= 0)
return htmlEscape(convert(str.replace("_HTMLIFIED", "")));
if (str.indexOf("_HTML") >= 0)
return htmlEscape(convert(str.replace("_HTML", "")));
if (str.indexOf("_ENCODE") >= 0)
return encodeURIComponent(convert(str.replace("_ENCODE", "")));
return convert(str);
});
function convert(str) {
switch(str) {
case "%T" : return win.document.title;
case "%TITLE%" : return win.document.title;
case "%U" : return win.location.href;
case "%URL%" : return win.location.href;
case "%H" : return win.location.host;
case "%HOST%" : return win.location.host;
case "%S" : return that.getSelection(win) || "";
case "%SEL%" : return that.getSelection(win) || "";
case "%L" : return context.linkURL || "";
case "%RLINK%" : return context.linkURL || "";
case "%RLINK_HOST%" : return context.link.host || "";
case "%RLINK_TEXT%" : return context.linkText() || "";
case "%RLINK_OR_URL%": return context.linkURL || win.location.href;
case "%IMAGE_ALT%" : return context.target.alt || "";
case "%IMAGE_TITLE%" : return context.target.title || "";
case "%I" : return context.imageURL || "";
case "%IMAGE_URL%" : return context.imageURL || "";
case "%M" : return context.mediaURL || "";
case "%MEDIA_URL%" : return context.mediaURL || "";
case "%P" : return readFromClipboard() || "";
case "%CLIPBOARD%" : return readFromClipboard() || "";
case "%FAVICON%" : return gBrowser.getIcon(tab ? tab : null) || "";
case "%EMAIL%" : return getEmailAddress() || "";
case "%EOL%" : return "\r\n";
}
return str;
}
function htmlEscape(s) {
return (s+"").replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/\"/g, "&quot;").replace(/\'/g, "&apos;");
};
function getEmailAddress() {
var url = context.linkURL;
if (!url || !/^mailto:([^?]+).*/i.test(url)) return "";
var addresses = RegExp.$1;
try {
var characterSet = context.target.ownerDocument.characterSet;
const textToSubURI = Cc['@mozilla.org/intl/texttosuburi;1'].getService(Ci.nsITextToSubURI);
addresses = textToSubURI.unEscapeURIForUI(characterSet, addresses);
} catch (ex) {
}
return addresses;
}
},
getSelection: function(win) {
win || (win = this.focusedWindow);
var sel = win.getSelection().toString();
return sel || this.getInputSelection(win.document.activeElement);
},
getInputSelection: function(elem) {
if (elem instanceof HTMLTextAreaElement || elem instanceof HTMLInputElement && elem.mozIsTextField(false))
return elem.value.substring(elem.selectionStart, elem.selectionEnd);
return "";
},
edit: function(aFile) {
if (!aFile || !aFile.exists() || !aFile.isFile()) return;
var editor = Services.prefs.getCharPref("view_source.editor.path");
if (!editor) return this.log(U("エディタのパスが未設定です。\n view_source.editor.path を設定してください"));
try {
var UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "Shift_JIS": "UTF-8";
var path = UI.ConvertFromUnicode(aFile.path);
this.exec(editor, path);
} catch (e) {}
},
copy: function(aText) {
Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper).copyString(aText);
XULBrowserWindow.statusTextField.label = "Copy: " + aText;
},
alert: function(aString, aTitle) {
Cc['@mozilla.org/alerts-service;1'].getService(Ci.nsIAlertsService)
.showAlertNotification("", aTitle||"addMenu" , aString, false, "", null);
},
log: log,
};
window.addMenu.init();
function $(id) { return document.getElementById(id); }
function $$(exp, doc) { return Array.prototype.slice.call((doc || document).querySelectorAll(exp)); }
function $A(args) { return Array.prototype.slice.call(args); }
function log() { Application.console.log(Array.slice(arguments)); }
function U(text) 1 < 'あ'.length ? decodeURIComponent(escape(text)) : text;
function $E(xml, doc) {
doc = doc || document;
xml = <root xmlns={doc.documentElement.namespaceURI}/>.appendChild(xml);
var settings = XML.settings();
XML.prettyPrinting = false;
var root = new DOMParser().parseFromString(xml.toXMLString(), 'application/xml').documentElement;
XML.setSettings(settings);
doc.adoptNode(root);
var range = doc.createRange();
range.selectNodeContents(root);
var frag = range.extractContents();
range.detach();
return frag.childNodes.length < 2 ? frag.firstChild : frag;
}
function addStyle(css) {
var pi = document.createProcessingInstruction(
'xml-stylesheet',
'type="text/css" href="data:text/css;utf-8,' + encodeURIComponent(css) + '"'
);
return document.insertBefore(pi, document.documentElement);
}
function loadText(aFile) {
var fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
var sstream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
fstream.init(aFile, -1, 0, 0);
sstream.init(fstream);
var data = sstream.read(sstream.available());
try { data = decodeURIComponent(escape(data)); } catch(e) {}
sstream.close();
fstream.close();
return data;
}
})(<![CDATA[
#contentAreaContextMenu:not([addMenu~="select"]) .addMenu[condition~="select"],
#contentAreaContextMenu:not([addMenu~="link"]) .addMenu[condition~="link"],
#contentAreaContextMenu:not([addMenu~="mailto"]) .addMenu[condition~="mailto"],
#contentAreaContextMenu:not([addMenu~="image"]) .addMenu[condition~="image"],
#contentAreaContextMenu:not([addMenu~="media"]) .addMenu[condition~="media"],
#contentAreaContextMenu:not([addMenu~="input"]) .addMenu[condition~="input"],
#contentAreaContextMenu[addMenu~="select"] .addMenu:-moz-any([condition~="normal"], [condition~="noselect"]),
#contentAreaContextMenu[addMenu~="link"] .addMenu:-moz-any([condition~="normal"], [condition~="nolink"]),
#contentAreaContextMenu[addMenu~="mailto"] .addMenu:-moz-any([condition~="normal"], [condition~="nomailto"]),
#contentAreaContextMenu[addMenu~="image"] .addMenu:-moz-any([condition~="normal"], [condition~="noimage"]),
#contentAreaContextMenu[addMenu~="media"] .addMenu:-moz-any([condition~="normal"], [condition~="nomedia"]),
#contentAreaContextMenu[addMenu~="input"] .addMenu:-moz-any([condition~="normal"], [condition~="noinput"]),
/*
#tabContextMenu .addMenu:-moz-any([condition~="link"], [condition~="mailto"], [condition~="image"], [condition~="media"], [condition~="input"]),
*/
.addMenu-insert-point
{ display: none; }
#addMenu-pagemenu,
menu.addMenu {
-moz-binding: url("chrome://global/content/bindings/menu.xml#menu-iconic");
}
menuitem.addMenu {
-moz-binding: url("chrome://global/content/bindings/menu.xml#menuitem-iconic");
}
.addMenu[url] {
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
}
.addMenu.exec,
.addMenu[exec] {
list-style-image: url("chrome://browser/skin/aboutSessionRestore-window-icon.png");
}
.addMenu.copy,
menuitem.addMenu[text]:not([url]):not([keyword]):not([exec])
{
list-style-image: url("chrome://browser/skin/appmenu-icons.png");
-moz-image-region: rect(0pt, 32px, 16px, 16px);
}
.addMenu.checkbox .menu-iconic-icon {
-moz-appearance: checkbox;
}
]]>.toString());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment