// ==UserScript==
// @name           GC-Vote
// @namespace      http://dosensuche.de
// @include        http*://www.geocaching.com/seek/cache_details.aspx?*
// @include        http*://www.geocaching.com/my/*
// @include        http*://www.geocaching.com/map*
// @include        http*://www.geocaching.com/seek/nearest.aspx*
// @include        http*://www.geocaching.com/seek/gmnearest.aspx*
// @include        http*://www.geocaching.com/seek/log.aspx?*
// @include        http*://www.geocaching.com/seek/cdpf.aspx?*
// @include        http*://www.geocaching.com/bookmarks/view.aspx?*
// @include        http://*gcvote.de/*
// @include        http://*gcvote.com/*
// @include        http://*dosensuche.de/GCVote/*
// @description    displays average votes and lets users vote for the quality of caches on geocaching.com
// ==/UserScript==
//
// Author: guido.wegener@gmx.de
// Version 2.3

var version="2.3";

var voteServerBase="http://gcvote.com"; // connection to server
var GETVOTES=voteServerBase+"/getVotes.php";
var SETVOTE=voteServerBase+"/setVote.php";
var LISTVOTES=voteServerBase+"/listUserVotes.php";
var CHANGEPASSWORD=voteServerBase+"/changePassword.php";

var LOGGING=getLogging();
var HALFSTARS=getHalfstars();
var SORTSIDEBAR=getSortSidebar();

var logInLink;
var userName;
var unescapedUserName;
var loggedIn;
var securityState;
var translations;

log("start");
init();
var GCVoteAdvertisementDefault = "\n"+tl("(Rated %%% stars with [url=http://www.gcvote.com]GCVote[/url])");
// This string is just a default and is only used for the first install.
// "%%%" will be replaced by your selected vote and the resulting string is written to the log.
if(document.GCVoteMarker) {
	log("multiple instances running ("+document.GCVoteMarker+")");
}
else {
	document.GCVoteMarker=version;
	if(document.URL.search("gcvote.de")>=0 || document.URL.search("gcvote.com")>=0 || document.URL.search("dosensuche.de")>=0) displayVersionInfo();
	else if(!document.getElementById("ctl00_SiteContent_lblSubmitErrorInfo")) {
		if(document.getElementById("ctl00_LoginUrl")) logInLink=document.getElementById("ctl00_LoginUrl");
		if(document.getElementById("Header1_urlLogin")) logInLink=document.getElementById("Header1_urlLogin");
		if(!logInLink || !logInLink.parentNode.getElementsByTagName("a")[1]) {
			try {
				logInLink=document.getElementById("hd").getElementsByTagName("a")[1];
				if(logInLink.href=="http://www.geocaching.com/my/") {
					userName=logInLink.firstChild.nodeValue;
				}
			} catch(e) {userName=null;}
		}
		else {userName=logInLink.parentNode.getElementsByTagName("a")[0].firstChild.nodeValue;}

		log("userName="+userName+"  escaped:"+encodeURIComponent(userName));
		unescapedUserName=userName;
		if(userName) userName=encodeURIComponent(userName);

		if(userName && document.URL.search("www\.geocaching\.com\/my\/")>=0) {insertGCVoteMenu();}
		if(document.URL=="http://www.geocaching.com/my/owned.aspx" || document.URL=="http://www.geocaching.com/seek/nearest.aspx?u="+userName) {userName=null;}
		if(document.URL.search("cache_details\.aspx")>=0) {pageType="details";initDetailsPage();}
		else if(document.URL.search("cdpf\.aspx")>=0) {pageType="print";initPrintPage();}
		else if(document.URL.search("logs\.aspx")>=0) {pageType="loglist";initLongListPage();}
		else if(document.URL.search("owned\.aspx")>=0) {pageType="loglist";initListPage();}
		else if(document.URL.search("www.geocaching.com\/map")>=0) {pageType="gmnearestlist";initGMListPage();}
		else if(document.URL.search("nearest\.aspx")>=0) {pageType="nearestlist";initListPage();}
		else if(document.URL.search("\/my\/$")>=0 || document.URL.search("\/my\/#")>=0 || document.URL.search("\/my\/[dD]efault\.aspx")>=0) {pageType="overviewlist1";initListPage();}
		else if(document.URL.search("\/my\/geocaches\.aspx")>=0) {pageType="overviewlist2";initListPage();}
		else if(document.URL.search("\/log\.aspx")>=0) {pageType="logedit";initLogEditPage();}
		else if(document.URL.search("\/bookmarks\/view\.aspx")>=0) {pageType="bookmarks";initListPage();}
		else if(document.URL.search("\/my\/watchlist\.aspx")>=0) {pageType="watchlist";userName=null;initListPage();}
	}
}

function init() {
	translations=[
"(Rated %%% stars with [url=http://www.gcvote.com]GCVote[/url])",["(%%% Sterne bei [url=http://www.gcvote.com]GCVote[/url])","J'ai donné %%% à cette cache grâce à [url=http://www.gcvote.com]GCVote[/url]","(Votei %%% estrelas com o [url=http://www.gcvote.com]GCVote[/url])","(Uděleno %%% hvězdiček prostřednictvím [url=http://www.gcvote.com]GCVote[/url])","(Ocenione na %%% gwiazdek w [url=http://www.gcvote.com]GCVote[/url])","(Gewaardeerd met %%% Sterren via [url=http://www.gcvote.com]GCVote[/url]"],
"Unable to get votes from server! Errorcode ",["Fehler bei der Server-Abfrage: ","Impossible de récupérer les cotes sur le serveur! Code d'erreur :","Impossível obter votos do servidor! Errorcode","Chyba při získávání hodnocení ze serveru! ErrorCode:","Nie można pobrac głosów z serwera! Błąd","Kon geen verbinding maken met de GCVote server! Errorcode"],
"Your Account is password protected and you supplied no or the wrong password. If you did not register a password, please inform me: guido.wegener@gmx.de",["Dein Account ist mit einem Passwort geschützt und Du hast kein oder ein falsches Passwort angegeben.","Ce compte est protégé par mot de passe","A tua conta está protegida com password e não a introduziste ou está errada. Se não registaste uma password, por favor contacta-me: guido.wegener@gmx.de","Nevyplněné, nebo chybné heslo. V případě potíží mne kontaktujte: guido.wegener@gmx.de","Twoje konto jest chronione hasłem, kórego nie wprowadziłeś lub podałeś błędne. Jeśli nie zarejestrowałeś hasła, skontaktuj się ze mną: guido.wegener@gmx.de","Uw account is beschermd met een wachtwoord of u hebt  geen of een verkeerd wachtwoord ingevoerd. Als u nog geen wachtwoord heeft aangevraagd, neem dan contact op met guido.wegener@gmx.de"],
"Unable to send vote to server! Errorcode",["Fehler beim Speichern der Bewertung: ","Impossible d'envoyer votre cote sur le serveur! Code d'erreur :","Impossível enviar o voto para o servidor! Errorcode","Chyba při ukládání hodnocení na server! ErrorCode:","Nie można wysłać głosów do serwera! Błąd","Kan geen verbinding maken met de GCVote server! Errorcode"],
"Average (mean) ",["Durchschnitt (Mittel) ","Moyenne ","Média","Průměr (střední)","Średnia","Gemiddelde (standaard)"],
" your vote: ",[" Deine Bewertung: "," votre cote: "," o teu voto:","mé hodnocení"," twój głos:","Uw stem:"],
"neutral / not rated yet",["unbewertet","aucune cote","sem voto","nehodnoceno","bez głosu","Geen stem"],
"1: poor",["1: schlecht","1: perte de temps","1: péssima","1: nevyhovující odpad","1: bardzo słaba","Slecht"],
"1.5: worthless",["1,5: lohnt nicht","1,5: sans intérêt","1.5: má","1.5: bezcenná","1.5: słaba","Matig"],
"2: below average",["2: schwach","2: sous la moyenne","2: fraca","2: dík za bod","2: raczej słaba","Onvoldoende"],
"2.5: not so bad",["2,5: ok","2,5: pas si mal","2.5: razoável","2.5: OK","2.5: może być","Net geen voldoende"],
"3: average",["3: durchschnittlich","3: moyenne","3: normal","3: stojí za návštěvu","3: średnia","Voldoende"],
"3.5: not bad at all",["3,5: besser","3,5: pas mal du tout","3.5: melhor","3.5: lepší průměr","3.5: prawie dobra","Ruim voldoende"],
"4: better than average",["4: gut","4: plus plaisante que la moyenne","4: boa","4: velmi dobrá","4: dobra","Goed"],
"4.5: very good",["4,5: fast perfekt","4,5: vraiment intéressante","4.5: quase perfeita","4.5: skvělá","4.5: bardzo dobra","Zeer goed"],
"5: awesome",["5: großartig","5: à faire absolument","5: excelente","5: zlatý fond","5: świetna","Uitstekend"],
"Insert GCVote Info",["GCVote-Info-Text einfügen","Ajouter signature GCVote","Inserir informação GCVote","Vložit notifikaci GCVote","Wstaw Gcvote Info","Voer GCVote informatie in"],
"Distribution of votes:",["Verteilung der Bewertungen:","Distribution des cotes","Distribuição dos votos:","Rozdělení hodnocení :","Przydział głosów","Verdeling van de stemmen"],
"Couldn't find entry tag for inserting GCVote configuration window. Maybe the geocaching.com website has been changed. Please have a look on http://gcvote.com and check for possibly released GCVote updates.",["Unerwartetes HTML gefunden. Probiere mal aus, die Seite neu zu laden oder schau auf http://gcvote.com nach, ob es schon eine neue Version gibt.","Couldn't find entry tag for inserting GCVote configuration window. Maybe the geocaching.com website has been changed. Please have a look on http://gcvote.com and check for possibly released GCVote updates.","Não foi possível encontrar a tag onde seria inserida a janela de configuração do GCVote. Talvez o site geocaching.com tenha mudado. Por favor vai a http://gcvote.com e verifica se há updates disponíveis.","Nelze zobrazit okno nastavení GCVote. Možná že došlo ke změně  internetových stránek geocaching.com. Prosím zkontrolujte aktualizaci na http://gcvote.com.","Nie można znaleźć znacznika wejściowego do wstawienia okna konfiguracyjnego GCVote. Być może strona geocaching.com uległa zmianie. Proszę zajrzeć na on http://gcvote.com i sprawdzić aktualizacje GCVote.","Kan geen verbinding maken met het GCVote configuratiescherm. Misschien is de geocaching.com website veranderd. Ga naar http://gvote.com om te controleren of er een update van GCVote is."],
"hide config",["Menü verstecken","cacher config","esconder configuração","skrýt nastavení","ukryj config","Verberg configuratiescherm"],
"show config",["Menü einblenden","voir config","mostrar configuração","zobrazit nastavení","pokaż config","Laat configuratiescherm zien"],
"GCVote Configuration",["GCVote Konfiguration","Configuration GCVote","Configuração GCVote","Nastavení GCVote","Konfiguracja GCVote","GCVote configuratiescherm"],
"Update GCVote",["Update GCVote","Mettre à jour GCVote","Actualizar GCVote","Aktualizace GCVote","Aktualizacja GCVote","Update GCVote"],
"Homepage",["Homepage","Site web GCVote","Homepage","Homepage GCVote","Strona domowa","Startpagina"],
"List my votes",["meine Bewertungen","Voir toutes mes cotes","Listar os meus votos","Seznam mých hodnocení","Lista moich głosów","Toon mijn stemmen"],
"Change password",["Passwort ändern","Changer mot de passe","Mudar password","Změna hesla","Zmień hasło","Wijzig wachtwoord"],
"Password:",["Passwort:","Mot de passe","Password:","Heslo :","Hasło:","Wachtwoord:"],
"passwords must be registered via GC.com-mail to BonnerGuido",["Passwörter müssen per GC.com-Mail an BonnerGuido registriert werden","Les mots de passe doivent être enregistrés auprèes de l'utilisateur BonnerGuido via le site geocaching.com","as passwords têm de ser registadas através do envio de um mail via GC.com ao BonnerGuido","heslo musí být registrováno prostřednictvím e-mailu kačeru BonnerGuido z gc.com","hasło musi być zarejestrowane przez GC.com-mail do BonnerGuido","Wachtwoorden moet geregistreerd worden dooor een mailtje te sturen via het profiel van BonnerGuido"],
"Template:",["Mustertext","Signature","Frase:","Šablona :","Szablon:","Template:"],
"GCVote info string to insert into logs",["GCVote-Informationstext, der bei Logs eingefügt werden soll","Texte à ajouter dans un log seulement lorsque vous appuyer sur le bouton prévu à cet effet","texto de informação GCVote para inserir nos logs","vloží do logu tuto informaci o hodnocení keše prostřednictvím GCVote","Tekst informacyjny do wstawiania w logach","GCVote informatieregel om bij je log toe te voegen"],
"Minimum vote count:",["Minimum Stimmenanzahl:","Compte minimum de cotes:","Contagem mínima de votos:","Minimální počet hlasů:","Minimalna liczba głosów","Minimaal aantal stemmen"],
"display stars only for caches with more than X votes",["nur Sterne anzeigen, wenn mehr als X Bewertungen vorhanden sind","montrer les cotes seulement pour les caches qui ont plus de X cotes","mostrar estrelas apenas para caches com mais de X votos","zobrazit jen keše s minimálním počtem hlasů vyšším, než x","wyświetl gwiazdki tylko dla skrytek z więcej niż X głosów","Laat het aantal sterren alleen zien bij caches met meer dan X stemmen"],
"Average calculation:",["Durchschnittsberechnung:","Méthode du calcul moyen:","Cálculo da média:","Způsob průměrování :","Obliczanie średniej:","Gemiddelde berekening"],
"how the number of displayed stars should be calculated",["Berechnungsmethode für die Sterne","la façon dont la moyenne est calculée","método de cálculo do número de estrelas mostradas","způsob průměrování pro výpočet zobrazených hvězdiček","jak liczba wyświetlanych gwiazdek powinna być obliczana","Hoe het aantal weergegeven sterren moet worden berekend"],
"Mean",["Durchschnitt","Moyenne","Média","Aritm. Průměr","Średnia","Gemiddelde"],
"arithmetic mean of all votes for the cache",["arithmetisches Mittel der Bewertungen","calcul de la moyenne selon toutes les cotes","média aritmética de todos os votos da cache","aritmetický průměr všech udělených hodnocení","średnia arytmetyczna wszystkich głosów dla skrytki","Berekend gemiddelde van alle stemmen voor de cache"],
"Median",["Median","Médiane","Mediana","Střední hodnota","Mediana","Mediaan "],
"median ignores unusual votes",["Der Median ignoriert ungewöhnliche Bewertungen","valeur médiane ignore les cotes exagérées","a mediana ignora votos díspares","pro výpočet střední hodnoty nebudou započítána krajní hodnocení","mediana pomija skrajne głosy","Mediaan negeert uitschietters "],
"save changes",["Änderungen speichern","Enregistrer","guardar alterações","Uložit nastavení","zapisz zmiany","Veranderingen opslaan"],
"Language:",["Sprache:","Langage:","Idioma:","Jazyk :","Język:","Taal:"],
"language for GCVote",["Sprache in GCVote","Langue d'affichage de ce module","o idioma para o GCVote","jazyk ve kterém bude GCVote zobrazen","język GCVote","Taal voor GCVote"],
"English",["Englisch","Anglais","Inglês","anglicky","angielski","Engels"],
"German",["Deutsch","Allemand","Alemão","německy","niemiecki","Duits"],
"enable logging",["Fehler-Log","aide au déboguage","activar registos","povolit protokolování","zezwól na logowanie","Activeer foutenrapportage"],
"write debugging information to the error console",["zusätzliche Meldungen in die Fehler-Konsole schreiben","écrit l'information de déboguage à la console","escrever informação de debugging para a consola de erro","zaznamenává hlášení do chybové konzole","zapisz informacje debugowania w wierszu poleceń błędów","Schrijf debugging informatie naar de server"],
"sorted sidebar",["Karte sortieren","tri selon les cotes","ordenar barra lateral","řazení","uporządkowanie","Gesorteerde zijbalk"],
"sort caches on the map page according to their ratings",["Caches in der Liste auf der Karte nach Bewertung sortieren","à droite de la carte, affiche les caches triées selon leur cote","ordenar as caches na página do mapa de acordo com as suas classificações","seřadí keše na stránce mapy podle jejich ohodnocení","kolejność skrytek na stronie z mapą w zależności od ich oceny","Sorteer caches op de kaart op waardering"],
"half stars",["halbe Sterne","demie-étoile","meias estrelas","půlhvězdy","pół gwiazdek","Halve sterren"],
"enable ratings 1.5, 2.5, 3.5 and 4.5",["auch halbe Sternchen vergeben","permet de donner des cotes et demi","permitir classificações de 1.5, 2.5, 3.5 e 4.5","povolí hodnocení půlhvězdami, tedy 1.5, 2.5, 3.5 a 4.5","zezwól na oceny 1.5, 2.5, 3.5 i 4.5","Maak waarderen met 1,5 2,5 3,5 en 4,5 mogelijk"],
"?",["?","?","?","?","?","?"],
" out of 5",[" von 5"," sur 5"," de 5"," z 5"," z 5",".. Van 5"],
"password active",["Passwort aktiviert","mot de passe actif","password activa","heslo je aktivované","hasło aktywne","Wachtwoord actief"],
"Help",["Hilfe","Aide","Ajuda","Nápověda","Pomoc","Help"],
"Quality",["Qualität","Appréciation","Qualidade","Hodnocení","Jakość","Kwaliteit"],
"French",["Französisch","Français","Francês","francouzsky","francuski","Frans"],
"compact layout",["kompaktes Layout","format compact","layout compacto","kompaktní zobrazení","wygląd prosty","Compacte opmaak"],
"improve GCVote's layout for small screens",["kompakteres Layout für kleine Bildschirme","Format compact pour les petits écrans","melhora o layout do GCVote para ecrans pequenos","kompaktní zobrazení pro monitoty s nízkým rozlišením obrazovky","dostosuj układ GCVote do małych ekarnów","Verbetert de opmaak van GCVote voor kleine beeldschermen"],
"Portuguese",["Portugiesisch","Portugais ","Português","portugalsky","portugalski","Portugees"],
"Czech",["Tschechisch","Tchèque","Tcheco","Česky","czeski","Tsjechisch"],
"Polish",["Polnisch","Polonais","Polonês","Polština","polski","Pools"],
"Dutch",["Niederländisch","Néerlandais","Holandês","Nizozemština","niderlandzki","Nederlandse"],
"show GCVote",["GCVote aktiv","show GCVote","show GCVote","show GCVote","show GCVote","show GCVote"],
"automatically load and update GCVote-stars on map",["automatisch GCVote-Sterne nachladen und anzeigen","automatically load and update GCVote-stars on map","automatically load and update GCVote-stars on map","automatically load and update GCVote-stars on map","automatically load and update GCVote-stars on map","automatically load and update GCVote-stars on map"],
"Total votes:",["Anzahl Stimmen:","cotes au total:","Total votes:","Total votes:","Total votes:","Total votes:"],
"hide on long lists",["auf langen Listen ausblenden","désactive longue liste","hide on long lists","hide on long lists","hide on long lists","hide on long lists"],
"Do not display star on pages that may contain many caches. Improves speed on slow computers.",["Sterne auf Seiten mit vielen Caches nicht nachladen, um nicht so zu bremsen.","désactive les cotes sur les pages qui affichent une longue liste de caches","Do not display star on pages that may contain many caches. Improves speed on slow computers.","Do not display star on pages that may contain many caches. Improves speed on slow computers.","Do not display star on pages that may contain many caches. Improves speed on slow computers.","Do not display star on pages that may contain many caches. Improves speed on slow computers."],
"load GCVote",["GCVote nachladen","load GCVote","load GCVote","load GCVote","load GCVote","load GCVote"],
"bar-graph statistics",["Balken-Statistik","stats graphiques","bar-graph statistics","bar-graph statistics","bar-graph statistics","bar-graph statistics"],
"display histogram as fancy bars",["Histogramme der Bewertungen als Balken-Diagramme anzeigen","Tableau 'Distribution des votes' affiché graphiquement plutôt qu'en texte","display histogram as fancy bars","display histogram as fancy bars","display histogram as fancy bars","display histogram as fancy bars"],
"no+votes",["keine+Bewertungen","Aucune+cote","no+votes","no+votes","no+votes","no+votes"],
"",["","","","","",""],
	];
// en  de fr pt cs pl nl
	return;
}

function displayMessage(message) {
	// display message on page or as alert
	log("displayMessage "+message);
    var messageBox=document.getElementById("GCVoteMessage");
    if(!messageBox) {
		var cont;
		if(document.getElementById("CacheName")) cont=document.getElementById("CacheName").parentNode.parentNode.parentNode;
		else if(document.getElementById("ctl00_ContentBody_SearchResultText")) cont=document.getElementById("ctl00_ContentBody_SearchResultText").parentNode.parentNode;
		else if(document.getElementById("__VIEWSTATE")) cont=document.getElementById("__VIEWSTATE").parentNode.parentNode;
		else if(document.getElementById("ctl00_Breadcrumbs")) cont=document.getElementById("ctl00_Breadcrumbs").parentNode.parentNode;
		messageBox=document.createElement("div");
		messageBox.id=("GCVoteMessage");
		setStyle(messageBox,"border-width:2px;border-style:solid");
		messageBox.innerHTML="<b>GCVote</b>";
		if(!cont || !cont.firstChild) {
			log("Unknown XML on page named "+document.title);
			if(document.title.substr(0,10)=="Geocaching")
				alert("GCVote: Please update at http://userscripts.org/scripts/show/14849 or http://gcvote.com");
		}
		cont.insertBefore(messageBox,cont.firstChild);
	}
	messageBox.innerHTML+="<p>"+message+"</p>";
	window.scrollTo(0,0);
}

function setVote(cacheId,vote) {
	// highlight user's vote
	log("setVote "+cacheId+" -> "+vote);
	for(var i=0;i<=5;i+=HALFSTARS?0.5:1) {
		var voteLink=document.getElementById("GCVoteLink"+cacheId+"="+i);
		var style;
		if(vote==i) {
			if(vote==0) {style="background-color:#30e030;font-weight:normal";}
			else {style="background-color:orange;font-weight:normal";}
		}
		else {style="font-weight:normal"};
		if(voteLink!=null) {setStyle(voteLink,style)}
	}
};

function initDetailsPage() {
	// on load of detail pages
	log("initDetails "+pageType);
	var loginurl=document.getElementById("ctl00_LoginUrl");
	if(!loginurl) {loginurl=document.getElementById("hd").childNodes[3];log("emergency loginurl=",loginurl);}
	var ref=loginurl.getAttribute("href");
	var regexp=/%3fguid%3d([^%]*)/;
	regexp.exec(ref);
	cacheId=RegExp.$1;
	if(!cacheId) {
		ref=document.getElementById("ctl00_ContentBody_lnkPrintFriendly").getAttribute("href");
		regexp=/\?guid=(.*)/;
		regexp.exec(ref);
		cacheId=RegExp.$1;
	}
	var wp=document.getElementById("ctl00_cacheCodeWidget").getElementsByTagName("p")[0].firstChild.data.replace(/\s/g,"");
	requestVote(cacheId,wp);
}

function initPrintPage() {
	// on load of printer friendly pages
	log("initPrintPage "+pageType);
	var ref=document.getElementById("Form1").getAttribute("action");
	var regexp=/guid=([^%]*)/;
	regexp.exec(ref);
	cacheId=RegExp.$1;
	log("ref="+ref+"   id="+cacheId);
	requestVote(cacheId);
}

function initLogEditPage() {
	// on load of "edit log"  pages
	log("initEdit "+pageType);
	var href=document.getElementById("ctl00_ContentBody_LogBookPanel1_WaypointLink");
	if(!href) {href=document.getElementById("ctl00_ContentBody_LogBookPanel1_lbLogText").getElementsByTagName("a")[1];}
	var ref=href.getAttribute("href");
	var regexp=/\?guid=([^%]*)/;
	regexp.exec(ref);
	cacheId=RegExp.$1;
	log("cacheid found: "+cacheId);
	requestVote(cacheId);
}

function myUpdateSideBarList() {
	log("updatesidebar");
	unsafeWindow.GCVoteOriginalUpdateSideBarList();
	var cb=document.getElementById("autoupdatemapinput");
	log("udsb "+cb.checked);
	if(cb.checked) {
		simClick();
	}
}

function updateSideBarListListener() {
	log("updatesidebarlistener");
	if(!document.getElementById("GCVoteWaitMap")) {
			var t=document.getElementById("chkShowNumbers").parentNode;
			var imgWait=document.createElement("img");
			imgWait.setAttribute("width","14px");imgWait.setAttribute("height","14px");
			imgWait.src="http://www.geocaching.com/images/loading.gif";
			imgWait.id="GCVoteWaitMap";
			t.appendChild(imgWait);
	}
	var waypoints=new Array();
	var sidebar = document.getElementById('cacheListBody');
	var lis=sidebar.getElementsByTagName("a");
	for (var i=0, l=lis.length; i<l; i++) {
		var li=lis[i];
		var link=li.getAttribute("href");
		var regexp=/wp=(\w*)/;
		regexp.exec(link);
		waypoint=RegExp.$1;
		waypoints[i]=waypoint;
		var span=document.createElement("span");
		span.id="td"+waypoint;
		var target=li.parentNode.parentNode.nextSibling;
		target.appendChild(span);
	}
	requestVotesForWaypoints(waypoints);
}

function simClick() {
	var input=document.getElementById("hiddenTriggerInput");
	var event=document.createEvent("MouseEvents");
	event.initEvent("click", true, false);
	input.dispatchEvent(event);
}

function handleMapUpdateChange() {
	var cb=document.getElementById("autoupdatemapinput");
	setAutoUpdateMap(cb.checked);
	log("handleMapUpdateChange to "+getAutoUpdateMap()+" type "+typeof(getAutoUpdateMap()));
	if(getAutoUpdateMap()) {simClick();}
}

function initGMListPage() {
	log("initMap "+pageType);
	if(typeof(unsafeWindow)=="undefined") {
		if(typeof(chrome)=="undefined") {
			return;
		} else {
			var input=document.createElement("input");
			addEvent(input,"click",function() {setTimeout(function() {updateSideBarListListener();},0)});
			input.setAttribute("type","button");
			input.setAttribute("value",tl("get GCVote ratings"));
			var t=document.getElementById("chkShowNumbers").parentNode;
			t.appendChild(document.createElement("br"));
			t.appendChild(input);
			return;
		}
	}
	if(typeof(chrome)=="undefined") {
		log("insert update box");
		var input=document.createElement("input");
		addEvent(input,"click",function() {setTimeout(handleMapUpdateChange,0)});
		input.setAttribute("type","checkbox");
		input.id="autoupdatemapinput";
		if(getAutoUpdateMap()) {input.checked="checked";}
		var t=document.getElementById("chkShowNumbers").parentNode;
		t.appendChild(document.createElement("br"));
		t.appendChild(input);
		t.appendChild(getTooltipSpan("show GCVote","automatically load and update GCVote-stars on map"));
		t.appendChild(document.createElement("br"));
	}
	unsafeWindow.GCVoteOriginalUpdateSideBarList=unsafeWindow.updateSideBarList;
	unsafeWindow.updateSideBarList=myUpdateSideBarList;
	var input=document.createElement("input");
	input.id="hiddenTriggerInput";
	addEvent(input,"click",function() {setTimeout(function() {updateSideBarListListener();},0)});
	input.setAttribute("type","hidden");
	document.getElementById("aspnetForm").appendChild(input);
//	document.getElementById("aspnetForm").appendChild(document.createElement('script')).innerHTML=
//		"GCVoteOriginalUpdateSideBarList=updateSideBarList;updateSideBarList=function() {GCVoteOriginalUpdateSideBarList();simClick();};";
//	document.body.appendChild(document.createElement('script')).innerHTML=simClick.toString();
}

function initLongListPage() {
	if(getDisableOnLongLists()) {
		var count=document.getElementById("ctl00_ContentBody_lbHeading").parentNode.nextSibling;
		var buttonLoad=document.createElement("input");
		buttonLoad.setAttribute("type","button");
		buttonLoad.setAttribute("value",tl("load GCVote"));
		addEvent(buttonLoad,"click",initListPage);
		buttonLoad.id="load_GCVotes";
		count.parentNode.insertBefore(buttonLoad,count.nextSibling);
		log("long list button inserted");
	}
	else {
		initListPage();
	}
}

function initListPage() {
	// on load of pages containing lists of caches
	log("initList "+pageType);
	var anchors=document.getElementsByTagName('a');
	var reg=/cache_details\.aspx\?guid=([^&]*)/;
	var regTrack=/track\/details\.aspx\?guid=/;
	var cacheIds=new Array();
	var cacheDone=new Object();
	var ignoreNextLink=false;
	
	if(document.getElementById("load_GCVotes")) {document.getElementById("load_GCVotes").parentNode.removeChild(document.getElementById("load_GCVotes"));}
   // create table header entry "QUALITY"
    {
        if(pageType=="bookmarks") {
            var tableHeaderRow=document.getElementById("ctl00_ContentBody_ListInfo_cboItemsPerPage").parentNode.parentNode;
            var qualityHeader=document.createElement("th");
            qualityHeader.appendChild(document.createTextNode(tl("Quality")));
            tableHeaderRow.appendChild(qualityHeader);
        }
        else if(pageType=="nearestlist") {
            var headers=document.getElementsByTagName("th");
            var tableHeaderRow=headers[0].parentNode;
            var qualityHeader=document.createElement("th");
            qualityHeader.setAttribute("scope","col");
            qualityHeader.appendChild(document.createTextNode(tl("Quality")));
            tableHeaderRow.appendChild(qualityHeader);
        }
        else if(pageType=="loglist") {
            var headers=document.getElementsByTagName("th");
            // logs.aspx has no table headers!
            if(headers.length!=0)
            {
                var tableHeaderRow=headers[0].parentNode;
                var qualityHeader=document.createElement("th");
                qualityHeader.setAttribute("scope","col");
                qualityHeader.appendChild(document.createTextNode(tl("Quality")));
                tableHeaderRow.appendChild(qualityHeader);
            }
        }
    }
        
	for(var i=0;i<anchors.length;i++) { // check all links
		var a=anchors[i];
		if(ignoreNextLink) {ignoreNextLink=false;continue;}
		if(reg.exec(a.href)) { // anchor is a link to a cache
			var cacheId=RegExp.$1;
			if(pageType=="overviewlist1" && (a.parentNode.tagName=="LI")) {
				continue; // cache is part of list of unpublished caches
			}
			var target=document.createElement("td"); // create container for control
			var ignore=false;
			if(cacheDone[cacheId]>0) { // only one control per cache
				ignore=true;
			}
			cacheDone[cacheId]=1;
			cacheIds.push(cacheId);
			log("found cache "+cacheId);
			if(!ignore) target.id="td"+cacheId;
			setStyle(target,"text-align:left");
			if(pageType=="overviewlist1")
				a.parentNode.parentNode.appendChild(target);
			if(pageType=="loglist" || pageType=="nearestlist") {
				var tr=a.parentNode.parentNode;
				if(tr.tagName!="TR") {tr=tr.parentNode;}
				tr.appendChild(target);
			}
			if(pageType=="watchlist") {
				var tr=a.parentNode.parentNode;
				if(tr.tagName!="TR") {tr=tr.parentNode;}
				tr.appendChild(target);
			}
			if(pageType=="bookmarks") {
                // One bookmark list entry spans two rows!
                target.setAttribute("rowspan", "2");
                a.parentNode.parentNode.appendChild(target);
            }
			if(pageType=="overviewlist2" && a.parentNode.parentNode.tagName=="TR") {
				a.parentNode.parentNode.replaceChild(target,a.parentNode.parentNode.getElementsByTagName("td")[2]);
			}
		}
		else if(regTrack.exec(a.href)) {ignoreNextLink=true;}
	}
	requestVotes(cacheIds);
}

function parseXML(xmlString) {
	// callback for XML containing the requested votes
	log("parseXML: "+xmlString);
	xmlDoc = getXmlDoc(xmlString);
	var messages=xmlDoc.getElementsByTagName("message");
	for(var i=0;i<messages.length;i++) {
		var message=messages[i].firstChild.nodeValue;
		displayMessage(message);
	}
	var rootNodes=xmlDoc.getElementsByTagName("votes");
	if(rootNodes) {
		var rootNode=rootNodes[0];
		var currentVersion=rootNode.getAttribute("currentVersion");
		if(currentVersion!=version) {
			var upd=document.getElementById("GC-Vote-update");
			
			// changed by Odilbert for better style
			if(upd) {setStyle(upd,"padding:5px; background-color:#ffe0c8");showConfig();}
		}
		securityState=rootNode.getAttribute("securityState");
		loggedIn=rootNode.getAttribute("loggedIn")=="true";
		log("cv="+currentVersion+" ss="+securityState+" li="+loggedIn);
		if(securityState=="locked") {
			var pwd=document.getElementById("GCVotePasswordActive");
			
			// changed by Odilbert for better style
			if(pwd) setStyle(pwd,"vertical-align:middle");
		}
		if(securityState=="locked" && !loggedIn) {showConfig();}
	}
	var votes=xmlDoc.getElementsByTagName("vote");
	var mapdivs=new Array();
	var displayStarsAboveIcon=false;
	if(pageType=="gmnearestlist") {
		var divs=document.getElementsByTagName("DIV");
		var mapdiv;
		for(var i=0;i<divs.length;i++) {
//			if(divs[i].className=="LabeledMarker_markerLabel") {mapdiv=divs[i];break;}
			if(divs[i].className=="LabeledMarker_markerLabel" || divs[i].className=="LD_markerLabel_1") {
				if(divs[i].className=="LD_markerLabel_1") displayStarsAboveIcon=true;
				mapdiv=divs[i];
				break;
			}
		}
		if(mapdiv) {
			var divs=mapdiv.parentNode.childNodes;
			var re=/\((\w+)\)\s*$/;
			for(var i=0;i<divs.length-1;i+=2) {
				if(divs[i].getElementsByTagName("span").length>0) {
					divs[i].removeChild(divs[i].getElementsByTagName("span")[0]);
				}
				re.exec(divs[i+1].title);
				var wp=RegExp.$1;
				mapdivs[wp]=divs[i];
			}
		}
	}
	var totalVoteCount=0;
	for(var i=0;i<votes.length;i++) {
		var vote=votes[i];
		var userName=vote.getAttribute("userName");
		var cacheId=vote.getAttribute("cacheId");
		var voteAvg=vote.getAttribute("voteAvg");
		var voteStars=vote.getAttribute(getStarAttributeName());
		var voteCnt=vote.getAttribute("voteCnt");
		totalVoteCount+=Number(voteCnt);
		var voteUser=vote.getAttribute("voteUser");
		var waypoint=vote.getAttribute("waypoint");
        var vote1=vote.getAttribute("vote1");
        var vote2=vote.getAttribute("vote2");
        var vote3=vote.getAttribute("vote3");
        var vote4=vote.getAttribute("vote4");
        var vote5=vote.getAttribute("vote5");
        var rawVotes=vote.getAttribute("rawVotes");        
		var span;
		if(pageType=="gmnearestlist") {
			if(waypoint && Number(voteCnt)>=getThreshold()) {
				var td=document.getElementById("td"+waypoint);
				if(td.getElementsByTagName("span").length>0) {
					td.removeChild(td.getElementsByTagName("span")[0]);
				}
				span=getSmallVoteSpan(cacheId,voteStars,voteAvg,voteCnt,voteUser,false,false);
				td.appendChild(span);
				td.parentNode.parentNode.setAttribute("GCVote_stars",voteStars);
				if(!mapdivs || !mapdivs[waypoint]) continue;
				mapdivs[waypoint].appendChild(getSmallVoteSpan(cacheId,voteStars,voteAvg,voteCnt,voteUser,true,displayStarsAboveIcon));
			}
			continue;
		}
		else {
			if(getStatType()=='classic') rawVotes=null;
			else if(rawVotes==null) rawVotes="";
			span=getNewSpan(cacheId,voteStars,voteAvg,voteCnt,voteUser, vote1, vote2, vote3, vote4, vote5,rawVotes);
		}
		var replace=false; // replace existing control or generate new one
		if(document.getElementById("GCVoteLink"+cacheId+"=1") && document.getElementById("GCVoteLink"+cacheId+"=1").firstChild) {replace=true;}
		if(pageType=="details") {
			var table=document.getElementById("yui-g").getElementsByTagName("table")[0].getElementsByTagName("tr")[0].getElementsByTagName("td")[0].getElementsByTagName("table")[0];
			var td=document.createElement("td");
			td.appendChild(span);
			var row=table.getElementsByTagName("tr")[1];
			if(replace) {log("replace");row.replaceChild(td,row.getElementsByTagName("td")[3]);}
			else row.appendChild(td);
//			var hidden=document.getElementById("ctl00_ContentBody_DateHidden");
//			if(!hidden) hidden=document.getElementById("ctl00_ContentBody_Difficulty");
//			if(replace) {log("replace");hidden.parentNode.replaceChild(span,hidden.parentNode.getElementsByTagName("div")[0]);}
//			else hidden.parentNode.appendChild(span);
//			if(replace) {log("replace");hidden.parentNode.replaceChild(span,hidden.parentNode.getElementsByTagName("div")[0]);}
//			else hidden.parentNode.insertBefore(span,hidden.parentNode.getElementsByTagName("br")[0]);
		}
        else if(pageType=="logedit") {
        	var oldtr=document.getElementById("GCVote-logedit");
        	if(oldtr) {oldtr.parentNode.removeChild(oldtr);}
            var comment=document.getElementById("divComment");
            var displayInsert=true;
            if(!comment) {comment=document.getElementById("ctl00_ContentBody_LogBookPanel1_LogText");displayInsert=false;}
            var newdiv=document.createElement("div");
            comment.parentNode.insertBefore(newdiv,comment);
			fillLogEditTR(newdiv,span,voteUser,displayInsert);
        }           
        else if(pageType=="print") {
        	var bd=document.getElementById("bd");
        	setStyle(span,"display:inline;float:right");
	       	setStyle(span.firstChild,"display:inline");
        	bd.getElementsByTagName("p")[7].appendChild(span);
        }           
		else {
			var td=document.getElementById("td"+cacheId);
			if(!td) {log("parseXML could not find td"+cacheId);continue;}
			if(replace) td.replaceChild(span,td.lastChild);
			else td.appendChild(span);
		}
		setVote(cacheId,voteUser);
	}
	if(document.URL=="http://www.geocaching.com/my/owned.aspx") { // add totals
		var tbody=document.getElementById("ctl00_ContentBody_lbHeading").parentNode.parentNode.getElementsByTagName("tbody")[0];
		var tr=document.createElement("tr");
		for(var i=0;i<2;i++) {
			var td=document.createElement("td");
			tr.appendChild(td);
		}
		var td=document.createElement("td");
		td.appendChild(document.createTextNode(tl("Total votes:")+" "+totalVoteCount));
		tr.appendChild(td);
		tbody.appendChild(tr);
	}
	if(pageType=="gmnearestlist" && SORTSIDEBAR) {
		var cacheList=document.getElementById("cacheListBody");
		var list=cacheList.getElementsByTagName("TR");
		var arr=new Array();
		log("Sidebar length: "+list.length);
		for(var i=0;list.length;i++) {
			arr[i]=list[0];
			cacheList.removeChild(list[0]);
		}
		arr.sort(function (a,b) {return b.getAttribute("GCVote_stars")-a.getAttribute("GCVote_stars");});
		for(var i=0;i<arr.length;i++) {
			cacheList.appendChild(arr[i]);
		}
		log("sorted");
	}
	if(document.getElementById("GCVoteWaitMap")){
		var e=document.getElementById("GCVoteWaitMap");
		e.parentNode.removeChild(e);
	}
}

function requestVote(cacheId) {
	// request vote for a single cache
	requestVote(cacheId,null);
}

function requestVote(cacheId,waypoint) {
	// request vote for a single cache
	log("requestVote "+cacheId);
	var cacheIds=new Array(cacheId);
	requestVotes(cacheIds,waypoint);
}

function requestVotes(cacheIds) {
	// request votes for a number of caches
	requestVotes(cacheIds,null);
}

function requestVotes(cacheIds,waypoint) {
	// request votes for a number of caches
	log("requestVotes");
	var user=userName;
	if(!user) user="uglyDUMMYusernamesolution";
	var dataString="version="+version+"&userName="+user+"&cacheIds="+cacheIds+"&password="+encodeURIComponent(getPassword());
	if(waypoint) {
		dataString+="&waypoint="+waypoint;
		log(waypoint);
	}
	xmlhttpRequest({
	method: 'POST',
	headers: {'Content-type':'application/x-www-form-urlencoded; charset=UTF-8'},
	data: dataString,
	url: GETVOTES,
	onload: function(responseDetails) {
		parseXML(responseDetails.responseText);
	},
	onerror: function(responseDetails) {
		alert(tl("Unable to get votes from server! Errorcode ")+responseDetails.status);
	}
	});
}

function requestVotesForWaypoints(waypoints) {
	// request votes for a number of caches identified by waypoints
	log("requestVotesForWaypoints");
	var user=userName;
	if(!user) user="uglyDUMMYusernamesolution";
	xmlhttpRequest({
	method: 'POST',
	headers: {'Content-type':'application/x-www-form-urlencoded; charset=UTF-8'},
	data: "version="+version+"&userName="+user+"&waypoints="+waypoints+"&password="+encodeURIComponent(getPassword()),
	url: GETVOTES,
	onload: function(responseDetails) {
		parseXML(responseDetails.responseText);
	},
	onerror: function(responseDetails) {
		alert(tl("Unable to get votes from server! Errorcode ")+responseDetails.status);
	}
	});
}

function sendVote(cacheId,voteUser) {
	// send vote for cache with unknown waypoint to server
	log("sendVote "+cacheId+" -> "+voteUser);
	sendVoteWaypoint(cacheId,null,voteUser);
}

function sendVoteWaypoint(cacheId,waypoint,voteUser) {
	// send the user's new vote including waypoint to server
	log("sendVoteWaypoint "+cacheId+" ("+waypoint+") -> "+voteUser);
	var seturl=SETVOTE+"?cacheId="+cacheId+"&userName="+userName+"&voteUser="+voteUser+"&password="+encodeURIComponent(getPassword());
	if(waypoint) {seturl+="&waypoint="+waypoint;}
	log(seturl);
	xmlhttpRequest({
	method: 'GET',
	url: seturl,
	onload: function(responseDetails) {
	if(responseDetails.responseText=="OK") {
		voteLink=document.getElementById("GCVoteLink"+cacheId+"="+voteUser)
		setStyle(voteLink,"background-color:orange;font-weight:bolder;color:black"); // highlight confirmed vote
		requestVote(cacheId); // request reload of displayed score
	}
	else if(responseDetails.responseText.indexOf("wrong password")>=0) {
		log(responseDetails.responseText);
		displayMessage(tl("Your Account is password protected and you supplied no or the wrong password. "
			+"If you did not register a password, please inform me: guido.wegener@gmx.de"));
		window.location=voteServerBase+"/passwordwrong.php";
		return;
	}
	else {
		displayMessage(tl("Error while sending vote: ")+responseDetails.status+"; '"+responseDetails.responseText)+"'";
	}
	},
	onerror: function(responseDetails) {
	alert(tl("Unable to send vote to server! Errorcode ")+responseDetails.status);
	}
	});
}

function GCVote_voteClick() {
	// user clicked a link to change his vote
	log("voteClick");
	if(securityState!="locked") {
		log("voteClick wrong");
		window.location=voteServerBase+"/passworderror.php";
		return;
	}
	log("voteClick ok");
	var reg=/#([^=]*)=([0-9\.]*)/;
	reg.exec(this);  // "this" contains the clicked URL
	var cacheId=RegExp.$1;
	var voted=RegExp.$2;
	setVote(cacheId,voted); // display user's choice
	var imgWait=document.getElementById("GCVoteWait"+cacheId);
	setStyle(imgWait,"position:relative;top:3px");
	sendVote(cacheId,voted); // send new vote to server
}

function avg2suffix(avg,voteCnt) {
//	log("avg2suffix "+avg+", "+voteCnt+" - "+Math.abs(Number(voteCnt))+" - "+getThreshold());
	if(Math.abs(Number(voteCnt))<getThreshold()) {return "0";}
	var avg2=Math.round(avg*2)/2;
	var favg2=Math.floor(avg2);
	var s=favg2;
	if(avg2-favg2>.25) {s+="_5";}
	return s;
}

function getSmallVoteSpan(cacheId,voteStars,voteAvg,voteCnt,voteUser,onMap,aboveIcon) {
	log("getsmallvote");
	var span=document.createElement("span");
	var em=document.createElement("em");
	em.setAttribute("style","font-size:xx-small;color:"+colorCodeForVoteCount(voteCnt)); //#909090")
	em.appendChild(document.createTextNode(" ("+voteCnt+")"));
	var img=document.createElement("img");
	var opacity=Math.min(0.4+Math.abs(Number(voteCnt))/6,1);
	if(onMap) {img.setAttribute("width","34px");img.setAttribute("height","8px");setStyle(img,"opacity:"+opacity+";position:relative;left:-7px;top:"+(aboveIcon?"-30":"-1")+"px");}
	else {img.setAttribute("width","36px");img.setAttribute("height","9px");}
	var s=avg2suffix(voteStars,voteCnt);
	var voteAvg1=new Number(voteAvg);
	img.src="http://www.geocaching.com/images/stars/stars"+s+".gif";
	span.appendChild(img);
	if(Number(voteCnt)>=getThreshold() && !onMap) span.appendChild(em);
	return span;
}

function colorCodeForVoteCount(voteCnt) {
	var voteColor=Math.log(Math.abs(voteCnt))/Math.log(50);
	if(voteColor>1) voteColor=1;
	if(voteColor<0) voteColor=0;
	voteColor=Math.floor(voteColor*180);
	voteColor=voteColor.toString(16);
	while(voteColor.length<2) {voteColor="0"+voteColor;}
//	log("voteCnt="+voteCnt+"  voteColor="+voteColor);
	return "#00"+voteColor+"00";
}

function getNewSpan(cacheId,voteStars, voteAvg, voteCnt, voteUser, vote1, vote2, vote3, vote4, vote5,rawVotes) {
	// generate HTML node containing average and user's vote
//	log("getspan cacheid="+cacheId);
	function getVoteLink(cacheId,vote,text) {
		// generate single link for a user's vote
		var voteLink=document.createElement("a");
		addEvent(voteLink,"click",GCVote_voteClick);
		voteLink.setAttribute("href","#"+cacheId+"="+vote);
		setStyle(voteLink,"text-decoration:none!important");
		voteLink.id="GCVoteLink"+cacheId+"="+vote;
		voteLink.title=text;
		var voteText=(vote==0?"?":Math.floor(vote));
		if(Math.floor(vote)<vote) {
			var halfVote=document.createElement("span");
			setStyle(halfVote,"color:grey;font-size:1.4ex");
			halfVote.appendChild(voteLink);
			voteLink.appendChild(document.createTextNode("\u00bd"));
			return halfVote;
		}
		voteLink.appendChild(document.createTextNode(voteText));
		return voteLink;
	}
	var div=document.createElement("div");
	setStyle(div,"z-index:200");
	if(pageType=="details") {setStyle(div,"float:right");}
	if(pageType=="loglist") {setStyle(div,"float:left");}
	if(pageType=="nearestlist") {setStyle(div,"float:left");}
	var span=document.createElement("div");
	setStyle(span,"white-space:nowrap;font-size:small;padding:0px;margin:0px;line-height:80%;z-index:200");
//	if(voteUser>0) {span.setAttribute("style","white-space:nowrap");}
//	else {span.setAttribute("style","white-space:nowrap;background-color:#FFF0FF");}

    // skip "Quality:"-string for all tables containing a table header
    if(pageType!="nearestlist" && pageType!="bookmarks" && pageType!="loglist" && (!getCompactCurrentPage())) {
        var bold=document.createElement("b");
        bold.appendChild(document.createTextNode(" "+tl("Quality")+": "));
        span.appendChild(bold);
    }

	var img=document.createElement("img");
	var s=avg2suffix(voteStars,voteCnt);
	var voteAvg1=new Number(voteAvg);
	img.src="http://www.geocaching.com/images/stars/stars"+s+".gif";
    var tooltip = tl("Average (mean) ")+voteAvg1.toFixed(1)+tl(" out of 5");
    img.setAttribute("alt",tooltip);
	img.setAttribute("title",tooltip);
	img.setAttribute("align","absmiddle");
    // set image id
    img.id = "gcvoteStars"+cacheId;
    // add onclick event listener
    addEvent(img,"click", toggleGCVoteDetails(cacheId));
    // modify img's cursor
    img.style.cursor = 'pointer';
    span.appendChild(img);
    if(rawVotes!=null) createGCVoteBarDetails( span, cacheId, voteCnt, rawVotes );
    else createGCVoteDetails( span, cacheId, voteCnt, vote1, vote2, vote3, vote4, vote5 );
	span.appendChild(img);
	var small=document.createElement("small");
	var em=document.createElement("em");
	setStyle(em,"color:"+colorCodeForVoteCount(voteCnt)+";font-weight:normal");
	em.appendChild(document.createTextNode(" ("+translateVoteCount(voteCnt)+")"));
	small.appendChild(em);
	span.appendChild(small);
	if(userName) {
		var span2=document.createElement("div");
		setStyle(span2,"white-space:nowrap");
		var small2=document.createElement("small");
		if(!getCompactCurrentPage()) {
			var em2=document.createElement("em");
			em2.appendChild(document.createTextNode(tl(" your vote: ")));
			small2.appendChild(em2);
		}
		span2.appendChild(small2);
		span2.appendChild(getVoteLink(cacheId,0,tl("neutral / not rated yet")));
		span2.appendChild(getVoteLink(cacheId,1,tl("1: poor")));
		if(HALFSTARS) span2.appendChild(getVoteLink(cacheId,1.5,tl("1.5: worthless")));
		span2.appendChild(getVoteLink(cacheId,2,tl("2: below average")));
		if(HALFSTARS) span2.appendChild(getVoteLink(cacheId,2.5,tl("2.5: not so bad")));
		span2.appendChild(getVoteLink(cacheId,3,tl("3: average")));
		if(HALFSTARS) span2.appendChild(getVoteLink(cacheId,3.5,tl("3.5: not bad at all")));
		span2.appendChild(getVoteLink(cacheId,4,tl("4: better than average")));
		if(HALFSTARS) span2.appendChild(getVoteLink(cacheId,4.5,tl("4.5: very good")));
		span2.appendChild(getVoteLink(cacheId,5,tl("5: awesome")));
		var imgWait=document.createElement("img");
		imgWait.setAttribute("width","14px");imgWait.setAttribute("height","14px");
		imgWait.src="http://www.geocaching.com/images/loading.gif";
		setStyle(imgWait,"display:none");
		imgWait.id="GCVoteWait"+cacheId;
		span2.appendChild(imgWait);
	}
	div.appendChild(span);
	if(userName) div.appendChild(span2);
	return div;
}

function fillLogEditTR(tr,span,voteUser,displayInsert) {
	log("filltr");
	var td = document.createElement("span");
	td.appendChild(span);
	tr.appendChild(td);
	
	var td2 = document.createElement("span");
	if(displayInsert) {
		var button = document.createElement("input");
		button.setAttribute( "type", "button" );
			button.setAttribute( "value", tl("Insert GCVote Info") );
		addEvent(button,"click", function(event) {
			var template=getAdvertisementTemplate();
	//		var string = template.replace("%%%",voteUser);
			var vu=voteUser;
			if(Math.round(voteUser)==vu) vu=Math.round(voteUser);
			var string = template.replace("%%%",vu);
			var logbox = document.getElementById("ctl00_ContentBody_LogBookPanel1_tbLogInfo");
			if(vu!=0) {logbox.value=logbox.value.substring(0, logbox.selectionStart) + string + logbox.value.substring(logbox.selectionEnd, logbox.value.length);}
		});        
		td2.appendChild(button);
	}
	td2.appendChild(document.createElement("br"));
	tr.appendChild(td2);
	tr.id="GCVote-logedit";
}

function toggleGCVoteDetails(cacheId) 
{
    return function() 
    {
        log( "toggleGCVoteDetails " + cacheId );
        
        var detailsDiv = document.getElementById("gcvoteDetails"+cacheId);
        var p = document.getElementById("gcvoteStars"+cacheId);
        
        if( !detailsDiv )
        {
            log( "detailsDiv is 0" );
            return false;
        }
        if( !p )
        {
            log( "parent is 0" );
            return false;
        }
        
        if (detailsDiv.style.visibility != "visible")
        {
            // compute position of popup
            var top  = p.offsetHeight+2;
            var left = 0;
            
            for (; p ; p = p.offsetParent)
            {
                top  += p.offsetTop;
                left += p.offsetLeft;
            }
            
            detailsDiv.style.position   = "absolute";
            detailsDiv.style.top        = top +'px';
            detailsDiv.style.left       = left+'px';
            detailsDiv.style.visibility = "visible";
        }
        else detailsDiv.style.visibility = "hidden";
        
        return false;
    }
}

function createGCVoteDetailsRow( table, vote, votecount )
{
    var row = document.createElement( "tr" );
    table.appendChild( row );
    
    var td1 = document.createElement( "td" );
    row.appendChild( td1 );

    var img = document.createElement("img");
    img.src="http://www.geocaching.com/images/stars/stars" + vote + ".gif";
    td1.appendChild( img );
    
    var td2 = document.createElement( "td" );
    if( votecount != 0 )
    {
        td2.style.fontWeight = "bold";
    }
    td2.appendChild( document.createTextNode( translateVoteCount(votecount)) );
    row.appendChild( td2 );
}

// Modifications by Flopp <flopp-gc@online.de>
// * Extract "half-stars" from "rawVotes"
// * Display "half-stars" in histrograms (google charts api)

function extractVotes( s, v ) {
    var r = new RegExp( "\\(" + v + ":([0-9]+)\\)" );
    var m = r.exec( s );
    if( m ) { return parseInt( m[1] ); } else { return 0; }
}

function createGCVoteBarDetails( parent, cacheId, votes, rawVotes )
{
    var table = document.createElement('table');
    setStyle(table,"z-index:200");
    table.id = "gcvoteDetails"+cacheId;
    table.style.position   = "absolute";
    table.style.visibility = "hidden";   
    table.style.backgroundColor = "#eff4f9";
    table.style.border = "solid 1px #c0cee3";
    addEvent(table,"click", toggleGCVoteDetails(cacheId));
    parent.appendChild( table );
    
    var row1 = document.createElement('tr');
    table.appendChild( row1 );
    
    var header = document.createElement( "td" );
    header.style.fontWeight = "bold";
    header.appendChild( document.createTextNode( tl("Distribution of votes:") ) );
    row1.appendChild( header );
    
    
    
    var v10 = extractVotes( rawVotes, "1.0" );
    var v15 = extractVotes( rawVotes, "1.5" );
    var v20 = extractVotes( rawVotes, "2.0" );
    var v25 = extractVotes( rawVotes, "2.5" );
    var v30 = extractVotes( rawVotes, "3.0" );
    var v35 = extractVotes( rawVotes, "3.5" );
    var v40 = extractVotes( rawVotes, "4.0" );
    var v45 = extractVotes( rawVotes, "4.5" );
    var v50 = extractVotes( rawVotes, "5.0" );
    
    var maxv = 0;
    if( v10 > maxv ) maxv = v10;
    if( v15 > maxv ) maxv = v15;
    if( v20 > maxv ) maxv = v20;
    if( v25 > maxv ) maxv = v25;
    if( v30 > maxv ) maxv = v30;
    if( v35 > maxv ) maxv = v35;
    if( v40 > maxv ) maxv = v40;
    if( v45 > maxv ) maxv = v45;
    if( v50 > maxv ) maxv = v50;
    
    if( maxv > 0 )
    {
        scale = maxv + maxv/2;
        u='http://chart.apis.google.com/chart?cht=bvg&chs=175x75&chm=N,000000,0,-1,10,,h&chds=0,' + scale +'&chd=t:'+v10+','+v15+','+v20+','+v25+','+v30+','+v35+','+v40+','+v45+','+v50+'&chco=ef6a2f&chbh=14,1,5&chxt=x&chxl=0:|1|1.5|2|2.5|3|3.5|4|4.5|5';
    }
    else
    {
        u="http://chart.apis.google.com/chart?chst=d_bubble_icon_text_big&chld=star||"+tl("no+votes")+"||000000";
    }
    
    var img = document.createElement("img");
    img.src=u;
    
    var row2 = document.createElement( "tr" );
    table.appendChild( row2 );
    
    var imgcontainer = document.createElement( "td" );
    imgcontainer.style.textAlign = "center";
    imgcontainer.appendChild( img );
    
    row2.appendChild( imgcontainer );
}

function createGCVoteDetails( parent, cacheId, votes, vote1, vote2, vote3, vote4, vote5 ) 
{
    var div = document.createElement('div');
    setStyle(div,"z-index:200");
    div.id = "gcvoteDetails"+cacheId;
    div.style.position   = "absolute";
    div.style.visibility = "hidden";   
    div.style.backgroundColor = "#eff4f9";
    div.style.border = "solid 1px #c0cee3";
    addEvent(div,"click", toggleGCVoteDetails(cacheId));
    parent.appendChild( div );

    var header = document.createElement( "div" );
    header.style.fontWeight = "bold";
    header.style.fontStyle = "small";
    header.appendChild( document.createTextNode( tl("Distribution of votes:") ) );
    div.appendChild( header );
    
    var table = document.createElement( "table" );
    
    div.appendChild( table );

    createGCVoteDetailsRow( table, "1", vote1 );
    createGCVoteDetailsRow( table, "2", vote2 );
    createGCVoteDetailsRow( table, "3", vote3 );
    createGCVoteDetailsRow( table, "4", vote4 );
    createGCVoteDetailsRow( table, "5", vote5 );
}

// code for log(), setValue(), getValue() is an edited version of code released by James Campos
// @copyright      2009, James Campos
// @license        cc-by-3.0; http://creativecommons.org/licenses/by/3.0/

function log(str) {
	if(LOGGING) {
		if(typeof(GM_log)=="undefined") {
			if(console && console.log) {
				console.log(str);
			}
		}
		else {
			GM_log(str);
		}
	}
}

function setValue(key,val) {
	if(typeof(GM_setValue)=="undefined") {
		val = (typeof val)[0] + val;
		localStorage.setItem(key, val);
	}
	else {
		GM_setValue(key,val);
	}

}

function getValue(key) {
	if(typeof(GM_getValue)=="undefined") {
		var value = localStorage.getItem(key);
		if (!value)
			return null;
		var type = value[0];
		value = value.substring(1);
		switch (type) {
			case 'b':
				return value == 'true';
			case 'n':
				return Number(value);
			default:
				return value;
		}
	}
	else {
		if(GM_getValue(key)=="false") return false;
		return GM_getValue(key);
	}
}

function xmlhttpRequest(request) {
	if(typeof(GM_xmlhttpRequest)=="undefined") {
		if(typeof(chrome)!="undefined" && chrome.extension) {
			log("calling extension");
			chrome.extension.sendRequest(request, function(response) {
	 			if(response.status == 200){
	 				log("response ok, calling "+request.onload+" for "+response);
	 				request.onload(response);
		  		} else {
	  				request.onerror(response);
	 	 		}
			});
		}
	}
	else {
		GM_xmlhttpRequest(request);
	}
}

function displayVersionInfo() {
	log("versionInfo");
	var vit=document.getElementById("VersionInfoText");
	log("vit="+vit);
	var vin=document.getElementById("VersionInfoNumber");
	log("vin="+vin);
	if(!vit || !vin) return;
	var currentversion=document.getElementById("currentversion").firstChild.data;
	log("versioninfo found: -"+currentversion+"-  installed: -"+version+"-");
	vin.appendChild(document.createTextNode(version));
	setStyle(vit,"");
	if(currentversion==version) {
		setStyle(document.getElementById("updatelink"),"display:none");
	}
	if(typeof(Pro_log)!="undefined") {
		document.getElementById("updatelink").getElementsByTagName("a")[0].href="gcvote.ieuser.js";
	}
}

function getTooltipSpan(text,tooltip) {
	var span=document.createElement("span");
	span.appendChild(document.createTextNode(tl(text)));
	span.setAttribute("title",tl(tooltip));
	return span;
}

function getAdvertisementTemplate() {
	var str=getValue("advertisementTemplate");
	if(!str) {
		log("no ad text in GM, using "+GCVoteAdvertisementDefault);
		setValue("advertisementTemplate",GCVoteAdvertisementDefault);
		str=GCVoteAdvertisementDefault;
	}
	return str;
}

function getStarAttributeName() {
	var str=getValue("starAttributeName");
	if(!str) {
		setValue("starAttributeName","voteAvg");
		str="voteAvg";
	}
	return str;
}

function getStatType() {
	var str=getValue("statType");
	if(!str) {
		setValue("statType","bars");
		str="bars";
	}
	return str;
}

function getPassword() {
	var str=getValue("password["+userName+"]");
	if(!str) {
		setValue("password["+userName+"]","");
		str="";
	}
	return str;
}

function getThreshold() {
	var threshold=getValue("threshold");
	if(!threshold) {
		setValue("threshold",1);
		threshold=1;
	}
	return Number(threshold);
}

function getSortSidebar() {
	var sortSidebar=getValue("sortSidebar");
	if(typeof(sortSidebar)=='undefined') {
		setValue("sortSidebar",true);
		sortSidebar=true;
	}
	return Boolean(sortSidebar);
}

function getHalfstars() {
	var halfstars=getValue("halfstars");
	if(typeof(halfstars)=='undefined') {
		setValue("halfstars",false);
		halfstars=false;
	}
	return Boolean(halfstars);
}

function getLogging() {
	var logging=getValue("logging");
	if(typeof(logging)=='undefined') {
		setValue("logging",false);
		logging=false;
	}
	return Boolean(logging);
}

function getCompact() {
	var compact=getValue("compact");
	if(typeof(compact)=='undefined') {
		setValue("compact",false);
		compact=false;
	}
	return Boolean(compact);
}

function getLanguage() {
	var language=getValue("language");
	if(!language) {
		language = (navigator.language) ? navigator.language : navigator.userLanguage;
		log("detected language "+language);
		language=language.substr(0,2);
//		if(language!="de" && language!="fr") language="en";
		setValue("language",language);
	}
	return language;
}

function getAutoUpdateMap() {
	var update=getValue("autoupdatemap");
	if(typeof(update)=='undefined') {
		setAutoUpdateMap(true);
		update=true;
	}
	return Boolean(update);
}

function setAutoUpdateMap(flag) {
	setValue("autoupdatemap",Boolean(flag));
}

function getDisableOnLongLists() {
	var update=getValue("DisableOnLongLists");
	if(typeof(update)=='undefined') {
		setAutoUpdateMap(false);
		update=false;
	}
	return Boolean(update);
}

function setDisableOnLongLists(flag) {
	setValue("DisableOnLongLists",Boolean(flag));
}

function getCompactCurrentPage() {
	if(!getCompact()) return false;
	switch(pageType) {
		case "details": return true;
		case "loglist": return true;
		case "gmnearestlist": return true;
		case "nearestlist": return true;
		case "overviewlist1": return true;
		case "overviewlist2": return true;
		case "logedit": return false;
		case "bookmarks": return true;
		case "watchlist": return true;
		case "print": return true;
		default: return false;
	}
}

function saveConfig(Event) {
	var newPwd=document.getElementById("GC-Vote-Password").value;
	var oldPwd=getPassword();
	var reload=false;
	if(newPwd!=oldPwd) {reload=true;}
	setValue("password["+userName+"]",newPwd);
	setValue("advertisementTemplate",document.getElementById("GC-Vote-Template").value);
	setValue("threshold",document.getElementById("GC-Vote-threshold").value);
	if(document.getElementById("GC-Vote-Stars-Average").checked) {setValue("starAttributeName","voteAvg");log("avg");}
	else if(document.getElementById("GC-Vote-Stars-Median").checked) {setValue("starAttributeName","voteMedian");log("med");}
	var options=document.getElementById("GC-Vote-language").options;
	for(i=0;i<options.length;i++) {
		if(options[i].selected) {setValue("language",options[i].value);log("language="+options[i].value);}
	}
	log("logging="+document.getElementById("GC-Vote-logging").checked);
	log("halfstars="+document.getElementById("GC-Vote-half").checked);
	log("sortSidebar="+document.getElementById("GC-Vote-sort").checked);
	setValue("logging",document.getElementById("GC-Vote-logging").checked);
	setValue("halfstars",document.getElementById("GC-Vote-half").checked);
	setValue("sortSidebar",document.getElementById("GC-Vote-sort").checked);
	setValue("compact",document.getElementById("GC-Vote-compact").checked);
	setValue("DisableOnLongLists",document.getElementById("GC-Vote-longList").checked);
	if(document.getElementById("GC-Vote-StatType-Bars").checked) {setValue("statType","bars");}
	else setValue("statType","classic");
	if(reload || true) {window.location.reload();}
}

function showConfig() {
	if(!document.getElementById("GCVote-Config")) return;
	setStyle(document.getElementById("GCVote-Config"),"");
	setStyle(document.getElementById("show GCVote-Config"),"display:none");
	setStyle(document.getElementById("hide GCVote-Config"),"");
	setStyle(document.getElementById("GC-Vote-Div-Dummy"),"display:none");
}

function hideConfig() {
	if(!document.getElementById("GCVote-Config")) return;
	setStyle(document.getElementById("GCVote-Config"),"display:none");
	setStyle(document.getElementById("show GCVote-Config"),"");
	setStyle(document.getElementById("hide GCVote-Config"),"display:none");
	setStyle(document.getElementById("GC-Vote-Div-Dummy"),"");
}

function insertGCVoteMenu() {
	log("insertGCVoteMenu");
	var sidebar=document.getElementById("ctl00_ContentBody_WidgetMiniProfile1_LoggedInPanel");
	if(!sidebar) 
	{
		if(document.URL=="http://www.geocaching.com/my/"
		  && !document.getElementById("ctl00_ContentBody_WidgetMiniProfile1_LoggedOutPanel")) {
			// Added by Odilbert for better error handling
			displayMessage(tl("Couldn't find entry tag for inserting GCVote configuration window. Maybe the geocaching.com website has been changed. "+
				"Please have a look on http://gcvote.com and check for possibly released GCVote updates."));
		}
		
		return;
	}
	var header=document.createElement("h3");
	header.setAttribute("class","widget-header");
	var imgMinus=document.createElement("img");
	imgMinus.setAttribute("src","http://www.geocaching.com/images/minus.gif");
	imgMinus.setAttribute("alt",tl("hide config"));
	var linkMinus=document.createElement("a");
	addEvent(linkMinus,"click",hideConfig);
	linkMinus.id="hide GCVote-Config"
	setStyle(linkMinus,"display:none");
	linkMinus.appendChild(imgMinus);
	header.appendChild(linkMinus);
	var imgPlus=document.createElement("img");
	imgPlus.setAttribute("src","http://www.geocaching.com/images/plus.gif");
	imgPlus.setAttribute("alt",tl("show config"));
	var linkPlus=document.createElement("a");
	addEvent(linkPlus,"click",showConfig);
	linkPlus.id="show GCVote-Config"
	linkPlus.appendChild(imgPlus);
	header.appendChild(linkPlus);
	header.appendChild(document.createTextNode(" "+tl("GCVote Configuration")));
	var divDummy=document.createElement("div");
	divDummy.appendChild(document.createTextNode("\u00A0"));
	divDummy.id="GC-Vote-Div-Dummy";
	var div=document.createElement("div");
	setStyle(div,"display:none");
	div.id="GCVote-Config";
	var p1=document.createElement("p");
	p1.id="GC-Vote-update";
	setStyle(p1,"display:none");
	var updateLink=document.createElement("a");
	updateLink.setAttribute("href",voteServerBase);
	updateLink.appendChild(document.createTextNode(tl("Update GCVote")));
	p1.appendChild(updateLink);
	div.appendChild(p1);
	var p2=document.createElement("p");
	setStyle(p2,"margin:5px");
	
	var linkHome=document.createElement("a");
	linkHome.setAttribute("href","http://www.gcvote.de");
	linkHome.appendChild(document.createTextNode(tl("Homepage")));
	var linkHelp=document.createElement("a");
	linkHelp.setAttribute("href",voteServerBase+"/help.html");
	setStyle(linkHelp,"position:relative;right:3px;float:right;font-size:larger;font-weight:bold");
	linkHelp.appendChild(getTooltipSpan("?","Help"));
	p2.appendChild(linkHelp);
	p2.appendChild(linkHome);
	p2.appendChild(document.createElement("br"));
	var linkListVotes=document.createElement("a");
	addEvent(linkListVotes,"click",listVotes);
	linkListVotes.setAttribute("href","#");
//	linkListVotes.setAttribute("style","cursor:pointer");
	linkListVotes.appendChild(document.createTextNode(tl("List my votes")));
	p2.appendChild(linkListVotes);
	p2.appendChild(document.createElement("br"));
	var linkChangePassword=document.createElement("a");
	addEvent(linkChangePassword,"click",changePassword);
	linkChangePassword.setAttribute("href","#");
	linkChangePassword.appendChild(document.createTextNode(tl("Change password")));
	p2.appendChild(linkChangePassword);
	p2.appendChild(document.createElement("br"));

	var textBoxesTable=document.createElement("table");
	textBoxesTable.id="GCVoteTextBoxesTable";
	textBoxesTable.setAttribute("cellpadding", "0");
	textBoxesTable.setAttribute("cellspacing", "0");
	textBoxesTable.setAttribute("cellborder", "0");
	setStyle(textBoxesTable, "margin-top:10px");
	
	var passwordRow=document.createElement("tr");
	
	var spanPwd=document.createElement("span");
	spanPwd.id="GCVotePasswordSpan";
	spanPwd.appendChild(getTooltipSpan("Password:","passwords must be registered via GC.com-mail to BonnerGuido"));
	
	var inputPassword=document.createElement("input");
	inputPassword.setAttribute("type","password");
	setStyle(inputPassword,"margin:1px 0px 1px 3px");
	inputPassword.id="GC-Vote-Password";
	inputPassword.value=getPassword();
	
	var imgPadlock=document.createElement("img");
	imgPadlock.id="GCVotePasswordActive";
	setStyle(imgPadlock,"display:none");
	imgPadlock.setAttribute("src",voteServerBase+"/padlock.gif");
	imgPadlock.setAttribute("alt",tl("password active"));
	
	var newtd = document.createElement("td");
	newtd.appendChild(spanPwd);
	passwordRow.appendChild(newtd);
	
	newtd = document.createElement("td");
	newtd.appendChild(inputPassword);
	passwordRow.appendChild(newtd);
	
	newtd = document.createElement("td");
	newtd.appendChild(imgPadlock);
	passwordRow.appendChild(newtd);
	
	var templateRow=document.createElement("tr");
	
	var inputTemplate=document.createElement("input");
	inputTemplate.setAttribute("type","text");
	setStyle(inputTemplate,"margin:1px 0px 1px 3px");
	inputTemplate.id="GC-Vote-Template";
	inputTemplate.value=getAdvertisementTemplate();

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("Template:","GCVote info string to insert into logs"));
	templateRow.appendChild(newtd);
	
	newtd = document.createElement("td");
	newtd.appendChild(inputTemplate);
	templateRow.appendChild(newtd);
	
	newtd = document.createElement("td");
	newtd.appendChild(document.createTextNode(" "));
	templateRow.appendChild(newtd);

	var textBoxesTBody=document.createElement("tbody");
	textBoxesTable.appendChild(textBoxesTBody);
	
	textBoxesTBody.appendChild(passwordRow);
	textBoxesTBody.appendChild(templateRow);
	
	var averageTable=document.createElement("table");
	var averageTableBody=document.createElement("tbody");
	averageTable.appendChild(averageTableBody);
	averageTableBody.id="GCVoteAverageTable";
	averageTableBody.setAttribute("cellpadding", "0");
	averageTableBody.setAttribute("cellspacing", "0");
	averageTableBody.setAttribute("cellborder", "0");

	var voteCountRow=document.createElement("tr");

	var inputThreshold=document.createElement("input");
	inputThreshold.setAttribute("type","text");
	setStyle(inputThreshold,"margin:1px 0px 1px 3px");
	inputThreshold.setAttribute("size","2");
	inputThreshold.id="GC-Vote-threshold";
	inputThreshold.value=getThreshold();

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("Minimum vote count:","display stars only for caches with more than X votes"));
	voteCountRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.setAttribute("colspan", "2");
	newtd.appendChild(inputThreshold);
	voteCountRow.appendChild(newtd);

	var meanRow=document.createElement("tr");

	var inputStarsAvg=document.createElement("input");
	inputStarsAvg.setAttribute("type","radio");
	inputStarsAvg.setAttribute("name","GC-Vote-Stars");
	inputStarsAvg.id="GC-Vote-Stars-Average";
	inputStarsAvg.value="voteAvg";
	
	newtd = document.createElement("td");
	setStyle(newtd, "padding-top:3px");
	newtd.appendChild(getTooltipSpan("Average calculation:","how the number of displayed stars should be calculated"));
	meanRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.appendChild(inputStarsAvg);
	meanRow.appendChild(newtd);

	newtd = document.createElement("td");
	setStyle(newtd, "padding-top:3px");
	newtd.appendChild(getTooltipSpan("Mean","arithmetic mean of all votes for the cache"));
	meanRow.appendChild(newtd);
	
	var medianRow=document.createElement("tr");

	var inputStarsMedian=document.createElement("input");
	inputStarsMedian.setAttribute("type","radio");
	inputStarsMedian.setAttribute("name","GC-Vote-Stars");
	inputStarsMedian.id="GC-Vote-Stars-Median";
	inputStarsMedian.value="voteMedian";
	
	newtd = document.createElement("td");
	newtd.appendChild(document.createTextNode(" "));
	medianRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.appendChild(inputStarsMedian);
	medianRow.appendChild(newtd);

	newtd = document.createElement("td");
	setStyle(newtd, "padding-top:3px");
	newtd.appendChild(getTooltipSpan("Median","median ignores unusual votes"));
	medianRow.appendChild(newtd);

	var checkTable=document.createElement("table");
	var checkTableBody=document.createElement("tbody");
	checkTable.appendChild(checkTableBody);
	checkTableBody.id="GCVoteCheckTable";
	checkTableBody.setAttribute("cellpadding", "0");
	checkTableBody.setAttribute("cellspacing", "0");
	checkTableBody.setAttribute("cellborder", "0");
	
	var selectTable=document.createElement("table");
	var selectTableBody=document.createElement("tbody");
	selectTable.appendChild(selectTableBody);
	selectTableBody.id="GCVoteSelectTable";
	selectTableBody.setAttribute("cellpadding", "0");
	selectTableBody.setAttribute("cellspacing", "0");
	selectTableBody.setAttribute("cellborder", "0");
	
	var languageRow=document.createElement("tr");

	var inputLanguage=document.createElement("select");
	inputLanguage.id="GC-Vote-language";

	function addLanguage(control,code,label) {
		var option=document.createElement("option");
		option.setAttribute("value",code);option.appendChild(document.createTextNode(tl(label)));
		if(getLanguage()==code) option.setAttribute("selected","selected");
		control.appendChild(option);
	}
	addLanguage(inputLanguage,"en","English");
	addLanguage(inputLanguage,"de","German");
	addLanguage(inputLanguage,"fr","French");
	addLanguage(inputLanguage,"nl","Dutch");
	addLanguage(inputLanguage,"cs","Czech");
	addLanguage(inputLanguage,"pt","Portuguese");
	addLanguage(inputLanguage,"pl","Polish");

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("Language:","language for GCVote"));
	languageRow.appendChild(newtd);

	newtd = document.createElement("td");
