-
-
Save halbtuerke/2723254 to your computer and use it in GitHub Desktop.
Straight Google
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
// ==UserScript== | |
// @name Straight Google | |
// @id straight_google_pokerface | |
// @namespace in.co.tossing.toolkit.google | |
// @description Remove URL redirection from google products | |
// @license GPL v3 or later version | |
// @updateURL http://userscripts.org/scripts/source/121261.meta.js | |
// @include *://www.google.*/*q=* | |
// @include *://www.google.*/*tbs=* | |
// @include *://www.google.*/search?* | |
// @include *://www.google.*/webhp?* | |
// @include *://www.google.*/?* | |
// @include *://www.google.*/#* | |
// @include *://www.google.*/ | |
// @include *://encrypted.google.* | |
// @include *://ipv6.google.* | |
// @include *://www.google.*/news* | |
// @include *://news.google.*/* | |
// @exclude *://plus.google.com/_/apps-static/* | |
// @exclude *://plus.google.com/u/*/_/streamwidgets* | |
// @include *://plus.google.com/* | |
// @include *://images.google.com/* | |
// @include *://docs.google.com/* | |
// @include *://maps.google.com/* | |
// @include *://www.google.com/maps* | |
// @include *://ditu.google.com/* | |
// @include *://www.youtube.* | |
// @include *://groups.google.com/group/* | |
// @include *://www.google.com/bookmarks/* | |
// @include *://www.google.com/history/* | |
// @include *://www.google.com/prdhp* | |
// @include *://www.google.com/products/catalog?* | |
// @include *://www.google.com/shopping/offerdetails?* | |
// @version 1.7 | |
// @author Pokerface - Kevin | |
// ==/UserScript== | |
/* | |
KissogramToolkit | |
build 5/13/2012 by Kevin Wang | |
[email protected] | |
*/ | |
var $K = KissogramToolkit = (function ($$d) { | |
// some configuration | |
var DEBUG_ON = true; | |
// Basic function ============================================== | |
// for each | |
function each($arr, $func) { | |
var item; | |
if (!$arr) | |
return; | |
//_debug('each function is called. arr length is '+ $arr.length); | |
if ($func) | |
for (item in $arr) | |
$func.call($arr[item]); | |
else | |
// the $arr is collection of function itself | |
for (item in $arr) | |
if (typeof $arr[item]==='function') | |
$arr[item](); | |
} | |
var utils = { | |
"isStrictArray" : function ($obj) { | |
return Object.prototype.toString.apply($obj) === '[object Array]'; | |
}, | |
"isRegExp" : function ($obj) { | |
return Object.prototype.toString.apply($obj) === '[object RegExp]'; | |
}, | |
"toArray" : function ($obj) { | |
if (!this.isArray($obj)) | |
return [$obj]; | |
else if (!this.isStrictArray($obj)) | |
return Array.prototype.slice.apply($obj); | |
else | |
return $obj; | |
}, | |
"isArray" : function ($obj) { | |
var type = Object.prototype.toString.apply($obj); | |
return type === '[object Array]' // array | |
|| type === '[object NodeList]' // document.querySelectorAll | |
|| type === '[object Arguments]' // function arguments | |
; | |
}, | |
"trim" : function ($str) { | |
return $str.replace(/^\s+|\s+$/g, ''); | |
}, | |
"trimS" : function ($str) { | |
return this.trim($str).replace(/\s{2,}/g, ' '); | |
} | |
}; | |
// shallow copy | |
function extend($target, $options) { | |
var name; | |
for (name in $options) { | |
if ($target === $options[name]) | |
continue; | |
if ($options[name]) | |
$target[name] = $options[name]; | |
} | |
return $target; | |
} | |
// Basic function ends ============================================= | |
// limit the interval/delay of running a specific function, return the changed function | |
function setFunctionTiming($func, $opt) { | |
$opt = $opt || {}; | |
var opt = { | |
interval : $opt.interval || 0, | |
delay : $opt.delay || 0, | |
check : $opt.check || 0 | |
}; | |
return (function () { | |
var lastRunTime = 0, instances = [], isRunning = false, checkInterval = null; | |
var res = function () { | |
if (opt.check > 0 && checkInterval==null) | |
checkInterval = setInterval(res, opt.check); | |
var timeRemain = (new Date().getTime()) - lastRunTime; | |
var _this = this, args = utils.toArray(arguments); | |
// the real function | |
function runFunc() { | |
lastRunTime = new Date().getTime(); | |
isRunning = true; | |
$func.apply(_this, args); | |
isRunning = false; | |
instances.shift(); | |
}; | |
if (instances.length < 1 || isRunning) { | |
// not time yet | |
if (timeRemain < opt.interval) | |
instances.push(setTimeout(runFunc, Math.max(100, opt.delay + opt.interval - (isRunning ? 0 : timeRemain)))); | |
else | |
instances.push(setTimeout(runFunc, Math.max(100, opt.delay))); | |
} | |
}; | |
return res; | |
})(); | |
} | |
var $$browser = (function getNavigator($n) { | |
var navigatorString = $n.userAgent.toLowerCase(), | |
// browser agent | |
rBrowsers = [ | |
/.*version\/([\w.]+).*(safari).*/, | |
/.*(msie) ([\w.]+).*/, | |
/.*(firefox)\/([\w.]+).*/, | |
/(opera).+version\/([\w.]+)/, | |
/.*(chrome)\/([\w.]+).*/ | |
], | |
// result | |
ret = { | |
name : 'unknown', | |
version : 'unknown', | |
language: $n.language || $n.userLanguage || '', | |
toString : function () { | |
return this.name; | |
} | |
}; | |
for (var i = 0, match=null; i < rBrowsers.length; ++i) | |
if ( match = rBrowsers[i].exec(navigatorString) ) { | |
// match safari | |
ret.name = (i==0 ? match[2] : match[1]) || 'unknown'; | |
ret.version = (i==0 ? match[1] : match[2]) || 'unknown'; | |
ret[ret.name] = true; | |
break; | |
} | |
return ret; | |
})(navigator); | |
// get unsafeWindow | |
var $$w = (function () { | |
var w = null, // window object | |
resizeTasks = [], | |
scrollTasks = []; | |
function getSize() { | |
return { | |
windowHeight : window.innerHeight, | |
windowWidth : window.innerWidth, | |
height : $$d.documentElement.clientHeight, | |
width : $$d.documentElement.clientWidth | |
}; | |
} | |
function _isScroll(el) { | |
// test targets | |
var elems = el ? [el] : [document.documentElement, document.body]; | |
var scrollX = false, scrollY = false; | |
for (var i = 0; i < elems.length; i++) { | |
var o = elems[i]; | |
// test horizontal | |
var sl = o.scrollLeft; | |
o.scrollLeft += (sl > 0) ? -1 : 1; | |
o.scrollLeft !== sl && (scrollX = scrollX || true); | |
o.scrollLeft = sl; | |
// test vertical | |
var st = o.scrollTop; | |
o.scrollTop += (st > 0) ? -1 : 1; | |
o.scrollTop !== st && (scrollY = scrollY || true); | |
o.scrollTop = st; | |
} | |
// ret | |
return { | |
scrollX: scrollX, | |
scrollY: scrollY | |
}; | |
}; | |
window.addEventListener('resize', function () { | |
each(resizeTasks); | |
}, false); | |
window.addEventListener('scroll', function () { | |
each(scrollTasks); | |
}, false); | |
// return true when unsafeWindow is loaded successfully | |
function _init($var) { | |
if (!w) { | |
// load unsafeWindow | |
if (typeof(unsafeWindow) !== "undefined" && typeof(unsafeWindow[$var]) !== "undefined") | |
w = unsafeWindow; | |
else if (typeof(window[$var]) !== "undefined") | |
w = window; | |
else | |
try { | |
// for Chrome | |
var a = document.createElement("a"); | |
a.setAttribute("onclick", "return window;"); | |
var win = a.onclick(); | |
if (typeof(win[$var]) !== "undefined") | |
w = win; | |
} | |
catch (e) { | |
_debug('Kissogram Toolkit : Unable to load unsafeWindow Object!'); | |
w = null; | |
} | |
} | |
return w; | |
} | |
function _onUnsafeWindowReady($var, $func, $options) { | |
$options = $options || {}; | |
$options.retry = (typeof $options.retry != "number") ? 30 : $options.retry; | |
$options.interval = $options.interval || 300; | |
if (_init($var) && (!$options.test || $options.test(w))) { | |
_debug("Kissogram Toolkit : unsafeWindow injection succeed!"); | |
return $func(w, w[$var]); | |
} | |
if ($options.retry-- > 0) | |
setTimeout(function () { _onUnsafeWindowReady($var, $func, $options); }, $options.interval); | |
} | |
var $c = { | |
// get unsafeWindow if possible | |
get : function ($var) { | |
return (this.getUnsafeWindow($var) || window)[$var]; // return safe window | |
}, | |
// get unsafeWindow | |
getUnsafeWindow : function ($var) { | |
return _init($var); | |
}, | |
/* | |
when specific function is ready | |
options : { | |
test : a function that test if specific variable is loaded properly | |
retry : retry times before test() returns a failure, default is 40 | |
interval : the interval between every check, default is 300 ms | |
} | |
*/ | |
onReady : _onUnsafeWindowReady , | |
size : getSize, | |
onResize : function ($func, $init) { | |
if ($init) | |
$func(); | |
resizeTasks.push($func); | |
return resizeTasks.length-1; | |
}, | |
_onResize : function ($id) { | |
if ($id || $id==0) | |
delete resizeTasks[$id]; | |
}, | |
isScroll : _isScroll, | |
onScroll : function ($func, $init) { | |
if ($init) | |
$func(); | |
scrollTasks.push($func); | |
return scrollTasks.length-1; | |
}, | |
_onScroll : function ($id) { | |
if ($id || $id==0) | |
delete scrollTasks[$id]; | |
} | |
}; | |
return $c; | |
})(); | |
var i18n = (function () { | |
var $c = function ($args) { | |
}; | |
var methods = { | |
lang : "en-US", | |
getMessage : function ($item) { | |
} | |
}; | |
})(); | |
// css Class | |
var $$css = (function () { | |
var css_enabled = [], | |
root = $$d.documentElement, | |
FEATURE_LIST_ATTR = "feature-list", | |
CSS_ELEM_REGEXP = /^\s*[.\w][.\w\d-]+[\w\d-]\s*$/; | |
var instance = function ($arg) { | |
extend(this, $c); | |
if ($arg) | |
this.dictionary = this.dictionary.concat($arg.reverse()); //define the css dictionary | |
}; | |
// effective only for Chrome | |
function _getMediaQueriesWidth() { | |
if ($$browser == "firefox") | |
return window.innerWidth; | |
// for Chrome, the width in Media Queries is quite close to window.outerWidth | |
for (var i=1, width = window.outerWidth, match=false; !match; i++) { | |
if (width > 0) | |
match = window.matchMedia('(min-width :' + width + 'px) and (max-width:'+ width + 'px)').matches; | |
if (match) | |
return width; | |
width += (i%2 == 0 ? 1 : -1) * i; | |
} | |
} | |
var $c = { | |
dictionary : [], | |
ns : 'gpp-', // name space | |
// append a class to an element | |
add : function ($elem, $className) { | |
if (!$elem || !CSS_ELEM_REGEXP.test($className = this.get($className))) | |
return; | |
$className = $className.replace(/\./g, ' '); | |
var arr = $className.split(' '), appendList = ""; | |
for (var i=0, clazz = " "+$elem.className+" "; i<arr.length; i++) | |
if (arr[i] && clazz.indexOf(' '+arr[i]+' ') < 0) | |
appendList+= ' '+ arr[i]; | |
$elem.className = utils.trimS($elem.className + appendList); | |
}, | |
remove : function ($elem, $className) { | |
if (!$elem || !CSS_ELEM_REGEXP.test($className = this.get($className))) | |
return; | |
$className = utils.trimS($className.replace(/\./g, ' ')); | |
var arr = $className.split(' '), clazz = " "+$elem.className+" "; | |
for (var i=0; i<arr.length; i++) | |
clazz = clazz.replace(' '+ arr[i] +' ', ' '); | |
$elem.className = utils.trimS(clazz); | |
}, | |
// append css | |
set : function ($str) { | |
GM_addStyle(this.get($str)); | |
}, | |
get : function ($str) { | |
$str = ($str || '').replace(/\/\*[\s\S]*?\*\//g, ''); // clear the comment | |
// backforwards | |
for (var i=0; i<this.dictionary.length; i++) | |
$str = $str.replace(this.dictionary[i][0], this.dictionary[i][1]); | |
return $str; | |
}, | |
push : function ($arg, $str, $opt) { | |
$opt = $opt || {}; | |
var condition = this.getCondition($arg); | |
if ($opt.enable) | |
this.enable($arg, $opt.value); | |
$str = $str.replace(/((?:[^,{]+,?)*)\s*{([^}]+)}/g, condition+"$1 {$2}"); | |
$str = $str.replace(/,/g, ","+condition); | |
this.set($str); | |
}, | |
pull : function ($feature) { | |
return css_enabled[$feature] || null; | |
}, | |
enable : function ($arg) { | |
if (!$arg) return; | |
var feaAttr = this.getFeatureListAttr(), | |
ns = this.ns, | |
data = " "+(root.getAttribute(feaAttr)||"")+" ", | |
appendList = ""; | |
utils.toArray($arg).forEach( | |
function ($item) { | |
var obj = (typeof $item=="string") ? { name: $item } : $item; | |
// when $value is null, assert the it is a boolean | |
if (!obj.value && obj.value != 0) { | |
var name = " "+ obj.name +" "; | |
if (data.indexOf(name) < 0) { | |
appendList += name; | |
} | |
} | |
else | |
root.setAttribute(ns + obj.name, obj.value); | |
css_enabled[obj.name] = obj.value || true; | |
} | |
); | |
if (appendList) | |
root.setAttribute(feaAttr, $K.utils.trimS(data + appendList)); | |
}, | |
disable : function ($arg) { | |
if (!$arg) return ''; | |
var feaAttr = this.getFeatureListAttr(), | |
ns = this.ns, | |
hasFeature = root.hasAttribute(feaAttr), | |
data = " "+(root.getAttribute(feaAttr)||"")+" "; | |
utils.toArray($arg).forEach( | |
function ($item) { | |
var obj = (typeof $item=="string") ? { name: $item } : $item; | |
if (hasFeature) | |
data = data.replace(" "+obj.name+" "," "); | |
root.removeAttribute(ns + obj.name); | |
delete css_enabled[obj.name]; | |
} | |
); | |
if (hasFeature) | |
root.setAttribute(feaAttr, $K.utils.trimS(data)); | |
}, | |
getFeatureListAttr : function () { | |
return this.ns + FEATURE_LIST_ATTR; | |
}, | |
// has specific class | |
is : function ($elem, $className) { | |
if (!$elem) | |
return false; | |
$className = utils.trimS(this.get($className).replace(/\./g, ' ')); | |
var arr = $className.split(' '), clazz = " "+$elem.className+" "; | |
for (var i=0; i<arr.length; i++) | |
if (clazz.indexOf(' '+ arr[i] +' ', ' ') < 0) | |
return false; | |
return true; | |
}, | |
select : function ($str) { | |
return $$d.querySelector(this.get($str)); | |
}, | |
selectAll : function ($str) { | |
return utils.toArray($$d.querySelectorAll(this.get($str))); | |
}, | |
getMediaQueriesWidth : _getMediaQueriesWidth, | |
extendDictionary : function ($dic) { | |
this.dictionary = this.dictionary.concat($dic.reverse()); | |
}, | |
getCondition : function ($arg) { | |
if (!$arg) return ''; | |
var condition = "html", | |
feaAttr = this.getFeatureListAttr(), | |
ns = this.ns; | |
utils.toArray($arg).forEach( | |
function ($item) { | |
var obj = (typeof $item=="string") ? { name: $item } : $item; | |
condition += "["+ (obj.value ? | |
ns + obj.name +'="'+ obj.value +'"' : | |
feaAttr +'~="'+ obj.name +'"')+"]"; | |
} | |
); | |
return condition+' '; | |
}, | |
// return a number of piexl from '##px' | |
getPiexls : function ($str) { | |
if (!/^\d+(px)?$/i.test($str)) | |
return null; // may be 'auto' or anything else | |
return parseInt($str.replace(/px$/i, "")); | |
}, | |
// get the absolute x / y of an element | |
getAbsPos : function ($e) { | |
var t = l = 0; | |
do { | |
t += $e.offsetTop; | |
l += $e.offsetLeft; | |
} while ($e = $e.offsetParent); | |
return { | |
left: l, | |
top: t | |
}; | |
} | |
}; | |
return extend(instance, $c); | |
})(); | |
// manipulate cookies | |
var cookies = (function () { | |
return {}; | |
})(); | |
// dataTransfer | |
var dataTransfer = (function () { | |
var data = {}; | |
return { | |
setData : function ($type, $data) { | |
data[$type] = $data; | |
}, | |
getData : function ($type) { | |
return data[$type]; | |
}, | |
clearData : function ($type) { | |
delete data[$type]; | |
} | |
}; | |
})(); | |
// the Class that process url change | |
var $$url = (function () { | |
var _url = formatUrl(), | |
urlChangeTasks = [], | |
hashChangeTasks = [], | |
urlMonitor = null; | |
function isUrlChanged($url) { | |
var url = formatUrl($url); | |
if (url != _url) { | |
_url = url; | |
return true; | |
} | |
else | |
return false; | |
} | |
// turn http://xxx.xxx into http://xxx.xxx/ | |
function formatUrl($url) { | |
var url = $url || $$d.location.href; | |
if (/^https?:\/\/[\w.]+\w+$/.test(url)) | |
url += '/'; | |
return url; | |
} | |
function execTask($e) { | |
if (!$e) { | |
_debug('Kissogram Toolkit: URL changed!'); | |
each(urlChangeTasks); | |
} | |
else if ($e.type == "popstate") { | |
_debug('Kissogram Toolkit: URL [popstate] changed!'); | |
each(urlChangeTasks); | |
} | |
else if ($e.type == "hashchange") { // hashchange | |
_debug('Kissogram Toolkit: URL [hash] changed!'); | |
each(hashChangeTasks); | |
} | |
} | |
// bind onpopstate | |
window.addEventListener('popstate', function (e) { | |
if (isUrlChanged()) | |
execTask(e); | |
}, false); | |
// hashchange | |
window.addEventListener('hashchange', function (e) { | |
execTask(e); | |
}, false); | |
var $c = { | |
onUrlChange : function ($func, $init) { | |
if ($init) | |
$func(); | |
// mointor | |
if (urlMonitor == null) { | |
_debug('Kissogram Toolkit: URL onChange inited!'); | |
urlMonitor = setInterval(function () { | |
if (isUrlChanged()) | |
execTask(); | |
}, 500); | |
} | |
urlChangeTasks.push($func); | |
}, | |
onHashChange : function ($func, $init) { | |
if ($init) | |
$func(); | |
hashChangeTasks.push($func); | |
}, | |
onUrlMatch : function ($match, $func, $init) { | |
if (!$match) | |
return; | |
}, | |
toString : function () { | |
return _url = formatUrl(); | |
} | |
}; | |
return $c; | |
})(); | |
/* | |
listen to specific event | |
$options { | |
init : boolean / function | |
runOnce : boolean | |
interval | |
} | |
*/ | |
var listen = (function () { | |
var interval_count=[]; // collection of interval count | |
return function ($selector, $event, $func, $options) { | |
$options = $options || {}; | |
// $event & $init cannot be false at the same time | |
if (!$event && !$options.init) | |
return; | |
var evt_listener = (function ($s, $e, $f, $o) { | |
var id = interval_count.length, | |
funcWithTiming = setFunctionTiming($f, { | |
interval : $o.interval || 0, | |
delay : $o.delay || 0 | |
}); | |
// bind event to dom object | |
var _bind = function ($d, $evt) { | |
$d.addEventListener($evt, | |
(function () { | |
var runOnceFunc = setFunctionTiming(function () { | |
$f.apply($d, utils.toArray(arguments), false); | |
$d.removeEventListener($evt, runOnceFunc); | |
}, { delay: $o.delay }), | |
newFunc = function () { | |
funcWithTiming.apply($d, utils.toArray(arguments)); | |
}; | |
return $o.runOnce ? runOnceFunc : newFunc ; | |
})() | |
); | |
}; | |
return function () { | |
// if $s is a element itself | |
var dom = utils.toArray( | |
(typeof $s == 'string') ? $$css.selectAll($s) : $s | |
); | |
if (dom.length > 0) { | |
// dom is captured | |
clearInterval(interval_count[id]); | |
delete interval_count[id]; | |
for (var i=0; i<dom.length; i++) { | |
// if the function need initiation (when the listen function capture the dom objects the first time) | |
if ($o.init) { | |
if (typeof $o.init == "function") | |
$o.init.call(dom[i]); | |
else | |
$f.call(dom[i]); | |
} | |
if (utils.isStrictArray($e)) | |
each($e, function () { _bind(dom[i], this); }); | |
else if ($e) // when $e != null | |
_bind(dom[i], $e); | |
else // do nothing | |
; | |
} | |
} | |
} | |
})($selector, $event, $func, $options); | |
// check it later | |
interval_count.push(setInterval(evt_listener, 500)); | |
} | |
})(); | |
var cache = function () { | |
var _cache = {}; | |
extend(this, { | |
// get a cache | |
get : function ($id) { | |
return _cache[$id]; | |
}, | |
// set a cache | |
set : function ($id, $val) { | |
_cache[$id] = $val; | |
}, | |
// delete a cache | |
"delete" : function ($id) { | |
delete _cache[$id]; | |
}, | |
// clear all cache | |
reset : function () { | |
_cache = {}; | |
}, | |
// if a cache exists | |
exists : function ($id) { | |
return _cache[$id] || _cache[$id]==0; | |
} | |
}); | |
} | |
var mouse = (function () { | |
// simluate a click event | |
function click($elem, $options) { | |
if (!$elem) | |
return; | |
$options = $options || {}; | |
var opt = { | |
button : $options.button || 0 | |
}; | |
// dispatch click event following the W3C order | |
var e = $$d.createEvent("MouseEvents"); | |
e.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, opt.button, null); | |
$elem.dispatchEvent(e); | |
e = $$d.createEvent("MouseEvents"); | |
e.initMouseEvent("mouseup", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, opt.button, null); | |
$elem.dispatchEvent(e); | |
e = $$d.createEvent("MouseEvents"); | |
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, opt.button, null); | |
$elem.dispatchEvent(e); | |
} | |
// gesture part | |
var gesture = (function () { | |
var _zigzag = (function () { | |
var zigzag_finished = 0, | |
event_inited = false, | |
lastX = lastY = X = Y = 0, | |
boundary = 20, // how many pixels should be past when defining a 'zigzag' | |
$c = {}; | |
var _detect = (function () { | |
var directionX = directionY = 0; // record which direction does the mouse move | |
return function (e) { | |
var offsetX = e.clientX - X, offsetY = e.clientY - Y; // direction | |
X = e.clientX; | |
Y = e.clientY; | |
if (!directionX || !directionY) { // init | |
directionX = offsetX; | |
directionY = offsetY; | |
return; | |
} | |
_debug(offsetX * directionX > 0,offsetY * directionY > 0 ,Math.abs(X-lastX) < boundary ,Math.abs(Y-lastY) < boundary); | |
// test if a 'z' is drawed | |
if (offsetX * directionX > 0 || offsetY * directionY > 0 || Math.abs(X-lastX) < boundary || Math.abs(Y-lastY) < boundary) | |
return; | |
lastX = X; | |
lastY = Y; | |
// when three zigzags are achieved | |
if (++zigzag_finished >= 3) | |
$c.success = true; | |
}; | |
})(); | |
function _init(e) { | |
zigzag_finished = 0; | |
X = lastX = e.clientX; | |
Y = lastY = e.clientY; | |
$c.success = false; | |
} | |
$c = { | |
init : _init, | |
detect : _detect, | |
success : false | |
}; | |
return $c; | |
})(); | |
return { | |
"zigzag" : _zigzag | |
}; | |
})(); | |
return { | |
"click" : click, | |
"gesture" : gesture | |
}; | |
})(); | |
function _debug($msg) { | |
if (DEBUG_ON) | |
console.debug($msg); | |
} | |
// Main function begin ======================================== | |
// constructor | |
var $$c = function () { | |
}; | |
return extend($$c, { | |
"each" : each, | |
"extend" : extend, | |
"css" : $$css, | |
"listen" : listen, | |
"url" : $$url, | |
"dataTransfer" : dataTransfer, | |
"mouse" : mouse, | |
"browser" : $$browser, | |
"window" : $$w, | |
"cookies" : cookies, | |
"select" : function (e) { return $$css.select(e) }, | |
"selectAll" : function (e) { return $$css.selectAll(e) }, | |
"tickTork" : setFunctionTiming, | |
"utils" : utils, | |
"cache" : cache, | |
"i18n" : i18n, | |
"debug" : _debug | |
}); | |
})(document); | |
// main function | |
var StraightGoogle = (function ($$d) { | |
// expand goo.gl shorten url | |
var expand_short_url = (function () { | |
var url_cache = {}; | |
var GOOGLE_SHORTEN_URL_REG = /^(?:https?:\/\/)?goo\.gl\/(\w+)$/i; | |
var GOOGLE_SHORTEN_URL_API = "https://www.googleapis.com/urlshortener/v1/url?shortUrl={$url}"; | |
return function ($url, $callback) { | |
var match = GOOGLE_SHORTEN_URL_REG.exec($url); | |
if (!match) | |
return; | |
var key = match[1]; | |
if (url_cache[key]) | |
return $f(url_cache[key]); | |
// query Google Shorten URL API | |
$K.debug('Straight Google : trying to expand shorten URL ['+ $url +']'); | |
$url = /^https?:\/\//.test($url) ? $url : 'http://'+ $url; | |
GM_xmlhttpRequest({ | |
method : 'GET', | |
url : GOOGLE_SHORTEN_URL_API.replace('{$url}', $url), | |
onload : (function ($u, $f) { | |
return function (res) { | |
try { | |
eval('var obj = '+ res.responseText); | |
} catch (e) { | |
return; | |
} | |
if (obj.status != "OK") | |
return; | |
$K.debug('Straight Google : shorten URL expanded ['+ obj.longUrl +']'); | |
// call back | |
url_cache[$u] = obj.longUrl; | |
$f(obj.longUrl); | |
}; | |
})($url, $callback), | |
onerror : function (res) { | |
$K.debug('Straight Google : fail to expand shorten URL ['+ res.finalUrl +']'); | |
} | |
}); | |
}; | |
})() | |
// fetch Google Redirection Traget | |
function get_google_url($url, $urlType) { | |
if (!$url) | |
return; | |
var google_url_reg = null; | |
// for Google Image Redirection | |
switch ($urlType) { | |
case 1 : // image reference url | |
google_url_reg = /^(?:https?:\/\/[-\w\d.]+\.google\.\w[\w.]*\w)?\/imgres\?(?:(?!imgrefurl)\w+=[^&]*&)*(?:imgrefurl)=((?:https?(?::\/\/|%3A%2F%2F))?[^&]+).*$/i; | |
break; | |
case 2 : // match imgurl only ( Google Image ) | |
google_url_reg = /^(?:https?:\/\/[-\w\d.]+\.google\.\w[\w.]*\w)?\/imgres\?(?:(?!imgurl)\w+=[^&]*&)*imgurl=((?:https?(?::\/\/|%3A%2F%2F))?[^&]+).*$/i; | |
break; | |
default : | |
google_url_reg = /^(?:https?:\/\/[-\w\d.]+\.google\.\w[\w.]*\w)?\/(?:(?:local_)?url|imgres)\?(?:(?!url|q|imgurl)\w+=[^&]*&)*(?:url|q|imgurl)=((?:https?(?::\/\/|%3A%2F%2F))?[^&]+).*$/i; | |
} | |
var mat = $url.match(google_url_reg); | |
var res = mat ? unescape(mat[1] || '') : ''; | |
// fix http:// | |
if (res && !/^https?:\/\//.test(res)) | |
res = "http://"+ res; // default http | |
return res; | |
} | |
function google_url_clean($urlType) { | |
var url = get_google_url(this.href, $urlType); | |
if (url) { | |
this.href = url; | |
$K.debug('Redirection of ['+ url +'] is now removed.'); | |
} | |
do_not_track.call(this); | |
// try to expand shorten url | |
expand_short_url(url || this.href, (function (obj) { | |
return function (url) { | |
if (obj) obj.href = url; | |
}; | |
})(this)); | |
return url || ''; | |
} | |
function common_clean_job() { | |
$K.listen('a[href*="/url?"]', null, google_url_clean, { init : true }); // this applys for static pages | |
} | |
function do_not_track() { | |
// add no follow | |
if (!this.getAttribute("rel")) this.setAttribute("rel", "noreferrer"); | |
} | |
// Main part begin ======================================== | |
function _start() { | |
// prevent Google Plus redirection : plus.url.google.com | |
if (/:\/\/plus\.google\.com\/.*$/.test($K.url)) { | |
function plus_clean() { | |
$K.each( | |
// use 'do not track me' feature | |
$K.selectAll('a.ot-anchor:not([rel])'), | |
google_url_clean | |
); | |
} | |
// notification bar | |
if (/\/notifications\/frame\?/.test($K.url)) { | |
$K.debug('Straight Google [Plus Notification] is now loaded'); | |
// plus home page | |
$K.window.onReady("AF_initData", | |
function ($w, $var) { | |
$var["1"][20]=""; | |
$K.debug('URL Redirection of Google Plus Notification is now prevented.'); | |
} | |
); | |
$K.listen( | |
// notification stream | |
'.sqb.oya', | |
"DOMSubtreeModified", | |
plus_clean, | |
{ init: true } | |
); | |
} | |
else { | |
$K.debug('Straight Google [Plus] is now loaded'); | |
// plus home page | |
$K.window.onReady("AF_initDataQueue", | |
function ($w, $var) { | |
for (var i=0; i<$var.length; i++) | |
if ($var[i].key=="1") { | |
$var[i].data[20]=""; // clear plus.url.google.com | |
$K.debug('URL Redirection of Google Plus is now prevented.'); | |
break; | |
} | |
} | |
); | |
// page switch | |
$K.url.onUrlChange( | |
function () { | |
$K.listen(".aw", "DOMNodeInserted", plus_clean); | |
}, | |
true | |
); | |
} | |
} | |
// remove google news redirection here | |
else if (/:\/\/news\.google\.[\w.]+\w\/.*$/.test($K.url) || /:\/\/www\.google\.[\w.]+\w\/news\/.*$/.test($K.url)) { | |
$K.debug('Straight Google [News] is now loaded'); | |
$K.listen( | |
'.blended-section', | |
"DOMNodeInserted", | |
function () { | |
$K.each( | |
$K.selectAll('a.article[url]:not(._tracked)'), | |
function () { | |
// fix link to its normal url | |
this.href = this.getAttribute('url'); | |
do_not_track.call(this); | |
$K.debug("Redirection of ["+ this.href +"] is now removed."); | |
// cheat google and say "it has been tracked already" | |
$K.css.add(this,' _tracked'); | |
} | |
); | |
}, | |
{ init: true } | |
); | |
} | |
// Google Docs | |
else if (/:\/\/docs\.google\.com\/.+/.test($K.url)) { | |
$K.debug('Straight Google [Docs] is now loaded'); | |
// Spread Sheet | |
if (/docs\.google\.com\/spreadsheet\/.+/.test($K.url)) | |
$K.listen( | |
'a.docs-bubble-link[target="_blank"]', | |
'mouseover', | |
google_url_clean | |
); | |
// Other products | |
else if (/docs\.google\.com\/(document|presentation|drawings)\/.+/.test($K.url)) | |
$K.listen( | |
'.docs-bubble a[target="_blank"]', | |
'mouseover', | |
google_url_clean | |
); | |
} | |
// Google Maps | |
else if (/:\/\/(ditu|maps)\.google\.com\/.*$/.test($K.url) || /:\/\/www\.google\.com\/maps(\?|\/).*$/.test($K.url)) { | |
$K.debug('Straight Google [Maps] is now loaded'); | |
var match_pattern = '#resultspanel a[href*="/local_url?"]'; | |
// inject as a local function when output is js | |
if (/output=js/.test($K.url)) | |
$K.window.onReady('w', | |
function ($w, $var) { | |
if (!$var.loadVPage) | |
return; | |
// select parent window's elements | |
$K.listen($var.document.querySelectorAll(match_pattern), null, google_url_clean, { init : true }); | |
} | |
); | |
else | |
$K.listen(match_pattern, null, google_url_clean, { init : true }); | |
} | |
// Google Groups | |
else if (/:\/\/groups\.google\.com\/(forum|group)\/.+/.test($K.url)) { | |
$K.debug('Straight Google [Groups] is now loaded'); | |
// for old Google Groups template | |
if (/groups\.google\.com\/group\/.+/.test($K.url)) | |
common_clean_job(); | |
} | |
// Google Bookmarks | |
else if (/:\/\/www\.google\.com\/bookmarks\/.*$/.test($K.url)) { | |
$K.debug('Straight Google [Bookmarks] is now loaded'); | |
$K.listen('.result a[id^="bkmk_href_"]', null, google_url_clean, { init : true }); | |
} | |
// Google Web History | |
else if (/:\/\/www\.google\.com\/history\/.*$/.test($K.url)) { | |
$K.debug('Straight Google [Web History] is now loaded'); | |
common_clean_job(); | |
} | |
// Google Image Search | |
else if (/:\/\/(www|encrypted|ipv6)\.google\.[\w.]+\w\/(imghp\?.+|search(\?|#)(.+&)*tbm=isch(&.+)*)$/.test($K.url)) { | |
$K.debug('Straight Google [Image] is now loaded'); | |
var refUrl = 'ref-url'; | |
function img_search_clean() { | |
// for Image links | |
var cur_expanded = $K.select('#rg_h[data-initialized="1"]'); | |
if (!cur_expanded) | |
return; | |
var span = cur_expanded.querySelector('.rg_hr span#rg_hr'); | |
var rg_hta = cur_expanded.querySelector('#rg_ht a#rg_hta'); | |
var clean_href = rg_hta.href; | |
var rg_l = $K.select('#ires a.rg_l[href="'+ clean_href +'"]['+ refUrl +']'); | |
if (!clean_href || !rg_l) | |
return; | |
var ref_url = rg_l.getAttribute(refUrl); | |
rg_hta.href = get_google_url(ref_url, 1); | |
if (!span) | |
return; | |
var a = $$d.createElement('a'); | |
a.textContent = span.textContent; // copy link | |
a.href = 'http://'+ a.textContent; | |
var link = $$d.createElement('a'); | |
link.href = ref_url; | |
link.textContent = '[link]'; | |
span.innerHTML = ''; | |
span.appendChild(a); | |
// two space | |
span.appendChild($$d.createTextNode('\u00a0\u00a0')); | |
span.appendChild(link); | |
} | |
// text css style | |
GM_addStyle('.rg_hr span#rg_hr a{ color: #093; white-space: nowrap; text-decoration: none; }'); | |
$K.url.onHashChange(function () { | |
$K.listen( | |
"#rg_s", | |
"DOMNodeInserted", | |
function () { | |
// before expanding | |
$K.each( | |
$K.selectAll('#ires a.rg_l[href*="/imgres?"]'), | |
function () { | |
this.setAttribute(refUrl, this.href); // straight google - url | |
google_url_clean.call(this, 2); | |
} | |
); | |
}, | |
{ init: true } | |
); | |
$K.listen( | |
"#rg_s", | |
"DOMSubtreeModified", | |
img_search_clean | |
); | |
}, true); | |
} | |
// Google Shopping | |
else if (/:\/\/www\.google\.com\/(products\/catalog\?|shopping\/offerdetails\?|prdhp).*/.test($K.url)) { | |
$K.debug('Straight Google [Shopping] is now loaded'); | |
common_clean_job(); | |
// Show All # function | |
if (/\/products\/catalog\?/.test($K.url)) | |
$K.window.onReady('showPlusBox', | |
(function () { | |
var originFunc = null; | |
return function ($w, $var) { | |
originFunc = $var; | |
$w.showPlusBox = function () { | |
originFunc.apply(this, $K.utils.toArray(arguments)); | |
common_clean_job(); | |
} | |
}; | |
})() | |
); | |
} | |
// Google Web Search | |
else if (/:\/\/(www|encrypted|ipv6)\.google\.[\w.]+\w\/(search|webhp\?.+|(search|webhp)?(\?|#)(.+&)*(q|tbs|as_q)=.+)?$/.test($K.url)) { | |
$K.debug('Straight Google [Web Search] is now loaded'); | |
function search_clean() { | |
// image redirection | |
$K.each( | |
$K.selectAll('#ires a[href^="/url?"]'), | |
google_url_clean | |
); | |
} | |
// do a deep clean, kill the rwt function | |
$K.window.onReady( | |
'rwt', | |
function ($w) { | |
$w.rwt = function ($_self) { | |
google_url_clean.call($_self); | |
$_self.removeAttribute('onmousedown'); | |
return true; | |
}; | |
}, | |
{ | |
test : function (w) { | |
return /google/i.test(''+ w['rwt']); | |
} | |
} | |
); | |
// for Google Instant | |
$K.url.onHashChange(search_clean, true); | |
// be cool with AutoPager | |
$K.listen("#cnt.big", "DOMNodeInserted", search_clean); | |
} | |
// for Youtube | |
else if (/:\/\/(\w+\.)*youtube\.com\//.test($K.url)) { | |
$K.debug('Straight Google [Youtube] is now loaded'); | |
var YOUTUBE_REDIRECT_CLASS = '.yt-uix-redirect-link'; | |
$K.each( | |
$K.selectAll(YOUTUBE_REDIRECT_CLASS), | |
function () { | |
$K.css.remove(this, YOUTUBE_REDIRECT_CLASS); | |
$K.debug("Redirection of link ["+ this.href +"] is now removed."); | |
} | |
); | |
} | |
} | |
return { | |
start : _start | |
}; | |
})(document); | |
// delay for 1 sec | |
setTimeout(StraightGoogle.start, 800); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment