Diff
checker
テキスト
テキスト
画像
ドキュメント
Excel
フォルダ
Legal
Enterprise
デスクトップ
料金
ログイン
Diffchecker デスクトップのダウンロード
テキスト比較
2 つのテキスト ファイルの違いを見つける
ツール
履歴
ライブエディター
未変更行を折りたたむ
折り返しなし
レイアウト
分割
統合
比較精度
スマート
単語
文字
シンタックスハイライト
構文を選択
無視
テキスト変換
最初の差分へ移動
入力を編集
Diffchecker Desktop
Diffcheckerを実行する最も安全な方法。Diffchecker Desktopアプリを入手:あなたの差分はコンピューターから出ることはありません!
Desktopを入手
Untitled diff
作成日
11 年前
差分は期限切れになりません
クリア
エクスポート
共有
説明
37 削除
行
合計
削除
文字
合計
削除
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
592 行
すべてコピー
47 追加
行
合計
追加
文字
合計
追加
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
601 行
すべてコピー
Components.utils.import("resource://gre/modules/AddonManager.jsm");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
var doAlphaSort = null; // for pref (alphabetical vs by-state sorting)
var doAlphaSort = null; // for pref (alphabetical vs by-state sorting)
var updatedSort = false; // for pref (sort by last updated)
var updatedSort = false; // for pref (sort by last updated)
var dontSort = false; // ignore sort pref in category-userstyles (provides own sorting)
var dontSort = false; // ignore sort pref in category-userstyles (provides own sorting)
var restore = null; // for pref (restore hilite after closing AoM)
var restore = null; // for pref (restore hilite after closing AoM)
var showUI = null; // for pref (whether to create/display ac menu)
var showUI = null; // for pref (whether to create/display ac menu)
var UIwidth = null; // for pref (ac menu size)
var UIwidth = null; // for pref (ac menu size)
var showVersionNumber = null; // for pref (whether to show version number in ac menu)
var showVersionNumber = null; // for pref (whether to show version number in ac menu)
var spacer = " ";
var spacer = " ";
var UIextra = null; // for restore-on-demand hidden pref
var UIextra = null; // for restore-on-demand hidden pref
var extraRows = null;
var extraRows = null;
var extArray = null;
var extArray = null;
var themeArray = null;
var themeArray = null;
var pluginArray = null;
var pluginArray = null;
var userstyleArray = null;
var userstyleArray = null;
var serviceArray = null;
var serviceArray = null;
var userscriptArray = null;
var userscriptArray = null;
コピー
コピー済み
コピー
コピー済み
var scriptishArray = null;
var custombuttonsArray = null;
var dictionaryArray = null;
var localeArray = null;
var savedAddonName = null;
var savedAddonName = null;
var displayDropdown = null; // used for Seamonkey & Tbird workaround
var displayDropdown = null; // used for Seamonkey & Tbird workaround
const LISTVIEW = 2;
const LISTVIEW = 2;
const DETAILVIEW = 4;
const DETAILVIEW = 4;
var supportedCats = [ "category-extension", "category-theme", "category-plugin", "category-userstyle",
var supportedCats = [ "category-extension", "category-theme", "category-plugin", "category-userstyle",
コピー
コピー済み
コピー
コピー済み
"category-service", "category-greasemonkey-user-script"
];
"category-service", "category-greasemonkey-user-script"
, "category-userscript",
"category-custombuttons", "category-dictionary", "category-locale"
];
// from http://erikvold.com/blog/index.cfm/2011/6/14/restartless-firefox-addons-part-6-better-includes
// from http://erikvold.com/blog/index.cfm/2011/6/14/restartless-firefox-addons-part-6-better-includes
// Thanks, Erik!
// Thanks, Erik!
(function(global) {
(function(global) {
global.include = function include(src) {
global.include = function include(src) {
var o = {};
var o = {};
Components.utils.import("resource://gre/modules/Services.jsm", o);
Components.utils.import("resource://gre/modules/Services.jsm", o);
var uri = o.Services.io.newURI(src, null, o.Services.io.newURI(__SCRIPT_URI_SPEC__, null, null));
var uri = o.Services.io.newURI(src, null, o.Services.io.newURI(__SCRIPT_URI_SPEC__, null, null));
o.Services.scriptloader.loadSubScript(uri.spec, global);
o.Services.scriptloader.loadSubScript(uri.spec, global);
};
};
})(this);
})(this);
include("components/addonList_autocomplete.js");
include("components/addonList_autocomplete.js");
function startup(data, reason) {
function startup(data, reason) {
Services.obs.addObserver(ChromeDocObserver, "chrome-document-global-created", false);
Services.obs.addObserver(ChromeDocObserver, "chrome-document-global-created", false);
var defPrefs = Services.prefs.getDefaultBranch("extensions.addonsmgrhilte@cfl.");
var defPrefs = Services.prefs.getDefaultBranch("extensions.addonsmgrhilte@cfl.");
defPrefs.setBoolPref("restore", true);
defPrefs.setBoolPref("restore", true);
defPrefs.setBoolPref("alphaSort", false);
defPrefs.setBoolPref("alphaSort", false);
defPrefs.setBoolPref("updatedSort", false);
defPrefs.setBoolPref("updatedSort", false);
defPrefs.setBoolPref("extraRows", false);
defPrefs.setBoolPref("extraRows", false);
defPrefs.setBoolPref("showUI", true); // should we default this to true now??????
defPrefs.setBoolPref("showUI", true); // should we default this to true now??????
defPrefs.setIntPref("listboxSize", 18);
defPrefs.setIntPref("listboxSize", 18);
defPrefs.setBoolPref("UIextra", false);
defPrefs.setBoolPref("UIextra", false);
defPrefs.setBoolPref("showVersion", false);
defPrefs.setBoolPref("showVersion", false);
// register our custom autocomplete component
// register our custom autocomplete component
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).registerFactory(CLASS_ID,
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).registerFactory(CLASS_ID,
CLASS_NAME, CONTRACT_ID, NSGetFactory(CLASS_ID));
CLASS_NAME, CONTRACT_ID, NSGetFactory(CLASS_ID));
if (reason == ADDON_ENABLE || reason == ADDON_INSTALL) {
if (reason == ADDON_ENABLE || reason == ADDON_INSTALL) {
var mgrs = findAddonsMgrs();
var mgrs = findAddonsMgrs();
var i;
var i;
for (i = 0; i < mgrs.length; i++) {
for (i = 0; i < mgrs.length; i++) {
mgrs[i].location.reload();
mgrs[i].location.reload();
}
}
}
}
}
}
function shutdown(data, reason) {
function shutdown(data, reason) {
Services.obs.removeObserver(ChromeDocObserver, "chrome-document-global-created");
Services.obs.removeObserver(ChromeDocObserver, "chrome-document-global-created");
// call flush due to the bundle service cache (for aomhilite.properties string bundle)
// call flush due to the bundle service cache (for aomhilite.properties string bundle)
Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService)
Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService)
.flushBundles();
.flushBundles();
// unregister our custom autocomplete component
// unregister our custom autocomplete component
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).unregisterFactory(CLASS_ID,
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).unregisterFactory(CLASS_ID,
NSGetFactory(CLASS_ID));
NSGetFactory(CLASS_ID));
// remove stylesheets
// remove stylesheets
removeStylesheet("chrome://aomhilite/content/aomhilite.css");
removeStylesheet("chrome://aomhilite/content/aomhilite.css");
removeStylesheet("chrome://aomhilite/content/aomhiliteLG.css");
removeStylesheet("chrome://aomhilite/content/aomhiliteLG.css");
removeStylesheet("chrome://aomhilite/content/aomhiliteOSX.css");
removeStylesheet("chrome://aomhilite/content/aomhiliteOSX.css");
if (reason == ADDON_DISABLE) {
if (reason == ADDON_DISABLE) {
// remove any UI from any open Add-ons Manager tabs and revert to default sorting
// remove any UI from any open Add-ons Manager tabs and revert to default sorting
var mgrs = findAddonsMgrs();
var mgrs = findAddonsMgrs();
var i;
var i;
for (i = 0; i < mgrs.length; i++) {
for (i = 0; i < mgrs.length; i++) {
AddonsMgrOnUnload.call(mgrs[i]);
AddonsMgrOnUnload.call(mgrs[i]);
// reverts to default sort;
// reverts to default sort;
// also allows aomhilite.xml to be removed from memory w/o waiting for user to close AoM
// also allows aomhilite.xml to be removed from memory w/o waiting for user to close AoM
mgrs[i].location.reload();
mgrs[i].location.reload();
}
}
}
}
}
}
function install(data, reason) {
function install(data, reason) {
}
}
function uninstall(data, reason) {
function uninstall(data, reason) {
// don't remove user's selection when updating ext (as opposed to actual uninstall)
// don't remove user's selection when updating ext (as opposed to actual uninstall)
if (reason != "ADDON_UNINSTALL") {
if (reason != "ADDON_UNINSTALL") {
return;
return;
}
}
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
var localstore = RDF.GetDataSource('rdf:local-store');
var localstore = RDF.GetDataSource('rdf:local-store');
var subj = RDF.GetResource('about:addons#addon-list');
var subj = RDF.GetResource('about:addons#addon-list');
var pred = RDF.GetResource('aomhilite');
var pred = RDF.GetResource('aomhilite');
var target = localstore.GetTarget(subj, pred, true);
var target = localstore.GetTarget(subj, pred, true);
if (target == null) {
if (target == null) {
return;
return;
} // if it's an empty string we want to remove it's entry
} // if it's an empty string we want to remove it's entry
target = target.QueryInterface(Components.interfaces.nsIRDFLiteral);
target = target.QueryInterface(Components.interfaces.nsIRDFLiteral);
var obj = RDF.GetLiteral(target.Value);
var obj = RDF.GetLiteral(target.Value);
localstore.Unassert(subj, pred, obj, true);
localstore.Unassert(subj, pred, obj, true);
}
}
function ChromeDocObserver(aSubject, aTopic, aData) {
function ChromeDocObserver(aSubject, aTopic, aData) {
try {
try {
if (aTopic != "chrome-document-global-created") {
if (aTopic != "chrome-document-global-created") {
return;
return;
}
}
var win = aSubject;
var win = aSubject;
var uri = win.document.documentURI;
var uri = win.document.documentURI;
// if Add-ons Manager Dialog Returns add-on is installed, uri will be about:blank until loaded
// if Add-ons Manager Dialog Returns add-on is installed, uri will be about:blank until loaded
if (uri == "about:addons" || uri == "about:blank") {
if (uri == "about:addons" || uri == "about:blank") {
win.addEventListener("load", AddonsMgrOnload, false);
win.addEventListener("load", AddonsMgrOnload, false);
}
}
} catch (e) {
} catch (e) {
Services.console.logStringMessage("Exception in ChromeDocObserver");
Services.console.logStringMessage("Exception in ChromeDocObserver");
}
}
}
}
function AddonsMgrOnload() {
function AddonsMgrOnload() {
// removing this load listener is req'd to prevent mem leak
// removing this load listener is req'd to prevent mem leak
// if we're at about:blank we need to do that *now*
// if we're at about:blank we need to do that *now*
// might as well do them all here
// might as well do them all here
// listener no longer needed since if the mgr is reloaded via F5,
// listener no longer needed since if the mgr is reloaded via F5,
// unload is called, then ChromeDocObserver re-adds the listener
// unload is called, then ChromeDocObserver re-adds the listener
this.removeEventListener("load", AddonsMgrOnload, false);
this.removeEventListener("load", AddonsMgrOnload, false);
if (this.document.documentURI != "about:addons") { return; }
if (this.document.documentURI != "about:addons") { return; }
this.addEventListener("unload", AddonsMgrOnUnload, false);
this.addEventListener("unload", AddonsMgrOnUnload, false);
var AMdoc = this.document; // document obj of Addons Mgr window
var AMdoc = this.document; // document obj of Addons Mgr window
var addonList = AMdoc.getElementById("addon-list");
var addonList = AMdoc.getElementById("addon-list");
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
.getService(Components.interfaces.nsIPrefService);
prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl.");
prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl.");
doAlphaSort = prefs.getBoolPref("alphaSort");
doAlphaSort = prefs.getBoolPref("alphaSort");
updatedSort = prefs.getBoolPref("updatedSort");
updatedSort = prefs.getBoolPref("updatedSort");
restore = prefs.getBoolPref("restore");
restore = prefs.getBoolPref("restore");
UIextra = prefs.getBoolPref("UIextra");
UIextra = prefs.getBoolPref("UIextra");
showUI = prefs.getBoolPref("showUI");
showUI = prefs.getBoolPref("showUI");
extraRows = prefs.getBoolPref("extraRows");
extraRows = prefs.getBoolPref("extraRows");
// restore-on-demand useless if already auto-restored, or the UI not even visible
// restore-on-demand useless if already auto-restored, or the UI not even visible
if (restore || !showUI) {
if (restore || !showUI) {
UIextra = false;
UIextra = false;
}
}
UIwidth = prefs.getIntPref("listboxSize");
UIwidth = prefs.getIntPref("listboxSize");
UIwidth = (UIwidth > 50) ? 50 : UIwidth;
UIwidth = (UIwidth > 50) ? 50 : UIwidth;
UIwidth = (UIwidth < 10) ? 10 : UIwidth;
UIwidth = (UIwidth < 10) ? 10 : UIwidth;
if (!restore) {
if (!restore) {
addonList.setAttribute('aomhilite', "");
addonList.setAttribute('aomhilite', "");
}
}
this.addEventListener("ViewChanged", onViewChange, false);
this.addEventListener("ViewChanged", onViewChange, false);
var cat = AMdoc.getElementById("categories");
var cat = AMdoc.getElementById("categories");
if (!cat || !addonList) {
if (!cat || !addonList) {
return;
return;
}
}
var attr = addonList.getAttribute("persist"); // 'persist' enables this info to survive a restart of fx
var attr = addonList.getAttribute("persist"); // 'persist' enables this info to survive a restart of fx
if (!attr) {
if (!attr) {
addonList.setAttribute("persist", "aomhilite");
addonList.setAttribute("persist", "aomhilite");
} else if (attr.indexOf("aomhilite") < 0) {
} else if (attr.indexOf("aomhilite") < 0) {
addonList.setAttribute("persist", attr + " aomhilite");
addonList.setAttribute("persist", attr + " aomhilite");
}
}
addonList.addEventListener("select", onSelect, false);
addonList.addEventListener("select", onSelect, false);
// let AoM finish loading list, before attempting potential resort
// let AoM finish loading list, before attempting potential resort
this.setTimeout(function() {initAddonList(AMdoc);}, 0);
this.setTimeout(function() {initAddonList(AMdoc);}, 0);
if (showUI) { this.setTimeout(function() {initUI(AMdoc);}, 100); }
if (showUI) { this.setTimeout(function() {initUI(AMdoc);}, 100); }
}
}
function initAddonList (AMdoc) {
function initAddonList (AMdoc) {
//Services.console.logStringMessage("initAddonList called");
//Services.console.logStringMessage("initAddonList called");
// check if we're in list view of a supported category; sort and hilite
// check if we're in list view of a supported category; sort and hilite
var cat = AMdoc.getElementById("categories");
var cat = AMdoc.getElementById("categories");
var selCat = cat.selectedItem.id;
var selCat = cat.selectedItem.id;
var view = AMdoc.getElementById('view-port');
var view = AMdoc.getElementById('view-port');
if ((supportedCats.indexOf(selCat) != -1) && view.getAttribute('selectedIndex') == LISTVIEW) {
if ((supportedCats.indexOf(selCat) != -1) && view.getAttribute('selectedIndex') == LISTVIEW) {
if (selCat == "category-userstyle" || selCat == "category-greasemonkey-user-script") {
if (selCat == "category-userstyle" || selCat == "category-greasemonkey-user-script") {
dontSort = true;
dontSort = true;
}
}
if (doAlphaSort || updatedSort) {
if (doAlphaSort || updatedSort) {
resort(AMdoc);
resort(AMdoc);
}
}
restoreHilite(AMdoc);
restoreHilite(AMdoc);
}
}
}
}
var addonListener = {
var addonListener = {
onInstalled : function(addon) {
onInstalled : function(addon) {
updateListboxContents(addon, "add");
updateListboxContents(addon, "add");
updateAllListboxes();
updateAllListboxes();
},
},
/*
/*
* due to the 'undo' option remaining available until aom closed/reopened, this won't get called until current
* due to the 'undo' option remaining available until aom closed/reopened, this won't get called until current
* instance (tab) is closed, because that's when the actual uninstall occurs (and when we should remove item from
* instance (tab) is closed, because that's when the actual uninstall occurs (and when we should remove item from
* dropdown list)
* dropdown list)
*/
*/
onUninstalled : function(addon) {
onUninstalled : function(addon) {
updateListboxContents(addon, "remove");
updateListboxContents(addon, "remove");
updateAllListboxes();
updateAllListboxes();
}
}
};
};
function initUI(AMdoc) {
function initUI(AMdoc) {
var acListboxStyle = "margin-left: 1em; margin-right: 1em; width: " + UIwidth + "em;";
var acListboxStyle = "margin-left: 1em; margin-right: 1em; width: " + UIwidth + "em;";
var acAddonList = AMdoc.createElement("textbox");
var acAddonList = AMdoc.createElement("textbox");
acAddonList.setAttribute("id", "aomhilite_ac_menu");
acAddonList.setAttribute("id", "aomhilite_ac_menu");
acAddonList.setAttribute("style", acListboxStyle);
acAddonList.setAttribute("style", acListboxStyle);
acAddonList.setAttribute("type", "autocomplete");
acAddonList.setAttribute("type", "autocomplete");
// acAddonList.setAttribute("size", 24); // seems to have no effect; set via css width instead
// acAddonList.setAttribute("size", 24); // seems to have no effect; set via css width instead
acAddonList.setAttribute("autocompletesearch", "addonList_autocomplete");
acAddonList.setAttribute("autocompletesearch", "addonList_autocomplete");
acAddonList.setAttribute("enablehistory", true);
acAddonList.setAttribute("enablehistory", true);
// acAddonList.setAttribute("completedefaultindex", true);
// acAddonList.setAttribute("completedefaultindex", true);
acAddonList.setAttribute("forcecomplete", true); // ensures selection is valid
acAddonList.setAttribute("forcecomplete", true); // ensures selection is valid
// only applies to typing in box; see aomhilite.xml
// only applies to typing in box; see aomhilite.xml
acAddonList.setAttribute("maxrows", 10); // default is about 6
acAddonList.setAttribute("maxrows", 10); // default is about 6
var notifyListbox = "var evt = document.createEvent('Events'); " + "evt.initEvent('textentered', true, true); " +
var notifyListbox = "var evt = document.createEvent('Events'); " + "evt.initEvent('textentered', true, true); " +
"this.dispatchEvent(evt);";
"this.dispatchEvent(evt);";
acAddonList.setAttribute("ontextentered", notifyListbox);
acAddonList.setAttribute("ontextentered", notifyListbox);
var strbundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(
var strbundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(
Components.interfaces.nsIStringBundleService).createBundle("chrome://aomhilite/locale/aomhilite.properties");
Components.interfaces.nsIStringBundleService).createBundle("chrome://aomhilite/locale/aomhilite.properties");
var selectaddon = strbundle.GetStringFromName("placeholderString");
var selectaddon = strbundle.GetStringFromName("placeholderString");
acAddonList.setAttribute("placeholder", selectaddon);
acAddonList.setAttribute("placeholder", selectaddon);
/* set up stylesheets */
/* set up stylesheets */
var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
addStylesheet("chrome://aomhilite/content/aomhilite.css");
addStylesheet("chrome://aomhilite/content/aomhilite.css");
if (osString == "Darwin") {
if (osString == "Darwin") {
addStylesheet("chrome://aomhilite/content/aomhiliteOSX.css");
addStylesheet("chrome://aomhilite/content/aomhiliteOSX.css");
}
}
var updateBtn = AMdoc.getElementById("header-utils-btn");
var updateBtn = AMdoc.getElementById("header-utils-btn");
var head = AMdoc.getElementById("header");
var head = AMdoc.getElementById("header");
head.insertBefore(acAddonList, updateBtn);
head.insertBefore(acAddonList, updateBtn);
// prevents "Extension cannot be installed because Nightly cannot modify the needed file"
// prevents "Extension cannot be installed because Nightly cannot modify the needed file"
// error when updating this ext (bug 719180)
// error when updating this ext (bug 719180)
// although 71980 is fixed in fx 19+, using (tested on fx 21.0a1):
// although 71980 is fixed in fx 19+, using (tested on fx 21.0a1):
// acAddonList.style.MozBinding = "url(chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite)";
// acAddonList.style.MozBinding = "url(chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite)";
// leaves the aomhilite.xml file in memory even when AoM is closed and aomhilite is disabled!
// leaves the aomhilite.xml file in memory even when AoM is closed and aomhilite is disabled!
var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
.getService(Components.interfaces.nsIChromeRegistry);
.getService(Components.interfaces.nsIChromeRegistry);
var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var bindingUri;
var bindingUri;
if (extraRows) {
if (extraRows) {
bindingUri = ioService.newURI("chrome://aomhilite/content/aomhiliteLG.xml#ac_menu_aomhilite", null, null);
bindingUri = ioService.newURI("chrome://aomhilite/content/aomhiliteLG.xml#ac_menu_aomhilite", null, null);
} else {
} else {
bindingUri = ioService.newURI("chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite", null, null);
bindingUri = ioService.newURI("chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite", null, null);
}
}
var convertedBindingUri = chromeReg.convertChromeURL(bindingUri);
var convertedBindingUri = chromeReg.convertChromeURL(bindingUri);
acAddonList.style.MozBinding = 'url("' + convertedBindingUri.spec + '")';
acAddonList.style.MozBinding = 'url("' + convertedBindingUri.spec + '")';
const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
if (appInfo.ID != FIREFOX_ID) { // workaround - Seamonkey/Tbird (bug 708520) aren't opening popup by default
if (appInfo.ID != FIREFOX_ID) { // workaround - Seamonkey/Tbird (bug 708520) aren't opening popup by default
displayDropdown = function(e) {
displayDropdown = function(e) {
var id = e.originalTarget.getAttribute("anonid");
var id = e.originalTarget.getAttribute("anonid");
if (id != "historydropmarker") { return; }
if (id != "historydropmarker") { return; }
//Services.console.logStringMessage("historydropmarker click");
//Services.console.logStringMessage("historydropmarker click");
var acAddonList = e.target.ownerDocument.getElementById("aomhilite_ac_menu")
var acAddonList = e.target.ownerDocument.getElementById("aomhilite_ac_menu")
acAddonList.showHistoryPopup();
acAddonList.showHistoryPopup();
};
};
acAddonList.addEventListener("click", displayDropdown, false);
acAddonList.addEventListener("click", displayDropdown, false);
}
}
acAddonList.addEventListener("textentered", onACaddonListSelection, false);
acAddonList.addEventListener("textentered", onACaddonListSelection, false);
AddonManager.addAddonListener(addonListener);
AddonManager.addAddonListener(addonListener);
if (UIextra) {
if (UIextra) {
var addonList = AMdoc.getElementById("addon-list");
var addonList = AMdoc.getElementById("addon-list");
addonList.setAttribute('restoreondemand', addonList.getAttribute('aomhilite'));
addonList.setAttribute('restoreondemand', addonList.getAttribute('aomhilite'));
}
}
// (do here since addonListCallback will require data initialized above)
// (do here since addonListCallback will require data initialized above)
AddonManager.getAddonsByTypes([ "extension" ], function(addons) {
AddonManager.getAddonsByTypes([ "extension" ], function(addons) {
addonListCallback(addons, AMdoc, "extension");
addonListCallback(addons, AMdoc, "extension");
});
});
AddonManager.getAddonsByTypes([ "theme" ], function(addons) {
AddonManager.getAddonsByTypes([ "theme" ], function(addons) {
addonListCallback(addons, AMdoc, "theme");
addonListCallback(addons, AMdoc, "theme");
});
});
AddonManager.getAddonsByTypes([ "plugin" ], function(addons) {
AddonManager.getAddonsByTypes([ "plugin" ], function(addons) {
addonListCallback(addons, AMdoc, "plugin");
addonListCallback(addons, AMdoc, "plugin");
});
});
AddonManager.getAddonsByTypes([ "userstyle" ], function(addons) {
AddonManager.getAddonsByTypes([ "userstyle" ], function(addons) {
addonListCallback(addons, AMdoc, "userstyle");
addonListCallback(addons, AMdoc, "userstyle");
});
});
AddonManager.getAddonsByTypes([ "service" ], function(addons) {
AddonManager.getAddonsByTypes([ "service" ], function(addons) {
addonListCallback(addons, AMdoc, "service");
addonListCallback(addons, AMdoc, "service");
});
});
AddonManager.getAddonsByTypes([ "greasemonkey-user-script" ], function(addons) {
AddonManager.getAddonsByTypes([ "greasemonkey-user-script" ], function(addons) {
addonListCallback(addons, AMdoc, "greasemonkey-user-script");
addonListCallback(addons, AMdoc, "greasemonkey-user-script");
});
});
コピー
コピー済み
コピー
コピー済み
// Scriptish
AddonManager.getAddonsByTypes([ "userscript" ], function(addons) {
addonListCallback(addons, AMdoc, "userscript");
});
// Custom Buttons
AddonManager.getAddonsByTypes([ "custombuttons" ], function(addons) {
addonListCallback(addons, AMdoc, "custombuttons");
});
AddonManager.getAddonsByTypes([ "dictionary" ], function(addons) {
addonListCallback(addons, AMdoc, "dictionary");
});
AddonManager.getAddonsByTypes([ "locale" ], function(addons) {
addonListCallback(addons, AMdoc, "locale");
});
}
}
function addStylesheet(sheet) {
function addStylesheet(sheet) {
var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
.getService(Components.interfaces.nsIStyleSheetService);
.getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var uri = ios.newURI(sheet, null, null);
var uri = ios.newURI(sheet, null, null);
if (!sss.sheetRegistered(uri, sss.USER_SHEET)) {
if (!sss.sheetRegistered(uri, sss.USER_SHEET)) {
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
}
}
}
}
function removeStylesheet(sheet) {
function removeStylesheet(sheet) {
var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
.getService(Components.interfaces.nsIStyleSheetService);
.getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var uri = ios.newURI(sheet, null, null);
var uri = ios.newURI(sheet, null, null);
if (sss.sheetRegistered(uri, sss.USER_SHEET)) {
if (sss.sheetRegistered(uri, sss.USER_SHEET)) {
sss.unregisterSheet(uri, sss.USER_SHEET);
sss.unregisterSheet(uri, sss.USER_SHEET);
}
}
}
}
function findAddonsMgrs() {
function findAddonsMgrs() {
// find all open mgrs
// find all open mgrs
var mgrs = [];
var mgrs = [];
var windows = Services.wm.getEnumerator("navigator:browser");
var windows = Services.wm.getEnumerator("navigator:browser");
var window;
var window;
while (windows.hasMoreElements()) {
while (windows.hasMoreElements()) {
window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
window.gBrowser.browsers.forEach(findMgrTab);
window.gBrowser.browsers.forEach(findMgrTab);
}
}
function findMgrTab(browser) {
function findMgrTab(browser) {
if (browser.currentURI.spec == "about:addons") {
if (browser.currentURI.spec == "about:addons") {
mgrs.push(browser.contentWindow);
mgrs.push(browser.contentWindow);
}
}
}
}
// Mgr in dialog window (for Add-ons Manager Dialog Returns compatibility)
// Mgr in dialog window (for Add-ons Manager Dialog Returns compatibility)
var topWin = Services.wm.getMostRecentWindow(null);
var topWin = Services.wm.getMostRecentWindow(null);
if (topWin.document.documentURI == "about:addons") {
if (topWin.document.documentURI == "about:addons") {
mgrs.push(topWin);
mgrs.push(topWin);
}
}
return mgrs;
return mgrs;
}
}
function updateListboxContents(addon, action) {
function updateListboxContents(addon, action) {
if (action != "add" && action != "remove") {
if (action != "add" && action != "remove") {
return;
return;
}
}
var currentArray = null;
var currentArray = null;
switch (addon.type) {
switch (addon.type) {
case "extension":
case "extension":
currentArray = extArray;
currentArray = extArray;
break;
break;
case "theme":
case "theme":
currentArray = themeArray;
currentArray = themeArray;
break;
break;
case "plugin":
case "plugin":
currentArray = pluginArray;
currentArray = pluginArray;
break;
break;
case "userstyle":
case "userstyle":
currentArray = userstyleArray;
currentArray = userstyleArray;
break;
break;
case "service":
case "service":
currentArray = serviceArray;
currentArray = serviceArray;
コピー
コピー済み
コピー
コピー済み
break;
case "greasemonkey-user-script":
case "greasemonkey-user-script":
currentArray = userscriptArray;
currentArray = userscriptArray;
break;
break;
コピー
コピー済み
コピー
コピー済み
case "userscript":
currentArray = scriptishArray;
break;
case "custombuttons":
currentArray = custombuttonsArray;
break;
case "dictionary":
currentArray = dictionaryArray;
break;
case "locale":
currentArray = localeArray;
break;
default:
default:
Services.console.logStringMessage("Addons Manager Hilite encountered an unsupported Add-on type: " +
Services.console.logStringMessage("Addons Manager Hilite encountered an unsupported Add-on type: " +
addon.type + " " + addon.name);
addon.type + " " + addon.name);
}
}
var entryFound = false;
var entryFound = false;
var element;
var element;
for (element = 0; element < currentArray.length; element++) {
for (element = 0; element < currentArray.length; element++) {
let
let
entry = currentArray[element];
entry = currentArray[element];
if (entry.indexOf(addon.name) != -1) { // found item
if (entry.indexOf(addon.name) != -1) { // found item
entryFound = true;
entryFound = true;
if (showVersionNumber && action == "add") { // version number needs updated
if (showVersionNumber && action == "add") { // version number needs updated
var nameVersion = entry.split(spacer, 2);
var nameVersion = entry.split(spacer, 2);
nameVersion[1] = (nameVersion[0].indexOf("<") == 0) ? addon.version + ">" : addon.version;
nameVersion[1] = (nameVersion[0].indexOf("<") == 0) ? addon.version + ">" : addon.version;
entry = nameVersion.join(spacer);
entry = nameVersion.join(spacer);
currentArray[element] = entry;
currentArray[element] = entry;
} else {
} else {
if (action == "remove") {
if (action == "remove") {
currentArray.splice(element, 1);
currentArray.splice(element, 1);
}
}
}
}
// process restoreondemand entry, if any + actual entry
// process restoreondemand entry, if any + actual entry
if (entry.indexOf("<") != 0) {
if (entry.indexOf("<") != 0) {
break;
break;
}
}
} // end if found
} // end if found
} // end for
} // end for
if (!entryFound && action == "add") { // item not present; needs added
if (!entryFound && action == "add") { // item not present; needs added
var entryToAdd = addon.name;
var entryToAdd = addon.name;
if (showVersionNumber) {
if (showVersionNumber) {
entryToAdd = entryToAdd + spacer + addon.version;
entryToAdd = entryToAdd + spacer + addon.version;
}
}
currentArray.push(entryToAdd);
currentArray.push(entryToAdd);
currentArray.sort(function(addonItem1, addonItem2) {
currentArray.sort(function(addonItem1, addonItem2) {
var addon1Name = addonItem1.toLowerCase();
var addon1Name = addonItem1.toLowerCase();
var addon2Name = addonItem2.toLowerCase();
var addon2Name = addonItem2.toLowerCase();
return addon1Name.localeCompare(addon2Name);
return addon1Name.localeCompare(addon2Name);
});
});
}
}
}
}
function updateAllListboxes() {
function updateAllListboxes() {
var mgrs = findAddonsMgrs();
var mgrs = findAddonsMgrs();
var i;
var i;
for (i = 0; i < mgrs.length; i++) {
for (i = 0; i < mgrs.length; i++) {
var AMdoc = mgrs[i].document;
var AMdoc = mgrs[i].document;
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var cat = AMdoc.getElementById('categories');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id;
var selCat = cat.selectedItem.id;
switch (selCat) { // select the proper menulist for the current category
switch (selCat) { // select the proper menulist for the current category
case "category-extension":
case "category-extension":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray));
break;
break;
case "category-theme":
case "category-theme":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray));
break;
break;
case "category-plugin":
case "category-plugin":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray));
break;
break;
case "category-userstyle":
case "category-userstyle":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray));
break;
break;
case "category-service":
case "category-service":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray));
コピー
コピー済み
コピー
コピー済み
break;
case "category-greasemonkey-user-script":
case "category-greasemonkey-user-script":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray));
break;
break;
コピー
コピー済み
コピー
コピー済み
case "category-userscript":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(scriptishArray));
break;
case "category-custombuttons":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(custombuttonsArray));
break;
case "category-dictionary":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(dictionaryArray));
break;
case "category-locale":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(localeArray));
break;
}
}
}
}
}
}
function restoreHilite(AMdoc) {
function restoreHilite(AMdoc) {
//Services.console.logStringMessage("restoreHilite called");
//Services.console.logStringMessage("restoreHilite called");
// purpose: retrieve saved selection and restore it
// purpose: retrieve saved selection and restore it
// content.document does not get document we want if AoM was opened in background via session restore
// content.document does not get document we want if AoM was opened in background via session restore
var selAddon;
var selAddon;
var addonList = AMdoc.getElementById('addon-list');
var addonList = AMdoc.getElementById('addon-list');
var savedSelections = addonList.getAttribute('aomhilite');
var savedSelections = addonList.getAttribute('aomhilite');
//Services.console.logStringMessage(savedSelections);
//Services.console.logStringMessage(savedSelections);
var cat = AMdoc.getElementById('categories');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id; // category-extension, etc.
var selCat = cat.selectedItem.id; // category-extension, etc.
var selectionArray = savedSelections.split(",");
var selectionArray = savedSelections.split(",");
var lastSel = selectionArray[supportedCats.indexOf(selCat)];
var lastSel = selectionArray[supportedCats.indexOf(selCat)];
if (lastSel) {
if (lastSel) {
selAddon = addonList.getElementsByAttribute('value', lastSel);
selAddon = addonList.getElementsByAttribute('value', lastSel);
}
}
if (!lastSel || !selAddon || !selAddon[0]) {
if (!lastSel || !selAddon || !selAddon[0]) {
// no lastSel will occur on newly opened AoM if (always) restore pref is false
// no lastSel will occur on newly opened AoM if (always) restore pref is false
// otherwise typically occurs when selected category has no installed items or has never had a saved selection
// otherwise typically occurs when selected category has no installed items or has never had a saved selection
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
if (acAddonList) {
if (acAddonList) {
acAddonList.value = "";
acAddonList.value = "";
} // onSelect not triggered (see below); need to clear this now
} // onSelect not triggered (see below); need to clear this now
return;
return;
}
}
addonList.selectItem(selAddon[0]); // will trigger onSelect
addonList.selectItem(selAddon[0]); // will trigger onSelect
//addonList.scrollBoxObject.scrollToElement(selAddon[0]);
//addonList.scrollBoxObject.scrollToElement(selAddon[0]);
selAddon[0].scrollIntoView();
selAddon[0].scrollIntoView();
addonList.focus();
addonList.focus();
}
}
function saveUpdatedSel(addonList, selCat, newSelId) {
function saveUpdatedSel(addonList, selCat, newSelId) {
var savedSelections = addonList.getAttribute('aomhilite');
var savedSelections = addonList.getAttribute('aomhilite');
var selectionArray = savedSelections.split(",");
var selectionArray = savedSelections.split(",");
selectionArray[supportedCats.indexOf(selCat)] = newSelId;
selectionArray[supportedCats.indexOf(selCat)] = newSelId;
var updatedSel = selectionArray.toString();
var updatedSel = selectionArray.toString();
addonList.setAttribute('aomhilite', updatedSel);
addonList.setAttribute('aomhilite', updatedSel);
}
}
function onSelect() { // called once per add-on upon loading mgr, but (this.currentIndex = = -1) at that point
function onSelect() { // called once per add-on upon loading mgr, but (this.currentIndex = = -1) at that point
// called when clicking an entry in addonList, selecting from autocomplete list, and from restoreHilite funct; also when changing categories?
// called when clicking an entry in addonList, selecting from autocomplete list, and from restoreHilite funct; also when changing categories?
//Services.console.logStringMessage("onSelect called");
//Services.console.logStringMessage("onSelect called");
//Services.console.logStringMessage(this.id); // addon-list
//Services.console.logStringMessage(this.id); // addon-list
if (this.currentIndex < 0) { return; } // there is no current selected item in this category
if (this.currentIndex < 0) { return; } // there is no current selected item in this category
if (!this.selectedItem) { return; } // avoid 'this.selectedItem is null' error in console (when opening Add-Ons Mgr)
if (!this.selectedItem) { return; } // avoid 'this.selectedItem is null' error in console (when opening Add-Ons Mgr)
var currentSel = this.selectedItem.mAddon.id;
var currentSel = this.selectedItem.mAddon.id;
var AMdoc = this.ownerDocument;
var AMdoc = this.ownerDocument;
var cat = AMdoc.getElementById('categories');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id;
var selCat = cat.selectedItem.id;
if (!currentSel || (supportedCats.indexOf(selCat) == -1)) { return; }
if (!currentSel || (supportedCats.indexOf(selCat) == -1)) { return; }
saveUpdatedSel(this, selCat, currentSel);
saveUpdatedSel(this, selCat, currentSel);
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
if (!acAddonList || !acAddonList.value) {
if (!acAddonList || !acAddonList.value) {
return;
return;
}
}
if (acAddonList.value.indexOf(this.selectedItem.mAddon.name) < 0) {
if (acAddonList.value.indexOf(this.selectedItem.mAddon.name) < 0) {
acAddonList.value = ""; // clear ac list input field, rather than show name of a now unselected item
acAddonList.value = ""; // clear ac list input field, rather than show name of a now unselected item
}
}
}
}
function onACaddonListSelection() {
function onACaddonListSelection() {
// called when selection made from ac dropdown list or pressing ENTER in input field
// called when selection made from ac dropdown list or pressing ENTER in input field
var AMdoc = this.ownerDocument;
var AMdoc = this.ownerDocument;
var cat = AMdoc.getElementById('categories');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id;
var selCat = cat.selectedItem.id;
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
// setting selectionStart & selectionEnd to same value sets the cursor position to that position
// setting selectionStart & selectionEnd to same value sets the cursor position to that position
// set to beginning so text looks cropped on right instead of on left
// set to beginning so text looks cropped on right instead of on left
acAddonList.inputField.selectionStart = 0;
acAddonList.inputField.selectionStart = 0;
acAddonList.inputField.selectionEnd = 0;
acAddonList.inputField.selectionEnd = 0;
var sel = AMdoc.getElementById("aomhilite_ac_menu").value;
var sel = AMdoc.getElementById("aomhilite_ac_menu").value;
if (UIextra && sel.indexOf("<") == 0 && sel.lastIndexOf(">") == sel.length - 1) {
if (UIextra && sel.indexOf("<") == 0 && sel.lastIndexOf(">") == sel.length - 1) {
sel = sel.slice(1, sel.length - 1); // remove angle brackets
sel = sel.slice(1, sel.length - 1); // remove angle brackets
}
}
if (showVersionNumber) {
if (showVersionNumber) {
let
let
nameEnd = sel.lastIndexOf(spacer);
nameEnd = sel.lastIndexOf(spacer);
if (nameEnd > 0) { // remove spacer and version #, if found (should be there, but...)
if (nameEnd > 0) { // remove spacer and version #, if found (should be there, but...)
sel = sel.slice(0, nameEnd);
sel = sel.slice(0, nameEnd);
}
}
}
}
var addonList = AMdoc.getElementById('addon-list');
var addonList = AMdoc.getElementById('addon-list');
var selAddon = addonList.getElementsByAttribute('name', sel);
var selAddon = addonList.getElementsByAttribute('name', sel);
if (selAddon && selAddon[0]) {
if (selAddon && selAddon[0]) {
var newSelId = selAddon[0].mAddon.id;
var newSelId = selAddon[0].mAddon.id;
if (!newSelId) {
if (!newSelId) {
return;
return;
}
}
saveUpdatedSel(addonList, selCat, newSelId);
saveUpdatedSel(addonList, selCat, newSelId);
var view = AMdoc.getElementById('view-port');
var view = AMdoc.getElementById('view-port');
if (view.getAttribute('selectedIndex') == LISTVIEW) {
if (view.getAttribute('selectedIndex') == LISTVIEW) {
restoreHilite(AMdoc);
restoreHilite(AMdoc);
} else {
} else {
selAddon[0].showInDetailView();
selAddon[0].showInDetailView();
}
}
} else {
} else {
/*
/*
* Workaround issue that occurs when using nav arrow takes us back into detail view of a non-current category,
* Workaround issue that occurs when using nav arrow takes us back into detail view of a non-current category,
* resulting in 'addon-list' element that is no longer populated with the list of add-ons, thus there are no
* resulting in 'addon-list' element that is no longer populated with the list of add-ons, thus there are no
* elements with the name we are looking for
* elements with the name we are looking for
*/
*/
savedAddonName = sel;
savedAddonName = sel;
// repopulates the list, finish workaround in the resulting onViewChange
// repopulates the list, finish workaround in the resulting onViewChange
cat.selectedItem.click();
cat.selectedItem.click();
}
}
}
}
コピー
コピー済み
コピー
コピー済み
function
onViewChange() {
function
on
//Services.console.logStringMessage("onViewChange called");
var AMdoc = this.document;
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var view = AMdoc.getElementById('view-port');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id;
if (selCat == "category-userstyle") {
dontSort = true;
}
if (view && view.getAttribute('selectedIndex') == LISTVIEW) {
if (savedAddonName) {
// finish workaround from onACaddonListSelection - display add-on in detail view
var addonList = AMdoc.getElementById('addon-list');
// prevents annoying flash of list view before detail view appears
addonList.setAttribute('hidden', true);
var selAddon = addonList.getElementsByAttribute('name', savedAddonName);
if (selAddon && selAddon[0]) {
selAddon[0].showInDetailView();
var newSelId = selAddon[0].mAddon.id;
saveUpdatedSel(addonList, selCat, newSelId);
}
addonList.removeAttribute('hidden');
savedAddonName = null;
// workaround finished, we're now in detail view, which retriggers viewchange
// (if we unexpectedly fail to find add-on for detail view, just continue in list view)
if (selAddon && selAddon[0]) {
return;
}
}
// need to recheck pref, since we're not using pref observer
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl.");
doAlphaSort = prefs.getBoolPref("alphaSort");
updatedSort = prefs.getBoolPre
保存された差分
原文
ファイルを開く
Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); var doAlphaSort = null; // for pref (alphabetical vs by-state sorting) var updatedSort = false; // for pref (sort by last updated) var dontSort = false; // ignore sort pref in category-userstyles (provides own sorting) var restore = null; // for pref (restore hilite after closing AoM) var showUI = null; // for pref (whether to create/display ac menu) var UIwidth = null; // for pref (ac menu size) var showVersionNumber = null; // for pref (whether to show version number in ac menu) var spacer = " "; var UIextra = null; // for restore-on-demand hidden pref var extraRows = null; var extArray = null; var themeArray = null; var pluginArray = null; var userstyleArray = null; var serviceArray = null; var userscriptArray = null; var savedAddonName = null; var displayDropdown = null; // used for Seamonkey & Tbird workaround const LISTVIEW = 2; const DETAILVIEW = 4; var supportedCats = [ "category-extension", "category-theme", "category-plugin", "category-userstyle", "category-service", "category-greasemonkey-user-script" ]; // from http://erikvold.com/blog/index.cfm/2011/6/14/restartless-firefox-addons-part-6-better-includes // Thanks, Erik! (function(global) { global.include = function include(src) { var o = {}; Components.utils.import("resource://gre/modules/Services.jsm", o); var uri = o.Services.io.newURI(src, null, o.Services.io.newURI(__SCRIPT_URI_SPEC__, null, null)); o.Services.scriptloader.loadSubScript(uri.spec, global); }; })(this); include("components/addonList_autocomplete.js"); function startup(data, reason) { Services.obs.addObserver(ChromeDocObserver, "chrome-document-global-created", false); var defPrefs = Services.prefs.getDefaultBranch("extensions.addonsmgrhilte@cfl."); defPrefs.setBoolPref("restore", true); defPrefs.setBoolPref("alphaSort", false); defPrefs.setBoolPref("updatedSort", false); defPrefs.setBoolPref("extraRows", false); defPrefs.setBoolPref("showUI", true); // should we default this to true now?????? defPrefs.setIntPref("listboxSize", 18); defPrefs.setBoolPref("UIextra", false); defPrefs.setBoolPref("showVersion", false); // register our custom autocomplete component Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).registerFactory(CLASS_ID, CLASS_NAME, CONTRACT_ID, NSGetFactory(CLASS_ID)); if (reason == ADDON_ENABLE || reason == ADDON_INSTALL) { var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { mgrs[i].location.reload(); } } } function shutdown(data, reason) { Services.obs.removeObserver(ChromeDocObserver, "chrome-document-global-created"); // call flush due to the bundle service cache (for aomhilite.properties string bundle) Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService) .flushBundles(); // unregister our custom autocomplete component Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).unregisterFactory(CLASS_ID, NSGetFactory(CLASS_ID)); // remove stylesheets removeStylesheet("chrome://aomhilite/content/aomhilite.css"); removeStylesheet("chrome://aomhilite/content/aomhiliteLG.css"); removeStylesheet("chrome://aomhilite/content/aomhiliteOSX.css"); if (reason == ADDON_DISABLE) { // remove any UI from any open Add-ons Manager tabs and revert to default sorting var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { AddonsMgrOnUnload.call(mgrs[i]); // reverts to default sort; // also allows aomhilite.xml to be removed from memory w/o waiting for user to close AoM mgrs[i].location.reload(); } } } function install(data, reason) { } function uninstall(data, reason) { // don't remove user's selection when updating ext (as opposed to actual uninstall) if (reason != "ADDON_UNINSTALL") { return; } var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); var localstore = RDF.GetDataSource('rdf:local-store'); var subj = RDF.GetResource('about:addons#addon-list'); var pred = RDF.GetResource('aomhilite'); var target = localstore.GetTarget(subj, pred, true); if (target == null) { return; } // if it's an empty string we want to remove it's entry target = target.QueryInterface(Components.interfaces.nsIRDFLiteral); var obj = RDF.GetLiteral(target.Value); localstore.Unassert(subj, pred, obj, true); } function ChromeDocObserver(aSubject, aTopic, aData) { try { if (aTopic != "chrome-document-global-created") { return; } var win = aSubject; var uri = win.document.documentURI; // if Add-ons Manager Dialog Returns add-on is installed, uri will be about:blank until loaded if (uri == "about:addons" || uri == "about:blank") { win.addEventListener("load", AddonsMgrOnload, false); } } catch (e) { Services.console.logStringMessage("Exception in ChromeDocObserver"); } } function AddonsMgrOnload() { // removing this load listener is req'd to prevent mem leak // if we're at about:blank we need to do that *now* // might as well do them all here // listener no longer needed since if the mgr is reloaded via F5, // unload is called, then ChromeDocObserver re-adds the listener this.removeEventListener("load", AddonsMgrOnload, false); if (this.document.documentURI != "about:addons") { return; } this.addEventListener("unload", AddonsMgrOnUnload, false); var AMdoc = this.document; // document obj of Addons Mgr window var addonList = AMdoc.getElementById("addon-list"); var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); doAlphaSort = prefs.getBoolPref("alphaSort"); updatedSort = prefs.getBoolPref("updatedSort"); restore = prefs.getBoolPref("restore"); UIextra = prefs.getBoolPref("UIextra"); showUI = prefs.getBoolPref("showUI"); extraRows = prefs.getBoolPref("extraRows"); // restore-on-demand useless if already auto-restored, or the UI not even visible if (restore || !showUI) { UIextra = false; } UIwidth = prefs.getIntPref("listboxSize"); UIwidth = (UIwidth > 50) ? 50 : UIwidth; UIwidth = (UIwidth < 10) ? 10 : UIwidth; if (!restore) { addonList.setAttribute('aomhilite', ""); } this.addEventListener("ViewChanged", onViewChange, false); var cat = AMdoc.getElementById("categories"); if (!cat || !addonList) { return; } var attr = addonList.getAttribute("persist"); // 'persist' enables this info to survive a restart of fx if (!attr) { addonList.setAttribute("persist", "aomhilite"); } else if (attr.indexOf("aomhilite") < 0) { addonList.setAttribute("persist", attr + " aomhilite"); } addonList.addEventListener("select", onSelect, false); // let AoM finish loading list, before attempting potential resort this.setTimeout(function() {initAddonList(AMdoc);}, 0); if (showUI) { this.setTimeout(function() {initUI(AMdoc);}, 100); } } function initAddonList (AMdoc) { //Services.console.logStringMessage("initAddonList called"); // check if we're in list view of a supported category; sort and hilite var cat = AMdoc.getElementById("categories"); var selCat = cat.selectedItem.id; var view = AMdoc.getElementById('view-port'); if ((supportedCats.indexOf(selCat) != -1) && view.getAttribute('selectedIndex') == LISTVIEW) { if (selCat == "category-userstyle" || selCat == "category-greasemonkey-user-script") { dontSort = true; } if (doAlphaSort || updatedSort) { resort(AMdoc); } restoreHilite(AMdoc); } } var addonListener = { onInstalled : function(addon) { updateListboxContents(addon, "add"); updateAllListboxes(); }, /* * due to the 'undo' option remaining available until aom closed/reopened, this won't get called until current * instance (tab) is closed, because that's when the actual uninstall occurs (and when we should remove item from * dropdown list) */ onUninstalled : function(addon) { updateListboxContents(addon, "remove"); updateAllListboxes(); } }; function initUI(AMdoc) { var acListboxStyle = "margin-left: 1em; margin-right: 1em; width: " + UIwidth + "em;"; var acAddonList = AMdoc.createElement("textbox"); acAddonList.setAttribute("id", "aomhilite_ac_menu"); acAddonList.setAttribute("style", acListboxStyle); acAddonList.setAttribute("type", "autocomplete"); // acAddonList.setAttribute("size", 24); // seems to have no effect; set via css width instead acAddonList.setAttribute("autocompletesearch", "addonList_autocomplete"); acAddonList.setAttribute("enablehistory", true); // acAddonList.setAttribute("completedefaultindex", true); acAddonList.setAttribute("forcecomplete", true); // ensures selection is valid // only applies to typing in box; see aomhilite.xml acAddonList.setAttribute("maxrows", 10); // default is about 6 var notifyListbox = "var evt = document.createEvent('Events'); " + "evt.initEvent('textentered', true, true); " + "this.dispatchEvent(evt);"; acAddonList.setAttribute("ontextentered", notifyListbox); var strbundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService( Components.interfaces.nsIStringBundleService).createBundle("chrome://aomhilite/locale/aomhilite.properties"); var selectaddon = strbundle.GetStringFromName("placeholderString"); acAddonList.setAttribute("placeholder", selectaddon); /* set up stylesheets */ var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS; addStylesheet("chrome://aomhilite/content/aomhilite.css"); if (osString == "Darwin") { addStylesheet("chrome://aomhilite/content/aomhiliteOSX.css"); } var updateBtn = AMdoc.getElementById("header-utils-btn"); var head = AMdoc.getElementById("header"); head.insertBefore(acAddonList, updateBtn); // prevents "Extension cannot be installed because Nightly cannot modify the needed file" // error when updating this ext (bug 719180) // although 71980 is fixed in fx 19+, using (tested on fx 21.0a1): // acAddonList.style.MozBinding = "url(chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite)"; // leaves the aomhilite.xml file in memory even when AoM is closed and aomhilite is disabled! var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"] .getService(Components.interfaces.nsIChromeRegistry); var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); var bindingUri; if (extraRows) { bindingUri = ioService.newURI("chrome://aomhilite/content/aomhiliteLG.xml#ac_menu_aomhilite", null, null); } else { bindingUri = ioService.newURI("chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite", null, null); } var convertedBindingUri = chromeReg.convertChromeURL(bindingUri); acAddonList.style.MozBinding = 'url("' + convertedBindingUri.spec + '")'; const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo); if (appInfo.ID != FIREFOX_ID) { // workaround - Seamonkey/Tbird (bug 708520) aren't opening popup by default displayDropdown = function(e) { var id = e.originalTarget.getAttribute("anonid"); if (id != "historydropmarker") { return; } //Services.console.logStringMessage("historydropmarker click"); var acAddonList = e.target.ownerDocument.getElementById("aomhilite_ac_menu") acAddonList.showHistoryPopup(); }; acAddonList.addEventListener("click", displayDropdown, false); } acAddonList.addEventListener("textentered", onACaddonListSelection, false); AddonManager.addAddonListener(addonListener); if (UIextra) { var addonList = AMdoc.getElementById("addon-list"); addonList.setAttribute('restoreondemand', addonList.getAttribute('aomhilite')); } // (do here since addonListCallback will require data initialized above) AddonManager.getAddonsByTypes([ "extension" ], function(addons) { addonListCallback(addons, AMdoc, "extension"); }); AddonManager.getAddonsByTypes([ "theme" ], function(addons) { addonListCallback(addons, AMdoc, "theme"); }); AddonManager.getAddonsByTypes([ "plugin" ], function(addons) { addonListCallback(addons, AMdoc, "plugin"); }); AddonManager.getAddonsByTypes([ "userstyle" ], function(addons) { addonListCallback(addons, AMdoc, "userstyle"); }); AddonManager.getAddonsByTypes([ "service" ], function(addons) { addonListCallback(addons, AMdoc, "service"); }); AddonManager.getAddonsByTypes([ "greasemonkey-user-script" ], function(addons) { addonListCallback(addons, AMdoc, "greasemonkey-user-script"); }); } function addStylesheet(sheet) { var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); var uri = ios.newURI(sheet, null, null); if (!sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.loadAndRegisterSheet(uri, sss.USER_SHEET); } } function removeStylesheet(sheet) { var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); var uri = ios.newURI(sheet, null, null); if (sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.unregisterSheet(uri, sss.USER_SHEET); } } function findAddonsMgrs() { // find all open mgrs var mgrs = []; var windows = Services.wm.getEnumerator("navigator:browser"); var window; while (windows.hasMoreElements()) { window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow); window.gBrowser.browsers.forEach(findMgrTab); } function findMgrTab(browser) { if (browser.currentURI.spec == "about:addons") { mgrs.push(browser.contentWindow); } } // Mgr in dialog window (for Add-ons Manager Dialog Returns compatibility) var topWin = Services.wm.getMostRecentWindow(null); if (topWin.document.documentURI == "about:addons") { mgrs.push(topWin); } return mgrs; } function updateListboxContents(addon, action) { if (action != "add" && action != "remove") { return; } var currentArray = null; switch (addon.type) { case "extension": currentArray = extArray; break; case "theme": currentArray = themeArray; break; case "plugin": currentArray = pluginArray; break; case "userstyle": currentArray = userstyleArray; break; case "service": currentArray = serviceArray; case "greasemonkey-user-script": currentArray = userscriptArray; break; default: Services.console.logStringMessage("Addons Manager Hilite encountered an unsupported Add-on type: " + addon.type + " " + addon.name); } var entryFound = false; var element; for (element = 0; element < currentArray.length; element++) { let entry = currentArray[element]; if (entry.indexOf(addon.name) != -1) { // found item entryFound = true; if (showVersionNumber && action == "add") { // version number needs updated var nameVersion = entry.split(spacer, 2); nameVersion[1] = (nameVersion[0].indexOf("<") == 0) ? addon.version + ">" : addon.version; entry = nameVersion.join(spacer); currentArray[element] = entry; } else { if (action == "remove") { currentArray.splice(element, 1); } } // process restoreondemand entry, if any + actual entry if (entry.indexOf("<") != 0) { break; } } // end if found } // end for if (!entryFound && action == "add") { // item not present; needs added var entryToAdd = addon.name; if (showVersionNumber) { entryToAdd = entryToAdd + spacer + addon.version; } currentArray.push(entryToAdd); currentArray.sort(function(addonItem1, addonItem2) { var addon1Name = addonItem1.toLowerCase(); var addon2Name = addonItem2.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); } } function updateAllListboxes() { var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { var AMdoc = mgrs[i].document; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; switch (selCat) { // select the proper menulist for the current category case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; } } } function restoreHilite(AMdoc) { //Services.console.logStringMessage("restoreHilite called"); // purpose: retrieve saved selection and restore it // content.document does not get document we want if AoM was opened in background via session restore var selAddon; var addonList = AMdoc.getElementById('addon-list'); var savedSelections = addonList.getAttribute('aomhilite'); //Services.console.logStringMessage(savedSelections); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; // category-extension, etc. var selectionArray = savedSelections.split(","); var lastSel = selectionArray[supportedCats.indexOf(selCat)]; if (lastSel) { selAddon = addonList.getElementsByAttribute('value', lastSel); } if (!lastSel || !selAddon || !selAddon[0]) { // no lastSel will occur on newly opened AoM if (always) restore pref is false // otherwise typically occurs when selected category has no installed items or has never had a saved selection var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); if (acAddonList) { acAddonList.value = ""; } // onSelect not triggered (see below); need to clear this now return; } addonList.selectItem(selAddon[0]); // will trigger onSelect //addonList.scrollBoxObject.scrollToElement(selAddon[0]); selAddon[0].scrollIntoView(); addonList.focus(); } function saveUpdatedSel(addonList, selCat, newSelId) { var savedSelections = addonList.getAttribute('aomhilite'); var selectionArray = savedSelections.split(","); selectionArray[supportedCats.indexOf(selCat)] = newSelId; var updatedSel = selectionArray.toString(); addonList.setAttribute('aomhilite', updatedSel); } function onSelect() { // called once per add-on upon loading mgr, but (this.currentIndex = = -1) at that point // called when clicking an entry in addonList, selecting from autocomplete list, and from restoreHilite funct; also when changing categories? //Services.console.logStringMessage("onSelect called"); //Services.console.logStringMessage(this.id); // addon-list if (this.currentIndex < 0) { return; } // there is no current selected item in this category if (!this.selectedItem) { return; } // avoid 'this.selectedItem is null' error in console (when opening Add-Ons Mgr) var currentSel = this.selectedItem.mAddon.id; var AMdoc = this.ownerDocument; var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; if (!currentSel || (supportedCats.indexOf(selCat) == -1)) { return; } saveUpdatedSel(this, selCat, currentSel); var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); if (!acAddonList || !acAddonList.value) { return; } if (acAddonList.value.indexOf(this.selectedItem.mAddon.name) < 0) { acAddonList.value = ""; // clear ac list input field, rather than show name of a now unselected item } } function onACaddonListSelection() { // called when selection made from ac dropdown list or pressing ENTER in input field var AMdoc = this.ownerDocument; var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); // setting selectionStart & selectionEnd to same value sets the cursor position to that position // set to beginning so text looks cropped on right instead of on left acAddonList.inputField.selectionStart = 0; acAddonList.inputField.selectionEnd = 0; var sel = AMdoc.getElementById("aomhilite_ac_menu").value; if (UIextra && sel.indexOf("<") == 0 && sel.lastIndexOf(">") == sel.length - 1) { sel = sel.slice(1, sel.length - 1); // remove angle brackets } if (showVersionNumber) { let nameEnd = sel.lastIndexOf(spacer); if (nameEnd > 0) { // remove spacer and version #, if found (should be there, but...) sel = sel.slice(0, nameEnd); } } var addonList = AMdoc.getElementById('addon-list'); var selAddon = addonList.getElementsByAttribute('name', sel); if (selAddon && selAddon[0]) { var newSelId = selAddon[0].mAddon.id; if (!newSelId) { return; } saveUpdatedSel(addonList, selCat, newSelId); var view = AMdoc.getElementById('view-port'); if (view.getAttribute('selectedIndex') == LISTVIEW) { restoreHilite(AMdoc); } else { selAddon[0].showInDetailView(); } } else { /* * Workaround issue that occurs when using nav arrow takes us back into detail view of a non-current category, * resulting in 'addon-list' element that is no longer populated with the list of add-ons, thus there are no * elements with the name we are looking for */ savedAddonName = sel; // repopulates the list, finish workaround in the resulting onViewChange cat.selectedItem.click(); } } function onViewChange() { //Services.console.logStringMessage("onViewChange called"); var AMdoc = this.document; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var view = AMdoc.getElementById('view-port'); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; if (selCat == "category-userstyle") { dontSort = true; } if (view && view.getAttribute('selectedIndex') == LISTVIEW) { if (savedAddonName) { // finish workaround from onACaddonListSelection - display add-on in detail view var addonList = AMdoc.getElementById('addon-list'); // prevents annoying flash of list view before detail view appears addonList.setAttribute('hidden', true); var selAddon = addonList.getElementsByAttribute('name', savedAddonName); if (selAddon && selAddon[0]) { selAddon[0].showInDetailView(); var newSelId = selAddon[0].mAddon.id; saveUpdatedSel(addonList, selCat, newSelId); } addonList.removeAttribute('hidden'); savedAddonName = null; // workaround finished, we're now in detail view, which retriggers viewchange // (if we unexpectedly fail to find add-on for detail view, just continue in list view) if (selAddon && selAddon[0]) { return; } } // need to recheck pref, since we're not using pref observer var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); doAlphaSort = prefs.getBoolPref("alphaSort"); updatedSort = prefs.getBoolPref("updatedSort"); if (doAlphaSort || updatedSort) { resort(AMdoc); } restoreHilite(AMdoc); } else if (view && view.getAttribute('selectedIndex') == DETAILVIEW) { // if we are in this ext's detail view if (AMdoc.getElementById("detail-name").textContent == "Addons Manager Hilite") { // set input field of numeric setting to sensible size & disable if not applicable var setting = AMdoc.getElementById("aomhilite_size"); var inputField = AMdoc.getAnonymousElementByAttribute(setting, "anonid", "input"); inputField.setAttribute("style", "max-width: 3em;"); } } // if our menu has not been created yet or the UI is pref'ed off, nothing else to do if (!acAddonList) { return; } switch (selCat) { // select the proper menulist for the current category case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; default: acAddonList.setAttribute('hidden', 'true'); // hide UI in unsupported cats return; } acAddonList.removeAttribute('hidden'); // show UI } function resort(AMdoc) { //Services.console.logStringMessage("resort called"); // use alphabetical (or optionally updated) sort instead of by-state sort implemented by Bug 624808 if (dontSort) { dontSort = false; return; } var addonList = AMdoc.getElementById("addon-list"); if (!updatedSort) { var sortby = [ "name" ]; AMdoc.defaultView.sortList(addonList, sortby, true); // true = ascending return; } // most recently updated var list = addonList.children; list.sort(function(addonItem1, addonItem2) { var addon1Time = Date.parse(addonItem1.mAddon.updateDate); var addon2Time = Date.parse(addonItem2.mAddon.updateDate); if (addon1Time > addon2Time) { return -1; } if (addon1Time < addon2Time) { return 1; } var addon1Name = addonItem1.mAddon.name.toLowerCase(); var addon2Name = addonItem2.mAddon.name.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); var i; for (i = 0; i < list.length; i++) { addonList.appendChild(list[i]); } } function addonListCallback(addons, AMdoc, addonType) { var addonList = AMdoc.getElementById("addon-list"); var prevHilite = addonList.getAttribute("restoreondemand"); var hiliteArray = prevHilite.split(","); var currentArray = null; var currentCat = null; addons.sort(function(addonItem1, addonItem2) { var addon1Name = addonItem1.name.toLowerCase(); var addon2Name = addonItem2.name.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); switch (addonType) { case "extension": extArray = []; currentArray = extArray; currentCat = "category-extension"; break; case "theme": themeArray = []; currentArray = themeArray; currentCat = "category-theme"; break; case "plugin": pluginArray = []; currentArray = pluginArray; currentCat = "category-plugin"; break; case "userstyle": userstyleArray = []; currentArray = userstyleArray; currentCat = "category-userstyle"; break; case "service": serviceArray = []; currentArray = serviceArray; currentCat = "category-service"; case "greasemonkey-user-script": userscriptArray = []; currentArray = userscriptArray; currentCat = "category-greasemonkey-user-script"; break; } var i; // need to recheck pref, since we're not using pref observer var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); showVersionNumber = prefs.getBoolPref("showVersion"); for (i = 0; i < addons.length; i++) { if (showVersionNumber && addons[i].version) { currentArray.push(addons[i].name + spacer + addons[i].version); } else { currentArray.push(addons[i].name); } // for vers # opt off if (UIextra && hiliteArray[supportedCats.indexOf(currentCat)] == addons[i].id) { // if this is the previously hilited item, add it to the top of list for easy access var entry = "<" + addons[i].name; if (showVersionNumber) { entry = entry + spacer + addons[i].version; } entry = entry + ">"; currentArray.unshift(entry); } } // wait for all 6 requests to arrive if (!extArray || !themeArray || !pluginArray || !userstyleArray || !serviceArray || !userscriptArray) { return; } var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var cat = AMdoc.getElementById("categories"); var selCat = cat.selectedItem.id; if (acAddonList) { switch (selCat) { case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; } } if (acAddonList && supportedCats.indexOf(selCat) != -1) { acAddonList.removeAttribute('hidden'); // hide ac menu in unsupported categories } else if (acAddonList) { acAddonList.setAttribute('hidden', true); } } function AddonsMgrOnUnload() { AddonManager.removeAddonListener(addonListener); this.removeEventListener("unload", AddonsMgrOnUnload, false); this.removeEventListener("ViewChanged", onViewChange, false); var addonList = this.document.getElementById("addon-list"); addonList.removeEventListener("select", onSelect, false); var acAddonList = this.document.getElementById("aomhilite_ac_menu"); if (acAddonList) { acAddonList.removeEventListener("textentered", onACaddonListSelection, false); acAddonList.removeEventListener("change", onACaddonListSelection, false); acAddonList.popup.removeEventListener("click", onACaddonListSelection, false); var arrow = this.document.getAnonymousElementByAttribute(acAddonList, "anonid", "historydropmarker"); if (arrow && displayDropdown) { arrow.removeEventListener("click", displayDropdown, false); displayDropdown = null; } var head = this.document.getElementById("header"); head.removeChild(acAddonList); } if (UIextra && addonList.hasAttribute("restoreondemand")) { // save needed info to aomhite so it will survive fx restart var savedSelections = addonList.getAttribute('aomhilite'); var selectionArray = savedSelections.split(","); var prevHilites = addonList.getAttribute('restoreondemand'); var hiliteArray = prevHilites.split(","); // save previous category selections until new ones have been made var i; for (i = 0; i < hiliteArray.length; i++) { if (hiliteArray[i] && !selectionArray[i]) { selectionArray[i] = hiliteArray[i]; } } var selectionsToSave = selectionArray.toString(); addonList.setAttribute('aomhilite', selectionsToSave); } extArray = null; themeArray = null; pluginArray = null; userstyleArray = null; serviceArray = null; userscriptArray = null; }
変更されたテキスト
ファイルを開く
Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); var doAlphaSort = null; // for pref (alphabetical vs by-state sorting) var updatedSort = false; // for pref (sort by last updated) var dontSort = false; // ignore sort pref in category-userstyles (provides own sorting) var restore = null; // for pref (restore hilite after closing AoM) var showUI = null; // for pref (whether to create/display ac menu) var UIwidth = null; // for pref (ac menu size) var showVersionNumber = null; // for pref (whether to show version number in ac menu) var spacer = " "; var UIextra = null; // for restore-on-demand hidden pref var extraRows = null; var extArray = null; var themeArray = null; var pluginArray = null; var userstyleArray = null; var serviceArray = null; var userscriptArray = null; var scriptishArray = null; var custombuttonsArray = null; var dictionaryArray = null; var localeArray = null; var savedAddonName = null; var displayDropdown = null; // used for Seamonkey & Tbird workaround const LISTVIEW = 2; const DETAILVIEW = 4; var supportedCats = [ "category-extension", "category-theme", "category-plugin", "category-userstyle", "category-service", "category-greasemonkey-user-script", "category-userscript", "category-custombuttons", "category-dictionary", "category-locale" ]; // from http://erikvold.com/blog/index.cfm/2011/6/14/restartless-firefox-addons-part-6-better-includes // Thanks, Erik! (function(global) { global.include = function include(src) { var o = {}; Components.utils.import("resource://gre/modules/Services.jsm", o); var uri = o.Services.io.newURI(src, null, o.Services.io.newURI(__SCRIPT_URI_SPEC__, null, null)); o.Services.scriptloader.loadSubScript(uri.spec, global); }; })(this); include("components/addonList_autocomplete.js"); function startup(data, reason) { Services.obs.addObserver(ChromeDocObserver, "chrome-document-global-created", false); var defPrefs = Services.prefs.getDefaultBranch("extensions.addonsmgrhilte@cfl."); defPrefs.setBoolPref("restore", true); defPrefs.setBoolPref("alphaSort", false); defPrefs.setBoolPref("updatedSort", false); defPrefs.setBoolPref("extraRows", false); defPrefs.setBoolPref("showUI", true); // should we default this to true now?????? defPrefs.setIntPref("listboxSize", 18); defPrefs.setBoolPref("UIextra", false); defPrefs.setBoolPref("showVersion", false); // register our custom autocomplete component Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).registerFactory(CLASS_ID, CLASS_NAME, CONTRACT_ID, NSGetFactory(CLASS_ID)); if (reason == ADDON_ENABLE || reason == ADDON_INSTALL) { var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { mgrs[i].location.reload(); } } } function shutdown(data, reason) { Services.obs.removeObserver(ChromeDocObserver, "chrome-document-global-created"); // call flush due to the bundle service cache (for aomhilite.properties string bundle) Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService) .flushBundles(); // unregister our custom autocomplete component Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).unregisterFactory(CLASS_ID, NSGetFactory(CLASS_ID)); // remove stylesheets removeStylesheet("chrome://aomhilite/content/aomhilite.css"); removeStylesheet("chrome://aomhilite/content/aomhiliteLG.css"); removeStylesheet("chrome://aomhilite/content/aomhiliteOSX.css"); if (reason == ADDON_DISABLE) { // remove any UI from any open Add-ons Manager tabs and revert to default sorting var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { AddonsMgrOnUnload.call(mgrs[i]); // reverts to default sort; // also allows aomhilite.xml to be removed from memory w/o waiting for user to close AoM mgrs[i].location.reload(); } } } function install(data, reason) { } function uninstall(data, reason) { // don't remove user's selection when updating ext (as opposed to actual uninstall) if (reason != "ADDON_UNINSTALL") { return; } var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); var localstore = RDF.GetDataSource('rdf:local-store'); var subj = RDF.GetResource('about:addons#addon-list'); var pred = RDF.GetResource('aomhilite'); var target = localstore.GetTarget(subj, pred, true); if (target == null) { return; } // if it's an empty string we want to remove it's entry target = target.QueryInterface(Components.interfaces.nsIRDFLiteral); var obj = RDF.GetLiteral(target.Value); localstore.Unassert(subj, pred, obj, true); } function ChromeDocObserver(aSubject, aTopic, aData) { try { if (aTopic != "chrome-document-global-created") { return; } var win = aSubject; var uri = win.document.documentURI; // if Add-ons Manager Dialog Returns add-on is installed, uri will be about:blank until loaded if (uri == "about:addons" || uri == "about:blank") { win.addEventListener("load", AddonsMgrOnload, false); } } catch (e) { Services.console.logStringMessage("Exception in ChromeDocObserver"); } } function AddonsMgrOnload() { // removing this load listener is req'd to prevent mem leak // if we're at about:blank we need to do that *now* // might as well do them all here // listener no longer needed since if the mgr is reloaded via F5, // unload is called, then ChromeDocObserver re-adds the listener this.removeEventListener("load", AddonsMgrOnload, false); if (this.document.documentURI != "about:addons") { return; } this.addEventListener("unload", AddonsMgrOnUnload, false); var AMdoc = this.document; // document obj of Addons Mgr window var addonList = AMdoc.getElementById("addon-list"); var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); doAlphaSort = prefs.getBoolPref("alphaSort"); updatedSort = prefs.getBoolPref("updatedSort"); restore = prefs.getBoolPref("restore"); UIextra = prefs.getBoolPref("UIextra"); showUI = prefs.getBoolPref("showUI"); extraRows = prefs.getBoolPref("extraRows"); // restore-on-demand useless if already auto-restored, or the UI not even visible if (restore || !showUI) { UIextra = false; } UIwidth = prefs.getIntPref("listboxSize"); UIwidth = (UIwidth > 50) ? 50 : UIwidth; UIwidth = (UIwidth < 10) ? 10 : UIwidth; if (!restore) { addonList.setAttribute('aomhilite', ""); } this.addEventListener("ViewChanged", onViewChange, false); var cat = AMdoc.getElementById("categories"); if (!cat || !addonList) { return; } var attr = addonList.getAttribute("persist"); // 'persist' enables this info to survive a restart of fx if (!attr) { addonList.setAttribute("persist", "aomhilite"); } else if (attr.indexOf("aomhilite") < 0) { addonList.setAttribute("persist", attr + " aomhilite"); } addonList.addEventListener("select", onSelect, false); // let AoM finish loading list, before attempting potential resort this.setTimeout(function() {initAddonList(AMdoc);}, 0); if (showUI) { this.setTimeout(function() {initUI(AMdoc);}, 100); } } function initAddonList (AMdoc) { //Services.console.logStringMessage("initAddonList called"); // check if we're in list view of a supported category; sort and hilite var cat = AMdoc.getElementById("categories"); var selCat = cat.selectedItem.id; var view = AMdoc.getElementById('view-port'); if ((supportedCats.indexOf(selCat) != -1) && view.getAttribute('selectedIndex') == LISTVIEW) { if (selCat == "category-userstyle" || selCat == "category-greasemonkey-user-script") { dontSort = true; } if (doAlphaSort || updatedSort) { resort(AMdoc); } restoreHilite(AMdoc); } } var addonListener = { onInstalled : function(addon) { updateListboxContents(addon, "add"); updateAllListboxes(); }, /* * due to the 'undo' option remaining available until aom closed/reopened, this won't get called until current * instance (tab) is closed, because that's when the actual uninstall occurs (and when we should remove item from * dropdown list) */ onUninstalled : function(addon) { updateListboxContents(addon, "remove"); updateAllListboxes(); } }; function initUI(AMdoc) { var acListboxStyle = "margin-left: 1em; margin-right: 1em; width: " + UIwidth + "em;"; var acAddonList = AMdoc.createElement("textbox"); acAddonList.setAttribute("id", "aomhilite_ac_menu"); acAddonList.setAttribute("style", acListboxStyle); acAddonList.setAttribute("type", "autocomplete"); // acAddonList.setAttribute("size", 24); // seems to have no effect; set via css width instead acAddonList.setAttribute("autocompletesearch", "addonList_autocomplete"); acAddonList.setAttribute("enablehistory", true); // acAddonList.setAttribute("completedefaultindex", true); acAddonList.setAttribute("forcecomplete", true); // ensures selection is valid // only applies to typing in box; see aomhilite.xml acAddonList.setAttribute("maxrows", 10); // default is about 6 var notifyListbox = "var evt = document.createEvent('Events'); " + "evt.initEvent('textentered', true, true); " + "this.dispatchEvent(evt);"; acAddonList.setAttribute("ontextentered", notifyListbox); var strbundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService( Components.interfaces.nsIStringBundleService).createBundle("chrome://aomhilite/locale/aomhilite.properties"); var selectaddon = strbundle.GetStringFromName("placeholderString"); acAddonList.setAttribute("placeholder", selectaddon); /* set up stylesheets */ var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS; addStylesheet("chrome://aomhilite/content/aomhilite.css"); if (osString == "Darwin") { addStylesheet("chrome://aomhilite/content/aomhiliteOSX.css"); } var updateBtn = AMdoc.getElementById("header-utils-btn"); var head = AMdoc.getElementById("header"); head.insertBefore(acAddonList, updateBtn); // prevents "Extension cannot be installed because Nightly cannot modify the needed file" // error when updating this ext (bug 719180) // although 71980 is fixed in fx 19+, using (tested on fx 21.0a1): // acAddonList.style.MozBinding = "url(chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite)"; // leaves the aomhilite.xml file in memory even when AoM is closed and aomhilite is disabled! var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"] .getService(Components.interfaces.nsIChromeRegistry); var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); var bindingUri; if (extraRows) { bindingUri = ioService.newURI("chrome://aomhilite/content/aomhiliteLG.xml#ac_menu_aomhilite", null, null); } else { bindingUri = ioService.newURI("chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite", null, null); } var convertedBindingUri = chromeReg.convertChromeURL(bindingUri); acAddonList.style.MozBinding = 'url("' + convertedBindingUri.spec + '")'; const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo); if (appInfo.ID != FIREFOX_ID) { // workaround - Seamonkey/Tbird (bug 708520) aren't opening popup by default displayDropdown = function(e) { var id = e.originalTarget.getAttribute("anonid"); if (id != "historydropmarker") { return; } //Services.console.logStringMessage("historydropmarker click"); var acAddonList = e.target.ownerDocument.getElementById("aomhilite_ac_menu") acAddonList.showHistoryPopup(); }; acAddonList.addEventListener("click", displayDropdown, false); } acAddonList.addEventListener("textentered", onACaddonListSelection, false); AddonManager.addAddonListener(addonListener); if (UIextra) { var addonList = AMdoc.getElementById("addon-list"); addonList.setAttribute('restoreondemand', addonList.getAttribute('aomhilite')); } // (do here since addonListCallback will require data initialized above) AddonManager.getAddonsByTypes([ "extension" ], function(addons) { addonListCallback(addons, AMdoc, "extension"); }); AddonManager.getAddonsByTypes([ "theme" ], function(addons) { addonListCallback(addons, AMdoc, "theme"); }); AddonManager.getAddonsByTypes([ "plugin" ], function(addons) { addonListCallback(addons, AMdoc, "plugin"); }); AddonManager.getAddonsByTypes([ "userstyle" ], function(addons) { addonListCallback(addons, AMdoc, "userstyle"); }); AddonManager.getAddonsByTypes([ "service" ], function(addons) { addonListCallback(addons, AMdoc, "service"); }); AddonManager.getAddonsByTypes([ "greasemonkey-user-script" ], function(addons) { addonListCallback(addons, AMdoc, "greasemonkey-user-script"); }); // Scriptish AddonManager.getAddonsByTypes([ "userscript" ], function(addons) { addonListCallback(addons, AMdoc, "userscript"); }); // Custom Buttons AddonManager.getAddonsByTypes([ "custombuttons" ], function(addons) { addonListCallback(addons, AMdoc, "custombuttons"); }); AddonManager.getAddonsByTypes([ "dictionary" ], function(addons) { addonListCallback(addons, AMdoc, "dictionary"); }); AddonManager.getAddonsByTypes([ "locale" ], function(addons) { addonListCallback(addons, AMdoc, "locale"); }); } function addStylesheet(sheet) { var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); var uri = ios.newURI(sheet, null, null); if (!sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.loadAndRegisterSheet(uri, sss.USER_SHEET); } } function removeStylesheet(sheet) { var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); var uri = ios.newURI(sheet, null, null); if (sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.unregisterSheet(uri, sss.USER_SHEET); } } function findAddonsMgrs() { // find all open mgrs var mgrs = []; var windows = Services.wm.getEnumerator("navigator:browser"); var window; while (windows.hasMoreElements()) { window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow); window.gBrowser.browsers.forEach(findMgrTab); } function findMgrTab(browser) { if (browser.currentURI.spec == "about:addons") { mgrs.push(browser.contentWindow); } } // Mgr in dialog window (for Add-ons Manager Dialog Returns compatibility) var topWin = Services.wm.getMostRecentWindow(null); if (topWin.document.documentURI == "about:addons") { mgrs.push(topWin); } return mgrs; } function updateListboxContents(addon, action) { if (action != "add" && action != "remove") { return; } var currentArray = null; switch (addon.type) { case "extension": currentArray = extArray; break; case "theme": currentArray = themeArray; break; case "plugin": currentArray = pluginArray; break; case "userstyle": currentArray = userstyleArray; break; case "service": currentArray = serviceArray; break; case "greasemonkey-user-script": currentArray = userscriptArray; break; case "userscript": currentArray = scriptishArray; break; case "custombuttons": currentArray = custombuttonsArray; break; case "dictionary": currentArray = dictionaryArray; break; case "locale": currentArray = localeArray; break; default: Services.console.logStringMessage("Addons Manager Hilite encountered an unsupported Add-on type: " + addon.type + " " + addon.name); } var entryFound = false; var element; for (element = 0; element < currentArray.length; element++) { let entry = currentArray[element]; if (entry.indexOf(addon.name) != -1) { // found item entryFound = true; if (showVersionNumber && action == "add") { // version number needs updated var nameVersion = entry.split(spacer, 2); nameVersion[1] = (nameVersion[0].indexOf("<") == 0) ? addon.version + ">" : addon.version; entry = nameVersion.join(spacer); currentArray[element] = entry; } else { if (action == "remove") { currentArray.splice(element, 1); } } // process restoreondemand entry, if any + actual entry if (entry.indexOf("<") != 0) { break; } } // end if found } // end for if (!entryFound && action == "add") { // item not present; needs added var entryToAdd = addon.name; if (showVersionNumber) { entryToAdd = entryToAdd + spacer + addon.version; } currentArray.push(entryToAdd); currentArray.sort(function(addonItem1, addonItem2) { var addon1Name = addonItem1.toLowerCase(); var addon2Name = addonItem2.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); } } function updateAllListboxes() { var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { var AMdoc = mgrs[i].document; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; switch (selCat) { // select the proper menulist for the current category case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); break; case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; case "category-userscript": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(scriptishArray)); break; case "category-custombuttons": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(custombuttonsArray)); break; case "category-dictionary": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(dictionaryArray)); break; case "category-locale": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(localeArray)); break; } } } function restoreHilite(AMdoc) { //Services.console.logStringMessage("restoreHilite called"); // purpose: retrieve saved selection and restore it // content.document does not get document we want if AoM was opened in background via session restore var selAddon; var addonList = AMdoc.getElementById('addon-list'); var savedSelections = addonList.getAttribute('aomhilite'); //Services.console.logStringMessage(savedSelections); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; // category-extension, etc. var selectionArray = savedSelections.split(","); var lastSel = selectionArray[supportedCats.indexOf(selCat)]; if (lastSel) { selAddon = addonList.getElementsByAttribute('value', lastSel); } if (!lastSel || !selAddon || !selAddon[0]) { // no lastSel will occur on newly opened AoM if (always) restore pref is false // otherwise typically occurs when selected category has no installed items or has never had a saved selection var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); if (acAddonList) { acAddonList.value = ""; } // onSelect not triggered (see below); need to clear this now return; } addonList.selectItem(selAddon[0]); // will trigger onSelect //addonList.scrollBoxObject.scrollToElement(selAddon[0]); selAddon[0].scrollIntoView(); addonList.focus(); } function saveUpdatedSel(addonList, selCat, newSelId) { var savedSelections = addonList.getAttribute('aomhilite'); var selectionArray = savedSelections.split(","); selectionArray[supportedCats.indexOf(selCat)] = newSelId; var updatedSel = selectionArray.toString(); addonList.setAttribute('aomhilite', updatedSel); } function onSelect() { // called once per add-on upon loading mgr, but (this.currentIndex = = -1) at that point // called when clicking an entry in addonList, selecting from autocomplete list, and from restoreHilite funct; also when changing categories? //Services.console.logStringMessage("onSelect called"); //Services.console.logStringMessage(this.id); // addon-list if (this.currentIndex < 0) { return; } // there is no current selected item in this category if (!this.selectedItem) { return; } // avoid 'this.selectedItem is null' error in console (when opening Add-Ons Mgr) var currentSel = this.selectedItem.mAddon.id; var AMdoc = this.ownerDocument; var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; if (!currentSel || (supportedCats.indexOf(selCat) == -1)) { return; } saveUpdatedSel(this, selCat, currentSel); var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); if (!acAddonList || !acAddonList.value) { return; } if (acAddonList.value.indexOf(this.selectedItem.mAddon.name) < 0) { acAddonList.value = ""; // clear ac list input field, rather than show name of a now unselected item } } function onACaddonListSelection() { // called when selection made from ac dropdown list or pressing ENTER in input field var AMdoc = this.ownerDocument; var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); // setting selectionStart & selectionEnd to same value sets the cursor position to that position // set to beginning so text looks cropped on right instead of on left acAddonList.inputField.selectionStart = 0; acAddonList.inputField.selectionEnd = 0; var sel = AMdoc.getElementById("aomhilite_ac_menu").value; if (UIextra && sel.indexOf("<") == 0 && sel.lastIndexOf(">") == sel.length - 1) { sel = sel.slice(1, sel.length - 1); // remove angle brackets } if (showVersionNumber) { let nameEnd = sel.lastIndexOf(spacer); if (nameEnd > 0) { // remove spacer and version #, if found (should be there, but...) sel = sel.slice(0, nameEnd); } } var addonList = AMdoc.getElementById('addon-list'); var selAddon = addonList.getElementsByAttribute('name', sel); if (selAddon && selAddon[0]) { var newSelId = selAddon[0].mAddon.id; if (!newSelId) { return; } saveUpdatedSel(addonList, selCat, newSelId); var view = AMdoc.getElementById('view-port'); if (view.getAttribute('selectedIndex') == LISTVIEW) { restoreHilite(AMdoc); } else { selAddon[0].showInDetailView(); } } else { /* * Workaround issue that occurs when using nav arrow takes us back into detail view of a non-current category, * resulting in 'addon-list' element that is no longer populated with the list of add-ons, thus there are no * elements with the name we are looking for */ savedAddonName = sel; // repopulates the list, finish workaround in the resulting onViewChange cat.selectedItem.click(); } } function onViewChange() { //Services.console.logStringMessage("onViewChange called"); var AMdoc = this.document; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var view = AMdoc.getElementById('view-port'); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; if (selCat == "category-userstyle") { dontSort = true; } if (view && view.getAttribute('selectedIndex') == LISTVIEW) { if (savedAddonName) { // finish workaround from onACaddonListSelection - display add-on in detail view var addonList = AMdoc.getElementById('addon-list'); // prevents annoying flash of list view before detail view appears addonList.setAttribute('hidden', true); var selAddon = addonList.getElementsByAttribute('name', savedAddonName); if (selAddon && selAddon[0]) { selAddon[0].showInDetailView(); var newSelId = selAddon[0].mAddon.id; saveUpdatedSel(addonList, selCat, newSelId); } addonList.removeAttribute('hidden'); savedAddonName = null; // workaround finished, we're now in detail view, which retriggers viewchange // (if we unexpectedly fail to find add-on for detail view, just continue in list view) if (selAddon && selAddon[0]) { return; } } // need to recheck pref, since we're not using pref observer var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); doAlphaSort = prefs.getBoolPref("alphaSort"); updatedSort = prefs.getBoolPref("updatedSort"); if (doAlphaSort || updatedSort) { resort(AMdoc); } restoreHilite(AMdoc); } else if (view && view.getAttribute('selectedIndex') == DETAILVIEW) { // if we are in this ext's detail view if (AMdoc.getElementById("detail-name").textContent == "Addons Manager Hilite") { // set input field of numeric setting to sensible size & disable if not applicable var setting = AMdoc.getElementById("aomhilite_size"); var inputField = AMdoc.getAnonymousElementByAttribute(setting, "anonid", "input"); inputField.setAttribute("style", "max-width: 3em;"); } } // if our menu has not been created yet or the UI is pref'ed off, nothing else to do if (!acAddonList) { return; } switch (selCat) { // select the proper menulist for the current category case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); break; case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; case "category-userscript": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(scriptishArray)); break; case "category-custombuttons": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(custombuttonsArray)); break; case "category-dictionary": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(dictionaryArray)); break; case "category-locale": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(localeArray)); break; default: acAddonList.setAttribute('hidden', 'true'); // hide UI in unsupported cats return; } acAddonList.removeAttribute('hidden'); // show UI } function resort(AMdoc) { //Services.console.logStringMessage("resort called"); // use alphabetical (or optionally updated) sort instead of by-state sort implemented by Bug 624808 if (dontSort) { dontSort = false; return; } var addonList = AMdoc.getElementById("addon-list"); if (!updatedSort) { var sortby = [ "name" ]; AMdoc.defaultView.sortList(addonList, sortby, true); // true = ascending return; } // most recently updated var list = addonList.children; list.sort(function(addonItem1, addonItem2) { var addon1Time = Date.parse(addonItem1.mAddon.updateDate); var addon2Time = Date.parse(addonItem2.mAddon.updateDate); if (addon1Time > addon2Time) { return -1; } if (addon1Time < addon2Time) { return 1; } var addon1Name = addonItem1.mAddon.name.toLowerCase(); var addon2Name = addonItem2.mAddon.name.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); var i; for (i = 0; i < list.length; i++) { addonList.appendChild(list[i]); } } function addonListCallback(addons, AMdoc, addonType) { var addonList = AMdoc.getElementById("addon-list"); var prevHilite = addonList.getAttribute("restoreondemand"); var hiliteArray = prevHilite.split(","); var currentArray = null; var currentCat = null; addons.sort(function(addonItem1, addonItem2) { var addon1Name = addonItem1.name.toLowerCase(); var addon2Name = addonItem2.name.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); switch (addonType) { case "extension": extArray = []; currentArray = extArray; currentCat = "category-extension"; break; case "theme": themeArray = []; currentArray = themeArray; currentCat = "category-theme"; break; case "plugin": pluginArray = []; currentArray = pluginArray; currentCat = "category-plugin"; break; case "userstyle": userstyleArray = []; currentArray = userstyleArray; currentCat = "category-userstyle"; break; case "service": serviceArray = []; currentArray = serviceArray; currentCat = "category-service"; break; case "greasemonkey-user-script": userscriptArray = []; currentArray = userscriptArray; currentCat = "category-greasemonkey-user-script"; break; case "userscript": scriptishArray = []; currentArray = scriptishArray; currentCat = "category-userscript"; break; case "custombuttons": custombuttonsArray = []; currentArray = custombuttonsArray; currentCat = "category-custombuttons"; break; case "dictionary": dictionaryArray = []; currentArray = dictionaryArray; currentCat = "category-dictionary"; break; case "locale": localeArray = []; currentArray = localeArray; currentCat = "category-locale"; break; } var i; // need to recheck pref, since we're not using pref observer var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); showVersionNumber = prefs.getBoolPref("showVersion"); for (i = 0; i < addons.length; i++) { if (showVersionNumber && addons[i].version) { currentArray.push(addons[i].name + spacer + addons[i].version); } else { currentArray.push(addons[i].name); } // for vers # opt off if (UIextra && hiliteArray[supportedCats.indexOf(currentCat)] == addons[i].id) { // if this is the previously hilited item, add it to the top of list for easy access var entry = "<" + addons[i].name; if (showVersionNumber) { entry = entry + spacer + addons[i].version; } entry = entry + ">"; currentArray.unshift(entry); } } // wait for all 6 requests to arrive if (!(extArray || themeArray || pluginArray || userstyleArray || serviceArray || userscriptArray || scriptishArray || custombuttonsArray || dictionaryArray || localeArray)) { return; } var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var cat = AMdoc.getElementById("categories"); var selCat = cat.selectedItem.id; if (acAddonList) { switch (selCat) { case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); break; case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; case "category-userscript": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(scriptishArray)); break; case "category-custombuttons": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(custombuttonsArray)); break; case "category-dictionary": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(dictionaryArray)); break; case "category-locale": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(localeArray)); break; } } if (acAddonList && supportedCats.indexOf(selCat) != -1) { acAddonList.removeAttribute('hidden'); // hide ac menu in unsupported categories } else if (acAddonList) { acAddonList.setAttribute('hidden', true); } } function AddonsMgrOnUnload() { AddonManager.removeAddonListener(addonListener); this.removeEventListener("unload", AddonsMgrOnUnload, false); this.removeEventListener("ViewChanged", onViewChange, false); var addonList = this.document.getElementById("addon-list"); addonList.removeEventListener("select", onSelect, false); var acAddonList = this.document.getElementById("aomhilite_ac_menu"); if (acAddonList) { acAddonList.removeEventListener("textentered", onACaddonListSelection, false); acAddonList.removeEventListener("change", onACaddonListSelection, false); acAddonList.popup.removeEventListener("click", onACaddonListSelection, false); var arrow = this.document.getAnonymousElementByAttribute(acAddonList, "anonid", "historydropmarker"); if (arrow && displayDropdown) { arrow.removeEventListener("click", displayDropdown, false); displayDropdown = null; } var head = this.document.getElementById("header"); head.removeChild(acAddonList); } if (UIextra && addonList.hasAttribute("restoreondemand")) { // save needed info to aomhite so it will survive fx restart var savedSelections = addonList.getAttribute('aomhilite'); var selectionArray = savedSelections.split(","); var prevHilites = addonList.getAttribute('restoreondemand'); var hiliteArray = prevHilites.split(","); // save previous category selections until new ones have been made var i; for (i = 0; i < hiliteArray.length; i++) { if (hiliteArray[i] && !selectionArray[i]) { selectionArray[i] = hiliteArray[i]; } } var selectionsToSave = selectionArray.toString(); addonList.setAttribute('aomhilite', selectionsToSave); } extArray = null; themeArray = null; pluginArray = null; userstyleArray = null; serviceArray = null; userscriptArray = null; scriptishArray = null; custombuttonsArray = null; dictionaryArray = null; localeArray = null; }
違いを見つける