function classCalendar(o){
	var c1=jml.obj,c2=jml.events,c3=jml.xml.node,l=isset(o.lang)?o.lang:'fr',f=isset(o.onSelect)?o.onSelect:null,uid='uiCalendar'+getUniqueId(),itm,db,tm,host,btns,cb,ifrm;
	var current={
		day:isset(o.date)&&isset(o.date.day)?o.date.day:new Date().getDate(),
		month:isset(o.date)&&isset(o.date.month)?o.date.month:new Date().getMonth(),
		year:isset(o.date)&&isset(o.date.year)?o.date.year:new Date().getFullYear()
	};
	var init={day:current.day,month:current.month,year:current.year};
	var label={
		day:{fr:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],en:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},
		month:{fr:["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"],en:["January","February","March","April","May","June","July","August","September","October","November","December"]},
		next:{fr:'Mois suivant',en:'Next month'},
		previous:{fr:'Mois précédent',en:'Previous month'},
		close:{fr:'Fermer le calendrier',en:'Close calendar'}
	}
	function getDays(n1,n2){return 32-new Date(n1,n2,32).getDate();}
	function writeStructure(){
		var  s = "<div class='uiCalendar' id='"+uid+"'>\n<table>\n",n1=1,n2=7;
		s += "<tr>\n";
		s += "<td class='left'><img src='/library/images/btns/calendar_arrow_left.gif' alt='"+label.previous[l]+"' title='"+label.previous[l]+"' class='$preload$swap$cursor' /></td>\n";
		s += "<td class='label'>Nom du mois</td>\n";
		s += "<td class='right'><img src='/library/images/btns/calendar_arrow_right.gif' alt='"+label.next[l]+"' title='"+label.next[l]+"' class='$preload$swap$cursor' /></td>\n";
		s += "<td class='close'><img src='/library/images/btns/calendar_close.gif' alt='"+label.close[l]+"' title='"+label.close[l]+"' class='$preload$swap$cursor' /></td>\n";
		s += "</tr>\n";
		s += "<tr>\n";
		s += "<td colspan='4'>\n";
		s += "<table>\n<tr>\n";
		
		for(var i=0;i<49;i++){
			if(i==n1*n2){
				s += "</tr>\n<tr>\n";
				n1++;
			}
			var s1=n1==1?label.day[l][i].slice(0,1):"";
			var s2=n1==1?"h":"d";
			s += "<t"+s2+">"+s1+"</t"+s2+">\n";
		}
		s += "</tr>\n";
		s += "</table>\n";
		s += "</td>\n";
		s += "</tr>\n";
		s += "</table>\n</div>\n";
		document.write(s);
	}
	function getPosition(n){return new Date(current.year,current.month,n).getDay();}
	function setDate(n){
		host.display(null,false);
		if(f) f(current.year,current.month+1,n,label.month[l][current.month],label.day[l][getPosition(n)]);		
	}
	function changeMonth(n){
		var n1=current.month;
		if(n1+n<0){
			current.month=11;
			current.year--;
		}else if(n1+n>11){
			current.month=1;
			current.year++;
		}else{
			current.month+=n;
		}
		populate();
	}
	function onDate(e){setDate(Number(c1.get(c2.getElement(c2.initialize(e)),'innerHTML')));}
	function onOver(e){
		var o=c2.getElement(c2.initialize(e));
		if(c1.get(o,'className').indexOf('currentDay')!=-1) return;
		c1.set(o,'className','active_over');
	}
	function onOut(e){
		var o=c2.getElement(c2.initialize(e));
		if(c1.get(o,'className').indexOf('currentDay')!=-1) return;
		c1.set(o,'className','active');
	}
	function populate(){
		if(!isset(db)) db=c3.byPath('0.0.1.0.0.0',itm);
		if(!isset(tm)){
			tm=c3.byPath('0.0.0.1',itm);
			if(!isset(btns)){
				btns={left:c3.byPosition(0,c3.byProximity(tm,-1)),right:c3.byPosition(0,c3.byProximity(tm,1))};
				c2.add(btns.left,'click',function(){changeMonth(-1)});
				c2.add(btns.right,'click',function(){changeMonth(1)});
			}
		}
		if(!isset(cb)){
			cb=c3.byPosition(0,c3.byProximity(c3.parent(btns.right,1),1));
			c2.add(cb,'click',function(){host.display(null,false);});
		}
		c1.set(tm,'innerHTML',label.month[l][current.month]+' '+current.year);
		var n0=getDays(current.year,current.month);
		var n5=1;
		var n1=c3.length(db);
		var n2=getPosition(1);
		for(var i=1;i<n1;i++){
			var x2=c3.byPosition(i,db);
			var n3=c3.length(x2);
			var n4=i==1?n2:0;
			for(var j=0;j<7;j++){
				var x3=c3.byPosition(j,x2);
				c1.set(x3,'className','');
				c1.set(c3.byPosition(j,x2),'innerHTML','&nbsp;');
				c2.remove(x3,'click',onDate);
				c2.remove(x3,'mouseover',onOver);
				c2.remove(x3,'mouseout',onOut);
			}
			var g1=current,g2=init;
			for(var j=n4;j<n3;j++){
				if(n5<=n0){
					var s3= (g1.month==g2.month&&g1.year==g2.year&&n5==init.day)?' currentDay':'';
					var x3=c3.byPosition(j,x2);
					c1.set(x3,'innerHTML',n5);
					c1.set(x3,'className','active'+ s3);
					c2.add(x3,'click',onDate);
					c2.add(x3,'mouseover',onOver);
					c2.add(x3,'mouseout',onOut);
					n5++;
				}
			}
		}
	}
	return {
		$:function(){
			if(!isset(host))host=this;
			c2.add(window,'load',function(){
				if(!isset(itm)) itm=getObj(uid);
				populate();
			});
			writeStructure();
			return this;
		},
		display:function(o,b){
			var b=b||false;
			var n1=0,n2=0,n3=10;
			if(isset(o)){
				n1=c1.get(o,'offsetLeft');
				n2=c1.get(o,'offsetTop')+c1.get(o,'offsetHeight');
				c1.set(uid,'left',n1+'px');
				c1.set(uid,'top',n2+'px');
			}
			c1.set(uid,'display',b?'block':'none');			
			if(lower(navigator.userAgent).match('msie 6')!=null){
				if(!isset(ifrm)) ifrm=c3.create('DIV',document.body);
				c1.set(ifrm,'innerHTML','<iframe></iframe>');
				c1.set(ifrm,'className','ie6UnderFloatBugForm');
				c1.set(ifrm,'width',(c1.get(itm,'offsetWidth')+n3)+'px');
				c1.set(ifrm,'height',(c1.get(itm,'offsetHeight')+n3)+'px');
				c1.set(ifrm,'left',(n1-(n3/2))+'px');
				c1.set(ifrm,'top',(n2-(n3/2))+'px');
			}				
		}
	}.$();
}