Skip to content

Instantly share code, notes, and snippets.

@2k1dmg
Last active August 11, 2016 04:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 2k1dmg/295e4443f31517b96f58 to your computer and use it in GitHub Desktop.
Save 2k1dmg/295e4443f31517b96f58 to your computer and use it in GitHub Desktop.
(function() {
// Context Search Compact 2016-08-11
'use strict';
let prefs = Cu.import('resource://gre/modules/Preferences.jsm', {}).Preferences;
let gSessionStore = (Cc['@mozilla.org/browser/sessionstore;1'] ||
Cc['@mozilla.org/suite/sessionstore;1']).getService(Ci.nsISessionStore);
let defaultImage = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDI0IDI0Ij4NCjxnIGZpbGw9IiNmYmZiZmIiIHN0cm9rZT0icmdiYSgwLDAsMCwwLjUpIiBzdHJva2Utd2lkdGg9Ii44Ij4NCiAgPGcgaWQ9InNlYXJjaCI+DQogICAgPHBhdGggZD0iTTIsMTAuMDE4YzAsNC40MywzLjU4NSw4LjAxOSw4LjAwOSw4LjAxOSBjMS42MDMsMCwzLjA5NS0wLjQ3Myw0LjM0OC0xLjI4NWw0LjgwNiw0LjgxYzAuNTgsMC41ODMsMS41MjMsMC41ODMsMi4xMDUsMGwwLjI5Ni0wLjI5N2MwLjU4Mi0wLjU4MywwLjU4Mi0xLjUyNywwLTIuMTEgbC00LjgwOC00LjgxNGMwLjgtMS4yNDcsMS4yNjUtMi43MywxLjI2NS00LjMyM2MwLTQuNDMtMy41ODctOC4wMTgtOC4wMTItOC4wMThDNS41ODUsMiwyLDUuNTg5LDIsMTAuMDE4eiBNNS4xMDQsMTAuMDIxIGMwLTIuNzE2LDIuMTk2LTQuOTE1LDQuOTA2LTQuOTE1YzIuNzEsMCw0LjkwOCwyLjE5OSw0LjkwOCw0LjkxNWMwLDIuNzEyLTIuMTk4LDQuOTExLTQuOTA4LDQuOTExIEM3LjMsMTQuOTMxLDUuMTA0LDEyLjczMiw1LjEwNCwxMC4wMjF6Ii8+DQogIDwvZz4NCjwvZz4NCjwvc3ZnPg==';
let defaultImage16 = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4NCjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDI0IDI0IiBoZWlnaHQ9IjE2cHgiIHdpZHRoPSIxNnB4Ij4NCjxnIGZpbGw9IiNmYmZiZmIiIHN0cm9rZT0icmdiYSgwLDAsMCwwLjUpIiBzdHJva2Utd2lkdGg9Ii44Ij4NCiAgPGcgaWQ9InNlYXJjaCI+DQogICAgPHBhdGggZD0iTTIsMTAuMDE4YzAsNC40MywzLjU4NSw4LjAxOSw4LjAwOSw4LjAxOSBjMS42MDMsMCwzLjA5NS0wLjQ3Myw0LjM0OC0xLjI4NWw0LjgwNiw0LjgxYzAuNTgsMC41ODMsMS41MjMsMC41ODMsMi4xMDUsMGwwLjI5Ni0wLjI5N2MwLjU4Mi0wLjU4MywwLjU4Mi0xLjUyNywwLTIuMTEgbC00LjgwOC00LjgxNGMwLjgtMS4yNDcsMS4yNjUtMi43MywxLjI2NS00LjMyM2MwLTQuNDMtMy41ODctOC4wMTgtOC4wMTItOC4wMThDNS41ODUsMiwyLDUuNTg5LDIsMTAuMDE4eiBNNS4xMDQsMTAuMDIxIGMwLTIuNzE2LDIuMTk2LTQuOTE1LDQuOTA2LTQuOTE1YzIuNzEsMCw0LjkwOCwyLjE5OSw0LjkwOCw0LjkxNWMwLDIuNzEyLTIuMTk4LDQuOTExLTQuOTA4LDQuOTExIEM3LjMsMTQuOTMxLDUuMTA0LDEyLjczMiw1LjEwNCwxMC4wMjF6Ii8+DQogIDwvZz4NCjwvZz4NCjwvc3ZnPg==';
let contextSearchCompact = {
initialized: false,
init: function() {
if(this.initialized)
return;
this.initialized = true;
this.nodeIDs = {
searchMenu: 'context-search-compact-by-2k1dmg-menu',
searchMenuPopup: 'context-search-compact-by-2k1dmg-popup'
};
if(document.getElementById(this.nodeIDs.searchMenu))
return;
let context = document.getElementById('contentAreaContextMenu');
let searchSelect = document.getElementById('context-searchselect');
//searchSelect.style.display = 'none';
context.addEventListener('popupshowing', this, false);
context.addEventListener('popuphidden', this, false);
Services.obs.addObserver(this, 'browser-search-engine-modified', false);
if(prefs.has('browser.search.hiddenOneOffs'))
prefs.observe('browser.search.hiddenOneOffs', this);
this.loadSheet(window, this.makeCSS());
this.createSearchMenu();
if(typeof addDestructor == 'function' && // userChromeJS/uc
addDestructor != ('addDestructor' in window && window.addDestructor)) {
addDestructor(function(reason) {
this.destroy(reason);
}, this);
}
},
destroy: function(reason) {
if(!this.initialized)
return;
this.initialized = false;
let context = document.getElementById('contentAreaContextMenu');
let searchSelect = document.getElementById('context-searchselect');
let menu = document.getElementById(this.nodeIDs.searchMenu);
//searchSelect.style.removeProperty('display');
context.removeEventListener('popupshowing', this, false);
context.removeEventListener('popuphidden', this, false);
Services.obs.removeObserver(this, 'browser-search-engine-modified', false);
if(prefs.has('browser.search.hiddenOneOffs'))
prefs.ignore('browser.search.hiddenOneOffs', this);
menu.removeEventListener('command', this, true);
menu.removeEventListener('click', this, true);
menu.remove();
this.removeSheet(window, this.makeCSS());
},
update: function() {
this.updateTimeoutID = null;
this.updateSearchMenu();
},
observe: function(subject, type, data) {
switch(type) {
case 'nsPref:changed':
case 'browser-search-engine-modified':
if(typeof this.updateTimeoutID == 'number') {
clearTimeout(this.updateTimeoutID);
this.updateTimeoutID = null;
}
this.updateTimeoutID = setTimeout(function() {
this.update();
}.bind(this), 1000);
break;
}
},
handleEvent: function(event) {
this[event.type](event);
},
popupshowing: function(event) {
if(event.target.id != 'contentAreaContextMenu')
return;
let menu = document.getElementById(this.nodeIDs.searchMenu);
let searchSelect = document.getElementById('context-searchselect');
menu.hidden = searchSelect.hidden;
menu.label = searchSelect.label;
},
popuphidden: function(event) {
if(event.target.id != 'contentAreaContextMenu')
return;
let menu = document.getElementById(this.nodeIDs.searchMenu);
let engine = Services.search.currentEngine || Services.search.defaultEngine;
menu.label = engine.name;
},
click: function(event) {
let node = event.target;
if(event.button === 1 || ('tagName' in node && node.tagName == 'menu')) {
this.command(event);
}
},
command: function(event) {
let {engine} = event.target;
let text = this.searchTerms || this.getSelection();
if(!engine || !text)
return;
let submission = engine.getSubmission(text, null);
if(!submission)
return;
let context = document.getElementById('contentAreaContextMenu');
let inBackground = prefs.get('browser.search.context.loadInBackground', false);
let relatedToCurrent = prefs.get('browser.tabs.insertRelatedAfterCurrent', true);
if(event.button === 1 || (event.ctrlKey || event.metaKey))
inBackground = !inBackground;
if(inBackground && prefs.get('browser.sessionstore.restore_on_demand', true)) {
let ellipsis = (gContextMenu && gContextMenu.ellipsis) ? gContextMenu.ellipsis : '\u2026';
if(event.shiftKey) {
event.stopPropagation();
event.preventDefault();
}
else {
context.hidePopup();
}
return this.loadTabOnDemand(submission.uri.spec, engine, text, relatedToCurrent, ellipsis);
}
context.hidePopup();
let gBrowser = window.gBrowser || getBrowser();
gBrowser.loadOneTab(submission.uri.spec, {
postData: submission.postData,
relatedToCurrent: relatedToCurrent,
inBackground: inBackground
});
},
loadTabOnDemand: function(url, engine, text, relatedToCurrent, ellipsis) {
let gBrowser = window.gBrowser || getBrowser();
let tab = gBrowser.addTab(null, {relatedToCurrent: relatedToCurrent});
let title = ((text.length > 56) ? text.slice(0,55)+ellipsis : text) +' - '+ engine.name;
gSessionStore.setTabState(tab, JSON.stringify({
entries: [
{ title: title }
],
userTypedValue: url,
userTypedClear: 2,
lastAccessed: tab.lastAccessed,
index: 1,
hidden: false,
attributes: {},
image: (engine.iconURI ? engine.iconURI.spec : null)
}));
},
get searchTerms() {
let searchSelect = document.getElementById('context-searchselect');
if(!searchSelect || !searchSelect.searchTerms)
return null;
return searchSelect.searchTerms;
},
getSelection: function() {
if('gContextMenuContentData' in window) {
return gContextMenuContentData.selectionInfo.text;
}
else if('BrowserUtils' in window) {
return BrowserUtils.getSelectionDetails(window).text;
}
let fe = document.commandDispatcher.focusedElement;
if(fe) try {
return fe.value.substring(fe.selectionStart, fe.selectionEnd);
}
catch(ex) {};
return document.commandDispatcher.focusedWindow.getSelection();
},
createSearchMenu: function() {
let menu = document.createElement('menu');
menu.setAttribute('id', this.nodeIDs.searchMenu);
menu.setAttribute('class', 'menu-iconic');
menu.addEventListener('command', this, true);
menu.addEventListener('click', this, true);
let popup = document.createElement('menupopup');
popup.setAttribute('id', this.nodeIDs.searchMenuPopup);
menu.appendChild(popup);
let context = document.getElementById('contentAreaContextMenu');
let searchSelect = document.getElementById('context-searchselect');
context.insertBefore(menu, searchSelect);
this.updateSearchMenu();
},
updateSearchMenu: function() {
let menu = document.getElementById(this.nodeIDs.searchMenu);
let engine = Services.search.currentEngine || Services.search.defaultEngine;
menu.engine = engine;
menu.setAttribute('label', engine.name);
menu.setAttribute('image', engine.iconURI ? engine.iconURI.spec : defaultImage);
let popup = document.getElementById(this.nodeIDs.searchMenuPopup);
for(let last; last = popup.lastChild;)
last.remove();
for(let mg of this.menugroups)
popup.appendChild(mg);
menu.classList[popup.firstChild ? 'remove' : 'add']('popup-is-empty');
},
get menugroups() {
let menugroups = [];
let pref = prefs.get('browser.search.hiddenOneOffs');
let hiddenList = pref ? pref.split(',') : [];
let currentEngineName = Services.search.currentEngine.name;
let engines = Services.search.getVisibleEngines().
filter(function(e) {
return /*e.name != currentEngineName &&*/ hiddenList.indexOf(e.name) == -1;
});
while(engines.length) {
let mgList = engines.splice(0, 5);
let mg = document.createElement('menugroup');
for(let engine of mgList) {
let item = document.createElement('menuitem');
item.setAttribute('tooltiptext', engine.name);
item.setAttribute('class', 'menuitem-iconic');
item.setAttribute('src', engine.iconURI ? engine.iconURI.spec : defaultImage);
item.engine = engine;
mg.appendChild(item);
}
menugroups.push(mg);
}
return menugroups;
},
SHEET_TYPE: {
'agent': 'AGENT_SHEET',
'user': 'USER_SHEET',
'author': 'AUTHOR_SHEET'
},
isTypeValid: function(type) {
return type in SHEET_TYPE;
},
makeCSSURI: function(url) {
if(!/css$/.test(url))
url = 'data:text/css,' + encodeURIComponent(url);
return this.ios.newURI(url, null, null);
},
get ios() {
delete this.ios;
return this.ios = Services.io;
},
getDOMWindowUtils: function(window) {
return window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
},
loadSheet: function(window, url, type) {
if(!(type && type in SHEET_TYPE))
type = 'author';
type = this.SHEET_TYPE[type];
if(!(url instanceof Ci.nsIURI))
url = this.makeCSSURI(url);
let winUtils = this.getDOMWindowUtils(window);
try {
winUtils.loadSheet(url, winUtils[type]);
}
catch(ex) {};
},
removeSheet: function(window, url, type) {
if(!(type && type in SHEET_TYPE))
type = 'author';
type = this.SHEET_TYPE[type];
if(!(url instanceof Ci.nsIURI))
url = this.makeCSSURI(url);
let winUtils = this.getDOMWindowUtils(window);
try {
winUtils.removeSheet(url, winUtils[type]);
}
catch(ex) {};
},
makeCSS: function() {
return [
'@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");',
'#'+this.nodeIDs.searchMenu+' > menupopup > menugroup {',
' background-color: menu;',
'}',
'#'+this.nodeIDs.searchMenu+' > menupopup > menugroup > .menuitem-iconic {',
' padding: 5px;',
'}',
'#'+this.nodeIDs.searchMenu+'.popup-is-empty > .menu-right,',
'#'+this.nodeIDs.searchMenu+'.popup-is-empty > menupopup,',
'#context-searchselect,',
'#'+this.nodeIDs.searchMenu+' > menupopup > menugroup > .menuitem-iconic > :-moz-any(.menu-iconic-text, .menu-accel-container) {',
' display: none;',
'}'
].join('\n');
}
};
contextSearchCompact.init();
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment