Skip to content

Instantly share code, notes, and snippets.

@os0x
Created October 19, 2008 18:42
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 os0x/17904 to your computer and use it in GitHub Desktop.
Save os0x/17904 to your computer and use it in GitHub Desktop.
XPath Anchor. This script is unsafe!
// ==UserScript==
// @name XPath Anchor
// @namespace http://ss-o.net/
// @description XPath Anchor. This script is unsafe!
// @include http://*
// ==/UserScript==
(function (unsafeWindow) {
var __hash = document.location.hash;
log(unsafeWindow.document.location.watch);
if (document.location.__defineGetter__) {
document.location.__defineGetter__("hash", function() {
return __hash;
});
document.location.__defineSetter__("hash", function(hash) {
__hash = '#' + hash;
hashlink();
});
window.location.__defineGetter__("hash", function() {
return __hash;
});
window.location.__defineSetter__("hash", function(hash) {
__hash = '#' + hash;
hashlink();
});
} else if (unsafeWindow.document.location.watch) {
unsafeWindow.document.location.watch('hash',function (id,oldhash,newhash) {
__hash = '#' + newhash;
log(newhash,hashlink+'');
setTimeout(hashlink,100);
return newhash;
});
unsafeWindow.location.watch('hash',function (id,oldhash,newhash) {
__hash = '#' + newhash;
log(newhash,hashlink+'');
setTimeout(hashlink,100);
return newhash;
});
}
hashlink();
function hashlink(){
var Smooth = true;
log(__hash+'');
var hash = /^#(?:(XPath|TEXT)=(.+)|(.+))/.exec(__hash+'');
log(hash);
if (!hash)
return;
var type = hash[1];
var path = hash[2];
log(type,path);
if (hash[3]) {
type = 'TEXT';
path = hash[3];
}
if (path.indexOf('%') >= 0) {
path = decodeURIComponent(path);
}
var xpath = ({XPath:path,TEXT:'//*[contains(text(), "' + path + '")]'})[type];
log(xpath);
if (!xpath) return;
var nodetype = document.body.nodeType;
var pageY = window.pageYOffset;
$X(xpath).some(function(target){
if (target.nodeType != nodetype || !target.getBoundingClientRect) return;
var pos = target.getBoundingClientRect();
if (pos.top == 0) return;
if (Smooth)
TweenFnc({scroll:function(v){window.scrollTo(pos.left,v);}},{scroll:{to:pos.top+pageY,from:pageY},time:0.3});
else
window.scrollTo(pos.left,pos.top);
return true;
});
}
function log () {
if (this.console) {
this.unsafeWindow.console.log(arguments);
} else if (window.opera) {
opera.postError(arguments);
}
}
// simple version of $X
// $X(exp);
// $X(exp, context);
// @source http://gist.github.com/3242.txt
function $X (exp, context) {
context || (context = document);
var expr = (context.ownerDocument || context).createExpression(exp, function (prefix) {
return document.createNSResolver(context.documentElement || context).lookupNamespaceURI(prefix) ||
context.namespaceURI || document.documentElement.namespaceURI || "";
});
var result = expr.evaluate(context, XPathResult.ANY_TYPE, null);
switch (result.resultType) {
case XPathResult.STRING_TYPE : return result.stringValue;
case XPathResult.NUMBER_TYPE : return result.numberValue;
case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
// not ensure the order.
var ret = [], i = null;
while (i = result.iterateNext()) ret.push(i);
return ret;
}
return null;
}
/*
// Tweener Like snippet
new TweenFnc(div.style,{time:1, onComplete:function(){},left:{to:0,from:100,tmpl:"+$#px"}});
*/
function TweenFnc(item, opt) {
var self = this, TIME = 10, time = opt.time * 1000, TM_EXP = /(\+)?\$([\#\d])/g, count = Math.ceil(time / TIME), sets = [], easing = opt.transition || function(t, b, c, d){return c*t/d + b;}, _T = {time:1,onComplete:1,transition:1,delay:1};
for (var k in opt) if (!_T[k]) {
var set = opt[k], from = set.from || parseFloat(item[k]) || 0, values = [], tmpl = set.tmpl || '$#';
for (var i = 1; i <= count; ++i) {
var val = easing(i * TIME, from, set.to - from , time);
values.push(tmpl.replace(TM_EXP, function(m, p, m1){return p && val < 0 ? 0 : (m1 == '#' ? val : val.toFixed(m1));} ));
}
sets.push({key:k, values:values, tmpl:tmpl});
}
var L = sets.length;
var run = function(i){
for (var k = 0; k < L; ++k) item[sets[k].key](sets[k].values[i]);
if (--count > 0) setTimeout(function(){run.call(self, ++i);},TIME);
else if (typeof opt.onComplete == 'function') opt.onComplete();
};
(typeof opt.delay == "number") ? setTimeout(function(){run(0);},opt.delay*1000) : run(0);
}
})(this.unsafeWindow||window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment