/**
 * P.I.C.S. JS Framework 5.0.0
 * Copyright(c) 2009 P.I.C.S. EDV GmbH
 * http://www.pics.co.at
 * 
 * @author Ing. Christian Grösswang
 * 
 * 	20100129,gc - v5.00.00		complete rework
 *  20100615,gc - v5.00.01		BUGFIX: missing handling of searchdepth in findElement
 *  20100803,gc - v5.00.02		BUGFIX: corrected pics.setHTML for empty destination
 *  20100803,gc - v5.03.00		added getNextElement, getPrevElement
 */

/**
 * @class pics
 * core utilities and functions.
 * @singleton
 */
var pics = {
    		version : '5.03.00'			//* @type String	version of the framework
		/* Browser detecion */
			,isOpera : false			//* @type Boolean	true if the detected browser is opera
			,isChrome : false			//* @type Boolean	true if the detected browser is chrome
			,isSafari : false			//* @type Boolean	true if the detected browser is safari
			,isSafari2 : false			//* @type Boolean	true if the detected browser is safari v2.x
			,isSafari3 : false			//* @type Boolean	true if the detected browser is safari v3.x
			,isSafari4 : false			//* @type Boolean	true if the detected browser is safari v4.x
			,isIE : false				//* @type Boolean	true if the detected browser is Internet Explorer
			,isIE6 : false				//* @type Boolean	true if the detected browser is Internet Explorer v6.x
			,isIE7 : false				//* @type Boolean	true if the detected browser is Internet Explorer v7.x
			,isIE8 : false				//* @type Boolean	true if the detected browser is Internet Explorer v8.x
			,isMozilla : false			//* @type Boolean	true if the detected browser is Firefox / Gecko 
			,isMozilla2 : false			//* @type Boolean	true if the detected browser is Firefox 2.x / Gecko <1.9
			,isMozilla3 : false			//* @type Boolean	true if the detected browser is Firefox 3.x / Gecko >=1.9
		/* OS detecion */
			,isWindows : false			//* @type Boolean	true if the detected platform is Windows
			,isLinux : false			//* @type Boolean	true if the detected platform is Linux
			,isMac : false				//* @type Boolean	true if the detected platform is Mac OS
		/* store for scroll-position */
			,scrollX : 0				//* @type {Int}		x-scroll-position for backup/restore					
			,scrollY : 0				//* @type {Int}		y-scroll-position for backup/restore					
		};	// pics
		
			
	/**
	 *	initialize the base object 
	 */
	pics.init = function() 
	{
		// do the browser-detection
		pics.checkBrowser();	
	
	}; // pics.init
	
	
	/**
	 *	do some browser detection
	 */
	pics.checkBrowser = function() 
	{
		/* browser detection */
		var lUserAgent=navigator.userAgent.toLowerCase();
		this.isOpera 	= /opera/i.test(lUserAgent);		// Opera
		this.isChrome 	= /chrome/i.test(lUserAgent);		// Chrome
		this.isSafari 	= !this.isChrome && /safari/i.test(lUserAgent);			// Safari
		this.isSafari2 	= this.isSafari && /applewebkit\/4/i.test(lUserAgent);	// Safari 2
		this.isSafari3 	= this.isSafari && /version\/3/i.test(lUserAgent);		// Safari 3
		this.isSafari4 	= this.isSafari && /version\/4/i.test(lUserAgent);		// Safari 4
		this.isIE 		= !pics.isOpera && /msie/i.test(lUserAgent);			// Internet Explorer
		this.isIE7 		= pics.isIE && /msie 7/i.test(lUserAgent);				// Internet Explorer 7
		this.isIE8 		= pics.isIE && /msie 8/i.test(lUserAgent);				// Internet Explorer 8
		this.isIE6 		= pics.isIE && !pics.isIE7 && !pics.isIE8;				// Internet Explorer 6
		var lisWebKit 		= /webkit/i.test(lUserAgent);
		this.isMozilla 	= !lisWebKit && /gecko/i.test(lUserAgent);				// Firefox / Gecko
		this.isMozilla2	= pics.isMozilla && /rv:1\.8/i.test(lUserAgent);		// Firefox 2.x / Gecko <1.9
		this.isMozilla3	= pics.isMozilla && /rv:1\.9/i.test(lUserAgent);		// Firefox 3.x / Gecko >=1.9
		/* os detection */
		this.isWindows 	= /windows|win32/i.test(lUserAgent);					// Windows
		this.isMac 		= /macintosh|mac os x/i.test(lUserAgent);				// Mac OS
		this.isLinux 	= /linux/i.test(lUserAgent);							// Linux
	}; // pics.checkBrowser


	/**
	 * pics.isElement()
	 *		check if pObject is a HTML-element
	 *		@param 	{Mixed} 	pObject 		Object to test
	 */
	pics.isElement = function(pObject) 
	{
		return !!pObject && pObject.tagName;
	}; // pics.isElement

	/**
	 * pics.isArray()
	 *		check if pObject is an Array
	 *		@param 	{Mixed} 	pObject 		Object to test
	 */
	pics.isArray = function(pObject) 
	{
		return pObject.constructor == Array;
	}; // pics.isArray

	/**
	 * pics.isEmpty()
	 *		check if pObject is empty
	 *		@param 	{Mixed} 	pObject 		Object to test
	 */
	pics.isEmpty = function(pObject) 
	{
		return pObject === null || pObject === undefined || pObject === '' || ((pics.isArray(pObject) && !pObject.length));
	}; // pics.isEmpty

	/**
	 * pics.isObject()
	 *		check if pObject is an object
	 *		@param 	{Mixed} 	pObject 		Object to test
	 */
	pics.isObject = function(pObject) 
	{
		return (typeof pObject == 'object');
	}; // pics.isObject

	/**
	 * pics.isFunction()
	 *		check if pObject is a HTML-element
	 *		@param 	{Mixed} 	pObject 		Object to test
	 */
	pics.isFunction = function(pObject) 
	{
		return (typeof pObject == 'function');
	}; // pics.isFunction

	/**
	 * pics.isString()
	 *		check if pObject is a HTML-element
	 *		@param 	{Mixed} 	pObject 		Object to test
	 */
	pics.isString = function(pObject) 
	{
		return (typeof pObject == 'string');
	}; // pics.isString

	/**
	 * pics.isNumber()
	 *		check if pObject is a HTML-element
	 *		@param 	{Mixed} 	pObject 		Object to test
	 */
	pics.isNumber = function(pObject) 
	{
		return (typeof pObject == 'number' && isFinite(pObject));
	}; // pics.isNumber

	/**
	 * pics.isUndefined()
	 *		check if pObject is a HTML-element
	 *		@param 	{Mixed} 	pObject 		Object to test
	 */
	pics.isUndefined = function(pObject) 
	{
		return (typeof pObject == 'undefined');
	}; // pics.isUndefined


/* 
 * ==================================================================================================================
 * 		positioning/screen functions
 * ==================================================================================================================
 */

	/**
	 * pics.getEX()
	 *		determine the x-position of an element
     * 		@param 	{Mixed} 	pElement 			Object or ID-String of the element
     * 		@return	{Int}							X-Position of the element 
	 */
	pics.getEX = function(pElement) 
	{
		var lX=0;
		var oParent=pics.obj(pElement);
		while (oParent) 
		{
			if (oParent.offsetLeft) lX+=oParent.offsetLeft;
			oParent = oParent.offsetParent;
		}
		return lX;
	}; // getEX
	

	/**
	 * pics.getEY()
	 *		determine the y-position of an element
     * 		@param 	{Mixed} 	pElement 			Object or ID-String of the element
     * 		@return	{Int}							Y-Position of the element 
	 */
	pics.getEY = function(pElement) 
	{
		var lY=0;
		var oParent=pics.obj(pElement);
		while (oParent) 
		{
			if (oParent.offsetTop) lY+=oParent.offsetTop;
			oParent = oParent.offsetParent;
		}
		return lY;
	}; // getEY
	

	/**
	 * pics.getEWidth(pElement)
	 *		get the width of an element
     * 		@param 	{Mixed} 	pElement 			Object or ID-String of the element
     * 		@return	{Int}							width of the element 
	 */
	pics.getEWidth = function(pElement) 
	{
		var lWidth=0;
		var oElement=pics.obj(pElement);
		lWidth = parseInt(pElement.style.width);	
		if (isNaN(lWidth)) lWidth = parseInt(pElement.offsetWidth);
		return lWidth;
	}; // getEWidth
	
	/**
	 * pics.getEHeight(pElement)
	 *		get the height of an element
     * 		@param 	{Mixed} 	pElement 			Object or ID-String of the element
     * 		@return	{Int}							height of the element 
	 */
	pics.getEHeight = function(pElement) 
	{
		var lHeight=0;
		var oElement=pics.obj(pElement);
		lHeight = parseInt(pElement.style.height);	
		if (isNaN(lHeight)) lHeight = parseInt(pElement.offsetHeight);
		return lHeight;
	}; // getEHeight
	
	/**
	 * pics.getPageScrollX()
	 *		determine the x-scrollposition of the page
     * 		@return	{Int}							X-scroll-Position of the page 
	 */
	pics.getPageScrollX = function() 
	{
		if (window.pageXOffset) return window.pageXOffset;
		if (document.body && document.body.scrollLeft) return document.body.scrollLeft;
	  	if (document.documentElement && document.documentElement.scrollLeft) return document.documentElement.scrollLeft;
		// if nothing succeds return 0
		return 0;
	};
	
	/**
	 * pics.getPageScrollY()
	 *		determine the y-scrollposition of the page
     * 		@return	{Int}							Y-scroll-Position of the page 
	 */
	pics.getPageScrollY = function() 
	{
		if (window.pageYOffset) return window.pageYOffset;
		if (document.body && document.body.scrollTop) return document.body.scrollTop;
	  	if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop;
		// if nothing succeds return 0
		return 0;
	}; // pics.getPageScrollY

	/**
	 * pics.getDocumentWidth()
	 *		determine the width of the document
     * 		@return	{Int}							width of the document 
	 */
	pics.getDocumentWidth = function() 
	{
		return Math.max(document.body.scrollWidth,document.documentElement.scrollWidth);
	}; // pics.getDocumentWidth

	/**
	 * pics.getDocumentHeight()
	 *		determine the height of the document
     * 		@return	{Int}							height of the document 
	 */
	pics.getDocumentHeight = function() 
	{
		return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight);
	}; // pics.getDocumentHeight

	/**
	 * pics.getScreenWidth()
	 *		determine the width of the screen
     * 		@return	{Int}							width of the screen 
	 */
	pics.getScreenWidth = function() 
	{
		return Math.max(document.body.clientWidth,document.documentElement.clientWidth);
	}; // pics.getScreenWidth

	/**
	 * pics.getScreenHeight()
	 *		determine the height of the screen
     * 		@return	{Int}							height of the screen 
	 */
	pics.getScreenHeight = function() 
	{
		return Math.max(document.body.clientHeight,document.documentElement.clientHeight);
	}; // pics.getScreenHeight

	/**
	 * pics.backupScroll()
	 *		backup the current scroll-position
	 */
	pics.backupScroll = function() 
	{
		this.scrollX=this.getPageScrollX();
		this.scrollY=this.getPageScrollY();
		// alert(this.scrollX+'/'+this.scrollY);
	}; // pics.backupScroll

	/**
	 * pics.restoreScroll()
	 *		restore the last scroll-position
	 */
	pics.restoreScroll = function() 
	{
		document.body.scrollTop=this.scrollX;
		document.body.scrollLeft=this.scrollY;
		// alert(this.scrollX+'/'+this.scrollY);
	}; // pics.restoreScroll
	
/* 
 * ==================================================================================================================
 * 		dom helper functions
 * ==================================================================================================================
 */

	/**
	 * pics.getObj()
	 *		shortcut to document.getElementById, if pID is already an object just return this 
     * 		@param 	{String} 	pID 		Id of the element
     * 		@return	{Object}		 
	 */
	pics.getObj = function(pID) 
	{
		return document.getElementById(pID);
	}; // pics.getObj

   /**
     * shortcut to pics.getObj
     * 		@param 	{String} 	pID 		Id of the element
     * 		@return	{Object}		 
     */
    pics.o = pics.getObj;

	/**
	 * pics.obj()
	 *		if pID as a string, return the corresponding object, otherwise the object itself 
     * 		@param 	{Mixed} 	pID 		Id of the element
     * 		@return	{Object}		 
	 */
	pics.obj = function(pID) 
	{
		if (typeof pID == 'string') return document.getElementById(pID);
		return pID;
	}; // pics.obj


	/**
	 * pics.findElement()
	 *		find all child elements or the first of the given criteria 
     * 		@param 	{String} 	pType 				type of search, allowed are: name, id, class, tag
     * 		@param 	{Mixed} 	pParentObject 		Object or ID-String of the start-object
     * 		@param 	{String} 	pSearchName 		part of the name to search
     * 		@param 	{Bool} 		pFirstOnly 			default=false ... return an array with all elements, true return the first object
     * 		@param 	{Int} 		pSearchDepth 		how deep do we search? default=255
     * 		@param 	{String} 	pSearchAttribute	attribute to search in, only for type=attribute
     * 		@return	{Mixed}							Array with the result or first object, null if nothing found 
	 */
	pics.findElement = function(pType, pParentObject, pSearch, pFirstOnly, pSearchDepth, pSearchAttribute) 
	{
		if (!pParentObject) 				pParentObject=document.body;
		
		// wt: save function calls to improve speed 60%! instead of pParentObject=pics.obj(pParentObject);
		if (typeof pParentObject == 'string') pParentObject = document.getElementById(pParentObject);
		
		if (!pParentObject.hasChildNodes) 	return null;
		if (!pSearch) 						return null;
		if (!pFirstOnly) 					pFirstOnly=false;
		if (!pSearchDepth)					pSearchDepth=99;
		if (!pSearchAttribute)				pSearchAttribute='';
		
		var aResult=new Array();
		var lText='';
		
	    if (pParentObject.hasChildNodes()) 
		{
			// walk throuh all the childs
		    for(var i=0;i<pParentObject.childNodes.length;i++)
		    {
				// detect the Criteria
				lText=null;
				switch(pType)
				{
					case 'name':
							if (pParentObject.childNodes[i].name) 
							{
								lText=pParentObject.childNodes[i].name;
							}
							else if (pParentObject.childNodes[i].attributes!=null)
							{
								lText=pParentObject.childNodes[i].getAttribute('name');
							}
						break;
					case 'id':
							if (pParentObject.childNodes[i].id) 
							{
								lText=pParentObject.childNodes[i].id;
							}
							else if (pParentObject.childNodes[i].attributes!=null)
							{
								lText=pParentObject.childNodes[i].getAttribute('id');
							}
						break;
					case 'class':
							if (pParentObject.childNodes[i].className) 
							{
								lText=pParentObject.childNodes[i].className;
							}
							else if (pParentObject.childNodes[i].attributes!=null)
							{
								lText=pParentObject.childNodes[i].getAttribute('class');
							}
						break;
					case 'tag':
							lText=pParentObject.childNodes[i].nodeName;
						break;
					case 'attribute':
							if (pParentObject.childNodes[i].attributes!=null)
							{
								if (pParentObject.childNodes[i].getAttribute(pSearch)) lText=pSearch;
							}
						break;
					case 'attributevalue':
							if (pParentObject.childNodes[i].attributes!=null)
							{
								lText=pParentObject.childNodes[i].getAttribute(pSearchAttribute);
							}
						break;
				}

				if (lText!=null)
				{
					var lOK=lText.indexOf(pSearch);
					if (lOK>=0) 
					{
						if (pFirstOnly) return pParentObject.childNodes[i];
						aResult.push(pParentObject.childNodes[i]);
					} // if found
				} // if child has name
				// 20100615gc - stop search if depth==1
				if (pSearchDepth!=1)
				{
					// continue search through all childs
					var lResult=pics.findElement(pType, pParentObject.childNodes[i], pSearch, pFirstOnly,pSearchDepth-1,pSearchAttribute);
					// do we have a result?
					if (lResult!=null) 
					{
						if (pFirstOnly) return lResult;
						// aResult.push(lResult);
						aResult=aResult.concat(lResult);
					} // if result
				} // if searchdepth
			} // for
		} // if hasChildNodes
	    if (aResult.length>0) return aResult;
	    return null;
	};	// pics.findElement



	/**
	 * pics.findByName()
	 *		find all child elements or the first of the given name 
     * 		@param 	{Mixed} 	pParentObject 		Object or ID-String of the start-object
     * 		@param 	{String} 	pSearchName 		part of the name to search
     * 		@param 	{Bool} 		pFirstOnly 			default=false ... return an array with all elements, true return the first object
     * 		@param 	{Int} 		pSearchDepth 		how deep do we search? default=255
     * 		@return	{Mixed}							Array with the result or first object, null if nothing found 
	 */
	pics.findByName = function(pParentObject, pSearchName, pFirstOnly, pSearchDepth) 
	{
		return pics.findElement('name', pParentObject, pSearchName, pFirstOnly, pSearchDepth); 
	};	// pics.findByName


	/**
	 * pics.findById()
	 *		find all child elements or the first of the given name 
     * 		@param 	{Mixed} 	pParentObject 		Object or ID-String of the start-object
     * 		@param 	{String} 	pSearchID 			part of the ID to search
     * 		@param 	{Bool} 		pFirstOnly 			default=false ... return an array with all elements, true return the first object
     * 		@param 	{Int} 		pSearchDepth 		how deep do we search? default=255
     * 		@return	{Mixed}							Array with the result or first object, null if nothing found 
	 */
	pics.findById = function(pParentObject, pSearchID, pFirstOnly, pSearchDepth) 
	{
		return pics.findElement('id', pParentObject, pSearchID, pFirstOnly, pSearchDepth); 
	};	// pics.findById



	/**
	 * pics.findByClass()
	 *		find all child elements or the first of the given class 
     * 		@param 	{Mixed} 	pParentObject 		Object or ID-String of the start-object
     * 		@param 	{String} 	pSearchClass 		className to search
     * 		@param 	{Bool} 		pFirstOnly 			default=false ... return an array with all elements, true return the first object
     * 		@return	{Mixed}							Array with the result or first object, null if nothing found 
	 */
	pics.findByClass = function(pParentObject, pSearchClass, pFirstOnly, pSearchDepth) 
	{
		return pics.findElement('class', pParentObject, pSearchClass, pFirstOnly, pSearchDepth); 
	};	// pics.findByClass



	/**
	 * pics.findByTag()
	 *		find all child elements or the first of the given Tag 
     * 		@param 	{Mixed} 	pParentObject 		Object or ID-String of the start-object
     * 		@param 	{String} 	pSearchTag 			TAG to search
     * 		@param 	{Bool} 		pFirstOnly 			default=false ... return an array with all elements, true return the first object
     * 		@return	{Mixed}							Array with the result or first object, null if nothing found 
	 */
	pics.findByTag = function(pParentObject, pSearchTag, pFirstOnly, pSearchDepth) 
	{
		return pics.findElement('tag', pParentObject, pSearchTag.toUpperCase(), pFirstOnly, pSearchDepth); 
	};	// pics.findByTag

	/**
	 * pics.findByAttribute()
	 *		find all child elements or the first of the given combination attribute/value  
     * 		@param 	{Mixed} 	pParentObject 		Object or ID-String of the start-object
     * 		@param 	{String} 	pSearchAttribute	attribute to compare
     * 		@param 	{Bool} 		pFirstOnly 			default=false ... return an array with all elements, true return the first object
     * 		@return	{Mixed}							Array with the result or first object, null if nothing found 
	 */
	pics.findByAttribute = function(pParentObject, pSearchAttribute, pFirstOnly, pSearchDepth) 
	{
		return pics.findElement('attribute', pParentObject, pSearchAttribute, pFirstOnly, pSearchDepth); 
	},	// pics.findByAttribute

	/**
	 * pics.findByAttributeValue()
	 *		find all child elements or the first of the given combination attribute/value  
     * 		@param 	{Mixed} 	pParentObject 		Object or ID-String of the start-object
     * 		@param 	{String} 	pSearchAttribute	attribute to compare
     * 		@param 	{String} 	pSearchValue 		value to search
     * 		@param 	{Bool} 		pFirstOnly 			default=false ... return an array with all elements, true return the first object
     * 		@return	{Mixed}							Array with the result or first object, null if nothing found 
	 */
	pics.findByAttributeValue = function(pParentObject, pSearchAttribute, pSearchValue, pFirstOnly, pSearchDepth) 
	{
		return pics.findElement('attributevalue', pParentObject, pSearchValue, pFirstOnly, pSearchDepth, pSearchAttribute); 
	};	// pics.findByAttributeValue

	/**
	 * 	pics.findParent()
	 *			find the parent element of by tag or id
     * 		@param 	{Mixed} 	pStartObject 		Object or ID-String of the start-object
     * 		@param 	{String} 	pObjectType 		type to search, TD for example
     * 		@param 	{String} 	pSearchID 			(optional) part of the ID to search
     * 		@param 	{Int} 		pMaxLevels 			how many levels to try
     * 		@return	{Mixed}							found object, false if nothing found 
	 */
	pics.findParent = function(pStartObject, pObjectType, pSearchID, pMaxLevels) 
	{
		// is a ID or maxlevel set (wt: reduce function calls by native calls)
		if (typeof pSearchID == 'undefined')	pSearchID='';
		if (typeof pMaxLevels == 'undefined')	pMaxLevels=10;

		var lObjType=pObjectType.toUpperCase();
		var oParent=pStartObject;
		if (!oParent.parentNode) return false;
		for(var i=0;i<pMaxLevels;i++)
		{
			oParent=oParent.parentNode;
			if (!oParent.parentNode) return false;
			// is element of the given type
			if (oParent.nodeName==lObjType && oParent.attributes) 
			{
				// do we search by ID
				// if (pSearchID=='' || oParent.getAttribute("id").indexOf(pSearchID)!=-1) return oParent;
				if (pSearchID=='') return oParent;
				var lID=oParent.getAttribute("id");
				if (lID && lID.indexOf(pSearchID)!=-1) return oParent;
			} 
		}
		return false;		
	};	// pics.findParent



	/**
	 * pics.getByClassName()
	 *		get all elements with the given class 
     * 		@param 	{String} 	pClassName 			part of the ID to search
     * 		@return	{Array}							Array with the result , null if nothing found 
	 */
	pics.getByClassName = function(pClassName) 
	{
		var aAllObjects,aResult=new Array(),j=0,lClass;
	
		// get all the Objects
		if (document.all) 
		{
			aAllObjects=document.all;
		}
		else if(document.getElementsByTagName && !document.all)
		{
			aAllObjects=document.getElementsByTagName("*");			
		}
	    
		// walk through and test
	    for(var i=0;i<aAllObjects.length;i++)
	    {
			if(aAllObjects[i].className.indexOf(pClassName)!=-1)
			{
				lClass=","+aAllObjects[i].className.split(" ").join(",")+",";
				if(lClass.indexOf(","+pClassName+",")!=-1) aResult.push(aAllObjects[i]);
			} // if
	    } // for
	    return aResult;
	};	// pics.getByClassName


	/**
	 * pics.getPrevElement()
	 *		get the previous element of a given type, ignore whitespaces
     * 		@param 	object 	pElement 		element to start from
     * 		@param 	string 	pTagName 		if tagname is given, search for element of this type
     * 		@return	object					previous element
	 */
	pics.getPrevElement = function(pElement, pTagName) 
	{
		oElement=pElement;
		if (typeof pTagName == 'undefined')	pTagName='';
		while ((oElement = oElement.previousSibling)) 
		{
    		if (oElement.nodeType!=3 && oElement.nodeType!=8) 
			{
				// if not tagname is given, return the first element
				if (pTagName=='' || oElement.tagName==pTagName) return oElement;
			} // if
  		} // while
  		return null;
	};	// pics.getPrevElement

	/**
	 * pics.getPrevElement()
	 *		get the previous element of a given type, ignore whitespaces
     * 		@param 	object 	pElement 		element to start from
     * 		@param 	string 	pTagName 		if tagname is given, search for element of this type
     * 		@return	object					previous element
	 */
	pics.getPrevElement = function(pElement, pTagName) 
	{
		oElement=pElement;
		if (typeof pTagName == 'undefined')	pTagName='';
		while ((oElement = oElement.previousSibling)) 
		{
    		if (oElement.nodeType!=3 && oElement.nodeType!=8) 
			{
				// if not tagname is given, return the first element
				if (pTagName=='' || oElement.tagName==pTagName) return oElement;
			} // if
  		} // while
  		return null;
	};	// pics.getPrevElement

	/**
	 * pics.getNextElement()
	 *		get the next element of a given type, ignore whitespaces
     * 		@param 	object 	pElement 		element to start from
     * 		@param 	string 	pTagName 		if tagname is given, search for element of this type
     * 		@return	object					previous element
	 */
	pics.getNextElement = function(pElement, pTagName) 
	{
		oElement=pElement;
		if (typeof pTagName == 'undefined')	pTagName='';
		while ((oElement = oElement.nextSibling)) 
		{
    		if (oElement.nodeType!=3 && oElement.nodeType!=8) 
			{
				// if not tagname is given, return the first element
				if (pTagName=='' || oElement.tagName==pTagName) return oElement;
			} // if
  		} // while
  		return null;
	};	// pics.getNextElement


