﻿// Kalendář od JB (c)2009

// je potřeba knihovny "prototype.js" min verze 1.6
// je podtřeba knihovna JB funkcí "JB_FN_code.js"

// Jak funguje:
// 1) tak, že se input pole vykreslí funkcí javascriptu viz níže
// 2) zaregistrují se události na Element pomocí funkce .AssignFn(element)
// 3) automaticky způsobí že všechny textové inputy s class "JBKalendarInput" budou automaticky přiřazeny události kalendáře

// Pokud se klikne na pole, je automaticky vyvolán kalendář
// kalendář lze ovládat i stiskem kláves v poli
//  1) klávesa "d" nastaví dnešní datum
// 2) klávesa "c" uzavře kalendář
// 3) klávesa "k" zobrazí kalendář

// Do políčka lze vložit jen datum, tzn čísla a tečky
// Po vyskočení z políčka je datum zkontrolováno a upraveno
// Akceptuje např - je rok 2009
//  1.1  => 1.1.2009
//  1.1. => 1.1.2009
// 1.1.8 => 1.1.2008
// 1.1.08 => 1.1.2008
// 1.1.99 => 1.1.1999
// 2009-03-02 => 2.3.2009

//do HTML kódu vlož tento javascript kód pro vykreslení
//      <script type="text/javascript">JBKalendar.DrawInput('in_pr','','','')</script>
// první hodnota je ID
// druhá                   NAME
// třetí                     SIZE
// čtvrtá                  VALUE
// pokud stačí jen označit id tak
//      <script type="text/javascript">JBKalendar.FastD('in_pr','1.1.2008')</script>
// FastD  použije první hodnotu pro název i id objektu s value nastaveným druhou hodnotou
// využíva def_code_spol.js pro test data

