Search On Google - Navigation 0.4.2

By littlespark Last update Nov 3, 2009 — Installed 333 times. Daily Installs: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 2, 5, 1, 0, 4, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 2, 0, 0

There are 9 previous versions of this script.

Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)

/*
	Search on Google - Navigation 
	First release: 28 Dec 2008 v0.1.0 (Greasemonkey version)
	
	UPDATES 
	* * * * * * 
	[ 3 Nov 2009 ]
	v.0.4.2 - [ + ] When in Navigation-Mode, pressing the refresh key 'x' will rebuild the hints nodes
	v.0.4.1 - [ + ] Green will now open the link in the current tab
	v.0.4.0 - [ + ] Highlight hint tag with black blackground to show current selected link 
	v.0.3.9 - [ + ] When in Navigation-Mode, pressing keyboard hint of form elements will bring focus to that element and back to Query-Mode
	v.0.3.8 - [ - ] When in Navigation-Mode, pressing the magicKey will no longer bring focus to the query box 
	
	[ 27 Feb 2009 ]
	v.0.3.7 - [ + ] Toggle visibility of hints in navigation mode with the holding down of g, w or r(related hints to results)
	v.0.3.6 - [ + ] Add related hints to results
	v.0.3.5 - [ + ] Additional hints at Google Bar (g), Summary Bar (w) and section on related searches from google (s)
	v.0.3.4 - [ + ] Added found unknown results (youtube entries) to the normal numbering indexing
	v.0.3.3 - [ * ] Tighter control in listening to keydown presses
	v.0.3.2 - [ * ] Tighter control in starting the run of the script
	v.0.3.1 - [ * ] Tidy codes for easier maintenance and better speed. Use of "common code".
	
*/

// ==UserScript==
// @name           Search On Google-n
// @namespace      http://userscripts.org/scripts/review/39358
// @description    Be mouseless! Pure keyboard navigation on google search pages. Quick jump to form elements too! Just two hot keys! Simple and straightforward.
// @include        http://www.google.*/search*
// @exclude
// ==/UserScript==

if (top != self) return;

// MAIN SCRIPT
var sog_n = {
	
	// USER SETTINGS
	nextKey: "0", 
	
	// GLOBAL VALUES
	displayNumber: null, startNumber: null, 
	
	init: function() {
		
		// test page
		if (!cc.$('#res')) return;

		// set values for the 'next' hint
		var numNode = cc.$2("//input[@name='num']", document, 0); // initialize result number
		sog_n.displayNumber = numNode ? parseInt(numNode.value) : 10;
		
		var re = /\?*&*start=(\d+)/; // initialize start number
		sog_n.startNumber = re.test(location.href) ? parseInt(re.exec(location.href)[1]) : 0;
		
		// start script
		KNS.init();
		sog_n.localValues();
		sog_n.hintTags.css();
		sog_n.hintTags.init();
		
		// add keydown listener
		document.addEventListener('keydown', function(e) {
			var keyPressed = String.fromCharCode(e.which).toLowerCase();
			if (KNS.magicKeyEnabled && keyPressed == sog_n.nextKey.toLowerCase()) { // when next key is pressed
				document.location = sog_n.startNumber == 0 ? document.location.href.replace(/\?/,"?start=" + sog_n.displayNumber + "&") : document.location.href.replace(/start=.*?&/, "start=" + (sog_n.displayNumber + sog_n.startNumber) + "&");
			} else {
				KNS.event.keydown(e);
			}
		}, false);
			
		// THE "SCRIPT VERSION CHECKER"
		GM_registerMenuCommand("Search On Google - Navigation (Settings)", SVC.versionInfo.manualChecking);
		SVC.versionInfo.autoChecking();
	},
	
	localValues: function () {
		var array = [ 
			['hintsGoogleBarVisible', 'boolean', true],
			['hintsFormVisible', 'boolean', true],
			['hintsSummaryBarVisible', 'boolean', true],
			['hintsRelatedToResultsVisible', 'boolean', true]
			];
	
		for (var i=0; i<array.length; i++) {
			if (typeof GM_getValue(array[i][0]) != array[i][1]) GM_setValue(array[i][0], array[i][2]);
		}
	},
	
	hintTags: {
		
		init: function () {
			sog_n.hintTags.atLinks();
			sog_n.hintTags.atForm();
			sog_n.hintTags.atResults();
			sog_n.hintTags.atOptions();
		},

		css: function () {
			KNS.hintTags.css();
			GM_addStyle(
				'li h3 spanhint { background:transparent; font-size:75%; padding-left:5px; padding-right:5px; vertical-align:super; display:inline } ' + 
				
				'#gbar spanhint, #gb spanhint, #tbd spanhint, #tsf spanhint, #ssb spanhint, #brs spanhint, li > spanhint, li *:not(h3) spanhint { position:absolute; border:1px solid silver; font-size:11px; padding-left:3px; padding-right:1px; margin-left:-5px; margin-top:-7px } ' +
				//'#gbar spanhint.rest, #gb spanhint.rest, #tsf spanhint.rest, #ssb spanhint.rest, #brs spanhint.rest, li > spanhint.rest, li *:not(h3) spanhint.rest { display:none } ' +
				
				'#gbar spanhint, #gb spanhint, #tsf spanhint, #gb spanhint, #tbd spanhint { z-index:99 } ' + 
				'#gbar spanhint, #gb spanhint, #tsf spanhint, #ssb spanhint, #brs spanhint, #tbd spanhint { letter-spacing:1px } ' +
				
				'#gbar spanhint, #gb spanhint { visibility:' + (GM_getValue('hintsGoogleBarVisible') ? 'visible' : 'hidden') + ' } ' +
				'#tsf spanhint { visibility:' + (GM_getValue('hintsGoogleBarVisible') ? 'visible' : 'hidden') + ' } ' +
				'#ssb spanhint { visibility:' + (GM_getValue('hintsSummaryBarVisible') ? 'visible' : 'hidden') + ' } ' +
				'li > spanhint, li *:not(h3) spanhint { visibility:' + (GM_getValue('hintsRelatedToResultsVisible') ? 'visible' : 'hidden') + ' }');
		},
	
		atLinks: function () {
			
			try { // at google bar
				var lastHint;
				cc.loop(cc.$("#gbar:a"), function () { 
					if (cc.node.parentNode.id != "gbi") {
						KNS.hintTags.build("g" + (cc.i == 0 ? "" : cc.i), cc.node); 
						lastHint = cc.i + 1;
					} 
				});
				
				cc.loop(cc.$("#gb:a"), function () { 
					KNS.hintTags.build("g" + (cc.i+lastHint == 0 ? "" : cc.i+lastHint), cc.node); } );
				
			} catch (err) {}
			
			try { // at summary bar
				cc.loop(cc.$('#prs:a'), function () { 
					KNS.hintTags.build("w" + (cc.i == 0 ? "" : cc.i), cc.node); } );
			} catch (err) {}
			
			try { // at summary bar (definitions)
				cc.loop(cc.$2(".//p//a", document.getElementById('ssb')), function () { 
					KNS.hintTags.build("d" + (cc.i == 0 ? "" : cc.i), cc.node); } );
			} catch (err) {}
			
			try { // extra info
				cc.loop(cc.$2("div[@class='e']//a", document.getElementById('res')), function () { 
					KNS.hintTags.build("e" + (cc.i == 0 ? "" : cc.i), cc.node); } );
			} catch (err) {}
			
			try { // related search section
				cc.loop(cc.$("#brs:a"), function () { 
					KNS.hintTags.build("s" + (cc.i+1), cc.node); } );
			} catch (err) {}
			
		},
		
		atForm: function () {
			var count = -1;
			try {
				cc.loop(document.forms[0].elements, function () { 
					if (cc.node.type != "hidden") 
						KNS.hintTags.build("f" + (++count == 0 ? "" : count), cc.node); 
				} );
			} catch (err) {}
			
			try {
				cc.loop(cc.$('#sff:a'), function () { 
					KNS.hintTags.build("f" + (++count == 0 ? "" : count), cc.node); 
				} );
			} catch (err) {}
		},
		
		atResults: function () {
			
			var count = 0, unknownCount = 1, resultNodes, videoLinkNodes, videoLinkNode, hint;
			resultNodes = cc.$2("//li//h3[@class='r']", document.getElementById('res'));

			var re = /\?*&*num=(\d+)/;
			var targetNum;
			re.test(location.search) ?	targetNum = parseInt(re.exec(location.search)[1]) : targetNum = 10;
			
			function related() {
				//GM_log((cc.i+1));
				var child = 1;
				
				// related links before h3 (favicons-SOG-i)
				var parent = cc.node.parentNode;
				if (parent.tagName == "LI") {
					var prevS = cc.node.previousSibling;
					if (prevS) KNS.hintTags.build(hint + "." + child++, prevS);
				} else {
					// while (parent = parent.parentNode) { if (parent.tagName == "LI" || parent.id == "res") break; }
					// var favicon = cc.$('a:0', parent);
					// if (favicon) KNS.hintTags.build(hint + "." + child++, favicon);
				}
				
				// related links after h3
				var nextS = cc.node.nextSibling;
				
				while (nextS) {
					if (!nextS.tagName) { nextS = nextS.nextSibling; continue }
					var relatedLinks = nextS.getElementsByTagName('A');
					for (var a=0; a<relatedLinks.length; a++) {
						//GM_log((cc.i+1) + " hint: " + hint + "." + child++ + " : " + relatedLinks[a].innerHTML);
						KNS.hintTags.build(hint + "." + child++, relatedLinks[a]);
					}
					nextS = nextS.nextSibling;
				}
			}
			
			if (resultNodes.snapshotLength == targetNum) {
				cc.loop(resultNodes, function () { 
					hint = cc.i+sog_n.startNumber+1; 
					KNS.hintTags.build(hint, cc.node.firstChild); 
					related();
				} );
				return;
			}

			var array = [
				[/.+youtube.com\/watch/i, ''],
				[/.+books\.google/i, 'b'],
				[/.+blogsearch\.google/i, 'bl'],
				[/.+images\.google/i, 'i'],
				[/.+maps\.google/i, 'm'],
				[/.+news\.google/i, 'n'],
				[/.+google\..+\/products\?/i, 's'],
				[/.+video\.google/i, 'v']
				];
			
			cc.loop(resultNodes, function () { 
			
				var link = cc.node.getElementsByTagName("A")[0];
				for ( i = 0; i < array.length; i++) {
					if (array[i][0].test(link.href)) {
						hint = array[i][1] == "" ? ++count+sog_n.startNumber : array[i][1];
						KNS.hintTags.build(hint, link); 
						if (array[i][0] == /.+video\.google/i) {
							videoLinkNodes = cc.node.nextSibling.getElementsByTagName('a');
							for (var j = 0; j < videoLinkNodes.length; j ++ ) {
								videoLinkNode = videoLinkNodes[j];
								if (j%2 == 1) KNS.hintTags.build(++count+sog_n.startNumber, videoLinkNode); 
							} 
						}
						break;
					}
					if (i == array.length - 1) {
						hint = cc.node.parentNode.nodeName == "LI" ? ++count+sog_n.startNumber : "u" + ++unknownCount;
						KNS.hintTags.build(hint, link);
					}
					
				}
				
				related();
			} );	
	},
		
		atOptions: function () {
			try {
				cc.loop(cc.$2("//div[@class='tbou']//a", document.getElementById('tbd')), function () { 
					KNS.hintTags.build("o" + (cc.i == 0 ? "" : cc.i), cc.node); } );
			} catch (err) {}
		},
	},
		
	toggle: {
		hintVisibility: function () {
			if (GM_getValue('visibilityTarget') == "") return;
			target = GM_getValue('visibilityTarget');
			
			switch(target) {
				case 'ggggggg':
					GM_setValue('hintsGoogleBarVisible', !GM_getValue('hintsGoogleBarVisible'));
					GM_addStyle('#gbar spanhint, #gb spanhint { visibility:' + (GM_getValue('hintsGoogleBarVisible') ? 'visible' : 'hidden') + ' }');
					break;
				case 'fffffff':
					GM_setValue('hintsFormVisible', !GM_getValue('hintsFormVisible'));
					GM_addStyle('#tsf spanhint { visibility:' + (GM_getValue('hintsFormVisible') ? 'visible' : 'hidden') + ' }');
					break;    
				case 'wwwwwww':
				case 'ddddddd':
					GM_setValue('hintsSummaryBarVisible', !GM_getValue('hintsSummaryBarVisible'));
					GM_addStyle('#ssb spanhint { visibility:' + (GM_getValue('hintsSummaryBarVisible') ? 'visible' : 'hidden') + ' }');
					break;
				case 'rrrrrrr':
					GM_setValue('hintsRelatedToResultsVisible', !GM_getValue('hintsRelatedToResultsVisible'));
					GM_addStyle('li > spanhint, li *:not(h3) spanhint { visibility:' + (GM_getValue('hintsRelatedToResultsVisible') ? 'visible' : 'hidden') + ' }');
			}
			
		},	
	},	
};

