想要在Firefox上下文菜单中提供多个搜索引擎。不断切换SE以在上下文菜单中设置活动SE是令人厌烦的
如何在Firefox上下文菜单中提供多个搜索引擎。在Firefox 33.0.2中,当您右键单击一个突出的术语时,只有一个搜索引擎处于活动状态,即搜索框中的活动搜索引擎。我经常在我的三大搜索引擎——维基百科、dictionary.com和Urban dictionary之间切换,这取决于我想查找的内容。这很烦人。我想能够选择我所选择的搜索引擎的一个子集作为上下文菜单中的活动。也许不是所有的。我使用一些比其他的多 好,这是复制粘贴代码(来自)想要在Firefox上下文菜单中提供多个搜索引擎。不断切换SE以在上下文菜单中设置活动SE是令人厌烦的,firefox,firefox-addon,contextmenu,search-engine,Firefox,Firefox Addon,Contextmenu,Search Engine,如何在Firefox上下文菜单中提供多个搜索引擎。在Firefox 33.0.2中,当您右键单击一个突出的术语时,只有一个搜索引擎处于活动状态,即搜索框中的活动搜索引擎。我经常在我的三大搜索引擎——维基百科、dictionary.com和Urban dictionary之间切换,这取决于我想查找的内容。这很烦人。我想能够选择我所选择的搜索引擎的一个子集作为上下文菜单中的活动。也许不是所有的。我使用一些比其他的多 好,这是复制粘贴代码(来自) 您需要为scratchpad启用环境选项。点击Ctrl
doUnregister()
。当你把它变成一个引导插件时,这将非常有用
function _loadSearch(searchText, useNewTab, purpose) {
useNewTab = true;
purpose = 'contextmenu';
searchText = this.parentNode.querySelector('#context-searchselect').searchTerms;
let engine;
// If the search bar is visible, use the current engine, otherwise, fall
// back to the default engine.
/*
if (isElementVisible(this.searchBar))
engine = Services.search.currentEngine;
else
engine = Services.search.defaultEngine;
*/
engine = Services.search.getEngineByName(this.getAttribute('engine_name'));
let submission = engine.getSubmission(searchText, null, purpose); // HTML response
// getSubmission can return null if the engine doesn't have a URL
// with a text/html response type. This is unlikely (since
// SearchService._addEngineToStore() should fail for such an engine),
// but let's be on the safe side.
if (!submission) {
return null;
}
let inBackground = Services.prefs.getBoolPref("browser.search.context.loadInBackground");
Services.wm.getMostRecentWindow('navigator:browser').openLinkIn(submission.uri.spec,
useNewTab ? "tab" : "current",
{ postData: submission.postData,
inBackground: inBackground,
relatedToCurrent: true });
return engine;
}
function showMyContexts(e) {
console.log('pop showing, e:', e)
var parentContext = e.target;
//var win = e.view;
var searchContext = parentContext.querySelector('#context-searchselect');
if (!searchContext.hasAttribute('hidden')) {
//var searchTermsQuoted = searchContext.searchTerms;
//var searchTermsQuoted = searchContext.getAttribute('label').match(/".*"/);
//show them
var currentlyVisAccessKeys = parentContext.parentNode.querySelectorAll('#' + parentContext.id + ' > menuitem[accesskey]:not([hidden]):not(.myContextWeev)');
console.log('currentlyVisAccessKeys:', currentlyVisAccessKeys)
var usedKeys = [];
for (var i=0; i<currentlyVisAccessKeys.length; i++) {
usedKeys.push(currentlyVisAccessKeys[i].getAttribute('accesskey').toUpperCase());
}
console.log('usedKeys:', usedKeys);
var myContexts = parentContext.querySelectorAll('.myContextWeev');
for (var i=0; i<myContexts.length; i++) {
myContexts[i].removeAttribute('hidden');
var engine_name = myContexts[i].getAttribute('engine_name');
var newLbl = searchContext.getAttribute('label').replace(Services.search.currentEngine.name, engine_name); //win.gNavigatorBundle.getFormattedString("contextMenuSearch", [Services.search.currentEngine.name, 'rawrr']); //myContexts[i].getAttribute('label').replace(/".*"/, searchTermsQuoted);
for (var j=0; j<engine_name.length; j++) {
var tryKey = engine_name[j].toUpperCase();
if (usedKeys.indexOf(tryKey) == -1) {
myContexts[i].setAttribute('accesskey', tryKey);
break;
}
}
myContexts[i].setAttribute('label', newLbl);
console.log('removing hiddnes')
}
}
}
function hideMyContexts(e) {
console.log('pop hiding')
var parentContext = e.target;
//hide them
var myContexts = parentContext.querySelectorAll('.myContextWeev');
for (var i=0; i<myContexts.length; i++) {
myContexts[i].setAttribute('hidden', 'true');
console.log('hid it')
}
}
/*start - windowlistener*/
var windowListener = {
//DO NOT EDIT HERE
onOpenWindow: function (aXULWindow) {
// Wait for the window to finish loading
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
aDOMWindow.addEventListener("load", function () {
aDOMWindow.removeEventListener("load", arguments.callee, false);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}, false);
},
onCloseWindow: function (aXULWindow) {},
onWindowTitleChange: function (aXULWindow, aNewTitle) {},
register: function () {
// Load into any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}
// Listen to new windows
Services.wm.addListener(windowListener);
},
unregister: function () {
// Unload from any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
}
//Stop listening so future added windows dont get this attached
Services.wm.removeListener(windowListener);
},
//END - DO NOT EDIT HERE
loadIntoWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
var contextSearchselect = aDOMWindow.document.getElementById('context-searchselect');
if (contextSearchselect) {
var insertBeforeEl = contextSearchselect.nextSibling;
var parentContext = contextSearchselect.parentNode; //should be id `contentAreaContextMenu`
parentContext.addEventListener('popupshowing', showMyContexts, false);
parentContext.addEventListener('popuphiding', hideMyContexts, false);
for (var i=0; i<addTheseEngineNamesToContext.length; i++) {
var myContext = aDOMWindow.document.createElement('menuitem'); //contextSearchselect.cloneNode(true);
myContext.setAttribute('class', 'myContextWeev');
myContext.setAttribute('hidden', 'true');
myContext.setAttribute('engine_name', addTheseEngineNamesToContext[i]);
myContext.addEventListener('command', _loadSearch, false);
parentContext.insertBefore(myContext, insertBeforeEl);
}
}
},
unloadFromWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
var contextSearchselect = aDOMWindow.document.getElementById('context-searchselect');
if (contextSearchselect) {
var parentContext = contextSearchselect.parentNode; //should be id `contentAreaContextMenu`
parentContext.removeEventListener('popupshowing', showMyContexts, false);
parentContext.removeEventListener('popuphiding', hideMyContexts, false);
var myContexts = parentContext.querySelectorAll('.myContextWeev');
for (var i=0; i<myContexts.length; i++) {
parentContext.removeChild(myContexts[i]);
}
}
}
};
/*end - windowlistener*/
var addTheseEngineNamesToContext = [];
function doRegister() {
var engines = Services.search.getVisibleEngines();
var engineNames = [];
engines.forEach(function(engine) {
engineNames.push(engine.name);
});
var check = {value: false};
var input = {value: "1"};
var result = Services.prompt.prompt(null, "Engine Count", "How many search engines to add to the conext menu? (Max: " + engines.length + ")", input, null, check);
if (result) {
if (isNaN(input.value) || input.value == '') {
Services.prompt.alert(null, "Error", "Must enter a number");
} else {
if (input.value > 0 && input.value <= engines.length) {
for (var i=0; i<input.value; i++) {
var selected = {};
var result = Services.prompt.select(null, "Select Engine " + (i + 1), "Select the engine to add to menu in position " + (i + 1), engineNames.length, engineNames, selected);
if (result) {
console.log(selected);
addTheseEngineNamesToContext.push(engineNames[selected.value]);
if (i == input.value-1) {
Services.prompt.alert(null, "ok windowListener.register", addTheseEngineNamesToContext);
windowListener.register();
}
} else {
Services.prompt.alert(null, "Cancelled", "Cancelled");
}
}
} else {
Services.prompt.alert(null, "Error", "You only have " + engines.length + " search engines, must enter a number between 1 and " + engines.length);
}
}
}
}
function doUnregister() {
windowListener.unregister();
}
doRegister();
//doUnregister();
函数\u加载搜索(搜索文本、使用新选项卡、目的){
useNewTab=true;
目的='上下文菜单';
searchText=this.parentNode.querySelector(“#context searchselect”).searchTerms;
让发动机;
//如果搜索栏可见,请使用当前引擎,否则,请使用fall
//返回默认引擎。
/*
if(isElementVisible(this.searchBar))
引擎=Services.search.currentEngine;
其他的
引擎=Services.search.defaultEngine;
*/
engine=Services.search.getEngineByName(this.getAttribute('engine_name'));
let submission=engine.getSubmission(searchText,null,purpose);//HTML响应
//如果引擎没有URL,getSubmission可以返回null
//使用文本/html响应类型。这不太可能(因为
//SearchService._addEngineToStore()对于这样的引擎应该失败),
//但让我们安全一点。
如果(!提交){
返回null;
}
让inBackground=Services.prefs.getBoolPref(“browser.search.context.loadInBackground”);
Services.wm.getMostRecentWindow('navigator:browser').openLinkIn(submission.uri.spec,
使用新选项卡?“选项卡”:“当前”,
{postData:submission.postData,
背景内:背景内,
relatedToCurrent:true});
返回引擎;
}
函数showMyContexts(e){
log('弹出显示,e:',e)
var parentContext=e.target;
//var-win=e.view;
var searchContext=parentContext.querySelector(“#context searchselect”);
如果(!searchContext.hasAttribute('hidden')){
//var searchTermsQuoted=searchContext.searchTerms;
//var searchTermsQuoted=searchContext.getAttribute('label').match(/“*”/);
//给他们看
var currentlyVisAccessKeys=parentContext.parentNode.querySelectorAll(“#”+parentContext.id+”>menuitem[accesskey]:非([hidden]):非(.myContextWeev));
log('currentlyVisAccessKeys:',currentlyVisAccessKeys)
var usedKeys=[];
对于(var i=0;我将发布一个可以转换为插件的代码段。是的,它在这里。经过一段时间后,仍然未批准。下一个版本我将用面板替换提示并保存设置,这样在重新启动时就不必重新输入选项,并且可以在重新启动之间修改行为。我已经看到了一个插件将所有搜索引擎作为图标放在上下文菜单(水平行)中的。我不记得名字了。一个很好的方法是,在弹出窗口显示时,你浏览菜单中的可见元素,获取它们的accesskey
s,然后为上下文菜单项分配一个当前可见菜单项尚未使用的accesskey。如果你需要如何操作的帮助,请告诉我,这是真的我最多工作10分钟。谢谢,Noitdart。对我来说很有效。唯一的一个小问题是第一个搜索引擎出现两次,然后是其他的。我的第一个测试是选择三个搜索引擎-我得到了#1 2x、#2 1x和#3 1x。否则,效果很好。我一弄明白,就会把它打包成一个附加组件。干杯/谢谢。Noitdart!如果我在评论5分钟后意识到我拼错了你的名字,则无法编辑我的答案。叹气…没问题,谢谢你的名字:)第一个出现两次的原因是因为通常的“当前选定”搜索引擎在那里。因此,如果搜索框中当前选定的内容将显示在那里,请测试:)按照此处的指南/模板将粘贴复制到您自己的加载项中,如果需要帮助,请告诉我:)是的,我能够制作加载项。它位于此处: