this.helpers_js = true;
this.tmg = {
array_search: function (arr, item) {
	for (var i in arr) {
		if (arr[i] === item) {return i;}
	}
	return null;
},

findcolarr: function (colarrs, item) {
	for (var i in colarrs) {
		if (colarrs[i][0] == item) {return i;}
	}
	return null;
},

// http://en.wikipedia.org/wiki/Quicksort
/*
quicksort: function (q)
		var list less, pivotList, greater
		if length(q) <= 1	
				return q	
		select a pivot value pivot from q
		for each x in q
				if x < pivot then add x to less
				if x = pivot then add x to pivotList
				if x > pivot then add x to greater
		return concatenate(quicksort(less), pivotList, quicksort(greater))
*/
array_usort: function (q, cb) {
	var less = [], pivotList = [], greater = [];
	if (q.length <= 1) {return q;}
	var pivotidx = Math.floor(Math.random()*q.length);
	var pivot = q[pivotidx];
	for (var i = 0; i < q.length; i++) {
		var x = q[i];
		var comp = cb(x, pivot);
		if (comp < 0) {less[less.length] = x;}
		if (!comp) {pivotList[pivotList.length] = x;}
		if (comp > 0) {greater[greater.length] = x;}
	}
	less = tmg.array_usort(less, cb);
	greater = tmg.array_usort(greater, cb);
	for (i = 0; i < pivotList.length; i++) {less[less.length] = pivotList[i];}
	for (i = 0; i < greater.length; i++) {less[less.length] = greater[i];}
	return less;
},

array_sort_comp: function (v1,v2) {
	if (v1 < v2) {return -1;}
	if (v1 > v2) {return 1;}
	return 0;
},

array_sort: function (arr) {
	return tmg.array_usort(arr, tmg.array_sort_comp);
},

// date-array: [day, month, year]
formatyyyymmdd: function (date, sep) {
	var curres = ''+date[0];
	if (curres.length < 2) {curres = '0'+curres;}
	return tmg.formatyyyymm([date[1], date[2]], sep)+sep+curres;
},

formatyyyymm: function (yyyymm, sep) {
	var curres = ''+yyyymm[0];
	if (curres.length < 2) {curres = '0'+curres;}
	return yyyymm[1]+sep+curres;
},

getmousepos: function (e, document) { // http://www.quirksmode.org/js/events_properties.html#link8
	var posx,posy;
	if (e.pageX || e.pageY) {
		posx = e.pageX;
		posy = e.pageY;
	} else if (e.clientX || e.clientY) {
		posx = e.clientX + document.body.scrollLeft +
			document.documentElement.scrollLeft;
		posy = e.clientY + document.body.scrollTop +
			document.documentElement.scrollTop;
	} else {
		alert('!e.pageX && !e.clientX :(\n'+e);
	}
	return [posx,posy];
},

findPos: function (obj) { // http://www.quirksmode.org/js/findpos.html#link8
	var curtop = 0;
	var curleft = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		obj = obj.offsetParent;
		while (obj) {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
			obj = obj.offsetParent;
		}
	}
	return [curleft,curtop];
},

gettarget: function (e) { // http://www.quirksmode.org/js/events_properties.html#target
	return tmg.eventTarget(e);
},

// Loosely from http://www.quirksmode.org/js/events_properties.html#target
eventTarget: function (e) {
	if (!e) {e = window.event;}
	var targ = null;
	if (e.target) {targ = e.target;}
	else if (e.srcElement) {targ = e.srcElement;}
	if (targ && targ.nodeType == 3) {targ = targ.parentNode;} // safari bug
	return targ;
},

getxhr: function () { // Various sources
	var lang = window.errlang ? window.errlang : 'en'; // en/da
	var A;
	if (window.XMLHttpRequest) {
		A = new window.XMLHttpRequest();
	} else {
		try {
			A = new window.ActiveXObject("Microsoft.XMLHTTP");
		} catch (e) {
			try {
				A = new window.ActiveXObject("Msxml2.XMLHTTP");
			} catch (oc) {
				A = null;
			}
		}
	}
	if (!A) {
		alert((lang === 'da') ? "Din browser understøtter ikke funktionen til at kommunikere med webservere dynamisk.\n\n"+
			"Find en browser, der understøtter AJAX/XMLHTTPRequest - Firefox er et godt valg!" :
			("Your browser isn't able to communicate dynamically in the background with the server\n\n"+
			"Find a browser which supports AJAX/XMLHttpRequests - Firefox for instance."));
	}
	
	return A;
},

xhr_type: function (url, callback, method, postdata, mimetype, localpayload) {
	var xhr;
	if (!(xhr = tmg.getxhr())) {return false;}
	method = method.toUpperCase();
	try {
		xhr.open(method, url, true);
	} catch (e) {
		return false;
	}
	xhr.onreadystatechange = function () {
		if (xhr.readyState != 4) {return;}
		if (callback) {callback(xhr);}
		xhr = false;
	};
	xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	if (mimetype && xhr.overrideMimeType) {xhr.overrideMimeType(mimetype);}
	xhr.localpayload = localpayload;
	xhr.send(postdata);
	return xhr;
},

xhr: function (url, callback, method, postdata, localpayload) {
	return tmg.xhr_type(url, callback, method, postdata, 'text/xml', localpayload);
},

xhr_plain: function (url, callback, method, postdata, localpayload) {
	return tmg.xhr_type(url, callback, method, postdata, 'text/plain', localpayload);
},

xhrget: function (url, callback, localpayload) {
	return tmg.xhr(url, callback, 'GET', null, localpayload);
},

xhrpost: function (url, callback, payload, localpayload) {
	return tmg.xhr(url, callback, 'POST', payload, localpayload);
},

xhrget_plain: function (url, callback, localpayload) {
	return tmg.xhr_plain(url, callback, 'GET', null, localpayload);
},

xhrpost_plain: function (url, callback, payload, localpayload) {
	return tmg.xhr_plain(url, callback, 'POST', payload, localpayload);
},

xhrgetj: function (url, callback, localpayload) {
	return tmg.xhr_plain(url, callback, 'GET', null, localpayload);
},

xhrpostj: function (url, callback, payload, localpayload) {
	return tmg.xhr_plain(url, callback, 'POST', payload, localpayload);
},

xhrform_type: function (frm, url, method, callback, mimetype, localpayload) {
	method = method.toUpperCase();
	var cont = '';
	for (var i = 0; i < frm.elements.length; i++) {
		if (!frm.elements[i].name) {continue;}
		cont += (cont ? '&' : '')+window.escape(frm.elements[i].name)+'='+window.escape(frm.elements[i].value);
	}
	return tmg.xhr_type(url+((method == 'POST')?'':'?'+cont), callback, method, ((method=='GET')?null:cont), mimetype, localpayload);
},

xhrpostform_type: function (frm, url, callback, mimetype, localpayload) {
	return tmg.xhrform_type(frm, url, 'POST', callback, mimetype, localpayload);
},

xhrgetform_type: function (frm, url, callback, mimetype, localpayload) {
	return tmg.xhrform_type(frm, url, 'GET', callback, mimetype, localpayload);
},

xhrpostform: function (frm, url, callback, localpayload) {
	return tmg.xhrpostform_type(frm, url, callback, 'text/xml', localpayload);
},

xhrgetform: function (frm, url, callback, localpayload) {
	return tmg.xhrgetform_type(frm, url, callback, 'text/xml', localpayload);
},

xhrpostform_plain: function (frm, url, callback, localpayload) {
	return tmg.xhrpostform_type(frm, url, callback, 'text/plain', localpayload);
},

xhrgetform_plain: function (frm, url, callback, localpayload) {
	return tmg.xhrgetform_type(frm, url, callback, 'text/plain', localpayload);
},

xhrpostformj: function (frm, url, callback, localpayload) {
	return tmg.xhrpostform_type(frm, url, callback, 'text/plain', localpayload);
},

xhrgetformj: function (frm, url, callback, localpayload) {
	return tmg.xhrgetform_type(frm, url, callback, 'text/plain', localpayload);
},

xhrxml: function (xhr) {
	if (!xhr || !xhr.responseXML) {alert('Ugyldigt svar fra server'); return false;}
	var root = xhr.responseXML;
	if (root.documentElement) {root = root.documentElement;}
	if (!root) {alert('Ugyldigt svar fra server (!root)'); return false;}
	return root;
},

xhrjson: function (xhr) {
	if (!xhr || !xhr.responseText) {alert('Ugyldigt svar fra server'); return false;}
	var root = ((typeof JSON) != 'undefined' && JSON.parse) ? JSON.parse(xhr.responseText) : eval('('+xhr.responseText+')');
	if (!root) {alert('Ugyldigt svar fra server (!root)'); return false;}
	return root;
},

parseIntDec: function (s) {
	if ((typeof s) === 'number') {return s;}
	if ((typeof s) !== 'string') {
		alert(typeof s);
		return s;
	}
	var i;
	for (i = 0; i < s.length-1 && s.charAt(i) === '0'; i++) {}
	if (s.charAt(i) === 'x') {i++;}
	if (i >= s.length) {s = '0';}
	else {s = s.substr(i, s.length-i);}
	return parseInt(s, 10);
},

trimchars: function (s, ch) {
	var t = '';
	var queue = '';
	for (var i = 0; i < s.length; i++) {
		var chr = s.charAt(i);
		if (!(ch.indexOf(chr) >= 0)) {
			t += queue+chr;
			queue = '';
		} else if (t !== '') {queue += chr;}
	}
	return t;
},

trim: function (s) {
	return tmg.trimchars(s, " \t\n\r\x0B\x00");
},

textContent: function (ele) {
	var s = '';
	if (!ele.nodeType) {return s;}
	if (ele.nodeType === 1) {
		/*if ((typeof ele.textContent) != 'undefined') {return ele.textContent;}
		else if ((typeof ele.innerText) != 'undefined') {return ele.innerText;}
		else if ((typeof ele.innerHTML) != 'undefined') {return ele.innerHTML;}
		else {
			var t = '';
			for (var i in ele) {t += i+', ';}
			alert(t);
			return 'aaah';
		}*/
		if ((typeof ele.textContent) != 'undefined') {return ele.textContent;}
		for (var i = 0; i < ele.childNodes.length; i++) {s += tmg.textContent(ele.childNodes[i]);}
		return s;
	}
	if (ele.nodeType === 3) {
		/*for (var i = 0; i < ele.childNodes.length; i++) {
			s += tmg.textContent(ele.childNodes[i]);
		}*/
		return ele.nodeValue;
	} else {return '<node'+ele.nodeType+' />';}
	return 'aaah';
},

workingimg: function (x,y) {
	var img = document.body.appendChild(document.createElement('img'));
	img.src = 'working.gif';
	img.style.position = 'absolute';
	img.style.left = x+'px';
	img.style.top = y+'px';
	return img;
},

emptyelement: function (ele) {
	while (ele.firstChild) {ele.removeChild(ele.firstChild);}
},

setTextContents: function (ele, s) {
	if ((typeof ele.textContent) != 'undefined') ele.textContent = s;
	else if ((typeof ele.innerText) != 'undefined') ele.innerText = s;
	else {
		tmg.emptyelement(ele);
		ele.appendChild(document.createTextNode(s));
	}
},

setwhitespace: function (ele, whitespace, overflow) {
	if (ele.nodeType === 1) {
		ele.style.whiteSpace = whitespace;
		ele.style.overflow = overflow;
		ele.style.overflowX = overflow;
		ele.style.overflowY = overflow;
		for (var i = 0; i < ele.childNodes.length; i++) {tmg.setwhitespace(ele.childNodes[i], whitespace, overflow);}
	}
},

nowrap: function (ele) {return tmg.setwhitespace(ele, 'pre', 'hidden');},
dowrap: function (ele) {return tmg.setwhitespace(ele, '', '');},

CREATEEVAL_NONE: 0,
CREATEEVAL_EVENT: 1,
createeval: function (s, mode) {
	if (mode === tmg.CREATEEVAL_EVENT) {return function (event) {eval(s);};}
	else {return function () {eval(s);};}
},

addslashes: function (s) {
	var news = '';
	for (var i = 0; i < s.length; i++) {
		var curchar = s.charAt(i);
		if (curchar == '\"' || curchar == '\\') {
			news += '\\';
		}
		if (curchar == '\n') {
			news += '\\n'; continue;
		}
		if (curchar == '\r') {
			news += '\\r'; continue;
		}
		news += curchar;
	}
	return news;
},

uniqid: function (s) {
	if ((typeof s) != 'string') {s = '';}
	return tmg.uniqid_(s, 0);
},

uniqid_: function (s, n) {
	var t = s;
	var charsfirst = 'abcdefghijklmnopqrstuvwxyz';
	var chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
	if (s.length > 24) {s = s.substring(0, 24);}
	while (s.length < 32) {
		var curchars = s.length ? chars : charsfirst;
		s += curchars.charAt(Math.floor(Math.random()*curchars.length));
	}
	if (n < 10 && document && document.getElementById && document.getElementById(s)) {
		return tmg.uniqid_(t, n+1);
	}
	return s;
},

parsePrice: function (s) {
	var supasl = s.match(/^\w\w\w\s+/);
	if (supasl) {s = s.substring(supasl[0].length, s.length);}
	if (s.match(/^\d+$/)) {return parseInt(s, 10);}
	if (s.match(/^\d+[\.,]\d\d$/)) {return parseFloat(s);}
	supasl = s.match(/^((?:^\d{1,3}|[\.,]\d{3})+)([\.,]\d{2})?$/);
	if (supasl) {
		supasl[1] = supasl[1].replace(/[.,]/g, '');
		if (supasl.length > 2) {supasl[1] += supasl[2];}
		return parseFloat(supasl[1]);
	}
	return null;
},

copyelement: function (srcele, trgtparent) {
	if (srcele.nodeType == 1) {
		var curtag = srcele.tagName.toLowerCase();
		var newtag = trgtparent.appendChild(document.createElement(curtag));
		tmg.copyattrs(srcele, newtag);
		for (var i = 0; i < srcele.childNodes.length; i++) {
			tmg.copyelement(srcele.childNodes[i], newtag);
		}
	} else if (srcele.nodeType == 3) {
		var curval = tmg.textContent(srcele);
		return trgtparent.appendChild(document.createTextNode(curval));
	} else {
		alert('copyelement: Unknown nodeType '+srcele.nodeType);
		return null;
	}
},

findattr: function (ele, attr) {
	for (var i = 0; i < ele.attributes.length; i++) {
		if (ele.attributes[i].name === attr) {return i;}
	}
	return false;
},

copyattrs: function (srcele, trgtele) {
	for (var i = 0; i < srcele.attributes.length; i++) {
		var curkey = srcele.attributes[i].name;
		var curval = srcele.attributes[i].value;
		trgtele.setAttribute(curkey, curval);
	}
},

nextele: function (e) {
	if (e.nodeType == 1 && e.firstChild) {
		e = e.firstChild;
	}
	else {
		while (e && !e.nextSibling) {
			e = e.parentNode;
		}
		if (e) {e = e.nextSibling;}
	}
	return e;
},

childOf: function (e, parente) {
	do {
		if (e && ((e.isSameNode && e.isSameNode(parente)) || e == parente)) {return true;}
	} while (e && (e = e.parentNode));
	return false;
},

parentOf: function (parente, e) {return tmg.childOf(e, parente);},

exportNode: function (e) {return tmg.exportNode_sh_adds(e, false, false);},
exportNode_sh: function (e, sh) {return tmg.exportNode_sh_adds(e, sh, false);},
exportNode_adds: function (e, adds) {return tmg.exportNode_sh_adds(e, false, adds);},
exportNode_sh_adds: function (e, shortHand, shouldAddSlashes) {
	var i;
	var s;
	if (!e) {return '-aaaaaaaah-';}
	if (!e.nodeType) {return '-aaaaah-';}
	switch (e.nodeType) {
		case 1:
			s = '<'+(e.tagName);
			if (shortHand) {
				if (e.attributes.length) {s += ' '+(e.attributes.length)+' attribs';}
			} else {
				for (i = 0; i < e.attributes.length; i++) {
					s += ' '+tmg.exportNode_sh_adds(e.attributes[i], shortHand, shouldAddSlashes);
				}
			}
			s += '>';
			if (shortHand) {
				if (e.childNodes.length) {
					s += e.childNodes.length+' child nodes';
				}
			} else {
				for (i = 0; i < e.childNodes.length; i++) {
					s += tmg.exportNode_sh_adds(e.childNodes[i], shortHand, shouldAddSlashes);
				}
			}
			s += '</'+e.tagName+'>';
			return s;
		case 2:
			return e.name+'="'+e.value+'"';
		case 3:
			s = tmg.textContent(e);
			if (shouldAddSlashes) {s = tmg.addslashes(s);}
			return s;
		case 4:
			return 'CDATA_SECTION_NODE';
		case 5:
			return 'ENTITY_REFERENCE_NODE';
		case 6:
			return 'ENTITY_NODE';
		case 7:
			return 'PROCESSING_INSTRUCTION_NODE';
		case 8:
			return '<!--'+e.nodeValue+'-->';
		case 9:
			return '<document>'+(shortHand ? '' : (tmg.exportNode_sh_adds(e.documentElement, shortHand, shouldAddSlashes)+'</document>'));
		case 10:
			return 'DOCUMENT_TYPE_NODE';
		case 11:
			return 'DOCUMENT_FRAGMENT_NODE';
		case 12:
			return 'NOTATION_NODE';
		default:
			return 'GENERIC_NODETYPE_'+(e.nodeType);
	}
	return 'OOPS';
},

countelements: function (e) {return tmg.countelements_max(e, false);},
countelements_max: function (e, max) {
	var tope = e;
	var cure = tmg.nextele(tope);
	var count = 0;
	while (cure && !tmg.parentOf(tope, cure)) {
		count++;
		if (max !== false && count >= max) {return count;}
		cure = tmg.nextele(cure);
	}
	return count;
},

element_map: function (parente, func) {return tmg.element_map_wait(parente, func, false, false);},
element_map_wait: function (parente, func, pertick, wait) {
	var cure = tmg.nextele(parente);
	if (cure) {
		tmg.element_map_tick(cure, parente, func, pertick, wait);
	}
},
element_map_tick: function (cure, parente, func, pertick, wait) {
	var num = 0;
	while (((pertick === false) || (num < pertick)) && !tmg.parentOf(cure, parente)) {
		func(cure);
		num++;
		cure = tmg.nextele(cure);
		if (!cure) { return; }
	}
	//if (!confirm('omgwhat')) {return;}
	setTimeout(function () {
		tmg.element_map_tick(cure, parente, func, pertick, wait);
	}, (wait === false) ? 0 : wait);
},
//tmg.element_map_wait(document.body, function (ele) {alert(tmg.exportNode(ele));}, 1, 100);

unserialize_ele: function (root, newele, vars) {
	var eles = [];
	//alert(newele);
	for (var i = 0; i < newele.length; i++) {
		var curidx = newele[i];
		if (typeof curidx == typeof 'what') {eles.push(root.appendChild(document.createTextNode(tmg._uns_ele_rep(curidx, vars))));}
		else {
			var curtag = tmg._uns_ele_rep(curidx[0], vars);
			var curadd = root.appendChild(document.createElement(curtag));
			var curattr = curidx[1];
			if (curattr) {for (var j = 0; j < curattr.length; j++) {
				curadd.setAttribute(tmg._uns_ele_rep(curattr[j][0], vars), tmg._uns_ele_rep(curattr[j][1], vars));
			}}
			var curcont = curidx[2];
			if (typeof curcont == typeof 'what') {curadd.innerHTML = tmg._uns_ele_rep(curcont, vars);}
			else {tmg.unserialize_ele(curadd, curcont, vars);}
			eles.push(curadd);
		}
	}
	return eles;
},
/*
	tmg.unserialize_ele(document.body, [
		['p',
			[['class', 'quote']],
			[
				"\n",
				['a',
					[['href', 'quote-%%QID%%.xhtml'],
					['onclick', 'return loadlocal(this)']],
					[
						"#%%QID%%"
					]],
				" ",
				['a',
					[['href', 'vote.xhtml?dir=1&id=%%QID%%'],
					['class', 'qa'],
					['onclick', 'return loadlocal(this)']],
					[
						"+"
					]],
				"(%%SCORE%%)",
				['a',
					[['href', 'vote.xhtml?dir=-1&id=%%QID%%'],
					['class', 'qa'],
					['onclick', 'return loadlocal(this)']],
					["-"]],
				" ",
				['a',
					[['href', 'vote.xhtml?dir=0&id=%%QID%%'],
					['class', 'qa'],
					['onclick', 'return loadlocal(this)']],
					['[X]']]
			]],
		['p',
			[['class', 'qt']],
			q
		]
	], [['QID', qid], ['SCORE', 0]]);
*/
isset: function (v){return typeof v != 'undefined';}, // only works for object children
isnull: function (v){return v === null;},
issetn: function (v){return tmg.isset(v) && !tmg.isnull(v);},

replaceall: function (from, to, hay) {
	if (!hay) return '';
	var news;
	try {
		while ((news = (hay.replace(from, to))) !== hay) {hay = news;}
	} catch (e) {
		return news ? news : hay;
	}
	return hay;
},

// http://www.quirksmode.org/js/eventSimple.html
addEventSimple: function (obj,evt,fn) {
	if (obj.addEventListener) {return obj.addEventListener(evt,fn,false);}
	else if (obj.attachEvent) {return obj.attachEvent('on'+evt,fn);}
},
removeEventSimple: function (obj,evt,fn) {
	if (obj.removeEventListener) {return obj.removeEventListener(evt,fn,false);}
	else if (obj.detachEvent) {return obj.detachEvent('on'+evt,fn);}
},
addLoad: function (fn) {
	if (tmg._loaded) {
		fn();
		return;
	}
	if (!tmg._loaders) {tmg._loaders = [];}
	tmg._loaders.push(fn);
},
_tmgloaded: function () {
	tmg._loaded = true;
	if (!tmg._loaders) {return;}
	while (tmg._loaders.length) {
		var fn = tmg._loaders.shift();
		fn();
	}
},

// doesn't support namespaced XML - http://www.zachleat.com/web/2008/05/10/selecting-xml-with-javascript/
getChildTags: function (par, tag) {
	if (!par) {return par;}
	if (!par.childNodes) {return null;}
	tag = tag.toLowerCase();
	var i;
	var ret = [];
	if (par.getElementsByTagName) {
		var collection = par.getElementsByTagName(tag);
		for (i = 0; i < collection.length; i++) {ret.push(collection[i]);}
		return ret;
	}
	for (i = 0; i < par.childNodes.length; i++) {
		var ele = par.childNodes[i];
		if (ele.nodeType != 1) {continue;}
		if (ele.tagName.toLowerCase() == tag) {ret.push(ele);}
		var eles = tmg.getChildTags(ele, tag);
		while (eles.length) {ret.push(eles.shift());}
	}
	return ret;
},

getAncestor: function (ele, anctag) {
	anctag = anctag.toLowerCase();
	while (ele && (ele = ele.parentNode) && (ele.tagName.toLowerCase() != anctag)) {}
	return ele;
},

isScalar: function (v) {
	var t = typeof v;
	if (t == 'object' || t == 'function' || t == 'undefined') {return false;}
	return true;
},

getClass: function (e) {
	if (e.className) {return e.className;}
	else if (e.getAttributeNode) {
		var o = e.getAttributeNode('class');
		if (o) {return o.value;}
		return '';
	}
	return '';
},

resolveClass: function (e) {
	var orig = e;
	if (!tmg.isScalar(e)) {
		//if (e instanceof Element) {
		if (e.nodeType) { // IE sucks
			e = tmg.getClass(e);
		} else {
			orig = false;
		}
	} else {
		orig = false;
	}
	return [orig, e];
},

hasClass: function (e, c) {
	e = tmg.resolveClass(e)[1];
	e = ' '+e+' ';
	return e.indexOf(' '+c+' ') > -1;
},

addClass: function (e, c) {
	e = tmg.resolveClass(e);
	if (!tmg.hasClass(e[1], c)) {
		e[1] += ' '+c;
		if (e[0]) {e[0].className = e[1];}
	}
	return e[0] ? e[0] : e[1];
},

removeClass: function (e, c) {
	e = tmg.resolveClass(e);
	e[1] = tmg.trim((' '+e[1]+' ').replace(new RegExp(' '+c+' ', 'g'), ' '));
	if (e[0]) {e[0].className = e[1];}
	return e[0] ? e[0] : e[1];
},

xpath: function (e, s) {
	var p = e.evaluate ? e : (e.documentElement ? e.documentElement : e.ownerDocument);
	var res = p.evaluate(s, e, null, window.XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
	var r = res.iterateNext();
	var a = [];
	while (r) {
		a.push(r);
		r = res.iterateNext();
	}
	return a;
},
scrollIntoView: function (ele) {
	var startheight = ele.offsetTop;
	var endheight = startheight+ele.offsetHeight;
	return tmg.scrollTo(startheight, startheight, endheight, 0);
},
scrollTo: function (topy, midy, endy, midradius) {
	if (typeof midradius == 'undefined') {
		midradius = 20;
	}
	if (typeof endy == 'undefined') {
		if (typeof midy == 'undefined') {
			endy = midy = topy;
		} else {
			endy = 2*midy-topy;
		}
	}
	if (typeof midy == 'undefined') {
		midy = (topy+endy)/2;
	}
	var from = document.documentElement.scrollTop + document.body.scrollTop;
	var height = document.documentElement.clientHeight;
	var frombottom = from+document.documentElement.clientHeight;
	document.documentElement.scrollTop = from;
	var to = from, tobottom = frombottom;
	var cond;
	if (from < topy && frombottom < endy) {
		tobottom = endy;
		to = tobottom-height;
	} else if (from > topy && frombottom > endy) {
		to = topy;
		tobottom = to+height;
	}
	if (tobottom < midy) {
		tobottom = midy+midradius;
		to = tobottom-height;
	} else if (to > midy) {
		to = midy-midradius;
		tobottom = to+height;
	}
	tobottom = null; // disregard this now
	to = Math.min(Math.max(to, 0), document.documentElement.scrollHeight-height);
	if (window.Animation && navigator.userAgent.toLowerCase().indexOf('chrom') < 0) {
		//alert(navigator.userAgent+" triggered the usage of FBJS anim\nto = "+to+"\nfrom = "+from);
		window.Animation(document.documentElement).to('scrollTop', to).ease(window.Animation.ease.end).go();
	} else {
		//alert("user agent triggered the usage of old fashioned window.scrollBy\nto = "+to+"\nfrom = "+from);
		window.scrollBy(0, to-from);
	}
},
preloader: {
oldurls: [],
urls: [],
nowurl: false,
continuetimer: false,
clearcontinuetimer: function () {
	if (tmg.preloader.continuetimer) {
		clearTimeout(tmg.preloader.continuetimer);
		tmg.preloader.continuetimer = false;
	}
},
setcontinuetimer: function () {
	tmg.preloader.clearcontinuetimer();
	tmg.preloader.continuetimer = setTimeout(tmg.preloader.forcecontinue, 5000);
},
forcecontinue: function () {
	tmg.preloader.nowurl = false;
	tmg.preloader.continuetimer = false;
},
preload: function (s) {
	if (tmg.array_search(tmg.preloader.oldurls, s) !== null || tmg.array_search(tmg.preloader.urls, s) !== null) {return;}
	if (tmg.preloader.preloading()) {
		tmg.preloader.urls.push(s);
	} else {
		tmg.preloader.preload_start(s);
	}
},
preload_start: function (s) {
	var img = new Image();
	tmg.preloader.oldurls.push(img.src = tmg.preloader.nowurl = s);
	tmg.preloader.setcontinuetimer();
	img.onload = tmg.preloader.onload;
},
preloading: function () {
	return tmg.preloader.nowurl ? true : false;
},
onload: function () {
	if (tmg.preloader.urls.length) {
		tmg.preloader.preload_start(tmg.preloader.urls.shift());
	} else {
		tmg.preloader.nowurl = false;
	}
}
}, // end preloader

noBubble: function (e) {
	e.cancelBubble = true;
	if (e.stopPropagation) {e.stopPropagation();}
},
catchEvent: function (e) {
	tmg.noBubble(e);
	if (e.preventDefault) {e.preventDefault();}
},
disablefields: function (ele) {
	var inputs = tmg.getChildTags(ele, 'input');
	var textareas = tmg.getChildTags(ele, 'textarea');
	while (textareas.length) {inputs.push(textareas.shift());}
	while (inputs.length) {
		ele = inputs.shift();
		ele.disabled = true;
	}
},

enablefields: function (ele) {
	var inputs = tmg.getChildTags(ele, 'input');
	var textareas = tmg.getChildTags(ele, 'textarea');
	while (textareas.length) {inputs.push(textareas.shift());}
	while (inputs.length) {
		ele = inputs.shift();
		ele.disabled = false;
	}
},

clearfields: function (ele) {
	var inputs = tmg.getChildTags(ele, 'input');
	var textareas = tmg.getChildTags(ele, 'textarea');
	while (textareas.length) {inputs.push(textareas.shift());}
	while (inputs.length) {
		ele = inputs.shift();
		ele.value = '';
	}
},

getElementsByClassName: function (base, s) {
	if (base && base.getElementsByClassName) {return tmg.cleanarray(base.getElementsByClassName(s));}
	var a = [];
	tmg.element_map(base, function (e) {
		if (tmg.hasClass(e, s)) {a.push(e);}
	});
	return a;
},

getElementsByTagName: function (base, s) {
	if (base && base.getElementsByTagName) {return tmg.cleanarray(document.getElementsByTagName(s));}
	var a = [];
	s = s.toLowerCase();
	tmg.element_map(base, function (e) {
		if (e.tagName.toLowerCase() == s) {a.push(e);}
	});
	return a;
},

getDOMId: function (ele, prefix) {
	if (ele.id) {return ele.id;}
	if (!(ele instanceof window.Node)) {ele = null;}
	var name = prefix;
	var i = 1;
	while (document.getElementById(name)) {name = prefix+(i++);}
	if (ele) {ele.id = name;}
	return name;
},

cleanarray: function (a) {
	var b = [];
	for (var i = 0; i < a.length; i++) {b.push(a[i]);}
	return b;
},

autofocushandler: function (e) {
	var inputs = tmg.getElementsByTagName(document.body, 'input');
	for (var i = 0; i < inputs.length; i++) {
		if (inputs[i].getAttributeNode && inputs[i].getAttributeNode('autofocus')) {
			inputs[i].focus();
			break;
		}
	}
},

autofocusregister: function () {
	tmg.addEventSimple(window, 'load', tmg.autofocushandler);
},

signz: function (i) {
	if (!i) {return 0;}
	return tmg.sign(i);
},
sign: function (i) {
	if (i < 0) {return -1;}
	return 1;
},
getStyle: function (el,styleProp) { // http://www.quirksmode.org/dom/getstyles.html#link7
	var x = (el instanceof window.Element) ? el : document.getElementById(el);
	if (!x) {return null;}
	if (x.currentStyle) {
		return x.currentStyle[styleProp];
	} else if (window.getComputedStyle) {
		return document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
	}
	return null;
},
// createCookie, readCookie and eraseCookie from http://www.quirksmode.org/js/cookies.html#script
createCookie: function (name,value,days) {
	var expires = '';
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		expires = "; expires="+date.toGMTString();
	}
	document.cookie = name+"="+value+expires+"; path=/";
},

