
	/*
	 *      klendar.js
	 *
	 *      Copyright 2010 Ismael Rodríguez <ismael.rodriguez@premper.com>
	 *
	 *      This program is free software; you can redistribute it and/or modify
	 *      it under the terms of the GNU General Public License as published by
	 *      the Free Software Foundation; either version 2 of the License, or
	 *      (at your option) any later version.
	 *
	 *      This program is distributed in the hope that it will be useful,
	 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
	 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	 *      GNU General Public License for more details.
	 *
	 *      You should have received a copy of the GNU General Public License
	 *      along with this program; if not, write to the Free Software
	 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
	 *      MA 02110-1301, USA.
	 */


	Date.prototype.stripTime = function(){
		return new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0, 0) ;
	}

	klendar = function(){

		this.lang				= 'es' ;
		this.weekdays			= new Array('D', 'L', 'M', 'Mi', 'J', 'V', 'S') ;
		this.months				= new Array('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre') ;
		this.first_day_of_week	= 1 ;
		this.id					= null ;
		this.start_date			= new Date().stripTime() ;
		this.selected_date		= new Date().stripTime() ;
		this.format				= '%Y-%m-%d' ;
		this.activator			= null ;
		this.shown				= false ;
		this.as_unixtime		= false ;

		this.start_year 		= this.start_date.getFullYear() - 10 ;
		this.stop_year			= this.start_date.getFullYear() + 10 ;

		this.grid				= document.createElement('tbody') ;
		this.calendar			= document.createElement('tbody') ;
		this.grid_table			= document.createElement('table') ;
		this.calendar_table		= document.createElement('table') ;

		if(typeof klendar.counter == 'undefined')
			klendar.counter = 0 ;

		this.container				= document.createElement('div')		;
		this.container.id			= 'klendar' + (klendar.counter++)	;
		this.container.className	= 'klendar'							;

		var copy = this ;

		this.container.onclick = function(){

			document.onclick = function(){
				return false ;
			}
			setTimeout("document.onclick = function(){ copy.setupAndClear() }", 100) ;
		}

		this.instances = new Array() ;
	}


	klendar.prototype.closeAllKalendars = function(){

		for(var i = 0 ; i < this.instances.length ; i++){
			this.instances[i].setupAndClear() ;
		}
	}

	klendar.prototype.setFormat = function(format){
		this.format = format
	}

	klendar.prototype.clear = function(){

		this.calendar		= document.createElement('tbody')	;
		this.grid			= document.createElement('tbody')	;
		this.grid_table		= document.createElement('table')	;
		this.calendar_table	= document.createElement('table')	;

		this.container.innerHTML		= ''		;
		this.container.style.display	= 'none'	;
		this.shown = false ;
	}

	klendar.prototype.getLeft = function(ele){

		if(ele.offsetParent)
			return ele.offsetLeft + this.getLeft(ele.offsetParent) ;
		else
			return ele.offsetLeft ;
	}

	klendar.prototype.getTop = function(ele){

		if(ele.offsetParent)
			return (ele.offsetTop + this.getTop(ele.offsetParent)) ;
		else
			return ele.offsetTop ;
	}

	klendar.prototype.draw = function(){


		if(this.shown == false){

			this.clear() ;
			//this.drawYearControls()		;
			this.drawMonthControls() 	;
			this.drawDaysHeader()		;
			this.drawGrid()				;
			this.fillGrid()				;
			this.drawFooter()			;
			//this.initActionsForYear()	;
			this.initActionsForMonth()	;

			this.joinCalendar() ;	// append tbody to table
			this.joinGrid() ;		// append tbody to table

			this.container.appendChild(this.calendar_table) ;

			if(this.activator != null){

				//this.activator.parentNode.style.position = 'relative' ;
				this.container.style.position = 'absolute' ;

				this.container.style.top	= this.getTop(this.activator) + 'px' ;
				this.container.style.left	= this.getLeft(this.activator) + this.activator.offsetWidth + 'px' ;

				this.activator.parentNode.appendChild(this.container) ;
			}
			this.container.style.display = '' ;
			this.shown = true ;
		}
	}

	klendar.prototype.joinCalendar = function(){
		this.calendar_table.appendChild(this.calendar) ;
	}

	klendar.prototype.joinGrid = function(){
		this.grid_table.appendChild(this.grid) ;
	}

	klendar.prototype.getFormatedDate = function(date_to_format){

		if(date_to_format != undefined){
			y = date_to_format.getFullYear()	;
			m = date_to_format.getMonth()		;
			d = date_to_format.getDate()		;
		}
		else{
			y = this.selected_date.getFullYear()	;
			m = this.selected_date.getMonth()		;
			d = this.selected_date.getDate()		;
		}

		if(!(parseInt(d) > 0) || !(parseInt(y) > 0))
			return '' ;

		var formated = this.format
		formated = this.format.replace('%Y', y) ;
		formated = formated.replace('%m', (m < 9	? ('0' + (m + 1))	: (m + 1)))	;
		formated = formated.replace('%d', (d < 10	? ('0' + d)			: d))		;
		formated = formated.replace('%y', ('' + y).substring(2, 4))					;
		formated = formated.replace('%M', this.months[m])							;

		return formated ;
	}

	klendar.prototype.drawFooter = function(){

		var tfoot	= document.createElement('tfoot')	;
		var tr		= document.createElement('tr')		;
		this.footer	= document.createElement('td')		;

		this.footer.setAttribute('colSpan', 3) ;
		this.footer.innerHTML = this.getFormatedDate() ;

		tr.appendChild(this.footer) ;
		tfoot.appendChild(tr) ;
		this.calendar_table.appendChild(tfoot) ;
	}

	klendar.prototype.drawYearControls = function(){

		this.year_controls = document.createElement('tr') ;

		var back	= document.createElement('td') ;
		var next	= document.createElement('td') ;
		var control = document.createElement('td') ;

		back.className = 'arrow' ;
		next.className = 'arrow' ;

		var lnkback	= document.createElement('a') ;
		var lnknext	= document.createElement('a') ;

		lnkback.innerHTML = '<img src="../images/cal-back.gif" />' ;
		lnknext.innerHTML = '<img src="../images/cal-next.gif" />' ;

		back.appendChild(lnkback) ;
		next.appendChild(lnknext) ;

		this.year_controls.appendChild(back)	;
		this.year_controls.appendChild(control)	;
		this.year_controls.appendChild(next)	;

		sel = document.createElement('select')	;
		sel.setAttribute('tabIndex', '-1')		;

		for(var i = this.start_year ; i <= this.stop_year ; i++){

			op = document.createElement('option')	;
			op.value = i		;
			op.text = i			;
			op.innerText = i	;
			sel.appendChild(op)	;
		}

		control.appendChild(sel) ;

		this.calendar.appendChild(this.year_controls)	;
	}

	klendar.prototype.initActionsForYear = function(){

		var controls	= this.year_controls.getElementsByTagName('td')			;
		var select		= this.year_controls.getElementsByTagName('select')[0]	;
		select.value	= this.start_date.getFullYear()							;

		var copy	= this	;

		// back
		controls[0].onclick = function(){

			copy.backYear()		;
			copy.shown	= false	;
			copy.draw()			;
		}

		// dropdown
		select.onchange = function(){

			copy.setYear(select.value) ;
			copy.shown	= false	;
			copy.draw() ;
		}

		// next
		controls[2].onclick = function(){

			copy.nextYear()		;
			copy.shown	= false	;
			copy.draw()			;
		}
	}

	klendar.prototype.backYear = function(){

		this.setYear(this.start_date.getFullYear() - 1) ;
	}

	klendar.prototype.nextYear = function(){

		this.setYear(this.start_date.getFullYear() + 1) ;
	}

	klendar.prototype.drawMonthControls = function(){

		this.month_controls = document.createElement('tr') ;

		var back	= document.createElement('td') ;
		var next	= document.createElement('td') ;
		var control = document.createElement('td') ;

		back.className = 'arrow' ;
		next.className = 'arrow' ;

		var lnkback	= document.createElement('a') ;
		var lnknext	= document.createElement('a') ;

		lnkback.innerHTML = '<img src="images/cal-back.gif" />' ;
		lnknext.innerHTML = '<img src="images/cal-next.gif" />' ;

		back.appendChild(lnkback) ;
		next.appendChild(lnknext) ;

		sel = document.createElement('select')	;
		sel.setAttribute('tabIndex', '-1')		;

		for(var i = 1 ; i < this.months.length + 1 ; i++){

			op = document.createElement('option')	;
			op.value = i							;
			op.text = this.months[i - 1]			;
			op.innerText = this.months[i - 1]		;
			sel.appendChild(op)						;
		}

		control.appendChild(sel) ;

		this.month_controls.appendChild(back)		;
		this.month_controls.appendChild(control)	;
		this.month_controls.appendChild(next)		;

		this.calendar.appendChild(this.month_controls)	;
	}

	klendar.prototype.initActionsForMonth = function(){

		var controls	= this.month_controls.getElementsByTagName('td')		;
		var select		= this.month_controls.getElementsByTagName('select')[0]	;
		select.value	= this.start_date.getMonth() + 1						;

		var copy = this ;

		// back
		controls[0].onclick = function(){

			copy.backMonth()	;
			copy.shown	= false	;
			copy.draw()			;
		}

		// dropdown
		select.onchange = function(){

			copy.setMonth(select.value - 1) ;
			copy.shown	= false	;
			copy.draw() ;
		}

		// next
		controls[2].onclick = function(){

			copy.nextMonth()	;
			copy.shown	= false	;
			copy.draw()			;
		}
	}

	klendar.prototype.backMonth = function(){
		this.start_date.setDate(15) ;
		this.setMonth(this.start_date.getMonth() - 1) ;
	}

	klendar.prototype.nextMonth = function(){
		this.setMonth(this.start_date.getMonth() + 1) ;
	}

	klendar.prototype.drawGrid = function(){

		for(var i = 0 ; i < 42 ; i++){

			weekday = (i + this.first_day_of_week ) % 7 ;

			if(i % 7 == 0){
				var tr = document.createElement('tr') ;
				this.grid.appendChild(tr) ;
			}
			var td = document.createElement('td') ;

			if(weekday == 0 || weekday == 6)
				td.className = 'weekend' ;

			tr.appendChild(td) ;
		}

		var tr = document.createElement('tr')	;
		var td = document.createElement('td')	;
		td.setAttribute('colSpan', 3)			;

		td.appendChild(this.grid_table)	;
		tr.appendChild(td)				;

		this.calendar.appendChild(tr) ;
	}

	klendar.prototype.fillGrid = function(){

		var this_month	= this.start_date.getMonth()	;	// set this_month variable before to set day to 1
		this.start_date.setDate(1)						;
		this.start_date.setHours(12)					;

		var iterator	= new Date(this.start_date)	;
		var previous_days = iterator.getDay() ;	// to draw some another month days ...

		if(previous_days < 3)
			previous_days += 7 ;

		iterator.setDate(1 - previous_days + this.first_day_of_week) ;

		var today		= new Date().stripTime()	;
		today.setHours(12) ;

		this.selected_date = this.selected_date.stripTime()	;
		this.selected_date.setHours(12)	;

		for(var i = 0 ; i < 42 ; i++){

			day		= iterator.getDate()		;
			month	= iterator.getMonth()		;
			year	= iterator.getFullYear()	;

			a		= document.createElement('a')		;
			a.id	= year + '-' + month + '-' + day	;

			copy = this ;

			a.onmouseover = function(){
				copy.footer.innerHTML = copy.getFormatedDate(copy.string2Date(this.id)) ;
			}

			if(this.activator != null){
				a.onclick = function(){

					copy.activator.value	= copy.getFormatedDate(copy.string2Date(this.id)) ;
					copy.selected_date		= copy.string2Date(this.id) ;

					if(copy.as_unixtime)
						copy.activator.receptor.value = (copy.selected_date.stripTime().getTime() / 1000) ;
					else
						copy.activator.receptor.value = copy.getDateForSql(this.id) ;

					copy.clear() ;
				}
			}

			if(month != this_month)
				a.className = 'other' ;

			if(('' + iterator) == ('' + this.selected_date))
				a.className = 'selected' ;

			if(('' + iterator) == ('' + today))
				this.grid.getElementsByTagName('td')[i].className = 'today' ;


			a.innerHTML = day ;

			this.grid.getElementsByTagName('td')[i].appendChild(a) ;
			iterator.setDate(day + 1) ;
		}
	}

	klendar.prototype.string2Date = function(date_string){
		
		if(date_string == '')
			return new Date().stripTime() ;

		date_array	= date_string.split('-')	;
		date		= new Date()				;
		
		date.setDate(date_array[2])				;
		date.setMonth(date_array[1])			;
		date.setFullYear(date_array[0])			;

		return date.stripTime() ;
	}

	klendar.prototype.string2DateSql = function(date_string){

		if(date_string == '')
			return new Date().stripTime() ;

		date_array	= date_string.split('-')	;
		date		= new Date()				;
		date.setFullYear(date_array[0])			;
		date.setMonth(date_array[1] - 1)		;
		date.setDate(date_array[2])				;

		return date.stripTime() ;
	}

	klendar.prototype.drawDaysHeader = function(){

		var counter	= 0 ;
		var header	= document.createElement('thead')	;
		var tr		= document.createElement('tr')		;

		for(var i = this.first_day_of_week ; i < 7 ; i++){

			var th = document.createElement('th')	;
			th.innerHTML = this.weekdays[i]			;
			tr.appendChild(th)						;

			counter++ ;
		}

		for(var j = 0 ; j < (7 - counter) ; j++){

			var th = document.createElement('th')	;
			th.innerHTML = this.weekdays[j]			;
			tr.appendChild(th)						;
		}

		header.appendChild(tr) ;
		this.grid_table.appendChild(header) ;
	}

	klendar.prototype.setMonth = function(m){
		this.start_date.setMonth(m) ;
	}

	klendar.prototype.setYear = function(y){
		this.start_date.setFullYear(y) ;
	}

	klendar.prototype.setupAndClear = function(){

		this.start_date.setMonth(this.selected_date.getMonth())			;
		this.start_date.setFullYear(this.selected_date.getFullYear())	;

		this.clear() ;
	}

	klendar.prototype.getDateAsUnixTime = function(bool){

		this.as_unixtime = bool ;
	}

	klendar.prototype.getDateForSql = function(date_js){

		var bits = date_js.split('-') ;
		return bits[0] + '-' + (parseInt(bits[1]) + 1) + '-' + bits[2] ;
	}

	klendar.prototype.init = function(){

		var inputs = document.body.getElementsByTagName('input') ;
		var copy = this ;

		for(var i = 0 ; i < inputs.length ; i++){

			input = inputs[i] ;

			if(input.type.toLowerCase() == 'text'){

				if(parseInt(input.getAttribute('date')) == 1){

					input.receptor				= document.createElement('input')			;
					input.receptor.type			= 'hidden'									;
					input.parentNode.appendChild(input.receptor)							;
					input.receptor.setAttribute('id', 'k_' + input.getAttribute('name'))	;
					input.receptor.setAttribute('name', input.getAttribute('name'))			;

					if(input.value != ''){
						input.receptor.value = input.value								;
						input.value = copy.getFormatedDate(copy.string2DateSql(input.receptor.value)) ;
					}

					input.setAttribute('name', '')		;
					input.setAttribute('readonly', '')	;

					input.onclick = function(){

						copy.closeAllKalendars() ;	// close all instances of klendar

						kal = new klendar()											;
						kal.start_date = kal.string2DateSql(this.receptor.value)	;
						kal.selected_date = kal.string2DateSql(this.receptor.value)	;
						kal.activator = this										;
						kal.setFormat(copy.format)									;
						kal.getDateAsUnixTime(copy.as_unixtime)						;
						kal.draw() ;

						copy.instances.push(kal) ;	// add this instance to intances array

						document.onclick = function(){
							return false ;
						}
						setTimeout("document.onclick = function(){ kal.setupAndClear() }", 100) ;

						this.associated_kalendar = kal ;

						this.onclick = function(){	// redefine onclick event for activator input

							copy.closeAllKalendars() ;	// close all instances of klendar

							this.associated_kalendar.draw() ;
							kalcopy = this.associated_kalendar ;

							copy.instances.push(kalcopy) ;	// add this instance to intances array

							document.onclick = function(){
								return false ;
							}
							setTimeout("document.onclick = function(){ kalcopy.setupAndClear() }", 100) ;
						}
					}
				}
			}
		}
	}

