function Calendar(calendar_name, css_prefix, images_path, p_days, p_months){

/************************ 
                                   VARIABLES INIT 
*****************************/	
	//defaults
	if (css_prefix == null) css_prefix = "calendar";
	if (images_path == null) images_path = "images/";

	this.name = calendar_name;
	this.cssPrefix = css_prefix;
	this.imagesPath = images_path;


	var days;
	if (p_days != null){
		days = p_days;
	}else{
		days = new Array(8);
		days[1] = "Po";
		days[2] = "Ut";
		days[3] = "Sr";
		days[4] = "Če";
		days[5] = "Pe";
		days[6] = "Su";
		days[7] = "Ne";
	}

	var months;
	if (p_months != null){
		months = p_months;
	}else{
		months = new Array(13)
		months[1]  = "siječanj";
		months[2]  = "veljača";
		months[3]  = "ožujak";
		months[4]  = "travanj";
		months[5]  = "svibanj";
		months[6]  = "lipanj";
		months[7]  = "srpanj";
		months[8]  = "kolovoz";
		months[9]  = "rujan";
		months[10] = "listopad";
		months[11] = "studeni";
		months[12] = "prosinac";
	}










/*************************    
                                //PROTOTYPE INIT 
**********************/

	
	if (Calendar.prototype.loaded == null){
		Calendar.prototype.loaded = "true";

		Calendar.prototype.prepareElement = prepareElement;
		Calendar.prototype.prepareDayList = prepareDayList;
		
		Calendar.prototype.hide = hide;
		Calendar.prototype.show = show;
		Calendar.prototype.isVisible = isVisible;
		Calendar.prototype.moveTo = moveTo;

		Calendar.prototype.sendDay = sendDay;
		Calendar.prototype.setDate = setDate;
		Calendar.prototype.sendDate = sendDate;
		Calendar.prototype.generate = generate;

		Calendar.prototype.setYear = setYear;
		Calendar.prototype.getYear = getYear;
		Calendar.prototype.decreaseYear = decreaseYear;
		Calendar.prototype.increaseYear = increaseYear;
		Calendar.prototype.setMonth = setMonth;
		Calendar.prototype.getMonth = getMonth;
		Calendar.prototype.decreaseMonth = decreaseMonth;
		Calendar.prototype.increaseMonth = increaseMonth;
		Calendar.prototype.setDay = setDay;
		Calendar.prototype.getDay = getDay;
		Calendar.prototype.increaseDay = increaseDay;
		Calendar.prototype.decreaseDay = decreaseDay;
		Calendar.prototype.calendars = new Array();//calendar repository, helps initializing multiple calendars in onload function
	}
	Calendar.prototype.calendars[Calendar.prototype.calendars.length] = this;//add self to repository







/**************************
                                 //CLASS METHODS
***************************/






	function sendDay(d){
		var y = this.yearInput.value;
		var m = this.monthInput.value
			this.sendDate(y,m,d);
	}
	function sendDate(y,m,d){
		this.setDate(y,m,d);
		if (this.onDate != null)
			this.onDate(y,m,d);
	}


	function makeDate(y,m,d){return new Date(y,(m-1),d);}
	function myDay(day){return (day + 6)%7 +1;}//make sunday da #7 monday day #1

	function generate(){
		var year = this.getYear();
		var month = this.getMonth();
		var dateObj = makeDate(year, month, 1);

		var wday    = myDay(dateObj.getDay());
		var lmonth  = dateObj.getMonth() + 1;
		var date    = dateObj.getDate();

		this.dayOffset = wday-1;
		var i=0;
		for (; i<this.dayOffset; i++){
			this.days[i].text.data = ".";
			this.days[i].day = null;
			this.days[i].classBase.remove(this.cssPrefix+"_full");
		}

		var day = 1;
		while((makeDate(year,month,day).getMonth()+1) == month){
			this.days[i].text.data = day;
			this.days[i].day = day;
			this.days[i].classBase.add(this.cssPrefix+"_full");
			day ++;
			i++;
		}

		for (; i<this.days.length; i++){
			this.days[i].text.data = ".";
			this.days[i].day = null;
			this.days[i].classBase.remove(this.cssPrefix+"_full");
		}
		this.setDay(this.dayInput.value);
	}
	
	function prepareDayList(){
		this.days = new Array();
		this.dayNames = new Array();
		var table = this.prepareElement("TABLE","CELLSPACING=0", "CELLPADDING=0", "WIDTH=100%");
		this.listDiv.appendChild(table);
		var tbody = document.createElement("TBODY");
		table.appendChild(tbody);
		table.className = this.cssPrefix+"_table";

		var tr = document.createElement("TR");
		tbody.appendChild(tr);
		for(var j=1; j<=7; j++){
			var td = document.createElement("TD");
			this.dayNames[j] = td;
			td.classBase = new ClassBase(td,this.cssPrefix+"_day_name");
			td.classBase.add(this.cssPrefix+"_day_name",this.cssPrefix+"_day_name"+j);
			td.innerHTML = days[j];
			tr.appendChild(td);
		}

		for(var i=0; i<6; i++){
			tr = document.createElement("TR");
			tbody.appendChild(tr);
			for(var j=0; j<7; j++){
				var td = this.prepareElement("TD");
				td.weekDay = j+1;
				td.onclick = dayClickExt;
				td.onmouseover = dayMouseOver;
				td.onmouseout = dayMouseOut;
				td.classBase = new ClassBase(td,this.cssPrefix+"_day");
				td.classBase.add(this.cssPrefix+"_day", this.cssPrefix+"_col"+j, this.cssPrefix+"_row"+i);
				td.text = document.createTextNode(i+""+j); 
				td.appendChild(td.text);
				this.days[this.days.length] = td;
				tr.appendChild(td)
			}
		}
	}

	function moveTo(container){
		var c = document.getElementById(container);
		c.appendChild(this.div);
		this.show();
	}


	function isVisible(){
		return (this.div.style.display != "none");
	}

	function hide(){
		this.div.style.display = "none";
	}

	function show(){
		this.div.style.display = "inline";
	}






// *************************
                                     //EVENT HANDLERS    
//**************************

	function dayMouseOver(){
		if (this.day == null) return;
		this.classBase.add(this.classBase.nameBase+"_over");
		var dayName = this.calendar.dayNames[this.weekDay]
		dayName.classBase.add(dayName.classBase.nameBase+"_over");
	}

	function dayMouseOut(){
		if (this.day == null) return;
		this.classBase.remove(this.classBase.nameBase+"_over");
		var dayName = this.calendar.dayNames[this.weekDay]
		dayName.classBase.remove(dayName.classBase.nameBase+"_over");
	}

	function extMouseOver(){
		this.classBase.add(this.classBase.nameBase+"_over");
	}

	function extMouseOut(){
		this.classBase.remove(this.classBase.nameBase+"_over");
	}

	function ExtInputFocus(){
		this.classBase.add(this.classBase.nameBase+"_focus");
	}

	function ExtInputBlur(){
		this.classBase.remove(this.classBase.nameBase+"_focus");
	}

	function ExtKeyDown(evt){
		if (evt == null) evt = event;
		if (evt.keyCode == 38){
			if (this.func == "month_input"){this.calendar.increaseMonth();}
			if (this.func == "year_input"){this.calendar.increaseYear();}
			if (this.func == "day_input"){this.calendar.increaseDay();}
		}else if (evt.keyCode == 40){
			if (this.func == "month_input"){this.calendar.decreaseMonth();}
			if (this.func == "year_input"){this.calendar.decreaseYear();}
			if (this.func == "day_input"){this.calendar.decreaseDay();}
		}
	}

	function ExtKeyPress(evt){
		if (evt == null) evt = event;
		if (evt.keyCode == 13){
			if (this.func == "month_input"){this.calendar.setMonth(this.calendar.getMonth());}
			else if (this.func == "year_input") this.calendar.setYear(this.calendar.getYear());
			else this.calendar.setDay(this.calendar.getDay());
			return false;
		}
	}

	function ExtInputChange(){
		if (this.func == "month_input"){this.calendar.setMonth(this.calendar.getMonth());}
		else if (this.func == "year_input") this.calendar.setYear(this.calendar.getYear());
		else this.calendar.setDay(this.calendar.getDay());
	}

	function isNumeric(str){
		if (str == null || str == "") return false;
		var num = "0123456789";
		for (var i=0; i<str.length; i++){
			if (num.indexOf(str.substring(i,i+1)) == -1) {
				return false;
			}
		}
		return true;
	}


	function ExtImageOver(){
		if (this.imageOver != null){
			this.normalSrc = this.src;
			this.src = this.imageOver.src;
		}
	}

	function ExtImageOut(){
		if (this.normalSrc != null){
			this.src = this.normalSrc;
		}
	}

	function ExtDisable(){
		return false;
	}

	function ExtBlur(){
		this.blur();
	}










/************************ //CONTROLL FUNCTIONS ************************/

	function dayClickExt(){
		if (this.day != null)
			this.calendar.sendDay(this.day);
	}	

//year
	//set (silent is for multiple changes to control refreshing, to be able to make few changes with one refresh)
	function getYear(){
		var year = ""+this.yearInput.value;
		if (isNumeric(year)) return eval(year);
		else return 2000;
	}
	function setYear(year, silent){
		this.yearInput.value = year;
		if (!silent) this.generate();
	}
	//decrease
	function decreaseYearExt(){this.calendar.decreaseYear();return false;}
	function decreaseYear(silent){
		this.setYear(this.getYear() - 1,silent);
	}
	//increase
	function increaseYearExt(){this.calendar.increaseYear();return false;}
	function increaseYear(silent){
		var year = this.getYear();
		if (year == null || typeof(year) == "undefined") year = 2000;
		this.setYear(year + 1, silent);
	}

//month
	//set
	function getMonth(){
		var month = this.monthInput.value;
		if (isNumeric(month)) {
			month = eval(month);
			if(month>12) return 12;
			if(month<1) return 1;
			return month;
		
		}else return 1;
	}
	function setMonth(month, silent){
		this.monthInput.value = month;
		this.monthInput.desc.innerHTML = months[month];
		if (!silent) this.generate();
	}
	//decrease
	function decreaseMonthExt(){this.calendar.decreaseMonth();return false;}
	function decreaseMonth(){
		var month = this.getMonth() - 1;
		if (month < 1){
			month = 12;
			this.decreaseYear(true);//silent decrease (generate is not called)
		}
		this.setMonth(month);
	}
	//increase
	function increaseMonthExt(){this.calendar.increaseMonth();return false;}
	function increaseMonth(){
		var month = this.getMonth() + 1;
		if (month > 12){
			month = 1;
			this.increaseYear(true);//silent decrease (generate is not called)
		}
		this.setMonth(month);
	}
//DAY
	//get
	function getDay(){
		var day = this.dayInput.value;
		if (isNumeric(day)) {
			day = eval(day);
			if(day < 1) return 1;
			return day;
		}else return 1;
	}
	//set
	function setDay(d){
		this.dayInput.value = d;
		var classname = this.cssPrefix+"_day_selected";
		for (var i=0; i<this.days.length; i++){
			var day = this.days[i];
			if (day.day == d){
				day.classBase.add(classname);
			}else
				day.classBase.remove(classname);
		}
	}
	//increase
	function increaseDay(){
		var newDay = this.getDay() + 1;
		var date = makeDate(this.getYear(), this.getMonth(), newDay);
		if (date.getMonth() + 1 != this.getMonth()){
			this.increaseMonth();
			this.setDay(date.getDate());//actual ay of the month
		}else this.setDay(newDay);
	}
	//decrease
	function decreaseDay(){
		var newDay = this.getDay() - 1;
		var date = makeDate(this.getYear(), this.getMonth(), newDay);
		if (date.getMonth()+1 != this.getMonth()){
			this.decreaseMonth();
			this.setDay(date.getDate());//actual ay of the month
		}else this.setDay(newDay);
	}
//DATE
	//set
	function setDate(y,m,d){
		this.setYear(y,true);//disable generate
		this.setMonth(m);//set month and generate
		this.setDay(d);
	}

























/********************* 
                                 //GUI 
******************/





/*
									 prepareElement

creating involved objects
(they need reference to this calndar instance)
*/
	function prepareElement(){
		var args = prepareElement.arguments;
		var elem = document.createElement(args[0]);
		elem.calendar = this;
		for (i=1; i<args.length; i++){
			var param = args[i];
			var idx  = param.indexOf("=");
			var attr = param.substring(0,idx);
			var val = param.substring(idx+1);
			elem.setAttribute(attr,val,0);
		}
		return elem;
	}

	this.div = this.prepareElement('TABLE', 'cellspacing=0', 'cellpadding=0');
	this.div.className = this.cssPrefix+"_main_table";
	var mainTableBody = document.createElement("TBODY");
	this.div.appendChild(mainTableBody);
	var mainTr1 = document.createElement("TR");
	mainTableBody.appendChild(mainTr1);
	var mainTd1 = document.createElement("TD");
	mainTr1.appendChild(mainTd1);
	var mainTr2 = document.createElement("TR");
	mainTableBody.appendChild(mainTr2);
	var mainTd2 = document.createElement("TD");
	mainTr2.appendChild(mainTd2);

	var ctrlTable = this.prepareElement('TABLE', 'cellspacing=0', 'cellpadding=0', 'border=0');
	ctrlTable.className = this.cssPrefix+"_control_table";
	var ctrlTableBody = document.createElement("TBODY");
	ctrlTable.appendChild(ctrlTableBody);
	mainTd1.appendChild(ctrlTable);
	//rows
	var tr1 = document.createElement("TR");
	ctrlTableBody.appendChild(tr1);
	var tr2 = document.createElement("TR");
	ctrlTableBody.appendChild(tr2);
//DAY
	//day control
		//Day value
		var td01 = this.prepareElement('TD', 'class='+this.cssPrefix + '_month_input');
		tr1.appendChild(td01);
		this.dayInput = this.prepareElement('input', 'size=1', 'title=Dan u mjesecu. Klikni za ručni unos(dodatno možete koristiti strijelice dolje i gore za jedinično smanjivanje i povečavanje).');
		this.dayInput.func = "day_input"; 
		this.dayInput.classBase = new ClassBase(this.dayInput,this.cssPrefix +'_month_input');
		this.dayInput.classBase.add(this.cssPrefix +"_month_input");
		this.dayInput.onchange = ExtInputChange;
		this.dayInput.onkeypress = ExtKeyPress;
		this.dayInput.onkeydown = ExtKeyDown;
		this.dayInput.onfocus = ExtInputFocus;
		this.dayInput.onblur = ExtInputBlur;
		this.dayInput.onmouseover = extMouseOver;
		this.dayInput.onmouseout = extMouseOut;
		td01.appendChild(this.dayInput);
		var td02 = this.prepareElement('td');
		//td02.innerHTML = "&nbsp;";
		tr2.appendChild(td02, 'class=ctrl_button');
//MONTH
	//month control
		//Month value
		var td11 = this.prepareElement('TD', 'colspan=2', 'class='+this.cssPrefix + '_month_input',"align=right");
		tr1.appendChild(td11);
		this.monthInput = this.prepareElement('input', 'size=1', 'title=Mjesec. Klikni za ručni unos(dodatno možete koristiti strijelice dolje i gore za jedinično smanjivanje i povečavanje).');
		this.monthInput.desc = document.createElement("span"); 
		this.monthInput.desc.className = this.cssPrefix +"_month_input"; 
		this.monthInput.func = "month_input"; 
		this.monthInput.classBase = new ClassBase(this.monthInput,this.cssPrefix +'_month_input');
		this.monthInput.classBase.add(this.cssPrefix +"_month_input");
		this.monthInput.onchange = ExtInputChange;
		this.monthInput.onkeypress = ExtKeyPress;
		this.monthInput.onkeydown = ExtKeyDown;
		this.monthInput.onfocus = ExtInputFocus;
		this.monthInput.onblur = ExtInputBlur;
		this.monthInput.onmouseover = extMouseOver;
		this.monthInput.onmouseout = extMouseOut;
		td11.appendChild(this.monthInput.desc);
		td11.appendChild(document.createTextNode("("));
		td11.appendChild(this.monthInput);
		td11.appendChild(document.createTextNode(")"));
		//decrease Month button
		var td12 = this.prepareElement('td', 'class=ctrl_button');
		tr2.appendChild(td12);
		this.decreaseMonthButton = this.prepareElement('a', 'href=#', 'onfocus=blur();');
		this.decreaseMonthButton.classBase = new ClassBase(this.decreaseMonthButton);
		this.decreaseMonthButton.classBase.add(this.cssPrefix +"_button", this.cssPrefix +"_decrease_button");
		this.decreaseMonthButton.onmouseover = extMouseOver;this.decreaseMonthButton.onmouseout = extMouseOut;
		this.decreaseMonthButton.onmousedown = decreaseMonthExt;this.decreaseMonthButton.ondblclick = decreaseMonthExt;
		this.decreaseMonthButton.onclick = ExtDisable;
		this.decreaseMonthButton.onfocus = ExtBlur;
		this.decreaseMonthButton.image = this.prepareElement('img', 'src='+this.imagesPath+'minus.gif', 'border=0', 'hspace=1', 'title=- mjesec');
		this.decreaseMonthButton.appendChild(this.decreaseMonthButton.image);
		this.decreaseMonthButton.image.imageOver = new Image(); 
		this.decreaseMonthButton.image.imageOver.src = this.imagesPath+"minus_over.gif"; 
		this.decreaseMonthButton.image.onmouseover = ExtImageOver;
		this.decreaseMonthButton.image.onmouseout = ExtImageOut;
		td12.appendChild(this.decreaseMonthButton);
		//increase Month button
		var td22 = this.prepareElement('td', 'width=70%', 'class=ctrl_button');
		tr2.appendChild(td22);
		this.increaseMonthButton = this.prepareElement('a', 'href=#', 'onfocus=blur();');
		this.increaseMonthButton.onmousedown = increaseMonthExt;this.increaseMonthButton.ondblclick = increaseMonthExt;
		this.increaseMonthButton.onclick = ExtDisable;
		this.increaseMonthButton.onfocus = ExtBlur;
		this.increaseMonthButton.image = this.prepareElement('img', 'src='+this.imagesPath+'plus.gif', 'border=0', 'hspace=1', 'title=+ mjesec');
		this.increaseMonthButton.appendChild(this.increaseMonthButton.image);
		this.increaseMonthButton.image.imageOver = new Image(); 
		this.increaseMonthButton.image.imageOver.src = this.imagesPath+"plus_over.gif"; 
		this.increaseMonthButton.image.onmouseover = ExtImageOver;
		this.increaseMonthButton.image.onmouseout = ExtImageOut;
		td22.appendChild(this.increaseMonthButton);

//YEAR
	//year control
		//year value
		var td31 = this.prepareElement('td', 'colspan=2', 'class='+this.cssPrefix +'_year_input');
		tr1.appendChild(td31);
		this.yearInput = this.prepareElement('input', 'size=2', 'type=text', 'title=Godina. Klikni za ručni unos(dodatno možete koristiti strijelice dolje i gore za jedinično smanjivanje i povečavanje).');
		this.yearInput.classBase = new ClassBase(this.yearInput,this.cssPrefix +"_year_input");
		this.yearInput.classBase.add(this.cssPrefix +"_year_input");
		this.yearInput.func = "year_input"; 
		this.yearInput.onchange = ExtInputChange;
		this.yearInput.onkeypress = ExtKeyPress;
		this.yearInput.onkeydown = ExtKeyDown;
		this.yearInput.onfocus = ExtInputFocus;
		this.yearInput.onblur = ExtInputBlur;
		this.yearInput.onmouseover = extMouseOver;
		this.yearInput.onmouseout = extMouseOut;
		td31.appendChild(this.yearInput);
		//decrease year button
		var td32 = this.prepareElement('td', 'class=ctrl_button');
		tr2.appendChild(td32);
		this.decreaseYearButton = this.prepareElement('a', 'href=#', 'onfocus=blur();');
		this.decreaseYearButton.className = this.cssPrefix + "_button"+this.cssPrefix +"_increase_button";
		this.decreaseYearButton.onmousedown = decreaseYearExt;this.decreaseYearButton.ondblclick = decreaseYearExt;
		this.decreaseYearButton.onclick = ExtDisable;
		this.decreaseYearButton.onfocus = ExtBlur;
		this.decreaseYearButton.image = this.prepareElement('img', 'src='+this.imagesPath+'minus.gif', 'border=0', 'hspace=1', 'title=- godina');
		this.decreaseYearButton.appendChild(this.decreaseYearButton.image);
		this.decreaseYearButton.image.imageOver = new Image(); 
		this.decreaseYearButton.image.imageOver.src = this.imagesPath+"minus_over.gif"; 
		this.decreaseYearButton.image.onmouseover = ExtImageOver;
		this.decreaseYearButton.image.onmouseout = ExtImageOut;
		td32.appendChild(this.decreaseYearButton);
		//increase year button
		var td42 = this.prepareElement('td', 'class=ctrl_button');
		tr2.appendChild(td42);
		this.increaseYearButton = this.prepareElement('a', 'href=#',  'onfocus=blur();');
		this.increaseYearButton.className = this.cssPrefix +"_button"+this.cssPrefix +"_increase_button";
		this.increaseYearButton.onmousedown = increaseYearExt;this.increaseYearButton.ondblclick = increaseYearExt;
		this.increaseYearButton.onclick = ExtDisable;
		this.increaseYearButton.onfocus = ExtBlur;
		this.increaseYearButton.image = this.prepareElement('img', 'src='+this.imagesPath+'plus.gif', 'border=0', 'hspace=1', 'title=+ godina');
		this.increaseYearButton.appendChild(this.increaseYearButton.image);
		this.increaseYearButton.image.imageOver = new Image(); 
		this.increaseYearButton.image.imageOver.src = this.imagesPath+"plus_over.gif"; 
		this.increaseYearButton.image.onmouseover = ExtImageOver;
		this.increaseYearButton.image.onmouseout = ExtImageOut;
		td42.appendChild(this.increaseYearButton);
		this.listDiv = this.prepareElement("div","align=center");
		mainTd2.appendChild(this.listDiv);

	this.prepareDayList();
	var date = new Date();
	this.setDate(date.getYear(), date.getMonth()+1, date.getDay());
}





















