Skip to content

Instantly share code, notes, and snippets.

@xulapp
Created November 11, 2010 14:01
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 xulapp/672527 to your computer and use it in GitHub Desktop.
Save xulapp/672527 to your computer and use it in GitHub Desktop.
long middle click == shift + middle click
// ==UserScript==
// @name middleClickFocusTab.uc.js
// @description long middle click == shift + middle click
// @include main
// @charset utf-8
// @compatibility Firefox 3.6+
// @namespace http://twitter.com/xulapp
// @author xulapp
// @license MIT License
// @version 2010/11/22 00:50 +09:00
// ==/UserScript==
// @version 2010/10/13 00:30 +09:00
(function middleClickFocusTab() {
const TIMEOUT = 300;
const TARGET_XPATH = 'ancestor-or-self::html:a | ancestor-or-self::html:area | ancestor-or-self::xul:toolbarbutton | ancestor-or-self::xul:*[@onclick] | ancestor-or-self::*[@xlink:href]';
const NAMESPACE = {
xul: 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul',
html: 'http://www.w3.org/1999/xhtml',
xlink: 'http://www.w3.org/1999/xlink',
};
const resolveNS = function resolveNS(name) NAMESPACE[name];
const tooltip = document.createElementNS(NAMESPACE.xul, 'tooltip');
tooltip.setAttribute('id', 'longclick-tooltip');
tooltip.setAttribute('label', '\u9577\u62bc\u3057');
document.getElementById('mainPopupSet').appendChild(tooltip);
document.addEventListener('mousedown', function({originalTarget, button, screenX, screenY}) {
if (button !== 1) return;
var clickable = originalTarget.ownerDocument.evaluate(
TARGET_XPATH,
originalTarget,
resolveNS,
XPathResult.BOOLEAN_TYPE,
null
).booleanValue;
if (!clickable) return;
first([
function(next) timeout(next, TIMEOUT, null),
function(next) listen(document, 'mouseup', next, true, false),
], function(e) {
if (e) return;
tooltip.openPopupAtScreen(screenX, screenY);
listenOnce(document, 'mouseup', function onMouseUp(event) {
tooltip.hidePopup();
if (event.originalTarget !== originalTarget) return;
listenOnce(document, 'click', function onClick(event) {
var {shiftKey} = event;
event.__defineGetter__('shiftKey', function() !shiftKey);
}, true, false);
}, true, false);
});
}, false, false);
function timeout() {
var timer = setTimeout.apply(null, arguments);
return function() clearTimeout(timer);
}
function listen(node) {
var args = Array.slice(arguments, 1);
node.addEventListener.apply(node, args);
return function() node.removeEventListener.apply(node, args);
}
function listenOnce() {
var args = Array.slice(arguments);
var listener = args[2];
args[2] = function onceGate() {
cancel();
return listener.apply(this, arguments);
};
var cancel = listen.apply(null, args);
return cancel;
}
function first(tasks, callback) {
var closed = false;
var cancelers = [];
var next = function(arg) {
if (closed) return;
callback(arg);
close();
};
var close = function() {
cancelers.forEach(function(fn) fn());
closed = true;
};
tasks.some(function(fn) {
var abort = fn(next);
if (closed)
return true;
if (typeof abort === 'function')
cancelers.push(abort);
});
return close;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment