Created
March 28, 2009 15:14
-
-
Save Griever/87118 to your computer and use it in GitHub Desktop.
Snap Links の真似事
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
javascript:({ | |
init: function() { | |
this.box = document.createElement("div"); | |
this.box.id = "snap-links-box"; | |
this.bs = this.box.style; | |
this.bs.backgroundColor = "rgba(0,128,255,.1)"; | |
this.bs.border = "1px solid rgb(255,255,0)"; | |
this.bs.WebkitBoxSizing = | |
this.bs.OBoxSizing = | |
this.bs.MozBoxSizing = | |
this.bs.boxSizing = 'border-box'; | |
this.bs.position = "absolute"; | |
this.bs.zIndex = "2147483647"; | |
this.cursor = document.body.style.cursor; | |
document.body.style.setProperty("cursor", "crosshair", "important"); | |
addEventListener("mousedown", this, true); | |
}, | |
uninit: function() { | |
var self = this; | |
removeEventListener("mousemove", this, true); | |
removeEventListener("mouseup", this, true); | |
setTimeout(function(){ | |
removeEventListener("click", self, true); | |
}, 10); | |
this.box.parentNode.removeChild(this.box); | |
this.box = null; | |
if (this.cursor) { | |
document.body.style.cursor = this.cursor; | |
} else { | |
document.body.style.removeProperty("cursor"); | |
} | |
}, | |
handleEvent : function(event){ | |
if (event.button) return false; | |
event.preventDefault(); | |
event.stopPropagation(); | |
switch(event.type){ | |
case "mousedown": | |
this.downX = event.pageX; | |
this.downY = event.pageY; | |
this.bs.left = this.downX + "px"; | |
this.bs.top = this.downY + "px"; | |
document.body.appendChild(this.box); | |
removeEventListener("mousedown", this, true); | |
addEventListener("mousemove", this, true); | |
addEventListener("mouseup", this, true); | |
addEventListener("click", this, true); | |
break; | |
case "mousemove": | |
var moveX = event.pageX; | |
var moveY = event.pageY; | |
if (this.downX > moveX) this.bs.left = moveX + "px"; | |
if (this.downY > moveY) this.bs.top = moveY + "px"; | |
this.bs.width = Math.abs(moveX - this.downX) + "px"; | |
this.bs.height = Math.abs(moveY - this.downY) + "px"; | |
break; | |
case "mouseup": | |
this.boxRect = this.box.getBoundingClientRect(); | |
this.uninit(); | |
if (this.boxRect.width > 0 && this.boxRect.height > 0) | |
this.command(event); | |
break; | |
} | |
}, | |
command: function(aEvent) { | |
var links = []; | |
var checks = []; | |
var linkhash = {}; | |
var x = document.evaluate( | |
'//a[not(.//img)] | //a//img | //input[@type="checkbox"]', | |
document.body, | |
null, | |
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, | |
null | |
); | |
for (var i = 0, len = x.snapshotLength; i < len; i++) { | |
var elem = x.snapshotItem(i); | |
if (elem.offsetWidth <= 1 || elem.offsetHeight === 0) | |
continue; | |
if (!this.isOverlap(elem)) | |
continue; | |
if (getComputedStyle(elem, null).visibility === "hidden") | |
continue; | |
if (elem instanceof HTMLImageElement) { | |
elem = document.evaluate( | |
'ancestor-or-self::a', elem, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null) | |
.singleNodeValue; | |
} | |
if (elem instanceof HTMLAnchorElement) { | |
if (!linkhash[elem.href] && | |
/^(?:http|data|file)/.test(elem.href) && | |
elem.hasAttribute("href") && | |
elem.getAttribute("href")[0] != "#") { | |
linkhash[elem.href] = true; | |
links.push(elem); | |
} | |
} | |
else if (!elem.disabled){ | |
checks.push(elem); | |
} | |
}; | |
if (links.length === 0 && checks.length === 0) | |
return; | |
if ((links.length === 0 || aEvent.shiftkey) && checks.length > 0) { | |
this.toggleChecks(checks); | |
} else if (links.length > 0 && aEvent.ctrlKey) { | |
alert(links.join("\n")); | |
} else if (links.length > 0 && checks.length === 0) { | |
this.openLinks(links); | |
} else if (confirm("OK: リンクを開く\nキャンセル: チェックボックス ON/OFF")) { | |
this.openLinks(links); | |
} else { | |
this.toggleChecks(checks); | |
} | |
}, | |
openLinks: function(links) { | |
if (window.chrome) { | |
for (var i = 0, len = links.length; i < len; i++) { | |
var evt = document.createEvent("MouseEvents"); | |
evt.initMouseEvent( | |
"click", true, true, window, | |
0, 0, 0, 0, 0, | |
true, false, i===0, false, | |
0, null); | |
var a = document.createElement("a"); | |
a.href = links[i].href; | |
a.dispatchEvent(evt); | |
}; | |
} else if (window.opera) { | |
var i = 0; | |
function o(url) { | |
var elem = links[i++]; | |
if (!elem) return; | |
window.open(elem.href); | |
setTimeout(o, i * 10); | |
} | |
setTimeout(o, i * 10); | |
} else { | |
for (var i = 0, len = links.length; i < len; i++) { | |
window.open(links[i].href); | |
}; | |
} | |
}, | |
toggleChecks: function(checks) { | |
for (var i = 0, len = checks.length; i < len; i++) { | |
checks[i].checked = !checks[i].checked; | |
}; | |
}, | |
isOverlap: function(aElem) { | |
var rects = aElem.getClientRects(); | |
for (var i = 0, rect; rect = rects[i]; i++) { | |
if (this.boxRect.left < rect.right && | |
this.boxRect.right > rect.left && | |
this.boxRect.top < rect.bottom && | |
this.boxRect.bottom > rect.top) | |
return true; | |
}; | |
return false; | |
}, | |
}).init(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment