	/*
		Useful X-Browser DOM functions

		Markus Fischer <markus@fischer.name>
	*/
	function TsDomGetParentByTagName(el, tagName) {
		tagName = tagName.toLowerCase();
		while (el.parentNode && el.tagName.toLowerCase() != tagName) {
			el = el.parentNode;
		}
		if (!el.tagName) {
			throw 'No parent "' + tagName + '" element found';
		}
		if (el.tagName.toLowerCase() != tagName) {
			throw 'No parent "' + tagName + '" element found';
		}
		return el;
	}

	function TsDomStopPropagation(e) {
		if (e.stopPropagation) {
			// W3C, like Gecko & Opera
			e.stopPropagation();
		} else if (typeof e['cancelBubble'] != 'undefined') {
			// M$
			e.cancelBubble = true;
		}
	}

	function TsDomGetElementsByClassName(classPart, tagName) {
		var ELs;
		if (typeof tagName == 'undefined') {
			ELs = document.getElementsByTagName('*');
		} else {
			ELs = document.getElementsByTagName(tagName);
		}
		var found = [];
		var reClass = new RegExp(classPart);
		for (var i = 0, l = ELs.length; i < l; i++) {
			if (reClass.test(ELs[i].className)) {
				found[found.length] = ELs[i];
			}
		}
		return found;
	}

	function TsDomFocusNextFormElement(element) {
		if (!element['form']) {
			throw 'Element probably not a form element';
		}
		var focusOnNext = false;
		for (var i = 0, l = element.form.elements.length; i < l; i++) {
			if (focusOnNext && element.form.elements[i].tagName.toUpperCase() != 'FIELDSET') {
				element.form.elements[i].focus();
				break;
			}
			if (element.form.elements[i] == element && i < l - 1) {
				focusOnNext = true;
			}
		}
	}

	/* Based on http://www.faqts.com/knowledge_base/view.phtml/aid/9095/fid/128 */
	function TsDomGetLayout(element) {
		var offsetWidth = element.offsetWidth;
		var offsetHeight = element.offsetHeight;
		for (var lx = 0, ly = 0; element != null;
			lx += element.offsetLeft - element.scrollLeft,
			ly += element.offsetTop - element.scrollTop,
			element = element.offsetParent);
		return {x:lx, y:ly, w:offsetWidth, h:offsetHeight}
	}

	/*
		Gegenstueck zu insertBefore -> insertAfter
	*/
	function TsDomInsertAfter(newElement, beforeElement) {
		// wenn beforeElement das letzte ist, einfach append beim parent-Element
		if (beforeElement.parentNode.lastChild == beforeElement) {
			return beforeElement.parentNode.appendChild(newElement);
		} else {
			return beforeElement.parentNode.insertBefore(newElement, beforeElement.nextSibling);
		}
	}

	function TsDomAddEventListener(element, eventName, func, bUseCapture) {
		if (typeof bUseCapture == 'undefined') {
			bUseCapture = false;
		}
		// IE
		if (element.attachEvent) {
			element.attachEvent("on" + eventName, func);
		// GECKO
		} else if (element.addEventListener) {
			element.addEventListener(eventName, func, bUseCapture);
		} else {
			element["on" + eventName] = func;
		}
	}

	function TsDomRemoveEventListener(element, eventName, func, bUseCapture) {
		if (typeof bUseCapture == 'undefined') {
			bUseCapture = false;
		}
		// IE
		if (element.detachEvent) {
			element.detachEvent("on" + eventName, func);
		// GECKO
		} else if (element.removeEventListener) {
			element.removeEventListenter(eventName, func, bUseCapture);
		} else {
			el["on" + eventName] = null;
		}
	}

	function TsDomEventTarget(e) {
		if (e) {
			var target = null;
			// W3C
			if (e.target) {
				target = e.target;
			// M$
			} else if (e.srcElement) {
				target = e.srcElement;
			}
			// Safari bug? see http://www.quirksmode.org/js/events_properties.html
			if (target && target.nodeType == 3) {
				target = target.parentNode;
			}
			return target
		}
		return null;
	}

	function TsDomInputSelectText(domInput, start, end) {
		if (typeof start == 'undefined') {
			start = 0;
		}
		if (typeof end == 'undefined') {
			end = domInput.value.length;
		}
		if (domInput.setSelectionRange) {
			// Mozilla
			domInput.setSelectionRange(start, end);
		} else if (domInput.createTextRange) {
			// IE
			var range = domInput.createTextRange();
			range.moveStart("character", start);
			range.moveEnd("character", end);
			range.select();
		}
	}

	function TsDomParseInt(num) {
		if (/^[0-9]+$/.test(num)) {
			return parseInt(num);
		}
		return 0;
	}