/* 
 * ==================================================================================================================
 * 		content functions
 * ==================================================================================================================
 */

	/**
	 * pics.setHTML(pElementID, pHtml)
	 *		set the innerHTML of an element
     * 		@param 	{Mixed} 	pElement 			element or ID of the element
     * 		@param 	{String} 	pHtml 				content for the element
	 */
	pics.setHTML = function(pElement, pHtml)
	{
		var oElement = (typeof pElement == 'string' ? document.getElementById(pElement) : pElement);
		// remember the current page position
		var lX=pics.getPageScrollX();
		var lY=pics.getPageScrollY();
		if (oElement.innerHTML) 
		{
			oElement.innerHTML = pHtml;
		}
		else
		{
			var oText = document.createTextNode(pHtml);
			oElement.appendChild(oText);	
		}
			
		// reset the page position
		window.scrollTo(lX,lY);
	}; // pics.setHTML

	/**
	 * pics.getHTML(pElementID)
	 *		get the innerHTML of an element
     * 		@param 	{Mixed} 	pElement 			element or ID of the element
	 */
	pics.getHTML = function(pElement)
	{
		var oElement = (typeof pElement == 'string' ? document.getElementById(pElement) : pElement);
		if (oElement.innerHTML) return oElement.innerHTML;		
		return '';
	}; // pics.getHTML
	
/* 
 * ==================================================================================================================
 * 		mathematic functions
 * ==================================================================================================================
 */


/* 
 * ==================================================================================================================
 * 		extension of javascript objects
 * ==================================================================================================================
 */










// -------OLD FUNCTIONS-----------------------------------------------------------------------------------------------------------

	
	/**
	 * pics.enableElements()
	 *	alle Elemente vom angegebenen Type deaktivieren
	 */
	 pics.enableElements = function(pElementType) 
	{
		var aSelect=document.getElementsByTagName(pElementType);
		for (var i=0;i<aSelect.length;i++)
		{
			aSelect[i].style.display='';
		}
	};
		
	/**
	 * pics.disableElements()
	 *	alle Elemente vom angegebenen Type aktivieren
	 */
	 pics.disableElements = function(pElementType) 
	{
		var aSelect=document.getElementsByTagName(pElementType);
		for (var i=0;i<aSelect.length;i++)
		{
			aSelect[i].style.display='none';
		}
	};	
	

	
	/**
	 * pics.getObjectTree(pElement)
	 *		liefert den Objektbaum ab pElement als HTML
	 *	@param	Object	pElement	Element das ausgegeben wird
	 */
	pics.getObjectTree = function(pElement)
	{
	    var lHtml;
	    lHtml = '<li>';
	    switch (pElement.nodeType) {
	        case 1 :
	            lHtml += '<strong>' + pElement.nodeName + '<\/strong>-Element';
	            if (pElement.hasChildNodes()) {
	                lHtml += ', ' + pElement.childNodes.length + ' Unterknoten';
	            }
				// wenn es eine ID gibt
				if (pElement.id) lHtml += ', id='+pElement.id;
				if (pElement.name) lHtml += ', name='+pElement.name;
				if (pElement.value) lHtml += ', value='+pElement.value;
	            break;
	        case 3 :
	            var knotenwert = pElement.nodeValue.replace(/</g, '&lt;').replace(/\n/g, '\\n');
	            lHtml += 'Textknoten: [<strong>' + knotenwert + '<\/strong>]';
	            break;
	        case 8 :
	            var knotenwert = pElement.nodeValue.replace(/</g, '&lt;').replace(/\n/g, '\\n');
	            lHtml += 'Kommentarknoten: [' + knotenwert + ']';
	            break;
	        default :
	            lHtml += 'Knoten des Typs ' + pElement.nodeType +
	                ', Wert: [' + pElement.nodeValue + ']';
	    }
	    if (pElement.hasChildNodes()) {
	        lHtml += '\n<ol>\n';
	        for (var i = 0; i < pElement.childNodes.length; i++) {
	            knotenneu = pElement.childNodes[i];
	            lHtml += pics.getObjectTree(knotenneu); // Rekursion
	        }
	        lHtml += '</ol>\n';
	    }
	    lHtml += '</li>\n';
	    return lHtml;
	};	// pics.getObjectTree(pElement)

	
	


	/**
	 * pics.swapElements(pElementIDOld, pElementIDNew)
	 *		blendet da pElementIDOld aus und das pElementIDEin
	 *	@param	string	pElementIDOld	ID des Elements, das ausgeblendet wird
	 *	@param	string	pElementIDNew	ID des Elements, das eingeblendet wird
	 */
	pics.swapElements = function(pElementIDOld, pElementIDNew)
	{
		if (document.getElementById(pElementIDOld)) document.getElementById(pElementIDOld).style.display='none';		
		if (document.getElementById(pElementIDNew)) document.getElementById(pElementIDNew).style.display='';		
	};	
	
	/**
	 * pics.setStyle
	 *		Stil eines Elements ändern, alten Speichern
	 *	@param	object	pElement	zu änderndes Objekt
	 *	@param	string	pStyle		Neuer Stil ( leer für Reset )
	 *	@return	
	 */
	pics.setStyle = function(pElement,pStyle)
	{
		if (typeof pStyle == 'undefined') pStyle='';

		// Aktuellen Stil auslesen und alle anderen Formatierungen entfernen außer wenn Aktiv
		var lStyle = pElement.className;
		
		if (pStyle!='')
		{
			// alten Stil merken und neuen setzen
			pElement.setAttribute("oldstyle",lStyle);
			pElement.className=pStyle;
		}
		else
		{
			// alten Stil setzen
			lStyle=pElement.getAttribute("oldstyle");
			pElement.className=lStyle;
		}
	}; // pics.setStyle

	/**
	 * pics.show(pElement)
	 *		sets the display attribute to ''
	 * 		@param 	{Mixed} 	pElement 			element or ID of the element
	 */
	pics.show = function(pElement)
	{
		var oElement=pics.obj(pElement);
		oElement.style.display='';
	}; // pics.show

	/**
	 * pics.show(pElement)
	 *		sets the display attribute to 'none'
	 * 		@param 	{Mixed} 	pElement 			element or ID of the element
	 */
	pics.hide = function(pElement)
	{
		var oElement=pics.obj(pElement);
		oElement.style.display='none';
	}; // pics.hide
	
	/**
	 * pics.showHideElement
	 *		 Element mit dem angegebenen Namen einblenden, ausblenden oder umschalten
	 *	@param	string	pElementID	ID des Elements
	 *	@param	bool	pShow		ein-/ausblenden ? wenn nicht angegeben, dann umschalten
	 *	@param	bool	pRemember	letztes Element umschalten und merken
	 *	@param	int		pDelay		Verzögerung von x ms zum ausführen
	 *	@return	
	 */
	pics.showHideElement = function(pElementID, pShow, pRemember, pDelay)
	{
		if (typeof pElementID=='undefined') pElementID=null;
		if (typeof pShow=='undefined') pShow=null;
		if (typeof pRemember=='undefined') pRemember=false;
		if (typeof pics.lastShowHideElement=='undefined') pics.lastShowHideElement='';
		if (typeof pDelay=='undefined') pDelay=0;

		// Parameter im Debug-Layer ausgeben
//		pics.debugLog+=pElementID+' - '+pShow+' - '+pRemember+' - '+pDelay+' : ('+pics.lastShowHideElement+')<br>';
//		pics.setHTML('divDebug',pics.debugLog);
		
		// falls es einen Timer gibt, diesen reseten
		if (pics.timerShowHideElement!=null)
		{
			window.clearTimeout(pics.timerShowHideElement);
			pics.timerShowHideElement=null;
		}

		// verzögerte deaktivierung
		if (pElementID==null && pDelay>0 && pics.lastShowHideElement!='') 
		{
			pics.timerShowHideElement=window.setTimeout("pics.showHideElement('"+pics.lastShowHideElement+"',"+!pShow+")", pDelay);
			return true;
		}

		// Bei verzögerter Deaktivierung das letzte Element zurücksetzen
//		if (pics.lastShowHideElement==pElementID) pics.lastShowHideElement='';
		
		// wenn pRemember, dann letztes ausschalten
		if (pRemember && pics.lastShowHideElement!='' && pics.lastShowHideElement!=pElementID) pics.showHideElement(pics.lastShowHideElement, !pShow);

		// wenn Element NULL, dann raus hier
		if (pElementID==null) return true;

		// wenn ein Delay, dann ein timeout darauf setzen
		if (pDelay>0)
		{
			pics.timerShowHideElement=window.setTimeout("pics.showHideElement('"+pElementID+"',"+pShow+","+pRemember+")", pDelay);
			return true;
		}
		
		
		var oElement=document.getElementById(pElementID);
//		if (pShow=='' && pShow!=false)
		if (pShow==null)
		{
		// wenn nicht angegeben, dann umschalten
			if (oElement.style.display=='')
			{ 
				oElement.style.display='none';
			}
			else
			{
				oElement.style.display='';
			}
		}
		else
		{
			// sonst ein/ausblenden
			if (pShow)
			{ 
				oElement.style.display='';
			}
			else
			{
				oElement.style.display='none';
			}
			if (pRemember) pics.lastShowHideElement=pElementID;
		}
		return true;
	}; // pics.showHideElement

	/**
	 * pics.showHideClearTimer()
	 *		 Timer zum Ausblenden eines Elements deaktivieren
	 *	@return	
	 */
	pics.showHideClearTimer = function()
	{
		// falls es einen Timer gibt, diesen reseten
		if (pics.timerShowHideElement!=null)
		{
			window.clearTimeout(pics.timerShowHideElement);
			pics.timerShowHideElement=null;
		}
	};
	
	/**
	 * pics.showHideElements
	 *		alle Elemente mit dem angegebenen Namen einblenden, ausblenden oder umschalten
	 *	@param	string	pName		Name der Elemente
	 *	@param	bool	pShow		ein-/ausblenden ? wenn nicht angegeben, dann umschalten
	 *	@return	
	 */
	pics.showHideElements = function(pName,pShow)
	{
		oElements=document.getElementsByName(pName);
		alert('pruefe '+oElements.length+' Elemente');
		for (i=0;i<oElements.length;i++)
		{
			if (typeof pShow=='undefined')
			{
			// wenn nicht angegeben, dann umschalten
				if (oElements[i].style.display=='')
				{ 
					oElements[i].style.display='none';
				}
				else
				{
					oElements[i].style.display='';
				}
			}
			else
			{
				// sonst ein/ausblenden
				if (pShow)
				{ 
					oElements[i].style.display='';
				}
				else
				{
					oElements[i].style.display='none';
				}
			}
		}
	}; // pics.showHideElements


	/**
	 * pics.setLoading
	 *		Loading-Animation anzeigen
	 *	@param	object	pElement	zu änderndes Objekt
	 *	@return	
	 */
	pics.setLoading = function(pElementID)
	{
		lHtml='<table width="100%" border="0" height="100%"><tr><td align="center"><img src="images/loading.gif" width="100" height="100" border="0"></td></tr></table>';
		pics.setHTML(pElementID,lHtml);
	};	// pics.setLoading
	

// ====== MENUE-FUNKTIONEN ==========
	
	
	pics.menuLast='';
	pics.menuTimer=null;
	
	// Menü mit x Minuten verzögerung anzeigen
	pics.menuShow = function(pMenu, pWait,pElement,pX,pY)
	{
		if (typeof pMenu=='undefined') pMenu='';	// aktuelles ausblenden
		if (typeof pWait=='undefined') pWait=500;	// Verzoegerung
		if (typeof pX=='undefined') pX=false;		// X-Position anpassen
		if (typeof pY=='undefined') pY=false;		// Y-Position  anpassen
		
		// muessen wir das Element verschieben?		
		if (pElement && pX)
		{
			lX=pics.getEX(pElement);
			document.getElementById(pMenu).style.left=lX+'px';
		}		
		if (pElement && pY)
		{
			lY=pics.getEY(pElement);
			document.getElementById(pMenu).style.top=lY+'px';
		}		
		
		// wenn das aktuelle angezeigt werden soll, dann gleich raus hier
		if (pMenu==pics.menuLast) 
		{
			pics.menuClearTimer();
			return false;
		}
		// läuft ein Timer, dann diesen reseten
		pics.menuClearTimer();
		
		if (pMenu=='')
		{
			// letztes Menü ausblenden
			pics.menuTimer=window.setTimeout("pics.menuHide('"+pics.menuLast+"')", pWait);
		}
		else
		{
			// existiert ein altes, dann dieses sofort ausblenden
			if (pics.menuLast!='') pics.menuHide(pics.menuLast);
			// und das neue verzögert einblenden
			pics.menuTimer=window.setTimeout("pics.showHideElement('"+pMenu+"',true)", pWait);
			pics.menuLast=pMenu;
		}
		return true;
	}; // doMenu

	pics.menuHide = function()
	{
		pics.showHideElement(pics.menuLast,false);
		pics.menuLast='';
	};


	pics.menuClearTimer = function()
	{
		if (pics.menuTimer!=null)
		{
			window.clearTimeout(pics.menuTimer);
			pics.menuTimer=null;
		}			
	};	

	
// ====== TASTENHANDLING ==========

	/**
	 * pics.checkKey
	 *		Prüfen auf Tast, und dann Aktion ausführen
 	 *	@param	object	pEvent	event-Referenz
	 *	@param	string	pFunction	zu auszuführende Funktion
	 *	@param	int		pKey	zu pruefende Taste, default = 13 ( ENTER )
	 */
	pics.checkKey = function(pEvent, pFunction, pKey)
	{
		if (typeof pEvent == 'undefined') 		return false;
		if (typeof pFunction == 'undefined') 	return false;
		if (typeof pKey == 'undefined') 		pKey=13;

		lKey= pEvent.which || pEvent.keyCode;
		if (lKey==pKey) eval(pFunction);
		
		return false;
	}; // checkKey	


// ====== HELPER FUNCTIONS ==========

	/**
	 * pics.getTS
	 *		returns current timestamp
	 */
	pics.getTS = function()
	{
		return (new Date().getTime());
	}; // pics.getTS	
	
	/**
	 * pics.trim
	 *		similar to php trim
	 */
	pics.trim = function(pString) {
		return pString.replace(/^\s+|\s+$/g,"");
	}; // pics.trim	
		
	
// ====== STRING / MAIL ==========

	/**
	 * pics.validateMail
	 *		E-Mail-Adresse validieren
	 *	@param	string	pMail	zu pruefende Adresse
	 *	@return	bool true/false ob valid
	 */
	pics.validateMail = function(pMail)
	{
		var lReg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*\.(\w{2}|(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum))$/;
		return lReg.test(pMail);
	}; // validateMail	
	

	
