Skip to content

Instantly share code, notes, and snippets.

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 satyr/369896 to your computer and use it in GitHub Desktop.
Save satyr/369896 to your computer and use it in GitHub Desktop.
Opera Style Link Drag
// ==UserScript==
// @name Opera Style Link Drag
// @author Griever satyr
// @include main
// @include chrome://global/content/viewSource.xul
// @include chrome://global/content/viewPartialSource.xul
// @version 0.0.1.20100421
// ==/UserScript==
Array.forEach(document.querySelectorAll('tabbrowser, browser'), function(b){
b.addEventListener('mousedown', this, true);
}, function OSLD_down(e){
if(e.button !== 0 || e.altKey || e.metaKey ||
e.explicitOriginalTarget.nodeType !== document.TEXT_NODE) return;
var link = e.target;
do if(link instanceof HTMLAnchorElement) break;
while(link = link.parentNode);
if(!link) return;
e.stopPropagation();
var {screenX: x, screenY: y} = e, sleep = true;
listen1(this, 'mousemove', function OSLD_move(e){
// cancel drag if moving horizontally (30 degree > elevation angle)
if(Math.tan(Math.PI/6) > Math.abs((e.screenY - y) / (e.screenX - x)))
link.setAttribute('draggable', false);
sleep = false;
}, true);
listen1(this, 'mouseup', function OSLD_up(e){
sleep = false;
link.removeAttribute('draggable');
// cancel click if still on same link and selected
var sel = e.view.getSelection();
if(sel.isCollapsed) return;
var {target} = e;
do if(target === link) break; while(target = target.parentNode);
if(!target) return;
var node = e.explicitOriginalTarget;
for(let i = sel.rangeCount; i--;) let(rng = sel.getRangeAt(i)){
if(rng.startContainer !== node && rng.endContainer !== node) continue;
listen1(this, 'click', function OSLD_click(e){
e.preventDefault();
e.stopPropagation();
}, true);
return;
}
}, true);
setTimeout(function(){ sleep = false; }, 8e3); // safety net
// hold mousedown
var thread = Cc['@mozilla.org/thread-manager;1'].getService().currentThread;
while(sleep) thread.processNextEvent(true);
function listen1(target, type, listener, capture){
target.addEventListener(type, function listener1(event){
target.removeEventListener(type, listener1, capture);
listener.call(this, event);
}, capture);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment