/*****************************************************************************************************************/
/*                                                JAVASCRIPT CALENDER                                            */
/*                                               (c)2007 PANATOM (fh)                                            */
/*                                                                                                               */
/* this script contains following classes                                                                        */
/*     Calender.Chart                                                                                            */
/*     Calender.Incrementer                                                                                      */
/*                                                                                                               */
/*                                                                                      last modified 09-03-2007 */
/*****************************************************************************************************************/





/*****************************************************************************************************************/
/* BEGIN OF CALENDER                                                                                             */
/*****************************************************************************************************************/	
var Calender = {

	calenderCollection : new Array(),									// collection of Calender objects

/*****************************************************************************************************************/
/* CALENDER ATTRIBUTES //can be changed from outside by Calender.attributename = attributevalue;                 */
/*****************************************************************************************************************/	

	imagePath : 'templates/kita/images/calender/',												// common path to the image files
	imageIcon : 'calender.gif',											// image file for the calender icon
	imageUp : 'arrow_up.gif',											// image file for arrow up of incrementer
	imageDown : 'arrow_down.gif',										// image file for arrow down of incermenter
	imageLeft : 'arrow_left.gif',										// image file for arrow left in calender scroll
	imageRight : 'arrow_right.gif',										// image file for arrow right in calender scroll
																				
	translApply : 'anwenden',												// translation for 'apply'
	translCancel : 'abbrechen',											// translation for 'cancel'
	translStart : 'Start',												// translation for 'start'
	translEnd : 'Ende',													// translation for 'end'
	translTime : 'Zeit',												// translation for 'time'
	translSuccesionError : 'ERROR : The first date should be before the second date!', // translation for succesion error message
	translWeek : ["So","Mo","Di","Mi","Do","Fr","Sa"],							// translation for weekday shortnames
	translMonth : ["Januar","Februar","März","April","Mai","Juni",	// translation for monthnames
	"Juli","August","September","Oktober","November","Dezember"],		
	
	colorBackground : '#FFFFFF',										// color of the calender background
	colorForeground : '#000000',										// color of the calender font and lines
	colorForegroundInactive : '#DDDDDD',								// color of the calender inactive elements
	colorHighlight : '#FF0000',											// color of the calender highlighted elements
	colorHighlightInactive : '#FFDDDD',									// color of the calender inactive hightlighted elements
	colorMarker : '#CCCCCC',											// color of the marker
	
																		// following attributes can also be set specific to each Calender 
	widthOfMonth : 220,													// width of the month in pixel
	incremDiffHour : 1,													// difference in hour incrementer
	incremDiffMinute : 15,												// difference in minute incrementer
	incremDiffSecond : 1,												// difference in second incrementer
	
	
	
	
/*****************************************************************************************************************/
/* CALENDER FUNCTIONS                                                                                               */
/*****************************************************************************************************************/	
	
	/**
	* calls in all input elements of the document their onload function if there is one
	*/	
	onLoadFormElements : function(){
		var input = document.getElementsByTagName('input');
		var inputs = new Array;
		var string='';

		for(var i=0;i<input.length;i++){
			if(input[i].attributes.onload){
				if(input[i].attributes.onload.value!='null'){
					inputs.push(input[i]);
				}
			}
		}
		for(var k=0;k<inputs.length;k++){
				inputs[k].onload = function(){eval(inputs[k].attributes.onload.value)};
				inputs[k].onload();			
				inputs[k].onload = null;
		}
	},
			
	
	/**
	* closes all dialogs of calender object, being hold in th Calender.calenderCollection array (use initialize for creating a calender!)
	* (if Dater is defined, then it closes also all Dater dialogs)
	*/	
	closeAllDialogs : function(){
		for(var i=0;i<Calender.calenderCollection.length;i++){
			Calender.calenderCollection[i].closeDialog();
		}
		if(typeof Dater != 'undefined')
			for(var i=0;i<Dater.daterCollection.length;i++){
				Dater.daterCollection[i].closeDialog();
			}
	},
	

	/**
	* compares two Calenders, if the ones date is before the others
	* @param	element:input			input element that has a calender connected
	* @param	element:input			input element that has a calender connected
	* @return 	bool					the first date is before the second
	*/	
	checkSuccesion : function(firstCalenderObj,secondCalenderObj){
		if(firstCalenderObj.type=='text')
			firstCalenderObj = firstCalenderObj.previousSibling;
		if(secondCalenderObj.type=='text')
			secondCalenderObj = secondCalenderObj.previousSibling;

		if(firstCalenderObj.value <= secondCalenderObj.value){
			return true; 
		}else{
			//alert(Calender.translSuccesionError);
			return false;
		}
	},
	
	
	/**
	* replaces an HTML input element within an timestamp value by an readonly field and a button to select the day in an calender
	* @param	element					input element (text)
	* @param	int 					min timestamp displayed in calender (0 for all)
	* @param	int 					max timestamp displayed in calender (0 for all)
	* @param	string 					date format to display and to edit (D d M m Y y H h I i S s)
	* @return 	object:Calender			the calender object
	*/
	initialize : function(objInput,minTs,maxTs,format,calType){
		if (!calType)
			var calType = null;

			
		var obj = new Calender.Chart(objInput,minTs,maxTs,format,calType);
		Calender.calenderCollection.push(obj);
		return obj;
	},
	

	/**
	* aligns an element to a cursor poisition where an event accured
	* @param	element					element to be aligned
	* @param	event 					event that accured
	*/	
	alignToMouse : function(obj,evt){
		/*if(obj.offsetParent.tagName=="BODY"){
			obj.style.left  = (evt.clientX) ? evt.clientX : evt.pageX ;
			obj.style.top = (evt.clientY) ? evt.clientY : evt.pageY ;
		}else{
			obj.style.left  = (evt.pageX) ? evt.pageX : obj.offsetLeft ;
			obj.style.top = (evt.pageY) ? evt.pageY : obj.offsetTop ;
		}*/
		
		var posx = 0;
		var posy = 0;
		if (!evt) var evt = window.event;
		if (evt.pageX || evt.pageY) 	{
			posx = evt.pageX;
			posy = evt.pageY;
		}
		else if (evt.clientX || evt.clientY) 	{
			posx = evt.clientX + document.body.scrollLeft
				+ document.documentElement.scrollLeft;
			posy = evt.clientY + document.body.scrollTop
				+ document.documentElement.scrollTop;
		}		
		
		/*
		obj.style.left = '10px';//(parseInt(obj.style.left) - parseInt(obj.offsetParent.style.left)) + 'px';
		obj.style.top = '10px';//(parseInt(obj.style.top) - parseInt(obj.offsetParent.style.top)) + 'px';
		*/
		
		obj.style.left = parseInt(posx) - parseInt(obj.parentNode.parentNode.offsetLeft) + 10 + 'px';
		obj.style.top = parseInt(posy) - 170  + 'px';
		
		//alert(parseInt(obj.parentNode.parentNode.offsetLeft) +' -- '+parseInt(posx));
		
	},
	
	
	/**
	* formats a figure
	* @param	int						figure to be formated
	* @param	int						min number of leading figures, if neccesary, filled up with zeros
	* @param	int						min number of floating figures, if neccessary, filled up with zeros
	* @param	bool 					if floating figures are longer then then minimum, cut them at the min position
	* @return 	string 					formated figure
	*/	
	formatFigure : function(fig,lead,float_,stripFloat){
		var i,numb = (fig.toString()).split(".");
		var out1 = numb[0],out2='';
		for(i=0;i<(lead-numb[0].length);i++)
			out1='0'+out1;
		for(i=0;i<((stripFloat)?(float_):(Math.max(numb[1].length,float_)));i++)
			out2+=(numb[1].charAt(i))?numb[1].charAt(i):'0';
		return out1+((out2.length>0)?'.'+out2:'');
	},
	
	
	/**
	* formats a timestamp to a date format
	* @param 	string					format (D d M m Y y H h I i S s)
	* @param	int						the timestamp (if 0 then now)
	* @return 	string 					formated date
	*/
	formatDate : function(format,timestamp){
		var time = new Date();
		if(timestamp>0)
			time.setTime(timestamp*1000);
		format = format.replace(/d/,time.getDate());
		format = format.replace(/D/,Calender.formatFigure(time.getDate(),2,0,1));
		format = format.replace(/m/,time.getMonth()+1);
		format = format.replace(/M/,Calender.formatFigure(time.getMonth()+1,2,0,1));
		format = format.replace(/y/,time.getFullYear());
		format = format.replace(/Y/,time.getFullYear());
		format = format.replace(/h/,time.getHours());
		format = format.replace(/H/,Calender.formatFigure(time.getHours(),2,0,1));
		format = format.replace(/i/,time.getMinutes());
		format = format.replace(/I/,Calender.formatFigure(time.getMinutes(),2,0,1));
		format = format.replace(/s/,time.getSeconds());
		format = format.replace(/S/,Calender.formatFigure(time.getSeconds(),2,0,1));
		return format;
	},
	
	
	/**
	* gets the first timestamp of an entity defined by an timestamp that contains to the entity (some entities can be specified by parting)
	* @param 	int						timestamp that is contained by the entity
	* @param	string					the entity ('year','month','day{_[0-23]}','hour{_[0-59]}','minute{_[0-59]}','second')
	* @return 	int 					the first timestamp of the entity
	*/
	getFirstTsOf : function(timeStamp,entity){
		var date = new Date();
		var pats = 0;
		var quant = (entity.indexOf('_')>0 && entity.indexOf('_')<entity.length)?entity.substring(entity.indexOf('_')+1,entity.length):0;
		
		date.setTime(timeStamp*1000);
		if(pats = (entity.indexOf('year')+1) ? 1 : pats)
			date.setMonth(0);
		if(pats = (entity.indexOf('month')+1) ? 1 : pats)
			date.setDate(1);
		if(pats = (entity.indexOf('day')+1) ? 1 : pats){
			if(quant)
				date.setHours(date.getHours()-(date.getHours()%quant));
			else
				date.setHours(0);
		}
		if(pats = (entity.indexOf('hour')+1) ? 1 : pats){
			if(quant)
				date.setMinutes(date.getMinutes()-(date.getMinutes()%quant));
			else
				date.setMinutes(0);
		}
		if(pats = (entity.indexOf('minute')+1) ? 1 : pats){
			if(quant)
				date.setSeconds(date.getSeconds()-(date.getSeconds()%quant));
			else
				date.setSeconds(0);
		}
		return Math.floor(date.getTime()/1000);
	},
	
	
	/**
	* gets the last timestamp of an entity defined by an timestamp that contains to the entity (some entities can be specified by parting)
	* @param 	int						timestamp that is contained by the entity
	* @param	string					the entity ('year','month','day{_[0-23]}','hour{_[0-59]}','minute{_[0-59]}','second')
	* @return 	int 					the last timestamp of the entity
	*/
	getLastTsOf : function(timeStamp,entity){
		var date = new Date();
		var pats = 0;
		var quant = (entity.indexOf('_')>0 && entity.indexOf('_')<entity.length)?entity.substring(entity.indexOf('_')+1,entity.length):0;
		date.setTime(timeStamp*1000);
		if(pats = (entity.indexOf('year')+1) ? 1 : pats)
			date.setMonth(11);
		if(pats = (entity.indexOf('month')+1) ? 1 : pats){
			day = 31;
			date.setDate(day);
			while(date.getDate()<28){
				day--;
				date.setDate(day);
				date.setMonth(date.getMonth()-1);
			}
		}
		if(pats = (entity.indexOf('day')+1) ? 1 : pats){
			if(quant)
				date.setHours(date.getHours()*(quant-(date.getHours()%quant)-1));
			else
				date.setHours(23);
		}
		if(pats = (entity.indexOf('hour')+1) ? 1 : pats){
			if(quant)
				date.setMinutes(date.getMinutes()*(quant-(date.getMinutes()%quant)-1));
			else
				date.setMinutes(59);
		}
		if(pats = (entity.indexOf('minute')+1) ? 1 : pats){
			if(quant)
				date.setSeconds(date.getSeconds()*(quant-(date.getSeconds()%quant)-1));
			else
				date.setSeconds(59);
		}
		return Math.floor(date.getTime()/1000);
	},
	
	
	/**
	* gets a break line element
	* @param 	string					clearing float ('none','left','right','both')
	* @return 	element 				br element
	*/
	getBrElement : function(float_){
		var br = document.createElement('br');
		br.setAttribute("style","height:1px;font-size:1px");
		br.clear=float_;
		return br;
	},

	

	
/*****************************************************************************************************************/
/* CLASSES ** CLASSES ** CLASSES ** CLASSES ** CLASSES ** CLASSES ** CLASSES ** CLASSES ** CLASSES ** CLASSES ** */
/*****************************************************************************************************************/




/*****************************************************************************************************************/
/* CHART                                                                                                         */
/*****************************************************************************************************************/	
	
	// BEGIN  - CHART
	
	/**
	* Constructor of a Chart
	* @param 	element					the text input field
	* @param 	int						min timestamp the calender displays
	* @param 	int						max timestamp the calender displays
	* @param 	string					date format
	*/
	Chart : function(objInput,minTs,maxTs,format,calType){
		this.objInput = objInput;
		this.minTs = minTs;
		this.maxTs = maxTs;		
		this.format = format;
		
		this.widthOfMonth = Calender.widthOfMonth;													// width of a month in pixel
		this.incremDiffHour = Calender.incremDiffHour;												// difference in hour incrementer
		this.incremDiffMinute = Calender.incremDiffMinute;											// difference in minute incrementer
		this.incremDiffSecond = Calender.incremDiffSecond;											// difference in second incrementer

		if(!(this.objInput.value>0)){																// if no timestamp available, take current one
			
			tempTime = new Date();
			//tempTime.setHours(0);
			if (calType=='begin') {
				tempTime.setHours(0);
				tempTime.setMinutes(0);
				tempTime.setSeconds(0);
			}	
			else if (calType=='end') {	
				tempTime.setHours(23);
				tempTime.setMinutes(59);
				tempTime.setSeconds(59);				
			}	
			
			tsTemp = parseInt(tempTime.getTime()/1000);
			
			this.objInput.value = tsTemp;

			//updateCommit(this.objInput,'upd');
		}
		
		this.icon = document.createElement('img');													// create icon
		this.icon.src = Calender.imagePath+Calender.imageIcon;
		this.icon.width=16;
		this.icon.height=16;
		this.icon.style.cursor = 'pointer';

		this.icon.className = 'calenderIcon';
		
		ts = this.objInput.value;																	// round timestamp to the incrementers needs
		ts = Calender.getFirstTsOf(ts,'day_'+this.incremDiffHour);
		ts = Calender.getFirstTsOf(ts,'hour_'+this.incremDiffMinute);
		ts = Calender.getFirstTsOf(ts,'minute_'+this.incremDiffSecond);
		this.objInput.value = ts;
		
		id = this.objInput.id;
	 	this.objInput.id = null;
		
		this.objInput.style.verticalAlign = 'top';
		
		this.objHidden = document.createElement('input');											// create hidden input, holding the timestamp
		this.objHidden.type = 'hidden';
		this.objHidden.id = id;
		this.objHidden.onchange = this.objInput.onchange;
		this.objHidden.onupdate = this.objInput.onupdate;
		this.objHidden.name = this.objInput.name;
		this.objHidden.value = this.objInput.value;
		
		this.objInput.readOnly = 'enabled';															// manipulate text input
		
		
		if (parseInt(this.objInput.offsetWidth)>0)
			this.objInput.style.width = (parseInt(this.objInput.offsetWidth)-20)+'px';
		else if (this.objInput.parentNode.style.display == 'none') {
			this.objInput.parentNode.style.display = 'block';				
			
			//this.objInput.style.width = (parseInt(this.objInput.offsetWidth)-20)+'px';
			this.objInput.style.width = '0px';
			this.objInput.parentNode.style.display = 'none';
		}	
		else if (parseInt(this.objInput.style.width)>0) {
			this.objInput.style.width = (parseInt(this.objInput.style.width)-20)+'px';
		}
		else {
			
			this.objInput.style.width = '84px';
		}

		
		this.objInput.name = null;
		this.objInput.value = Calender.formatDate(this.format,this.objInput.value);
		
		this.objInput.parentNode.insertBefore(this.objHidden,this.objInput);						// insert hidden input and icon
		this.objInput.parentNode.insertBefore(this.icon,this.objInput.nextSibling);		
		
		this.time = new Date();																		// set time
		this.time.setTime(this.objHidden.value*1000);
		
		var obj = this;
		this.icon.onclick = function(evt){															// icon onclick eventhandler
			if(!obj.dialog){
				obj.openChart(evt);
			}else{
				obj.closeDialog();
			}
		}
		this.objInput.onclick = function(evt){															// icon onclick eventhandler
			if(!obj.dialog){
				obj.openChart(evt);
			}else{
				obj.closeDialog();
			}
		}		
		
		/* Chart *
		* sets the date format
		* @param 	string					date format
		*/			
		this.setFormat = function(format){
			this.format = format;
			this.objInput.value = Calender.formatDate(this.format,this.objHidden.value);
		}
		
		
		
		/* Chart *
		* opens the chart dialog
		* @param 	event					event that activated this action
		*/	
		this.openChart = function(evt){
			var obj = this;
			Calender.closeAllDialogs();																	// close all dialogs
			this.time.setTime(this.objHidden.value*1000);												// set time
			this.dialog = document.createElement('div');												// dialog div
			this.dialog.style.border = '1px solid '+Calender.colorForeground;
			this.dialog.style.width = this.widthOfMonth+'px';
			
			this.dialog.style.position = 'absolute';
			/*this.dialog.style.top = '25px';*/
			if (navigator.userAgent.indexOf('MSIE 8')>0) {
				this.dialog.style.marginLeft = '120px';
				this.dialog.style.marginTop = '5px';
			}	
			
			//alert(obj.tagName);
			this.dialog.style.backgroundColor = Calender.colorBackground;
			
			this.dialog.style.fontFamily = 'georgia,times new roman,Verdana,Helvetica,Arial';
			this.dialog.style.fontSize = '13px';
			this.dialog.style.zIndex = '500';
			this.dialog.id = 'calenderDialog';			
			this.icon.parentNode.insertBefore(this.dialog,this.icon.nextSibling);						// insert dialog
			if((this.format.toLowerCase()).indexOf('y')>-1)												// year selector
				this.dialog.appendChild(this.getScrollSelector('year'));
			if((this.format.toLowerCase()).indexOf('m')>-1)												// month selector
				this.dialog.appendChild(this.getScrollSelector('month'));
			if((this.format.toLowerCase()).indexOf('d')>-1){											// day selector
				this.divDays = document.createElement('div');
				//this.divDays.style.borderTop = '1px solid '+Calender.colorForeground;
				this.divDays.style.height = '120px';
				this.dialog.appendChild(this.divDays);
			}
			if((this.format.toLowerCase()).indexOf('h')>-1 												// time selector
			|| (this.format.toLowerCase()).indexOf('i')>-1 
			|| (this.format.toLowerCase()).indexOf('s')>-1)	
				this.dialog.appendChild(this.getTimeSelector());
						
			var divButtons = document.createElement('div');												// buttons
			//divButtons.style.borderTop = '1px solid '+ Calender.colorForeground;
			divButtons.style.padding = '2px 4px';

			var divSave = document.createElement('div');
			divSave.style.cssFloat='left';
			divSave.style.styleFloat='left';
			divSave.style.cursor = 'pointer';
			divSave.appendChild(document.createTextNode(Calender.translApply));
			divSave.onclick = function(){obj.saveDialog();}
			var divCancel = document.createElement('div');
			divCancel.style.cssFloat='right';
			divCancel.style.styleFloat='right';
			divCancel.style.cursor = 'pointer';
			divCancel.appendChild(document.createTextNode(Calender.translCancel));		
			divCancel.onclick = function(){obj.closeDialog();}
			divButtons.appendChild(divSave);
			divButtons.appendChild(divCancel);
			divButtons.appendChild(Calender.getBrElement('both'));
			this.dialog.appendChild(divButtons);	
			/*if (this.dialog.offsetTop+this.dialog.offsetHeight>(document.body.clientHeight-document.body.scrollTop-document.documentElement.scrollTop-150)) {				
				this.dialog.style.top = parseInt(this.objInput.offsetTop)-parseInt(this.dialog.offsetHeight)-1+5+'px';
			}	*/
			this.updateChart();																		// update the calender
		},
		
		
		/* Chart *
		* builds a horizontal selector
		* @param 	string					type of scroll content ('year','month')
		* @return  	element					the scroller element
		*/	
		this.getScrollSelector = function(type){
			var obj = this;
			
			var div = document.createElement('div');
			
			var divBack = document.createElement('div');												// back button
			divBack.style.cssFloat='left';
			divBack.style.styleFloat='left';
			divBack.style.width='6px';
			divBack.style.margin='3px';
			var imgBack = document.createElement('img');
			imgBack.src = Calender.imagePath+Calender.imageLeft;
			imgBack.style.cursor = 'pointer';
			divBack.appendChild(imgBack);
			imgBack.onclick = function(){																// back eventhandler
				oldTs = obj.time.getTime();	
				oldMonth = obj.time.getMonth();
				switch(type){
					case 'month':	obj.time.setMonth(obj.time.getMonth()-1);break;
					case 'year':	if (obj.time.getFullYear()>2001) obj.time.setFullYear(obj.time.getFullYear()-1);break;
				}
				if((type=='month' && Math.abs(oldMonth-obj.time.getMonth())<1 && oldMonth!=0) 
				|| (type=='year' &&Math.abs(oldMonth-obj.time.getMonth())>0)){
					obj.time.setMonth(obj.time.getMonth()-1);
					obj.time.setDate(1);
				}
				if(obj.updateChart(obj)){
					return true;
				}else{
					obj.time.setTime(oldTs);
					return false;
				}
			}
			
			var divFwd = document.createElement('div');													// forward
			divFwd.style.cssFloat='right';
			divFwd.style.styleFloat='right';
			divFwd.style.width='6px';
			divFwd.style.margin='3px';
			var imgFwd = document.createElement('img');
			imgFwd.src = Calender.imagePath+Calender.imageRight;
			imgFwd.style.cursor = 'pointer';
			divFwd.appendChild(imgFwd);	
			imgFwd.onclick = function(){																// forward eventhandler
				oldTs = obj.time.getTime();	
				var oldMonth = obj.time.getMonth();
							
				switch(type){
					case 'month':	obj.time.setMonth(obj.time.getMonth()+1);break;
					case 'year':	obj.time.setFullYear(obj.time.getFullYear()+1);break;
					default : 		return;
				}
	
				if((type=='month' && Math.abs(oldMonth-obj.time.getMonth())>1 && oldMonth!=11)
				|| (type=='year' && Math.abs(oldMonth-obj.time.getMonth())>0)){
					obj.time.setMonth(obj.time.getMonth()-1);
					obj.time.setDate(1);
				}
				
				if(obj.updateChart(obj)){
				
					return true;
				}else{
					obj.time.setTime(oldTs);
					return false;
				}
				return false;
			}
			
			var divDisp = document.createElement('div');											// value display
			divDisp.style.cssFloat='left';
			divDisp.style.styleFloat='left';
			divDisp.style.width=(parseInt(this.dialog.offsetWidth)-34)+'px';
			divDisp.style.margin='1px';
			divDisp.style.textAlign='center';
			divDisp.style.fontWeight='bold';
			divDisp.appendChild(document.createTextNode('-'));
			switch(type){
				case 'month':	this.divMonth = divDisp;break;
				case 'year':	this.divYear = divDisp;break;
			}
			
			div.appendChild(divBack);																// insert back, forward and display
			div.appendChild(divDisp);
			div.appendChild(divFwd);
			div.appendChild(Calender.getBrElement('both'));
						
			return div;
		},

		
		/* Chart *
		* builds the months day selection chart
		* @return 	element			the month div element
		*/		
		this.getMonthChart = function(){
			var divMonth = document.createElement('div');
			divMonth.style.cssFloat='left';
			divMonth.style.styleFloat='left';
			if (navigator.userAgent.indexOf('irefox')>0)
				divMonth.style.width=(this.widthOfMonth-9)+'px';
			else	
				divMonth.style.width=(this.widthOfMonth-10)+'px';
			divMonth.style.backgroundColor='#D6D6D6';
			divMonth.style.marginLeft='4px';
			divMonth.style.display='inline';
			divMonth.style.marginTop='5px';
			divMonth.style.borderLeft='1px solid #D6D6D6';
			divMonth.style.borderTop='1px solid #D6D6D6';
			var divWeekDays = document.createElement('div');										// weekdays row
			//divWeekDays.style.borderBottom='1px solid '+Calender.colorForeground;
			var divWeekDay = [];
			for(var i=0;i<7;i++){
				divWeekDay[i] = document.createElement('div');
				divWeekDay[i].style.cssFloat='left';
				divWeekDay[i].style.styleFloat='left';
				divWeekDay[i].style.width=((this.widthOfMonth-2)/7)-2+'px';
				divWeekDay[i].style.margin='0px 1px 1px 0px';
				divWeekDay[i].style.backgroundColor='#fff';
				divWeekDay[i].style.textAlign='center';
				divWeekDay[i].style.fontWeight='bold';
				if(i==6)  {
					divWeekDay[i].style.color=Calender.colorHighlight;
					divWeekDay[i].style.marginRight='0px';
				}
				divWeekDay[i].appendChild(document.createTextNode(Calender.translWeek[(i+1)%7]));
				divWeekDays.appendChild(divWeekDay[i]);
			}
			divWeekDays.appendChild(Calender.getBrElement('left'));
			
			var divWeeks = [];																	// create chart
			var divDays = [];
			var tempDate = new Date;
			tempDate.setTime(this.time.getTime());
			tempDate.setDate(1);
			var offset = (tempDate.getDay()>0)?tempDate.getDay()-1:6;
			var firstTs = Calender.getFirstTsOf(this.time.getTime()/1000,'month');
			var lastTs = Calender.getLastTsOf(firstTs,'month');
			for(var i=0;i<6;i++){																// weeks
				
				for(var j=0;j<7;j++){															// days
					if(offset>0 || lastTs<firstTs){												// whitespacers
						if (i>0 && j==0)
							break;	
						if (j==0)
							divWeeks[i] = document.createElement('div');
						divDays[i*7+j] = document.createElement('div');
						divDays[i*7+j].style.cssFloat='left';
						divDays[i*7+j].style.styleFloat='left';
						divDays[i*7+j].style.width=((this.widthOfMonth-2)/7)-2+'px';
						divDays[i*7+j].style.margin='1px';
						divDays[i*7+j].style.margin='0px 1px 1px 0px';
						divDays[i*7+j].style.backgroundColor='#fff';	
						divDays[i*7+j].style.padding='0px 0px 2px 0px';
						divDays[i*7+j].innerHTML = '&nbsp;';						
						offset--;

					}else{																		// day elements
						if (j==0)
							divWeeks[i] = document.createElement('div');
							
						divDays[i*7+j] = this.getDaySelector(Calender.getFirstTsOf(firstTs,'day'));
						firstTs = Calender.getLastTsOf(firstTs,'day')+1;					
					}
					if(j==6)  divDays[i*7+j].style.marginRight='0px';
					divWeeks[i].appendChild(divDays[i*7+j]);
				}
				if (divWeeks[i])
					divWeeks[i].appendChild(Calender.getBrElement('left'));
			}
			divMonth.appendChild(divWeekDays);													// insert weekdays and weeks
			for(var i=0;i<divWeeks.length;i++)
				divMonth.appendChild(divWeeks[i]);
			return divMonth;
		}
		
		
		/* Chart *
		* builds a days selection element
		* @param 	int				first timestamp of day
		* @return 	element			the day div element
		*/		
		this.getDaySelector = function(firstTs){
			var date = new Date();
			date.setTime(firstTs*1000);
			
			//active = (((firstTs+86399)>this.minTs || this.minTs==0) && (firstTs<this.maxTs || this.maxTs==0))? true : false ;
			active = true;
			var monthStr = (date.getMonth()>8)?(date.getMonth()+1).toString():'0'+(date.getMonth()+1).toString();
			var dayStr = (date.getDate()>9)?date.getDate().toString():'0'+date.getDate().toString();
			var idStr = 'day'+date.getFullYear().toString()+monthStr+dayStr;
			
			var div = document.createElement('div');											// div element
			div.style.cssFloat='left';
			div.style.styleFloat='left';
			div.style.width=((this.widthOfMonth-2)/7)-2+'px';
			div.style.margin='0px 1px 1px 0px';
			div.style.padding='0px 0px 2px 0px';
			div.style.textAlign='center';
			div.id = idStr;
			div.className = 'calenderDay';
			if(date.getDate()==this.time.getDate())	{											// set marker if day is selected
				div.style.background = 'transparent';
				div.style.backgroundColor = Calender.colorMarker;
			}	
			div.appendChild(document.createTextNode(date.getDate()));
			if(active){																			// active days are selectable days
				div.style.color = (!date.getDay()) ? Calender.colorHighlight : Calender.colorForeground;
				div.style.cursor = 'pointer';
			}else{
				div.style.color = (!date.getDay()) ? Calender.colorHighlightInactive : Calender.colorForegroundInactive;
			}
			if(active){	
				var obj = this;	
				div.onclick = function(evt){													// onclick eventhandler for active days
					var oldTs = obj.time.getTime();
					obj.time.setDate(date.getDate());
					if(obj.updateChart(obj)){
						return true;
					}else{
						obj.time.setTime(oldTs);
						return false;
					}
				}
			}
			return div;
		}
		
		
		/** Chart *
		* builds a time selection line with hour minute and second
		* @return 	element			the time div element
		*/		
		this.getTimeSelector = function(){
			var obj = this;
																									// hour incrementer
			this.divHour = new Calender.Incrementer(Math.floor(obj.time.getHours()/this.incremDiffHour)*this.incremDiffHour,0,23,this.incremDiffHour);
			this.divHour.incrementer.style.cssFloat='left';
			this.divHour.incrementer.style.styleFloat='left';
			this.divHour.incrementer.style.margin='3px';
																									// minute incrementer
			this.divMinute = new Calender.Incrementer(Math.floor(obj.time.getMinutes()/this.incremDiffMinute)*this.incremDiffMinute,0,59,this.incremDiffMinute);
			this.divMinute.incrementer.style.cssFloat='left';
			this.divMinute.incrementer.style.styleFloat='left';
			this.divMinute.incrementer.style.margin='3px';
																									// second incrementer
			this.divSecond = new Calender.Incrementer(Math.floor(obj.time.getSeconds()/this.incremDiffSecond)*this.incremDiffSecond,0,59,this.incremDiffSecond);
			this.divSecond.incrementer.style.cssFloat='left';
			this.divSecond.incrementer.style.styleFloat='left';
			this.divSecond.incrementer.style.margin='3px';

			this.divHour.onchange = function(){														// onchange eventhandler for hours
				oldTs = obj.time.getTime();
				obj.time.setHours(parseInt(obj.divHour.value));
				if(obj.updateChart()){
					return true;
				}else{
					obj.time.setTime(oldTs);
					return false;
				}			
			}

			this.divMinute.onchange = function(value){												// onchange eventhandler for minutes
				oldTs = obj.time.getTime();
				obj.time.setMinutes(parseInt(obj.divMinute.value));
				if(obj.updateChart()){
					return true;
				}else{
					obj.time.setTime(oldTs);
					return false;
				}			
			}
			
			this.divSecond.onchange = function(value){												// onchange eventhandler for seconds
				oldTs = obj.time.getTime();
				obj.time.setSeconds(parseInt(obj.divSecond.value));
				if(obj.updateChart()){
					return true;
				}else{
					obj.time.setTime(oldTs);
					return false;
				}			
			}
			
			var div = document.createElement('div');												// time selector element
			div.style.borderTop = '1px solid '+Calender.colorForeground;
			div.style.height='22px';
			str = document.createElement('div');
			str.style.cssFloat='left';
			str.style.styleFloat='left';
			str.style.margin='3px';
			str.style.paddingTop='1px';
			str.appendChild(document.createTextNode(Calender.translTime));
			div.appendChild(str);
			
			if((this.format.toLowerCase()).indexOf('h')>-1)											// insert hour incrementer
				div.appendChild(this.divHour.incrementer);	
			if((this.format.toLowerCase()).indexOf('i')>-1){										// insert minute incrementer
				spacer = document.createElement('div');
				spacer.style.cssFloat='left';
				spacer.style.styleFloat='left';
				spacer.style.margin='3px';
				spacer.appendChild(document.createTextNode(':'));
				div.appendChild(spacer);
				div.appendChild(this.divMinute.incrementer);
			}
			if((this.format.toLowerCase()).indexOf('s')>-1){										// insert second incrementer
				spacer = document.createElement('div');
				spacer.style.cssFloat='left';
				spacer.style.styleFloat='left';
				spacer.style.margin='3px';
				spacer.appendChild(document.createTextNode(':'));
				div.appendChild(spacer);
				div.appendChild(this.divSecond.incrementer);
			}
			div.appendChild(Calender.getBrElement('left'));
						
			return div;
		},
		
		
		/* Chart *
		* closes the dialog
		* @return 	bool			closed
		*/		
		this.closeDialog = function(){
			if(this.dialog){
				this.dialog.parentNode.removeChild(this.dialog);
				this.dialog = null;
			}
			return true;
		}
		

		/* Chart *
		* saves the dialog changes to the form
		* @return 	bool			saved
		*/		
		this.saveDialog = function(){
			var res = true;
			var oldTs = this.objHidden.value;
			this.objHidden.value = this.time.getTime()/1000;
			this.objInput.value = Calender.formatDate(this.format,(this.time.getTime()/1000));
			
			if (typeof checkDateRange == 'function') {
				checkDateRange(this.objHidden);
			} 	
				
			if(this.objInput.onchange) {
		
				res = this.objInput.onchange();
				res = true;
			}	
			
			if(!res){				
				this.objHidden.value = oldTs;
				this.objInput.value = Calender.formatDate(this.format,oldTs);
				return false;
			}else{
				return this.closeDialog();
			}
		}
			
		
		/* Chart *
		* updates the dater calender // currently unused, just to can use the Calender like a Dater
		*/	
		this.update = function(){
			this.closeDialog();
			this.objInput.value = Calender.formatDate(this.format,this.objHidden.value);
			return true;
		}
		
		
		/* Chart *
		* updates the dater object min and max timestamps
		* @param	int 					new min ts
		* @param	int 					new max ts
		*/
		this.upadteDatingIntervall = function(minTs,maxTs){
			this.minTs = minTs;
			this.maxTs = maxTs;
		}
		
		
		/* Chart *
		* updates the calenders internal and visual timestamp and time values
		* @return 	bool			update was successfull
		*/		
		this.updateChart = function(obj){
		
			if (!obj)
				obj = this;
				
			var ts = Math.floor(obj.time.getTime()/1000);
			if(ts<this.minTs && obj.minTs>0)												// check if new date is in intervall
				obj.time.setTime(obj.minTs*1000);
			if(ts>obj.maxTs && obj.maxTs>0)	
				obj.time.setTime(obj.maxTs*1000);

			if((obj.format.toLowerCase()).indexOf('y')>-1)									// update year
				obj.divYear.firstChild.nodeValue = obj.time.getFullYear();
			if((obj.format.toLowerCase()).indexOf('m')>-1)									// update month
				obj.divMonth.firstChild.nodeValue = Calender.translMonth[obj.time.getMonth()];
				
			if((obj.format.toLowerCase()).indexOf('d')>-1){								// update days
				if(obj.divDays.firstChild)
					obj.divDays.removeChild(obj.divDays.firstChild)
				obj.divDays.appendChild(obj.getMonthChart());
			}
			if((obj.format.toLowerCase()).indexOf('h')>-1){								// update hours
				obj.divHour.checkOnChange = false;
				obj.divHour.setField(obj.time.getHours());
				obj.divHour.checkOnChange = true;
			}
			if((obj.format.toLowerCase()).indexOf('i')>-1){								// update minutes
				obj.divMinute.checkOnChange = false;
				obj.divMinute.setField(obj.time.getMinutes());
				obj.divMinute.checkOnChange = true;
			}
			if((obj.format.toLowerCase()).indexOf('s')>-1){								// update seconds
				obj.divSecond.checkOnChange = false;
				obj.divSecond.setField(obj.time.getSeconds());
				obj.divSecond.checkOnChange = true;
			}
			
			return true;		
		}
																							// upon objects initialization...
	},
	
	// END - CALENDER




/*****************************************************************************************************************/
/* INCREMENTER                                                                                                   */
/*****************************************************************************************************************/	
	
	// BEGIN  - INCREMENTER
	
	/**
	* Constructor of a Incrementer
	* @param 	int						init value
	* @param 	int						min value
	* @param 	int						max value
	* @param	int 					difference for in-/ decrementing
	*/
	Incrementer : function(init,minValue,maxValue,diff){
		this.value = init;																// value
		this.minValue = minValue;														// min value
		this.maxValue = maxValue;														// max value
		this.diff = diff;																// diffrence
		this.incrementer = null;														// the incementer element
		this.field = null;																// the field element
		this.upButton = null;															// the up element
		this.downButton = null;															// the down element
		this.checkOnChange = true;														// execute onchange upon change
		
		/* Incrementer *
		* creates an incrementer element
		*/	
		this.createIncrementer = function(){
			var obj=this;
			
			this.incrementer = document.createElement('div');							// incrementer div
			
			this.field = document.createElement('div');									// value div
			this.field.style.height='14px';
			this.field.style.cssFloat='left';
			this.field.style.styleFloat='left';
			this.field.style.width='20px';
			this.field.style.backgroundColor='#FFFFFF';						
			this.field.style.border='1px solid '+Calender.colorForeground;
			this.field.style.textAlign='center';
			this.field.style.color='#000000';
			this.field.appendChild(document.createTextNode(''));
			
			var divButtons = document.createElement('div');								// buttons div
			divButtons.style.position='relative';
			divButtons.style.height='14px';
			divButtons.style.width='11px';
			divButtons.style.cssFloat='left';
			divButtons.style.styleFloat='left';
			divButtons.style.border='1px solid '+Calender.colorForeground;
			divButtons.style.borderLeft='none';
			
			this.upButton = document.createElement('div');								// up div
			this.upButton.style.position = 'absolute';
			this.upButton.style.top = '0px';
			var imgUp = document.createElement('img');
			imgUp.src=Calender.imagePath+Calender.imageUp;
			imgUp.style.cursor='pointer';
			this.upButton.appendChild(imgUp);
			
			this.downButton = document.createElement('div');							// down div
			this.downButton.style.position = 'absolute';
			this.downButton.style.bottom = '0px';
			var imgDown = document.createElement('img');
			imgDown.src=Calender.imagePath+Calender.imageDown;
			imgDown.style.cursor='pointer';
			this.downButton.appendChild(imgDown);
			
			divButtons.appendChild(this.upButton);
			divButtons.appendChild(this.downButton);
		
			this.incrementer.appendChild(this.field);
			this.incrementer.appendChild(divButtons);
			this.incrementer.appendChild(Calender.getBrElement('left'));
																					
			imgUp.onclick = function(){obj.handleClick(obj.diff);}					// eventhandler for up
			imgDown.onclick = function(){obj.handleClick((-1)*obj.diff);}			// eventhandler for down
		}
		
		
		/* Incrementer *
		* sets the value if allowed an in the given intervall
		* @param 	int						new value
		* @return 	bool					setting was successfull
		*/	
		this.setField = function(value){
			if(this.minValue<=(value) && this.maxValue>=(value)){					// value is in intervall
				var oldValue = this.value;
				this.value = value;
				if(this.checkOnChange){												// execute onchange
					if(this.onchange()){
						this.field.firstChild.nodeValue = Calender.formatFigure(this.value,2,0,1);
						this.settedLoop = false;
						return true;
					}else{
						this.value = oldValue;
						this.settedLoop = false;
						return false;
					}				
				}else{
					this.field.firstChild.nodeValue = Calender.formatFigure(this.value,2,0,1);
					this.settedLoop = false;
					return true;				
				}
			}
			return false;
		}


		/* Incrementer *
		* is called when changing the value
		* @return 	bool					changing value is allowed
		*/	
		this.onchange = function(){
			return true;
		}
		
		
		/* Incrementer *
		* handles a click on up or down
		* @param 	int					difference to the old value
		*/	
		this.handleClick = function(change){
			this.setField(this.value+change);
		}
		
																							// upon objects initialization...
		this.createIncrementer();															// creates the incrementer element
		this.setField(this.value);															// set the value to the init value
	}
	
	// END  - INCREMENTER
	

/*****************************************************************************************************************/
/* NOCLASSES ** NOCLASSES ** NOCLASSES ** NOCLASSES ** NOCLASSES ** NOCLASSES ** NOCLASSES ** NOCLASSES ** NOCLA */
/*****************************************************************************************************************/
	
}
/*****************************************************************************************************************/
/* END OF CALENDER                                                                                               */
/*****************************************************************************************************************/	
