﻿/*
Geocaching Waypoint Finder - v02.31 2011-09-08
(c) 2011, Prime Suspect Software

Greasemonkey user script: see http://greasemonkey.mozdev.org

This script adds a waypoint/travel bug ID search box to the left
hand menu on every page of the geocaching.com website. Home page
and search pages are excluded, as they already have a search box.

Change Log:

* (02.31) 2011-09-08 Change spacing of social media icons, so everything
	fits on one line again.

* (02.30) 2011-05-17 Added "Your Profile" to the "Your Stuff" menu.

* (02.20) 2011-05-07 Compacted "Your Stuff" menu to take up less screen space.

* (02.10) 2011-05-05 Added drop-down menu entry for uploading field notes.
	Added option to turn off the GCxxxx default in the input box.

* (02.00) 2011-04-28 Moved input box to header menu bar. Added "Your Stuff"
	drop-down menu, for quick access to pages. Menu items adopt localized
	titles, based on language settings, when you visit a menu page.

* (01.60) 2010-06-02 Update for site changes. Added auto update
	notification.

* (01.50) 2010-01-15 Update for site changes.

* (01.40) 2009-01-26 Travel bug owners no longer need to enter the
	tracking number when posting to their own bugs.

* (01.30) 2008-12-02 Added support for Tracking ID entry. When a
	tracking ID is entered, it will automatically be passed to the
	logging page, removing the need to enter it twice.

* (01.20) 2008-08-14 Minor fix to accomodate website changes.

* (01.10) 2007-10-10 Minor fix to accomodate website changes.

* (01.00) Initial release.


// ==UserScript==
// @name           GC Waypoint Finder
// @description    Adds Waypoint Finder box plus useful links to GC pages
// @version        02.31
// @namespace      http://gmscripts.locusprime.net/
// @include        http://*.geocaching.com/*
// @icon           http://gmscripts.locusprime.net/script_icons/mag_glass.png
// @require        VrChk.js
// ==/UserScript==

*/

// ------------------------Version Checking------------------------ //
fCheckScriptVersion('e1950af6-8b94-4c8b-ac1d-0be5cf384cac', '02.31');
// ------------------------Version Checking------------------------ //




	//  Get currently signed-on geocaching.com profile.
	var SignedInLink = document.evaluate(
			"//a[contains(@class, 'SignedInProfileLink')]",
			document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
			).singleNodeValue;
	if (SignedInLink) {
		var SignedInAs = SignedInLink.firstChild.data;
	} else {
		var SignedInLink = document.evaluate(
				"//a[contains(@class, 'CommonUsername')]",
				document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
				).singleNodeValue;
		if (SignedInLink) {
			SignedInAs = SignedInLink.title;
		}
	}
	if (SignedInAs) {
		SignedInAs = SignedInAs.replace(/<\&amp;>/g, '&');
	} else { return; }


	//  Get Show-Menu value, and set up menu option to change setting.
	var ShowYS = (GM_getValue('ShowMenu' + SignedInAs, 'On') == 'On');
	GM_registerMenuCommand('Show "Your Stuff" menu?', fSetShowMenu);

	//  Get Show GC value, and set up menu option to change setting.
	var ShowGC = (GM_getValue('ShowGC' + SignedInAs, 'On') == 'On');
	GM_registerMenuCommand('Show "GCxxxx" as default?', fSetShowGC);


	//  Find navagation container
	var e_menu_nav = document.getElementById("Navigation");
	if (e_menu_nav) {
		var e_menu = e_menu_nav.childNodes[1];
		if (e_menu.nodeName != 'UL') { return; }
	} else { return; }

	var MagGlassSrc =
		"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA" +
		"AXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAH" +
		"UwAADqYAAAOpgAABdwnLpRPAAAABl0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuODc7" +
		"gF0AAAPtSURBVDhPpZRbTFN3HMfdpg%2FbMmNMlizZsrgse%2BNhW7aH%2BbQXspABDyMO" +
		"NlAGCB2BKpObICAUWgItl1VsuRQECnSDQqWi5RYuVoJ0glA6Qa2rFUpLL5RbL9D2fHf%2B" +
		"dImpIg%2FzJN%2Bc%2Fz8nv8%2F%2F8%2F%2Bd8z9vHHrh4tY0Hvvk08%2B%2BcLpc31M%" +
		"2B3%2BdeL3XU5XYdcjicY06Xu399Y33ebrPaxUKu98XagDmrnP9Wnbg7qE02WC0buuscnH" +
		"yAkXtaDN59CPmYGq29SnAbpBtZnKudiemsb39iZB45EChs6fpKqlAqBiY0u8oZHVQaA2Yf" +
		"WaHW2jG9YMbwlBYt1yeQX92OtKIaVVza5eBXAn9v6PhIcmO0%2BZZS7Z7SLOOJwYGVNQom" +
		"O2C0UzDQY73Zg3uLNlSLx5FV1oJzBdWqU3Hnj78EvVhU%2FqagtfuHTsWdtYlZHfSrbhoC" +
		"mDeeZ3UdMNFZtlG4rV5DoUCB3AqxL%2B785fSXgIVcwfHadnlT78g0Fp%2FaaTNAt%2BrP" +
		"ks0PIkCyALlrjRRkt1eQUyHBb6yahz8mpB0LgHKuNH%2FMb5ZN909ooDc5YdsE1rb8AAMN" +
		"11uAZ1bsLURaoDMDk4s7KBb24VJFy9LplJxvAoCFVY0nSgUdmpvj92G0ubHuADadwMZ%2F" +
		"Wdv2W%2BppELHWGoFZnQ9XOiaQV9Vqpl%2FOqQBgOot%2FIqesXiMbUsFid2PLBWy7n4fM" +
		"CdxCmy%2FRposGQK0HBJI7YF2VmFNzSwOBjCzOh3QvlG29YzBatuDcAVy7%2FpAxgRMoMS" +
		"dt0JoAzTMKVc394DVd1zNzS78MMIxMvPBuan5lYUlNm3duQYcdDwWPD%2FB4QY%2F9YAcN" +
		"JZZk649WKIzPrEIoGQKvQdq%2F77dIW57MYAsXWnsGYTRbQVHYCwETKDElhmTLc0%2B2Ib" +
		"mlQlPPqIfNbw7dF%2FgzI%2FO9lEu8i7ncRmu7bBAG4yq8Xh98NHSXNiWGJrsP9xctkI%2" +
		"BqIZIOo0YsX45LzX4%2FNDR0%2FyMYy8z7IDWvoii7rH6jtqMPitFJzD14DPXCP5j5%2By" +
		"lujs%2Bia0CFaz0ju1lsoYd%2FrXvzTHxST0xMTAKTydwf%2Bsu5%2FKNJmeyIjBLBfHmD" +
		"FKKuYYjlSvw5MIXOgSmfuHfscV1H34Wk7PJUaW%2B%2FJeHsWYo21MXGxp6hoYdfebYZGU" +
		"WH0wq4QQXc%2BtPltZIUXt0fKfyGtpMSieRtUiQSiYJ4PJ6qsrISERERCAsLs0RHR%2F%2" +
		"BamJj4zoF%2FoIMe0lv9uqSkZJ7D4SAyMhLh4eFmAv3fQFKYnJwczGazVcXFxXtQYvpaQN" +
		"ryCN277wiUmIaEhOC1gKSYQOPj44MZDMZ8VFTUX%2F8CmzoL%2BxPXAH4AAAAASUVORK5C" +
		"YII%3D";

	//  Add style for waypoint input box.
	GM_addStyle(".wpfinder {border: 2px solid rgb(118, 132, 84); margin-top: 2px; " +
			"border-radius:7px; -moz-border-radius:7px; background-color:rgb(227,221,194);" +
			"padding:1px; }");


	//  Find social media paragraph and compress icon spacing.
	var pars = document.getElementsByClassName('SocialMediaIcons');
	if (pars) {
		var par = pars[0];
		var ic = par.childNodes.length - 1;
		for (var i = ic; i >= 0; i--) {
			var cn = par.childNodes[i];
			if (cn.nodeName == '#text') {
				removeNode(cn);
			} else if (cn.nodeName == 'A') {
				cn.style.marginLeft = '4px';
			}
		}
	}


	//  Get current URL.
	var UrlHere = document.URL;

	//  If tracking item by tracking ID, or owns tracking item, then add to log link.
	if (UrlHere.match(/\/track\/details\.aspx/i)) {
		//  Check for owned item.
		var e_lblTBID = document.getElementById("ctl00_ContentBody_lblTBID");
		if (e_lblTBID) {
			var tracker = e_lblTBID.childNodes[1].firstChild.data;
		} else {
			var tracker = UrlParm('tracker');
		}
		if (tracker && (!tracker.match(/^TB.*/i))) {
			var e_LogLink = document.getElementById("ctl00_ContentBody_LogLink");
			if (e_LogLink) {
				e_LogLink.href += '&tracker=' + tracker;
			}
		}

	//  If tracking log entry, and tracker number in URL, insert into entry box.
	} else if (UrlHere.match(/\/track\/log\.aspx\?wid=.*?&tracker=/i)) {
		var tracker = UrlParm('tracker');
		var e_tbCode = document.getElementById("ctl00_ContentBody_LogBookPanel1_tbCode");
		if (e_tbCode) {
			e_tbCode.value = tracker;
		}
	}



	//  Create new list entry for input box.
	var liFinder = document.createElement('li');

	//  Create form.
	var form_wpFinder = document.createElement('form');
	form_wpFinder.id = 'form_wpFinder';
	form_wpFinder.name = 'form_wpFinder';
	liFinder.appendChild(form_wpFinder);
	form_wpFinder.action = 'javascript:func_wpFinder()';

	//  Create script.
	var script_wpFinder = document.createElement('script');
	script_wpFinder.language = "javascript";
	script_wpFinder.type = "text/javascript";
	script_wpFinder.appendChild(document.createTextNode(
			"function func_wpFinder() { \n" +
			"	xinput_wpFinder = document.getElementById('input_wpFinder'); \n" +
			"	xwp = xinput_wpFinder.value.toUpperCase(); \n" +
			"	for (var j = 0; j < xwp.length; j++) { \n" +
			"		if (xwp.charCodeAt(j) != 32) { \n" +
			"			xwp = xwp.substring(j); \n" +
			"			j = xwp.length; \n" +
			"		} \n" +
			"	} \n" +
			"	if (xwp.match(/^GC.*/)) { \n" +
			"		xwpurl = '../seek/cache_details.aspx?wp=' + xwp; \n" +
			"	} else { \n" +
			"		xwpurl = '../track/details.aspx?tracker=' + xwp; \n" +
			"	} \n" +
			"	window.location.assign(xwpurl); \n" +
			"} \n"
	));
	form_wpFinder.appendChild(script_wpFinder);


	//  Create input box.
	var input_wpFinder = document.createElement('input');
	input_wpFinder.type = 'text';
	input_wpFinder.id = 'input_wpFinder';
	input_wpFinder.setAttribute('class', 'wpfinder');
	input_wpFinder.title = 'Enter waypoint or travel bug ID to find';
	input_wpFinder.size = 10;
	input_wpFinder.maxLength = 8;
	input_wpFinder.style.fontWeight = 'bold';
	input_wpFinder.style.fontFamily = 'sans-serif';
	input_wpFinder.style.color = 'rgb(66, 66, 66)';
	form_wpFinder.appendChild(input_wpFinder);
	if (ShowGC) {
		input_wpFinder.defaultValue = 'GCxxxx';
		input_wpFinder.addEventListener('focus', rmvxxxx, false);
	}

	//  Add image trigger.
	var img_wpFinder = document.createElement('input');
	img_wpFinder.type = 'image';
	img_wpFinder.id = 'img_wpFinder';
	img_wpFinder.src = MagGlassSrc;
	img_wpFinder.title = 'Click to go to cache or travel bug page';
	img_wpFinder.border = 0;
	img_wpFinder.align = 'top';
	img_wpFinder.style.marginTop = '3px';
	img_wpFinder.style.marginLeft = '4px';
	form_wpFinder.appendChild(img_wpFinder);

	//  Add form to list.
	liFinder.appendChild(form_wpFinder);
	e_menu.appendChild(liFinder);





	//  If showing "Your Stuff" menu.
	if (ShowYS) {

		//  Determine type of membership. If not signed on, exit.
		//  The MembershipInformation code is a kludge to get around the profile block error
		//  on the membership details page. Can be removed if error fixed.
		var MembershipInformation = document.getElementById("ctl00_ContentBody_uxMembershipInformation");
		if (!MembershipInformation) {
			if (document.getElementById("ctl00_hlUpgrade")) {
				var PM = false;
			} else if (document.getElementById("ctl00_hlRenew")) {
				var PM = true;
			} else if (document.getElementById("ctl00_litPMLevel")) {
				var PM = true;
			} else { return; }
		} else {
			PM = (MembershipInformation.childNodes.length > 4);
		}


		//  Create array of menu urls as an index. DO NOT CHANGE ORDER. New entries can be
		//  added to the end of the array. This does not affect display order.
		var aMenuUrls = [
			'/account/default.aspx',
			'/bookmarks/',
			'/my/favorites.aspx',
			'/my/inventory.aspx',
			'/my/logs.aspx',
			'/my/myfriends.aspx',
			'/my/owned.aspx',
			'/my/statistics.aspx',
			'/my/watchlist.aspx',
			'/notify/default.aspx',
			'/pocket/default.aspx',
			'/my/uploadfieldnotes.aspx',
			'/profile/',
		];


		//  Get selected language.
		var selLanguage = document.getElementById("selected_language");
		if (selLanguage) {
			selLanguage = selLanguage.childNodes[1].firstChild.data;
			selLanguage = selLanguage.replace(/\u25bc/g,'').trim();
		} else { selLanguage = 'none'; }
		var sMenuTitles = GM_getValue(selLanguage, '');
		var aMenuTitles = sMenuTitles.split('\u00A7');

		//  Get URL path.
		var UrlPath = location.pathname;
		//  Update menu title with breadcrumb data, if this is a menu page.
		var j = aMenuUrls.indexOf(UrlPath);
		if (j >= 0) {
			var breadcrumb = document.getElementById("ctl00_Breadcrumbs");
			if (breadcrumb) {
				var bcTitle = breadcrumb.lastChild.firstChild.data.trim();
				if (bcTitle) {
					aMenuTitles[j] = bcTitle;
					sMenuTitles = aMenuTitles.join('\u00A7');
					GM_setValue(selLanguage, sMenuTitles);
				}
			}
		}



		//  Create new list entry for Your Stuff menu.
		var liNavProfile = document.getElementById("ctl00_liNavProfile");
		var liYourStuff = document.createElement('li');
		liYourStuff.setAttribute('class', 'hover');
		var aYourStuff = document.createElement('a');
		aYourStuff.appendChild(document.createTextNode('Your Stuff \u25bc'));
		aYourStuff.href = '#';
		aYourStuff.title = 'Your Stuff';
		aYourStuff.id = 'aYourStuff';
		aYourStuff.setAttribute('accesskey', 7);
		liYourStuff.appendChild(aYourStuff);
		insertAfter(liYourStuff, liNavProfile);

		//  Add Your Stuff menu items.
		var ulYourSubMenu = document.createElement('ul');
		ulYourSubMenu.setAttribute('class', 'SubMenu');
		liYourStuff.appendChild(ulYourSubMenu);

					fAddMenuItem('Your Account Details', 			'/account/default.aspx');
					fAddMenuItem('User Profile',					'/profile/');
					fAddMenuItem('Your Owned Geocaches',			'/my/owned.aspx');
					fAddMenuItem('Your Logs',						'/my/logs.aspx');
		if (PM) {	fAddMenuItem('Your Pocket Queries', 			'/pocket/default.aspx'); }
					fAddMenuItem('Upload Field Notes',				'/my/uploadfieldnotes.aspx');
		if (PM) {	fAddMenuItem('Bookmark Lists',					'/bookmarks/'); }
					fAddMenuItem('Your Watchlist', 					'/my/watchlist.aspx');
		if (PM) {	fAddMenuItem('Instant Notification Service',	'/notify/default.aspx'); }
		if (PM) {	fAddMenuItem('Favorites List', 					'/my/favorites.aspx'); }
					fAddMenuItem('Your Friends', 					'/my/myfriends.aspx');
		if (PM) {	fAddMenuItem('Your Statistics', 				'/my/statistics.aspx'); }
					fAddMenuItem('Your Trackable Item Inventory', 	'/my/inventory.aspx');

	}



	// ----------------------------- FUNCTIONS ------------------------------//



	//  Set option to initially hide or show inventory.
	function fSetShowMenu() {
		var ShowYSval = GM_getValue('ShowMenu' + SignedInAs, 'On');
		var Resp = confirm('Show the "Your Stuff" menu?\n\n' +
				'Click OK to turn Show "Your Stuff" Menu On.\n' +
				'Click CANCEL turn Show "Your Stuff" Menu Off.\n\n' +
				'Show "Your Stuff" Menu is currently turned ' + ShowYSval + '.');
		if (Resp) {
			ShowYSval = 'On';
		} else {
			ShowYSval = 'Off';
		}
		GM_setValue('ShowMenu' + SignedInAs, ShowYSval);
		alert('Show "Your Stuff" Menu has been turned ' + ShowYSval + '.\n\n' +
				'This change will appear when the page is refreshed.\n');
	}


	function fSetShowGC() {
		var ShowGCval = GM_getValue('ShowGC' + SignedInAs, 'On');
		var Resp = confirm('Show "GCxxxx" as the input default?\n\n' +
				'Click OK to turn "GCxxxx" as default On.\n' +
				'Click CANCEL to turn "GCxxxx" as default Off.\n\n' +
				'Use "GCxxxx" as default is currently turned ' + ShowGCval + '.');
		if (Resp) {
			ShowGCval = 'On';
		} else {
			ShowGCval = 'Off';
		}
		GM_setValue('ShowGC' + SignedInAs, ShowGCval);
		alert('Use "GCxxxx" as default has been turned ' + ShowGCval + '.\n\n' +
				'This change will appear when the page is refreshed.\n');
	}



	//  Function to Add items to Your Stuff menu.
	function fAddMenuItem(sTitle, sUrl) {
		//  Lookup URL in alternate language array. Use alternate, if found.
		var j = aMenuUrls.indexOf(sUrl);
		if (j >= 0) {
			if (aMenuTitles[j]) {
				sTitle = aMenuTitles[j];
			}
		}
		//  Create menu item.
		var newItem = document.createElement('li');
		var newLink = document.createElement('a');
		newLink.href = '..' + sUrl;
		newLink.title = sTitle;
		newItem.style.lineHeight = '0.75em';
		newLink.appendChild(document.createTextNode(sTitle));
		newItem.appendChild(newLink);
		ulYourSubMenu.appendChild(newItem);
	}



	//  Remove XXXX when entry box gets focus.
	function rmvxxxx() {
		if (input_wpFinder.value == input_wpFinder.defaultValue) {
			input_wpFinder.value = 'GC';
		}
	}



	//  Returns a URL parameter.
	//    ParmName - Parameter name to look for.
	//    IgnoreCase - (optional) *false, true. Ignore parmeter name case.
	//    UrlString - (optional) String to search. If omitted, document URL is used.
	function UrlParm(ParmName, IgnoreCase, UrlString) {
		var RegRslt, sc = '', RtnVal = '';
		if (IgnoreCase) {sc = 'i'}
		if(UrlString) {
			var PageUrl = UrlString;
		} else {
			PageUrl = document.location + '';
		}
		var ParmString = PageUrl.substring(PageUrl.indexOf('?') + 1);
		var RegEx1 = new RegExp('(^|&)' + ParmName + '=(.*?)(&|#|$)', sc);
		RegRslt = RegEx1.exec(ParmString);
		if (RegRslt) {RtnVal = RegRslt[2]}
		return RtnVal;
	}



	//	Insert element after an existing element.
	function insertAfter(newElement, anchorElement) {
		anchorElement.parentNode.insertBefore(newElement, anchorElement.nextSibling);
	}

	//  Insert element ahead of an existing element.
	function insertAheadOf(newElement, anchorElement) {
		anchorElement.parentNode.insertBefore(newElement, anchorElement);
	}


	//  Remove element and everything below it.
	function removeNode(element) {
		element.parentNode.removeChild(element);
	}