function FN_JBKalendar(){
	var JBKalendarAktivEl,JBKalendarAktivY,JBKalendarAktivM,JBKalendarAktivD,tm,shw,psn,unfcs;
	var mn=new Array('Leden','Únor','Březen','Duben','Květen','Červen','Červenec','Srpen','Září','Říjen','Listopad','Prosinec');
	var dnnms= new Array('Po','Út','St','Čt','Pá','So','Ne');
	var mnn=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
	
	var CSSInp='JBKalendarInput'; // touto třídou musí být označeny textinputy, které chceme jako datum
	var IDKal='JBKalendar_TBL'; // ID kalendáře v DOM

	shw=false;psn=false;unfcs=false;

	// BOF - vykreslovací funkce
	this.DrawInput = function(id,name,size,val) {
		s  ='<input type="text"';
		if(name!=''){s += (s!='' ? ' ' : '') + 'name="'+name+'"'};
		if(size!=''){s += (s!='' ? ' ' : '') + 'size="'+size+'"'};
		if(id!=''){s += (s!='' ? ' ' : '') + 'id="'+id+'"'};
		if(val!=''){s += (s!='' ? ' ' : '') + 'value="'+val+'"'};
		s += ' class="JBTextCalendar"';
		s += ' onkeypress="return JBKalendar.stisk(event,this)"';
		s += ' onclick="JBKalendar.show(this)"';
		s += ' onfocus="JBKalendar.show(this)"';
		s += ' onblur="JBKalendar.kontrola(this)"';
		s += '>';
		document.write(s);
	}
	this.FastD = function(id_name,val) {
		this.DrawInput(id_name,id_name,'',val);
	}
	// EOF - vykreslovací funkce

	// registruje na všechny elementy s class="CSSInp" editaci datumu
	this.RegisterOnClass=function(){
		var els,a;
		els=$$('.'+CSSInp);
//		els=$(document.body).getElementsByClassName(CSSInp);
		for (a=0; a<els.length; a++){
			this.AssignFn(els[a]);
		};
	}
	
	// přiřadí eventy elementu pro kompletní editaci datumu
	this.AssignFn = function(id){
		Event.observe(id,'keypress', function(event){
//		$(id).observe('keypress', function(event){
			if (!JBKalendar.stisk(event,this)){
				Event.stop(event);
			};
		});
		Event.observe(id,'click', function(event){
			JBKalendar.show(this);
		});
		Event.observe(id,'focus', function(event){
			JBKalendar.show(this);
		});
		Event.observe(id,'blur', function(event){
			unfcs=true;
			JBKalendar.kontrola(this);
		});
	}
	
	// Nastaví datum na který bylo kliknuto
	this.Set = function(el){
	var kal;
		JBKalendarAktivEl.value=el.innerHTML + '.' + (JBKalendarAktivM+1) + '.' + JBKalendarAktivY;
		this.close();
	}
	
	// Nastaví dnešní datum
	this.Dnes = function (){
	var kal,dnes;
		dnes=new Date();
		dnes=dnes.getDate() + '.' + (dnes.getMonth()+1) + '.' + dnes.getFullYear();
		dnes=dnes.split(/\./gi);

		JBKalendarAktivEl.value= dnes[0] + '.' + dnes[1] + '.' + dnes[2];
		this.close();
	}
	
	// časované uzavření kalendáře - problém IE, toto musí být použito pro uzavření kalendáře
	this.close = function(){
		if(psn)return;
		tm=setTimeout("JBKalendar.close_abs()",200);
		if(!unfcs) if($(IDKal).visible()) JBKalendarAktivEl.focus();
	}
	// absolutní Close kalendáře, nesmí být voláno přímo !!!!
	this.close_abs = function(){
		clearTimeout(tm);
		Element.hide(IDKal);
		shw=false; unfcs=false;
	}
	
	// nastaví eventy pro button kalendáře
	this.button= function (el,text,mouseover,mouseout,Fonclick){
	//vše krom el musí být text
		el.onmouseover=Function('this.className="'+mouseover+'"');
		el.onmouseout =Function('this.className="'+mouseout+'"');
		el.innerHTML  =text;
		if(Fonclick!="" || Fonclick!=null){
			el.onclick=Function(Fonclick);
		}else{
			el.onclick=null;
		}
	}
	
	// vlož buňku a nastav potřebné
	this.InserCell = function (table_row,id,colspan,tx_class){
	// pokud id nebo colspan je '', tak nebude použit
	var cl;
		cl=table_row.insertCell(-1);
		if(id != ''){cl.setAttribute('id',id);}
		//if(colspan != ''){cl.setAttribute('colspan',colspan);}
		if(colspan != ''){cl.colSpan=colspan;cl.width='';cl.style.width='auto';}
		if(tx_class != ''){cl.className=tx_class;}
		return cl;
	}
	
	// hlavní vytvoření kalendáře, nesmí být voláno přímo !!!! jen z funkce show
	this.CreateKal = function(){
			//první inicializace kalendáře
			kal=document.createElement('table');
			kal.setAttribute('id',IDKal);
			document.body.appendChild(kal);
			//vytvoř první řádek
			rw=kal.insertRow(-1);
			this.InserCell(rw,'JBKalendarDatum',5,'');
			this.InserCell(rw,'JBKalendarDnes','','');
			this.InserCell(rw,'JBKalendarClose','','');
			this.button(rw.cells[1],'Dnes','JBKalMouseOverD','','JBKalendar.Dnes()')
			this.button(rw.cells[2],'X','JBKalMouseOverC','','JBKalendar.close()')
	
			//vytvoř druhý řádek
			rw=kal.insertRow(-1);
			this.InserCell(rw,'','','');
			this.InserCell(rw,'','','');
			this.InserCell(rw,'',3,'');
			this.InserCell(rw,'','','');
			this.InserCell(rw,'','','');

			this.button(rw.cells[0],'-R','JBKalMouseOverM','','JBKalendar.Posun("y",-1)')
			this.button(rw.cells[1],'-M','JBKalMouseOverM','','JBKalendar.Posun("m",-1)')
			this.button(rw.cells[3],'+M','JBKalMouseOverP','','JBKalendar.Posun("m",1)')
			this.button(rw.cells[4],'+R','JBKalMouseOverP','','JBKalendar.Posun("y",1)')	
			
			//třetí řádek
			rw=kal.insertRow(-1);
			for (a=0; a<7; a++){
				cl=rw.insertCell(-1);
				cl.innerHTML=dnnms[a];
				cssNorm='JBKalendarDnyHead';
				if(a==5){cssNorm='JBKalendarSo'}else{if (a==6){cssNorm='JBKalendarNe'}}
				cl.className=cssNorm;
			}
			
			
			return kal;			
	}
	
	// zobrazí kalendář, pokud neexistuje, tak si jej vytvoří
	this.show = function(el) {
	var a,b,aa,d,ted,kal,rok,mes,den,dent,maxden,pres,rw,cl,x,xx,cssNorm,cssOn,cstdt,s,dnes;
		if (shw && !psn) return;
		JBKalendarAktivEl=el;
		clearTimeout(tm);
		shw=true;
		
		//pokud neexistuje, tak vytvoř
		kal=$(IDKal);
		if(kal==null) kal = this.CreateKal();
		
		b=kal.rows.length-3;
		//smaž obsah datumů
		if (b>0) for(a=0; a<b; a++) kal.deleteRow(kal.rows.length-1);
		
		
		if(!InputIsDatum(el)){
			//vytvoř datum do inputu na dnešek pokud enní zadáno, nebo je špatné
			ted= new Date();
			a=ted.getDate()+'.'+(ted.getMonth()+1)+'.'+ted.getFullYear();
			el.value=a;
		};

		s=String(el.value);
		a=s.split(/\./gi);
		ted = new Date(a[2],(a[1]-1),1);
		cstdt=Math.floor(a[0]);
		JBKalendarAktivD=a[0];
		
		
		dnes=new Date();
		dnes=dnes.getDate() + '.' + (dnes.getMonth()+1) + '.' + dnes.getFullYear();
		dnes=dnes.split(/\./gi);
	
		rok=ted.getFullYear();
		JBKalendarAktivY=rok;
		pres= (rok/4)==Math.floor(rok/4) ? true : false; // řestupný rok
		mes=ted.getMonth();//mesic - Vrací měsíc ze zadaného data v rozmezí 0 až 11
		JBKalendarAktivM=mes;
		den=ted.getDate();// datum
		dent=ted.getDay();// Vrací den v týdnu od 0 do 6, kde 0=neděle, 6=sobota
		dent=(dent==0 ? 7 : dent)-1; // vrací 1-7 kde 1=po a 7=ne zredukováno o 1 opět na 0-6
		maxden=mnn[mes] +( (pres && mes==1) ? 1 : 0 );//max den v měsíci - ošetřen přestupný rok
		b = (maxden+dent)/7;
		b = Math.floor(b) + (Math.floor(b)==b ? 0 : 1);// pokud není celé číslo, tak řádek navíc, v "b" je počet řádků

		// nastav info kalendáře
		a=(cstdt==-1 ? den : cstdt);
		x=new Date(rok,mes,JBKalendarAktivD).getDay();
		x=(x==0 ? 7 : x)-1;
		kal.rows[0].cells[0].innerHTML= dnnms[x] + ' ' + a + '. ' + mn[Math.floor(mes)] + ' ' + rok;

		
		x=1;xx=0;
		//vytvoř dny kalendáře
		for (a=0; a<b ; a++){
			rw=kal.insertRow(-1);
			for (aa=0; aa<7; aa++){
				cl=rw.insertCell(-1);
				if(xx>=dent && x<=(maxden)){
					cssNorm='';
					cssOn='JBKalMouseOver';
					d=Math.floor(xx/7);
					d=Math.round((xx/7-d)*7);
					if(d==5){
						cssNorm='JBKalendarSo';
					}
					if(d==6){
						cssNorm='JBKalendarNe';
					}

					if(x==dnes[0] && rok==dnes[2] && (mes+1)==dnes[1]){cssNorm += (cssNorm!='' ? ' ' : '') + "JBKalDnes"};
					if(x==cstdt){cssNorm += (cssNorm!='' ? ' ' : '') + "JBKalCustDt"};
				
					cl.className=cssNorm;
					this.button(cl,x,cssOn,cssNorm,'JBKalendar.Set(this)')
					x += 1;
				}
				xx += 1;
			}
		}
		
		//v el je element u kterého se má kalendář zobrazit
		//v kal je element kalendáře
		Element.absolutize(kal);
		//kal.style.position='absolute';
		a=Element.cumulativeOffset(el);
		Element.setStyle(kal,{
			left: a.left+'px',
			top: (a.top + el.offsetHeight)+'px'
		});
		
		
		//a=String(this.left(el));
		//kal.style.left=a.left+'px';
		//kal.style.top= a.top + el.offsetHeight;
		
		Element.show(kal);
		clearTimeout(tm);
		psn=false;
	}
	
	// posun data
	this.Posun = function (co,kolik){
	var a;
	// co =	"se"-sekundy
	//	  = "mi"=minuty
	//    = "ho"=hodiny
	//    = "d"=dny
	//    = "m"=měsíce
	//	  = "y"=roky
		psn=true;
		a = date_to_num(JBKalendarAktivD + '.' + (JBKalendarAktivM+1) + '.' + JBKalendarAktivY);
		a = add_to_numdatetime(a,co,kolik);
		JBKalendarAktivEl.value=num_to_date(a);
		this.show(JBKalendarAktivEl);
	}
	
	//zjistí umístění elementu na stránce
	this.left = function (obj){
		var curleft = 0;
		if (obj.offsetParent)
		{
			while (obj.offsetParent)
			{
				curleft += obj.offsetLeft
				obj = obj.offsetParent;
			}
		}
		else if (obj.x)
			curleft += obj.x;
		return curleft;
	}
	//zjistí umístění elementu na stránce
	this.top = function (obj){
		var curtop = 0;
		if (obj.offsetParent)
		{
			while (obj.offsetParent)
			{
				curtop += obj.offsetTop
				obj = obj.offsetParent;
			}
		}
		else if (obj.y)
			curtop += obj.y;
		return curtop;
	}

	// použití při onblur, pro kontrolu pole a uzavření kalendáře
	this.kontrola = function(el){
		if(!InputIsDatum(el)){
			if(el.value!='') alert('Chyba v datumu!!');
			el.value='';
		};
		JBKalendar.close();
	}
	
	// kontrola povolených kláves a ovládání klávesnicí
	this.stisk = function(e,el){
		var kod,znak,zakaz,op,cl,dn;
		zakaz=/[0-9.]/;
		op=/[kK]/;
		cl=/[cC]/;
		dn=/[dD]/;
		
		if(window.event){ // IE
			kod = e.keyCode;
		}else if(e.which){ // Netscape/Firefox/Opera
			kod = e.which;
		}
		if (kod<32 || kod==null){return true};
		znak = String.fromCharCode(kod);
		if (op.test(znak)){
			this.show(el);
			return false;
		};
		if (cl.test(znak)){
			this.close();
			JBKalendarAktivEl.focus();
			return false;
		};
		if (dn.test(znak)){
			this.Dnes();
			return false;
		};
		return zakaz.test(znak);
	}
}// konec definice kalendáře

// inicializace ve skriptu
var JBKalendar = new FN_JBKalendar;
Event.observe(window,'load',function(){
	JBKalendar.RegisterOnClass();
});