// KEYBOARD NAVIGATION SYSTEM
// VERSION AS AT 3 NOV 2009
var KNS = {
	
	// USER SETTINGS
	magicKeyUnicode: 120, navKey: "z", refreshKey: "x", hintReadSpeed: 800,
	openLeisure: "blue", openCurrent: "green", openTab: "red", 
	
	// GLOBAL VALUES
	magicKeyEnabled: false, lastHintPress: null, formElement: null, processFlag: false, timer: null, keypressed: null,
	
	// SYCHRONIZATION
	setValue: GM_setValue('visibilityTarget', ''),
	visibilityFunction: function() { sog_n.toggle.hintVisibility(); },
	buildHintTagsFunction: function() { sog_n.hintTags.init(); },
		
	init: function () {
		var array = [ 
			//['magicKey', 'number', KNS.magicKeyUnicode],
			//['navigationKey', 'string', KNS.navKey],
			['openType', 'string', KNS.openLeisure]
			];
	
		for (var i=0; i<array.length; i++) {
			if (typeof GM_getValue(array[i][0]) != array[i][1]) GM_setValue(array[i][0], array[i][2]);
		}
	},
	hintTags: {
		css: function () {
			GM_addStyle(
				'spanhint { background:white; opacity:0.8; -moz-border-radius:5px 5px 5px 5px; display:none } ' + // all hints
				'spanhint.focus { background:black; color:white } ');
		},
		build: function (hintText, targetNode) {
			var newTag = document.createElement('spanhint');
			newTag.id = "tagHint" + hintText;
			
			var parent = targetNode.parentNode;
			while (parent) {
				if (parent.tagName == "TD") break;
				parent = parent.parentNode;
			}
			if (!parent) newTag.style.left = targetNode.offsetLeft + "px";
			newTag.innerHTML = hintText; 
			targetNode.parentNode.insertBefore(newTag, targetNode);
			
			// add focus listener to links
			// used to retrieve the last hint highlight
			targetNode.addEventListener('focus', KNS.event.focus, false);
		},
		refresh: function () {
			var hintNodes = document.getElementsByTagName('SPANHINT');
			while (hintNodes.length > 0) hintNodes[0].parentNode.removeChild(hintNodes[0]);
			KNS.buildHintTagsFunction();
		}
	},
	toggle: {
		hintStyle: function () {
			if (!KNS.magicKeyEnabled) { 
				GM_addStyle('spanhint { font-weight:inherit; color:inherit; display:none }');
				if (KNS.lastHintPress) KNS.lastHintPress.setAttribute('class', '');
			} else {
				GM_addStyle('spanhint { font-weight:bolder; color:' + GM_getValue("openType") + '; display:inline }');
				if (KNS.lastHintPress) KNS.lastHintPress.setAttribute('class', 'focus');
			}
		},
		magicKey: function () {
			KNS.magicKeyEnabled = !KNS.magicKeyEnabled;
			KNS.toggle.hintStyle();
		},
		navKey: function () {
			switch(GM_getValue('openType')) {
				case KNS.openLeisure: GM_setValue('openType', KNS.openCurrent); break;
				case KNS.openCurrent: GM_setValue('openType', KNS.openTab); break;
				case KNS.openTab: GM_setValue('openType', KNS.openLeisure);
			}
			KNS.toggle.hintStyle();
		},
	},
	event: {
		focus: function (e) {
			var hintPressed = e.target.previousSibling;
			if (hintPressed.tagName != "SPANHINT") return;
			
			//remove previous highlight and set the new highlight
			if (KNS.lastHintPress) KNS.lastHintPress.setAttribute('class', '');
			KNS.lastHintPress = hintPressed;
			if (KNS.magicKeyEnabled) hintPressed.setAttribute('class', 'focus');
		},
		keydown: function (e) {
			// activate form element
			if (KNS.formElement && KNS.formElement.hasAttribute('onkeypress')) KNS.formElement.removeAttribute('onkeypress');
			
			// when magic key is pressed
			if (e.which == KNS.magicKeyUnicode) { KNS.toggle.magicKey(); return; }
			
			// do nothing when magic key isn't enabled or certain keys are pressed
			if (!KNS.magicKeyEnabled || e.ctrlKey || e.shiftKey || e.altKey || e.metaKey 
				|| e.which == 9 || e.which == 13) return; // tab: 9, enter: 13
			
			// if current target is a form element, set value
			e.target.form ? KNS.formElement = e.target : KNS.formElement = null;
			
			var keyPressed = String.fromCharCode(e.which).toLowerCase();
			if (keyPressed == KNS.navKey.toLowerCase()) { // when leisure or quick key is pressed
				KNS.toggle.navKey(); 				
			} else if (keyPressed == KNS.refreshKey.toLowerCase()) { // refresh
				KNS.hintTags.refresh();
			} else { // other keys
				KNS.checkKeyPressed(e, keyPressed);
			}
			
			if (KNS.formElement) KNS.formElement.setAttribute('onkeypress', 'return false');
		},
	},
	checkKeyPressed: function (e, keyPressed) {
		function timerReachedAction() {
			if (!KNS.keypressed || KNS.processFlag) return;
			var re = /^(g{7}|f{7}|w{7}|d{7}|r{7})/;
			if (re.test(KNS.keypressed)) {
				KNS.processFlag = true;
				GM_setValue('visibilityTarget', re.exec(KNS.keypressed)[1]);
				KNS.visibilityFunction();
				
				setTimeout(function() {
					KNS.processFlag = false;
					KNS.keypressed = null;
				}, 1200);
			} else {
				var hintPressed = cc.$('#tagHint' + KNS.keypressed);
				if (hintPressed) {
					var next = hintPressed.nextSibling;
					next.focus();
					if (next.form) {
						KNS.toggle.magicKey();
					} else {
						switch(GM_getValue('openType')) {
							case KNS.openCurrent: cc.click(next); break;
							case KNS.openTab: GM_openInTab(next.href);
						}
					}
				}
				KNS.keypressed = null;
			}
		}
		if (KNS.keypressed) {
			KNS.keypressed += e.which == 190 ? "." : keyPressed;
			KNS.timer = setTimeout(timerReachedAction, KNS.hintReadSpeed);
		} else {
			KNS.keypressed = keyPressed;
			KNS.timer = setTimeout(timerReachedAction, KNS.hintReadSpeed);
		}
	},
};

// COMMON CODE
// VERSION AS AT 1 NOV 2009
var cc = {
	newNode: null,
	$: function (x, c) { // dom
		if (!c) c = document;
		re = /(#|^)(.+?)(:|$)(.+?)(:|$)(.*$)/;
		if (!re.test(x)) re = /(#|^)(.+?)(:|$)(.*$)/;
		//id
		if (re.exec(x)[1] == "#") { 
			if (re.exec(x)[6]) return c.getElementById(re.exec(x)[2]).getElementsByTagName(re.exec(x)[4].toUpperCase())[re.exec(x)[6]];
			if (re.exec(x)[4]) return c.getElementById(re.exec(x)[2]).getElementsByTagName(re.exec(x)[4].toUpperCase());
			if (re.exec(x)[2]) return c.getElementById(re.exec(x)[2]);
		}
		
		//tagname
		if (re.exec(x)[4]) return c.getElementsByTagName(re.exec(x)[2].toUpperCase())[re.exec(x)[4]];
		return c.getElementsByTagName(re.exec(x)[2].toUpperCase());
		
	},
	
	$2: function (x, c, n) { // xpath
		try {
			if (typeof n == "number") return document.evaluate(x, c || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(n);
			return document.evaluate(x, c || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		} catch (err) {GM_log("err: " + err + ": " + x + ": " + c + ": " + n);}
	},
	
	loop: function (nodes, func) {
		if (!nodes) return;
		if (nodes.length > 0) {
			for (this.i=0; this.i<nodes.length; this.i++) { this.node = nodes[this.i]; func(); }
			return;
		} 
		if (nodes.snapshotLength > 0) {
			for (this.i=0; this.i<nodes.snapshotLength; this.i++) {
				this.node = nodes.snapshotItem(this.i); func(); }
			return;
		}
	},
	
	$$: function (tagName, nodeId, styleAttr, innerText, parentNode, position, sibling) {
		cc.newNode = document.createElement(tagName);
		if (nodeId) cc.newNode.id = nodeId;
		if (styleAttr) cc.newNode.setAttribute('style', styleAttr);
		if (innerText) cc.newNode.innerHTML = innerText;
		if (position == 0 && !sibling) parentNode.appendChild(cc.newNode); 
		if (position == 1 && !sibling) parentNode.insertBefore(cc.newNode, parentNode.firstChild);
		return cc.newNode;
	},

	script: function (scriptText) {
		var node = document.createElement('script');
		script_tag.type = 'text/javascript';
		script_tag.innerHTML = scriptText;
		document.getElementsByTagName('head')[0].appendChild(script_tag);
	},
	
	click: 	function(link) {
		var flag = false;
		if (document.createEvent) {
			var event = document.createEvent("MouseEvents");
			event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
			flag = !link.dispatchEvent(event);
		}
		if (!flag) window.location = link.href;
	},
};

// SCRIPT VERSION CHECKER
// VERSION 0.1.0
var SVC = {

	currentVersion: "0.4.2",
	scriptName: "Search On Google - Navigation",
	scriptNum: 39358,
	
	currentDate: null,
	latestVersion: null,
	userRequestCheck: null,
	
	versionInfo: {
	
		init: function () {
			SVC.currentDate = new Date();
			var cv = parseInt( String(/[1-9].*/.exec(SVC.currentVersion)).replace(/\./g, "") );
			
			// INITIALIZE LOCAL VALUES (FOR FIRST-TIME USE)
			if (!GM_getValue("latest")) GM_setValue("latest", cv );
			if (!GM_getValue("notified")) GM_setValue("notified", false);
			if (!GM_getValue("lastChecked")) GM_setValue("lastChecked", (SVC.currentDate.getTime() - 1000*60*60*25) + "");

			// UPDATE LOCAL VALUES (FOR FIRST-TIME USE AFTER REINSTALL NEWER VERSION)
			if (GM_getValue("latest") < cv) {
				GM_setValue("latest", cv);
				GM_setValue("notified", false);
				GM_setValue("lastChecked", SVC.currentDate.getTime() + "");
			}
		},
		
		verifyNotification: function() {
			SVC.userRequestCheck = false;
			var sp = SVC.currentDate.getTime() - parseInt(GM_getValue("lastChecked"));
			
			// CHECK SOURCE IF USER HAS BEEN NOTIFIED OF AN UPDATED VERSION BEFORE AND 14 DAYS HAVE PASSED
			if (GM_getValue("notified")) {
				if ( sp / (1000*60*60*24) > 14 ) SVC.versionInfo.startXmlHttp();
				
			// CHECK SOURCE FOR THE LATEST VERSION IF ONE DAY HAS PASSED SINCE LAST CHECKED
			} else {
				if ( sp / (1000*60*60*24) > 1 ) SVC.versionInfo.startXmlHttp();
			}		
		},
		
		startXmlHttp: function () {	
			try {
				GM_xmlhttpRequest({
					method: 'GET', url: "http://userscripts.org/scripts/show/" + SVC.scriptNum, 
					onload: function(responseDetails) {
						if (responseDetails.status == 404) {
						
							if (SVC.userRequestCheck) SVC.versionInfo.manualErrorMsg();

						} else if (responseDetails.status == 200) {
						
							var uv = SVC.versionInfo.processResponseText(responseDetails.responseText);
							if (uv) {
								SVC.updatedVersion = parseInt( uv.replace(/\./g, "") );
								SVC.versionInfo.compareVersions(SVC.updatedVersion);
							} else {
								if (SVC.userRequestCheck) SVC.versionInfo.manualErrorMsg();
							}
						}

					}
				});
			}
			catch(err) {
			}
		},
			
		processResponseText: function (responseText) {		
			var re = /<h1.+class=.?title.?>.+?(\s?[1-9].+)<\/h1>/;
			if (re.test(responseText)) return re.exec(responseText)[1];
		},

		compareVersions: function (updatedVersion) {
			
			// DO NOTHING IF NO CHANGE IN VERSIONS
			if (updatedVersion <= GM_getValue("latest")) {
				if (SVC.userRequestCheck) alert('Auto-check completed!\n---------------------------\n\nYou are using the latest greasemonkey script \n\n~ ' + SVC.scriptName + ' ~ version ' + SVC.currentVersion + '.\n\n  ');
				return;
			}
			
			// UPDATE LOCAL VALUES			
			if (String(updatedVersion).length == 2) updatedVersion = "0" + String(updatedVersion);
			SVC.latestVersion = String(updatedVersion).replace(/\B/g, ".");
			
			GM_setValue("notified", true);
			GM_setValue("lastChecked", SVC.currentDate.getTime() + "");
			
			// NOTIFY USER
			if (SVC.userRequestCheck) {
			
				var reply = confirm('Auto-check completed!\n---------------------------\n\nThe Greasemonkey Script ~ ' + SVC.scriptName + ' ~ has recently been updated to v.' + SVC.latestVersion + '. \n\nYou are currently using version ' + SVC.currentVersion + '.\nWould you like to visit the download page at userscript.org now?\n\n  ');
				
				if (reply) GM_openInTab("http://userscripts.org/scripts/show/" + SVC.scriptNum);
				
			} else {
			
				var reply = confirm('Latest news for Greasemonkey Scripts!\n-----------------------------------------------\n\nThe Greasemonkey Script ~ ' + SVC.scriptName + ' ~ has recently been updated to v.' + SVC.latestVersion + '. \n\nYour current working version is ' + SVC.currentVersion + '.\nWould you like to visit the download page at userscript.org now?\n\n  ');
				
				if (reply) GM_openInTab("http://userscripts.org/scripts/show/" + SVC.scriptNum);
			
			}
		},
		
		autoChecking: function () {
			SVC.versionInfo.init();
			SVC.versionInfo.verifyNotification();
		},
		
		manualChecking: function () {
			SVC.userRequestCheck = true;
			SVC.versionInfo.startXmlHttp();
		},

		manualErrorMsg: function () {
			var reply = confirm('Alert!\n-------\n\nAuto-checking for the latest version of the Greasemonkey Script ~ ' + SVC.scriptName + ' ~ has not been successful.\n\nYou may wish to try again later or visit the download page to check manually. For your information, your current working version is ' + SVC.currentVersion + '. \n\nWould you like to visit the download page at userscript.org now?\n\n  ');
			if (reply) GM_openInTab("http://userscripts.org/scripts/show/" + SVC.scriptNum);
		},
		
	}

};

window.addEventListener('load', sog_n.init, false);