//							CLASS BASE






function ClassBase(tag,nameBase){
	this.tag = tag;
	if (nameBase == null) nameBase = "";
	this.nameBase = nameBase;
	this.classes = new Array();
	this.used = new Object();
	this.classes.realLength = 0;
	
	function add(){
		var args = add.arguments;
		var p= null;
		var changed = false;
		for (var i=0; i<args.length; i++){
			p = args[i];
			if (p==null) continue;
			if(this.used[p] == null){
				this.used[p] = this.classes.length;
				this.classes[this.classes.length] = p;
				changed = true;
			}
		}
		if (changed && this.tag != null) this.tag.className = this.toString();
	}

	function remove(){
		var args = remove.arguments;
		var p= null;
		var changed = false;
		for (var i=0; i<args.length; i++){
			p = args[i];
			if (p==null) continue;
			if (this.used[p] == null) continue;
			this.classes[this.used[p]] = null;
			this.used[p] = null;
			changed = true;
		}
		if (changed && this.tag != null) this.tag.className = this.toString();
	}

	function toString(){
		var delim = "";
		var ret = "";
		for(var i=0; i<this.classes.length; i++){
			if(this.classes[i] == null) continue;
			ret += delim + this.classes[i];
			delim = " ";
		}
		return ret;
	}

	if (!(ClassBase.prototype.initDone)){
		ClassBase.prototype.initDone = true;

		ClassBase.prototype.add = add;
		ClassBase.prototype.remove = remove;
		ClassBase.prototype.toString = toString;
	}
}