//	newtd.setAttribute("colspan", "2");
	newtd.appendChild(inputLanguage);
	languageRow.appendChild(newtd);

	var loggingRow=document.createElement("tr");

	var inputLogging=document.createElement("input");
	inputLogging.setAttribute("type","checkbox");
//	setStyle(inputLogging,"margin:1px 0px 1px 3px");
//	inputLogging.setAttribute("size","2");
	inputLogging.id="GC-Vote-logging";

	newtd = document.createElement("td");
//	newtd.setAttribute("colspan", "2");
	newtd.appendChild(inputLogging);
	loggingRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("enable logging","write debugging information to the error console"));
	loggingRow.appendChild(newtd);

	var sortRow=document.createElement("tr");

	var inputSort=document.createElement("input");
	inputSort.setAttribute("type","checkbox");
	inputSort.id="GC-Vote-sort";

	newtd = document.createElement("td");
	newtd.appendChild(inputSort);
	sortRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("sorted sidebar","sort caches on the map page according to their ratings"));
	sortRow.appendChild(newtd);

	var longListRow=document.createElement("tr");

	var inputlongList=document.createElement("input");
	inputlongList.setAttribute("type","checkbox");
	inputlongList.id="GC-Vote-longList";

	newtd = document.createElement("td");
	newtd.appendChild(inputlongList);
	longListRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("hide on long lists","Do not display star on pages that may contain many caches. Improves speed on slow computers."));
	longListRow.appendChild(newtd);

	var halfstarsRow=document.createElement("tr");

	var inputHalfstars=document.createElement("input");
	inputHalfstars.setAttribute("type","checkbox");
	inputHalfstars.id="GC-Vote-half";

	newtd = document.createElement("td");
	newtd.appendChild(inputHalfstars);
	halfstarsRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("half stars","enable ratings 1.5, 2.5, 3.5 and 4.5"));
	halfstarsRow.appendChild(newtd);

	var compactRow=document.createElement("tr");

	var inputCompact=document.createElement("input");
	inputCompact.setAttribute("type","checkbox");
	inputCompact.id="GC-Vote-compact";

	newtd = document.createElement("td");
	newtd.appendChild(inputCompact);
	compactRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("compact layout","improve GCVote's layout for small screens"));
	compactRow.appendChild(newtd);

	var statRow=document.createElement("tr");

	var inputStat=document.createElement("input");
	inputStat.setAttribute("type","checkbox");
	inputStat.id="GC-Vote-StatType-Bars";

	newtd = document.createElement("td");
	newtd.appendChild(inputStat);
	statRow.appendChild(newtd);

	newtd = document.createElement("td");
	newtd.appendChild(getTooltipSpan("bar-graph statistics","display histogram as fancy bars"));
	statRow.appendChild(newtd);

	averageTableBody.appendChild(voteCountRow);
	averageTableBody.appendChild(meanRow);
	averageTableBody.appendChild(medianRow);
	selectTableBody.appendChild(languageRow);
	checkTableBody.appendChild(halfstarsRow);
	checkTableBody.appendChild(sortRow);
	checkTableBody.appendChild(compactRow);
	checkTableBody.appendChild(longListRow);
	checkTableBody.appendChild(statRow);
	checkTableBody.appendChild(loggingRow);
	
	p2.appendChild(textBoxesTable);
	p2.appendChild(averageTable);
	p2.appendChild(selectTable);
	p2.appendChild(checkTable);

	var buttonSave=document.createElement("input");
	buttonSave.setAttribute("type","button");
	buttonSave.setAttribute("value",tl("save changes"));
	setStyle(buttonSave,"margin-top:5px");
	
	addEvent(buttonSave,"click",saveConfig);
	p2.appendChild(buttonSave);
	div.appendChild(p2);
	sidebar.appendChild(header);
	sidebar.appendChild(div);
	sidebar.appendChild(divDummy);
	if("voteAvg"==getStarAttributeName()) {inputStarsAvg.checked="checked";}
	if("voteMedian"==getStarAttributeName()) {inputStarsMedian.checked="checked";}
	if(HALFSTARS) inputHalfstars.setAttribute("checked","checked");
	if(getDisableOnLongLists()) inputlongList.setAttribute("checked","checked");
	if(SORTSIDEBAR) inputSort.setAttribute("checked","checked");
	if(getCompact()) inputCompact.setAttribute("checked","checked");
	if(getStatType()=='bars') inputStat.setAttribute("checked","checked");
	if(LOGGING) inputLogging.setAttribute("checked","checked");
	log("insertGCVoteMenu done");
}

function listVotes() {
// faking a POST-form to hide password while redirecting
  var myForm = document.createElement("form");
  setStyle(myForm,"display:none");
  myForm.method="POST" ;
  myForm.action = LISTVOTES;
  i1=document.createElement("input");
  i1.setAttribute("name","userName");
  i1.setAttribute("value",unescapedUserName);
  myForm.appendChild(i1);
  i2=document.createElement("input");
  i2.setAttribute("name","password");
  i2.setAttribute("value",getPassword());
  myForm.appendChild(i2);
  document.body.appendChild(myForm) ;
  myForm.submit() ;
  document.body.removeChild(myForm) ;
}

function changePassword() {
// faking a POST-form to hide password while redirecting
  var myForm = document.createElement("form");
  setStyle(myForm,"display:none");
  myForm.method="POST" ;
  myForm.action = CHANGEPASSWORD;
  i1=document.createElement("input");
  i1.setAttribute("name","userName");
  i1.setAttribute("value",unescapedUserName);
  myForm.appendChild(i1);
  i2=document.createElement("input");
  i2.setAttribute("name","oldPassword");
  i2.setAttribute("value",getPassword());
  myForm.appendChild(i2);
  document.body.appendChild(myForm) ;
  myForm.submit() ;
  document.body.removeChild(myForm) ;
}

// IE-Mod (by qByter): Added funtion to provide alternative to addEventListener for Internet Explorer
function addEvent( obj, type, fn ) {
        if (obj.addEventListener)
                obj.addEventListener(type, fn, false);
        else if (obj.attachEvent)
                obj.attachEvent('on' + type, function() { return fn.apply(obj, new Array(window.event));});
}

function getXmlDoc(xmlString) {
	if(typeof(DOMParser) == 'undefined') {
		xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async="false";
		xmlDoc.loadXML(xmlString);
	}
	else {
		var parser = new DOMParser();
		xmlDoc = parser.parseFromString(xmlString, "text/xml");
	}
	return xmlDoc;
}

function setStyle(obj,style) {
//	obj.setAttribute("style",style);
	obj.style.cssText=style;
}

function translateVoteCount(count) {
	if(getCompactCurrentPage()) return count;
	if(getLanguage()=="de") return count + " Stimme"+(count==1?"":"n");
	if(getLanguage()=="pt") return count + " voto"+(count==1?"":"s");
	if(getLanguage()=="fr") return count + " cote"+(count>1?"s":"");
	if(getLanguage()=="cs") return count + " "+(count==0?"hlasů":(count==1?"hlas":"hlasy"));
	if(getLanguage()=="pl") return count + " "+(count==0?"głosów":(count==1?"głos":"głosy"));
	if(getLanguage()=="nl") return count + " "+(count==0?"stemmen":(count==1?"stem":"stemmen"));
	return count + " vote"+(count==1?"":"s");
}

function tl(str) {
	var index=-1;
	switch(getLanguage()) {
		case "de":index=0;break;
		case "fr":index=1;break;
		case "pt":index=2;break;
		case "cs":index=3;break;
		case "pl":index=4;break;
		case "nl":index=5;break;
	}
	if(index<0) return str;
	var p=-1;
	if(translations.indexOf) {p=translations.indexOf(str);}
	else {
		for(var i=0;i<translations.length;i+=2) {
			if(translations[i]==str) {
				p=i;
				break;
			}
		}
	}
	if(p<0) {
		log("missing translation for '"+str+"'.");
		return str;
	}
	var trans=translations[p+1];
	return trans[index];
}