readCookie: function (name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') {c = c.substring(1,c.length);}
		if (c.indexOf(nameEQ) === 0) {return c.substring(nameEQ.length,c.length);}
	}
	return null;
},

eraseCookie: function (name) {
	tmg.createCookie(name,"",-1);
},

errhandle: function (errormessage, errorfile, errorline) {
	var n = tmg.readCookie('jserrcount');
	if (!n) {n = 0;}
	var cookieid = n++;
	var cookiename = 'jserr'+cookieid;
	var cookies = {'message': errormessage, 'file': errorfile, 'line': errorline};
	for (var i in cookies) {
		if (cookies.hasOwnProperty ? cookies.hasOwnProperty(i) : (typeof cookies[i] !== 'function')) {
			tmg.createCookie(cookiename+i, cookies[i], 1);
		}
	}
	tmg.createCookie('jserrcount', n);
},

errhandleregister: function () {
	if (!window.onerror) {window.onerror = tmg.errhandle;}
},

loadedscripts: [],
loadScript: function (s) {
	// we might want to run the same script several times, so don't keep going even if it has already been loaded
	//if (tmg.array_search(tmg.loadedscripts, s) != null) {return;}
	tmg.loadedscripts.push(s);
	var newscr = document.createElement('script');
	newscr.type = 'text/javascript';
	newscr = document.body.appendChild(newscr);
	newscr.src = s;
},
loadStyle: function (s) {
	if (tmg.array_search(tmg.loadedscripts, s) !== null) {return;}
	tmg.loadedscripts.push(s);
	var newscr = document.createElement('link');
	newscr.rel = 'stylesheet';
	newscr.type = 'text/css';
	newscr = document.body.appendChild(newscr);
	newscr.href = s;
},
metaKey: function (e) {
	return (e.modifiers || e.ctrlKey || e.altKey || e.shiftKey) ? true : false;
},
setTitle: function (s) {
	var methods = [ // all the different ways we're going to try
		function (s) {
			try {
				var ele = document.createElement('div');
				ele.innerHTML = s;
				document.title = tmg.textContent(ele);
				return true;
			} catch (exc) {
			}
			return false;
		},
		function (s) {
			try {
				var ele = document.createElement('div');
				ele.style.display = 'none';
				ele = document.body.appendChild(ele);
				ele.innerHTML = s;
				document.title = tmg.textContent(ele);
				return true;
			} catch (exc) {
			}
			return false;
		}
	];
	for (var i = 0; i < methods.length; i++) {
		document.title = '';
		var ret = methods[i](s);
		if (ret && document.title) {
			window.luckytitlemethod = i;
			tmg.setTitle = methods[i]; // replace ourselves, so the next request will be just as successful, but faster
			return;
		}
	}
	document.title = '-'; // error condition
},
trackUrl: function (url) {
	var o;
	if (typeof inpage != 'undefined' && inpage.url) {
		if (typeof url == 'string') {
			url = inpage.localPart(inpage.split(url));
		}
	} else if (o = /^[a-zA-Z0-9]+:\/\/[^\/]*(\/.*)/.exec(url)) {
		url = o[1];
	}
	if (window.pageTracker && window.pageTracker._trackPageview) // Google Analytics
		window.pageTracker._trackPageview(url);
}
};
tmg.addEventSimple(window, 'load', tmg._tmgloaded);