// ====== ZAHLENFORMATIERUNG =====	
	/**
	 * pics.formatNumber((pZahl, pKommastellen, pKomma, pTausender)
	 *		formatiert eine Zahl für die Ausgabe
	 *	@param	float	pZahl			zu formatierende Zahl
	 *	@param	int		pKommastellen	Anzahl der Kommastellen, default=2
	 *	@param	string	pKomma			Kommazeichen, default=,
	 *	@param	string	pTausender		Tausendertrennzeichen, default=.
	 */
	pics.formatNumber = function(pZahl, pKommastellen, pKomma, pTausender)
	{
		// Parameter prüfen und zur not überschreiben
		if (typeof pZahl			=='undefined') return 0;
		if (typeof pKommastellen	=='undefined') pKommastellen=2;
		if (typeof pKomma			=='undefined') pKomma=',';
		if (typeof pTausender		=='undefined') pTausender='.';

		// Übergebenen Wert in Zahl umwandeln
		// lZahl=pics.clearNumber(pZahl);
		lZahl=pZahl*1;
		// kürzen auf Kommastellen und PUNKT in KOMMA ändern
		lZahl= lZahl.toFixed(pKommastellen).replace(".", pKomma);
		// Müssen wir 1000er-Zeichen einführen ?
		if (pTausender!='')
		{
			// dann suchen wir die Position des Kommas
			lPosKomma=lZahl.indexOf(pKomma);
			lPos=lPosKomma-3;
			// und jetzt alle Zeichen davor in 3er-Gruppen splitten
			while(lPos>0)
			{
				if (lZahl.slice(0,lPos)!='-') lZahl=lZahl.slice(0,lPos)+pTausender+lZahl.slice(lPos);
				lPos=lPos-3;
			}
		}	
		return lZahl;
	};  // pics.formatNumber
	
	/**
	 * pics.clearNumber((pZahl, pKomma, pTausender)
	 *		wandelt einen String in eine Zahl um indem Sonderzeichen entfernt werden
	 *	@param	string	pZahl			zu formatierende Zahl
	 *	@param	string	pKomma			Kommazeichen, default=,
	 *	@param	string	pTausender		Tausendertrennzeichen, default=.
	 */
	pics.clearNumber = function(pZahl, pKomma, pTausender)
	{
		// Parameter prüfen und zur not überschreiben
		if (typeof pZahl			=='undefined') return 0;
		if (typeof pKomma			=='undefined') pKomma=',';
		if (typeof pTausender		=='undefined') pTausender='.';
		
		// Schritt 1 - Tausender entfernen
		// lZahl=pZahl.replace(/\./,'');
		// das mit dem Replace war nicht so zuverlässig, daher mach ich das mit einer Schleife
		lZahl=pZahl+'';
		while (lZahl.indexOf(pTausender)>0)
		{
			lZahl=lZahl.replace(pTausender,'');
		}
		// jetzt noch das Komma in den Punkt umwandeln
		lZahl=lZahl.replace(pKomma,'.');
		// schritt 2 - in Zahl umwandeln
		lZahl=parseFloat(lZahl);
		// wenn keine Zahl, dann 0
		if (isNaN(lZahl)) lZahl=0;
		return lZahl;
	};  // pics.clearNumber

	/**
	 * pics.isDate(pDate)
	 *		prüft einen Wert, ob es ein Datum ist
	 *	@param	string	pDate			zu prüfendes Datum
	 *	@return	bool	true/false
	 */
	pics.isDate = function(pDate)
	{
		if (pDate=='') return false;
// Weil ich gerade keine einzelne regex finde probier ich es mit mehreren
// die erst ist für nur Datum, die 2. ist für Datum+Zeit, 3. für datum+Zeit+Sek
//		aDate = pDate.match(/^((\d\d)?\d\d)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/);
//		aDate = pDate.match(/^((\d\d)?\d\d)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$|^((\d\d)?\d\d)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)\s(\d\d)\:\d\d$|^((\d\d)?\d\d)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)\s(\d\d)\:\d\d\:\d\d$/);
		aDate = pDate.match(/^(\d+)[\/\.-](\d+)[\/\.-]((\d\d)?\d\d)$|^((\d\d)?\d\d)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)\s(\d\d)\:\d\d$|^((\d\d)?\d\d)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)\s(\d\d)\:\d\d\:\d\d$/);
		if (aDate) return true;
		return false;
	};  // pics.isDate
	

	/**
	 * pics.convertDate(pDate)
	 *		Wandelt einen beliebigen Datum/Zeit-String in einen String der Form yyyymmddhhnnss um
	 * 		gültige Zeitformate sind hh:nn und hh:nn:ss
	 * 		gültige Datumsformate sind yyyy-mm-dd, dd.mm.yyyy, mm/dd/yyyy
	 *	@param	string	pDate			zu prüfendes Datum
	 *	@return	bool	true/false
	 */
	pics.convertDate = function(pDate)
	{
		var aDatum = new Array('0000','00','00','00','00','00');
	
		// Schritt 1 - Datum und Zeit trennen
		var aParts=pDate.split(' ');
		// Datum / Zeit vorbelegen
		var lDate='';
		var lTime='';
		
		// Ist der erste Teil Datum oder Zeit?
		if (aParts[0].indexOf(':')>0)
		{
			// Zeit
			lTime=aParts[0];
			if (aParts.length>1) lDate=aParts[1];
		}
		else
		{
			// Datum
			lDate=aParts[0];
			if (aParts.length>1) lTime=aParts[1];
		}
		
	//	alert(pDate+' = '+lDate+' / '+lTime);
		
		// jetzt splitten
		if (lTime!='')
		{
			aTime = lTime.split(':');
			for(var i=0;i<aTime.length;i++) { aDatum[3+i]='00'+aTime[i]; aDatum[3+i]=aDatum[3+i].substr(aDatum[3+i].length-2); }
		}
		if (lDate!='')
		{
			if (lDate.indexOf('.')>0)
			{
				aDate=lDate.split('.');
				aDatum[0]='00'+aDate[2];
				aDatum[1]='00'+aDate[1];
				aDatum[2]='00'+aDate[0];
			}
			else if (lDate.indexOf('-')>0)
			{
				aDate=lDate.split('-');
				aDatum[0]='00'+aDate[0];
				aDatum[1]='00'+aDate[1];
				aDatum[2]='00'+aDate[2];
			}
			else if (lDate.indexOf('/')>0)
			{
				aDate=lDate.split('/');
				aDatum[0]='00'+aDate[2];
				aDatum[1]='00'+aDate[0];
				aDatum[2]='00'+aDate[1];
			}
			aDatum[0]=aDatum[0].substr(aDatum[0].length-4);
			aDatum[1]=aDatum[1].substr(aDatum[1].length-2);
			aDatum[2]=aDatum[2].substr(aDatum[2].length-2);
		}
	//	alert(pDate+':'+lDate+' / '+lTime+' ('+aDatum+')');
		return aDatum.join('');
	};  // pics.convertDate
	
	
/* 
 *	====================================================================================
 *	===== GLOBALE INITALISIERUNG													====
 *	====================================================================================
 */
	/**
	 * pics.onLoad(pFunction)
	 *		Fügt dem window.onload Event einen Funktionsaufruf hinzu 
	 *		um mehrere OnLoads aus unterschiedlichen Scripts zu managen
	 *
	 *		pics.onLoad(init); 								=> nur Funktion ohne Parameter aufrufen
	 *		pics.onLoad(function(){ init('Wert 1') });		=> Funktion mit Parameter aufrufen
	 *
	 *	@param	function 	pFunction			Funktion für Aufruf beim Laden der Seite
	 *	@return	bool		true/false
	 */
	pics.onLoad = function(pFunction) 
	{
		if (typeof window.addEventListener!="undefined") {
			window.addEventListener("load",pFunction,false);
		}
		else if (typeof window.attachEvent!="undefined") {
			window.attachEvent("onload",pFunction);
		}
		else 
		{
			if (window.onload!= null) {
				var oldOnload = window.onload;
				window.onload = function (e) {
					oldOnload(e);
					window[pFunction]();
				};
			}
			else window.onload = pFunction;
		}
	}; // pics.onLoad
	 
// pics-Framework-Initialisieren
	pics.init();






