var terminkalender;
var startDates;

jscontrol.addEvent(window, 'load', function () {saveDates(); }, false);
jscontrol.addEvent(window, 'load', function () {terminkalender = new Terminkalender("CalStart", "CalEnd");}, false);
jscontrol.addEvent(window, 'load', function () {activate(); }, false);

String.prototype.trim = function () {
	return (this.replace(/\s+$/,"").replace(/^\s+/,""));
};


//BEGIN GLOBAL, MISC. FUNCTIONS
function _(id) {
	return document.getElementById(id);
}

function _text(text) {
	return document.createTextNode(text);
}

function _el(el) {
	return document.createElement(el);
}

function clearValue(el) {
	if(el.value == "Schnelleingabe") {
		el.value = "";
	}
}

function saveDates() {
	startDates = {};
    if (_("calStartwoJS") != null)
        startDates["start"] = _("calStartwoJS").value;
	if (_("calEndwoJS") != null)
        startDates["end"] = _("calEndwoJS").value;
}

/**
* Calcualates difference of months and browses given calender to the specific month
*
* @param m int new month
* @param cm int current month
* @param y int new year
* @param cy int current year
* @param cid string id of the calendar element
*/
function monthDiff(m, cm, y, cy, cid) {
	dm = 0;

	//calc diff
	if(m != cm) {
		dm = m - cm;
	}
	if(y != cy) {
		dy = y - cy;
		dm = dm + (dy * 12);
	}

	//apply diff
	while (dm > 0) {
		terminkalender._Cal._HTMLCal._turnCalendar(cid, "further");
	  	dm -= 1;
	}
	while (dm < 0) {
	  	terminkalender._Cal._HTMLCal._turnCalendar(cid, "earlier");
	  	dm += 1;
	}
}

function activate() {
    if (_("terminsuche-extended") != null)
        _("terminsuche-extended").style.display = "block";

	//zuvor gewähltes Datum bei neuer Suche setzen
	//dd.mm.yyyy
    if (_("zeitraum_1") != null) 
	if(_("zeitraum_1").checked) {
		terminkalender.toggleSel(_("zeitraum_1"));
	} else if(_("zeitraum_2").checked) {
		terminkalender.toggleSel(_("zeitraum_2"));
	} else if(_("zeitraum_3").checked) {
		terminkalender.toggleSel(_("zeitraum_3"));
		aStart = startDates["start"].split(".");
		aEnd = startDates["end"].split(".");

		//some date magic beforehand
		d = new Date();
		cm = d.getMonth();
		cy = d.getYear();
		if(cy.toString().length == 3) {
			cy += 1900;
		}
		//EndDate
		m = aEnd[1]-1;
		monthDiff(m, cm, aEnd[2], cy, terminkalender._Cal._endID);

		terminkalender._Cal._HTMLCal._setSelDate(terminkalender._Cal._endID, parseInt(aEnd[0]), m, aEnd[2]);
		terminkalender._Cal._HTMLCal._outlineSelDate(terminkalender._Cal._endID);

		//StartDate
		m = aStart[1]-1;
		monthDiff(m, cm, aStart[2], cy, terminkalender._Cal._startID);

		terminkalender._Cal._HTMLCal._setSelDate(terminkalender._Cal._startID, parseInt(aStart[0]), m, aStart[2]);
		terminkalender._Cal._HTMLCal._outlineSelDate(terminkalender._Cal._startID);
	}
}

function clone(obj) {
	//this function has been found at: http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
	if(obj == null || typeof(obj) != 'object') {
		return obj;
	}

	var temp = {};
	for(var key in obj) {
		temp[key] = clone(obj[key]);
	}
	return temp;
}
//END GLOBAL, MISC. FUNCTIONS

//BEGIN CLASS TERMINKALENDER
function Terminkalender(startElement, endElement) {
	//CLASS FUNCTIONS
	this.toggleSel = function(el) {
		if(!el) {
			this._setError("Objekt nicht definiert!");
			return false;
		}

		if(el.value == 0) {
			this._Cal.setToday();
		} else if(el.value == 1) {
			this._Cal.setThisWeek();
		} else if(el.value == 2) {
			this._Cal.setThisMonth();
		} else if(el.value == 3) {
			this._Cal.setManualCal();
		}

		this.update();
	}

	this.update = function() {

		if(!this._elStart || !this._elEnd) {
			this._setError("Kein g�ltiges Element f�r Start- und/oder Enddatum!");
			return false;
		}

		try {
			_(this._elStart).innerHTML = "";
			var node = typeof(this._Cal.getStart()) == "string" ? _text(this._Cal.getStart()) : (typeof(this._Cal.getStart()) == "object") ? this._Cal.getStart() : "";
			_(this._elStart).appendChild(node);
			if(node.nodeType == 3) {		//Textknoten
				var field = _el("input");
				field.type = "hidden";
				field.name = "calStart";
				field.value = node.nodeValue;
				_(this._elStart).appendChild(field);
			}

			_(this._elEnd).innerHTML = "";
			var node = typeof(this._Cal.getEnd()) == "string" ? _text(this._Cal.getEnd()) : this._Cal.getEnd();
			_(this._elEnd).appendChild(node);
			if(node.nodeType == 3) {		//Textknoten
				var field = _el("input");
				field.type = "hidden";
				field.name = "calEnd";
				field.value = node.nodeValue;
				_(this._elStart).appendChild(field);
			}

			this._Cal.updated();
		} catch (ex) {
			this._setError("Bei der Aktualisierung der Anzeige ist ein Fehler aufgetreten:\n" + ex);
			return false;
		}

		return true;
	}

	this.suggest = function(eid, strItems) {
		if(strItems == "[]" || strItems == "") {
			if(_("terminsuche_suggest")) {
				_("terminsuche_suggest").style.display = "none";
			}
			return;
		}
		jItems = eval(strItems);
		if(!_("terminsuche_suggest")) {
			nDiv = _el("div");
			nDiv.id = "terminsuche_suggest";
			nDiv.className = "terminsuche-suggest";
			nDiv.style.height = "16ex";
			nDiv.style.display = "none";
			document.getElementsByTagName("body")[0].appendChild(nDiv);
		}

		text = "";
		for (index in jItems) {
			if(unescape(jItems[index]["name"]) == 'undefined') {
			  //don't let IE7 display crap
			  continue;
			}
			text += "<span class='terminsuche-suggest-text' onclick='terminkalender.useSuggest(\"" + eid + "\", this.innerHTML)'>" + unescape(jItems[index]["name"]) + "</span>";
			if(jItems[index]["id"]) {
				if(!terminkalender.__hashes[eid]) {
					terminkalender.__hashes[eid] = {};
				}
				terminkalender.__hashes[eid][jItems[index]["name"]] = jItems[index]["id"];
			}
		}
			
		_("terminsuche_suggest").style.top = (terminkalender.__mouse["y"] + 5) + "px";
		_("terminsuche_suggest").style.left = (terminkalender.__mouse["x"] + 5) + "px";
		_("terminsuche_suggest").style.height = jItems.length < 7 ? (jItems.length * 3) + "ex" : "19.6ex";
		_("terminsuche_suggest").innerHTML = text;
		_("terminsuche_suggest").style.display = "block";
	}

	this.useSuggest = function(id, text) {
		//Semikolon als Trennzeichen, da diese nicht vorkommen aber Kommata oft bei Veranstaltern vorhanden sind
		//dennoch bzw aufgrund dessen dirty ;)
		komma = _(id).value.lastIndexOf(terminkalender.__suggest_trennzeichen);
		pretext = "";
		if(komma > 0) {
			pretext = _(id).value.substr(0, ++komma) + " ";
		}
		_(id).value = pretext + text + terminkalender.__suggest_trennzeichen + " ";

		_(id).focus();
	}

	this._hideSuggest = function() {
		if(_("terminsuche_suggest")) {
			_("terminsuche_suggest").style.display = "none";
		}
	}

	this.getStart = function() {
		try {
			return this._Cal.getStart();
		} catch (ex) {
			this._setError("Fehlerhafte (oder keine) Instanz von 'Kalender'!\n" + ex);
			return false;
		}
	}

	this.getEnd = function() {
		try {
			return this._Cal.getEnd();
		} catch (ex) {
			this._setError("Fehlerhafte (oder keine) Instanz von 'Kalender'!\n" + ex);
			return false;
		}
	}

	this.process = function(ev) {
		if(!ev) {
			ev = window.event;
		}
		if(!this.value) {
			//IE6 hack.........
			el = ev.srcElement;
		} else {
			el = this;
		}
		//Trennungen via Kommata <-- war einmal, jetzt Semikolon
		try {
			if(el.value.lastIndexOf(terminkalender.__suggest_trennzeichen) > 0) {
				eingabe = el.value.substr(el.value.lastIndexOf(terminkalender.__suggest_trennzeichen) + 1)
			} else {
				eingabe = el.value;
			}
			terminkalender._Ajax.getSuggestList(el.id, eingabe.trim(), terminkalender.suggest);
		} catch (ex) {
			//Fehler unterdr�cken, wenn value == ""
		}
	}

	this._setMousePos = function(ev) {
		if(!ev) {
			ev = window.event;
		}

		//Scroll position
		var scrOfX = 0, scrOfY = 0;
		if( typeof( window.pageYOffset ) == 'number' ) {
		  //Netscape compliant
		  scrOfY = window.pageYOffset;
		  scrOfX = window.pageXOffset;
		} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
		  //DOM compliant
		  scrOfY = document.body.scrollTop;
		  scrOfX = document.body.scrollLeft;
		} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
		  //IE6 standards compliant mode
		  scrOfY = document.documentElement.scrollTop;
		  scrOfX = document.documentElement.scrollLeft;
		}

		terminkalender.__mouse["x"] = ev.clientX + scrOfX;
		terminkalender.__mouse["y"] = ev.clientY + scrOfY;
	}

	this._setError = function(msg) {
		if(this._debug) {
			alert(msg);
		}
	}

	this._init = function() {
		jscontrol.addEvent(document.getElementsByTagName("body")[0], 'mousemove', this._setMousePos, false);
		jscontrol.addEvent(document.getElementsByTagName("body")[0], 'mouseup', this._hideSuggest, false);
		jscontrol.addEvent(_("rubrik"), 'keyup', this.process, false);
		jscontrol.addEvent(_("ort"), 'keyup', this.process, false);
		jscontrol.addEvent(_("veranstalter"), 'keyup', this.process, false);
	}

	//PRIVATE CLASS FUNCTIONS

	//PRIVATE CLASS MEMBERS
	this._debug = false;

	try {
		this._Cal = new Kalender();
		this._Ajax = new Terminax();
	} catch (ex) {
		this._setError("Instanz von 'Kalender' konnte nicht erzeugt werden.\n" + ex);
	}
	this._elStart = _(startElement) ? startElement : false;
	this._elEnd = _(endElement) ? endElement : false;
	this.__mouse = {};
	this.__mouse["x"] = 0;
	this.__mouse["y"] = 0;
	this.__hashes = {};		//pattern: hashes[rubrik|ort][bezeichnung] = id
	this.__suggest_trennzeichen = ";";

	this._init();
	this.update();
}
//END CLASS TERMINKALENDER

//BEGIN CLASS KALENDER
function Kalender() {
	this.getStart = function() {
		if(this._start.isDate) {
			return this._getDateStr(this._start);
		} else {
			return this._start;
		}
	}

	this.getEnd = function() {
		if(this._hasEnd) {
			this._setError("666: " + this._end.isDate);
			if(this._end.isDate) {
				return this._getDateStr(this._end);
			} else {
				return this._end;
			}
		}
		return unescape("%u221E");	//Unendlich-Zeichen
	}

	this.updated = function() {
		if(this._callActivator) {
			this._HTMLCal.activate();
			this._callActivator = false;
		}
	}

	this._getDateStr = function(dateObj) {
		day = dateObj.getDate();
		month = dateObj.getMonth();
		month += 1;
		year = dateObj.getYear();
		year = (year > 999 ? year : year + 1900);

		if(day < 10){
			day = "0" + day;
		}
		if(month < 10) {
			month = "0" + month;
		}

		str = day + "." + month + "." + year;

		return str;
	}

	this._getMonthDays = function(month, year) {
		month += 1;
		year = (year > 999 ? year : year + 1900);

		if ((month == 2) && ((year % 4 == 0 && year % 100 != 0)  || year % 400 == 0)) {
			var days = 29;
		} else if (month == 2) {
			days = 28;
		} else if (month == 4 || month == 6 || month == 9 ||month == 11) {
			var days = 30;
		} else {
			var days = 31;
		}

		return days;
	}

	this._setToday = function() {
		this._start = new Date();
		this._start.isDate = true;
	}

	this.setToday = function() {
		this._setToday();
		this._end = this._start;
		this._hasEnd = true;
		this._end.isDate = true;
	}

	this.setThisWeek = function() {
		this._setToday();

		var date = new Date();
		if(date.getDay() == 6) {
			shift = 8;
		} else {
			shift = 7 - date.getDay();
		}

		newMonth = date.getMonth();
		newYear = date.getYear();

		newDate = date.getDate() + shift;
		if(newDate > 28 && newDate > this._getMonthDays(date.getMonth(), date.getYear())) {
			newDate = newDate - this._getMonthDays(date.getMonth(), date.getYear());
			newMonth = date.getMonth() + 1;
			if(newMonth == 12) {
				newMonth = 0;
				newYear = date.getYear() + 1;
			}
		}

		newYear = (newYear > 999 ? newYear : newYear + 1900);

		this._end = new Date(newYear, newMonth, newDate);
		this._hasEnd = true;
		this._end.isDate = true;
	}

	this.setThisMonth = function() {
		this._setToday();

		var date = new Date();
		if(date.getDate() < (this._getMonthDays(date.getMonth(), (date.getYear() > 999 ? date.getYear() : date.getYear() + 1900 )) - 4)) {
			newMonth = date.getMonth();
			newYear = date.getYear();
		} else {
			newMonth = date.getMonth() + 1;
			if(newMonth == 12) {
				newMonth = 0;
				newYear = date.getYear() + 1;
			} else {
				newYear = date.getYear();
			}
		}

		newYear = (newYear > 999 ? newYear : newYear + 1900);

		this._end = new Date(newYear, newMonth, this._getMonthDays(newMonth, newYear));
		this._hasEnd = true;
		this._end.isDate = true;
	}

	this.setManualCal = function () {
		this._HTMLCal.setHiddenName(this._startID, "calStart");
		this._HTMLCal.setHiddenName(this._endID, "calEnd");
		this._start = this._HTMLCal.getSkel(this._startID);
		this._start.isDate = false;
		this._end = this._HTMLCal.getSkel(this._endID);
		this._end.isDate = false;
		this._HTMLCal.setCornerDates(this._startID, this._endID);
		this._hasEnd = true;
		this._callActivator = true;
	}

	this._setError = function(msg) {
		if(this._debug) {
			alert(msg);
		}
	}

	this._debug = false;
	this._startID = "terminkalender_man_startdate";
	this._start = new Date();
	this._start.isDate = true;
	this._endID = "terminkalender_man_enddate";
	this._end = new Date();
	this._end.isDate = true;
	this._hasEnd = true;
	this._callActivator = false;
	this._HTMLCal = new HTMLKalender(this);
}
//END CLASS KALENDER

//BEGIN CLASS HTMLKALENDER
function HTMLKalender(parent) {
	this.activate = function() {
		ids = this._getIds();

		while(id = ids.pop()) {
			this._applyFunctions(id);
			this._outlineSelDate(id);
		}
	}

	this.setCornerDates = function(idStart, idEnd) {
		if(idStart == idEnd) {
			return false;
		}

		if(typeof(this.__corners[idStart]) == "undefined") {
			this.__corners[idStart] = {};
		}
		if(!this.__corners[idStart].starts) {
			this.__corners[idStart].starts = new Array();
		}
		if(!this.__corners[idStart].ends) {
			this.__corners[idStart].ends = new Array();
		}
		if(typeof(this.__corners[idEnd]) == "undefined") {
			this.__corners[idEnd] = {};
		}
		if(!this.__corners[idEnd].starts) {
			this.__corners[idEnd].starts = new Array();
		}
		if(!this.__corners[idEnd].ends) {
			this.__corners[idEnd].ends = new Array();
		}

		this.__corners[idStart].ends.push(idEnd);
		this.__corners[idEnd].starts.push(idStart);
	}

	this.getSkel = function (id) {
		if(arguments.length == 2 && arguments[1] == false) {
			//Optionaler, 2. Parameter "finite" gesetzt
			finite = false;
		} else {
			finite = true;
		}
		this._init(id);

		var divCal = _el("div");
		divCal.id = id + "_divcal";

		var nDiv = _el("div");

// << MONAT JAHR >>
		var nTab = _el("table");
		nTab.className = "terminsuche-kalender-container-tabelle";

		var nTBody = _el("tbody");

		var nRow = _el("tr");

		var nCell = _el("td");
		nCell.className = "terminsuche-kalender-navigation-links";
		nCell.innerHTML = "<a id='" + id + "_earlier'>&lt;&lt;</a>";
		earlier = nCell;
		nRow.appendChild(nCell);

		var nCell = _el("td");
		nCell.id = id + "_monthName";
		nCell.className = "terminsuche-kalender-monat-titel";
		nCell.appendChild(_text(this._getMonthName(id) + " " + this._getYear(id)));
		nRow.appendChild(nCell);

		var nCell = _el("td");
		nCell.className = "terminsuche-kalender-navigation-rechts";
		nCell.innerHTML = "<a id='" + id + "_further'>&gt;&gt;</a>";
		further = nCell;
		nRow.appendChild(nCell);

		nTBody.appendChild(nRow);
		nTab.appendChild(nTBody);
		nDiv.appendChild(nTab);
		divCal.appendChild(nDiv);

// KALENDER
		var nDiv = _el("div");
		nDiv.id = id + "_month";
		nDiv.appendChild(this._makeMonth(id, "today"));

		divCal.appendChild(nDiv);

// FOOTER
		var nDiv = _el("div");
		nA = _el("a");
		nA.id = id + "_today";
		nA.appendChild(_text("Heute"));
		nDiv.appendChild(nA);
		if(!finite) {
			nCb = _el("input");
			nCb.type = "checkbox";
			nCb.checked = "";
			nCb.id = id + "|0|0|0";
			nCb.name = id + "_unlimited";
			nCb.onclick = this.markDate;
			nText = _text("unbegrenzt");
			nDiv.appendChild(nCb);
			nDiv.appendChild(nText);
		}
		if(!this.getHiddenName(id)) {
			this.setHiddenName(id, id + "_hiddenfield");
		}
		nHidden = _el("input");
		nHidden.type = "hidden";
		nHidden.name = this.getHiddenName(id);
		nHidden.id = id + "_hiddenfield";
		nHidden.value = this._getHumanDate(id);
		nDiv.appendChild(nHidden);

		divCal.appendChild(nDiv);

// FUNKTIONEN + ANZEIGE
		divCal.style.display = "block";

		return divCal;
	}

	this._applyFunctions = function(id) {
		buttons = new Array("earlier", "today", "further");

// 		for(var button in buttons) {
        for(var button = 0; button < 3; button++) {
			if(_(id + "_" + buttons[button])) {
				this._setFunc(id, buttons[button]);
				this._controller.addEvent(_(id + "_" + buttons[button]), 'click', this.__functions[id], false);
			} else {
				this._setError("error: " + id + "_" + buttons[button]);
			}
		}

	}

	this._getDayRow = function() {
		if(this.__dayrow) {
			return this.__dayrow.cloneNode(true);
		}

		var nTr = _el("tr");

		var caps = new Array("Mo", "Di", "Mi", "Do", "Fr", "Sa", "So");

		for(var i=0; i<7; i++) {
			var day = _el("th");
			var text = _text(caps[i]);
			day.appendChild(text);
			if(i >= 5) {
				day.className = "terminsuche-kalender-wochenende";
			}
			nTr.appendChild(day);
		}

		this.__dayrow = nTr;

		return nTr;
	}

	this.setHiddenName = function(id, hname) {
		if(_(id + "_hiddenfield")) {
			var parent = _(id + "_hiddenfield").parentNode;
			var node = _el("input");
			node.type="hidden";
			node.nodeValue = _(id + "_hiddenfield").nodeValue;
			parent.removeChild(_(id + "_hiddenfield"));
			node.id = id + "_hiddenfield";
			node.name = hname;
			parent.appendChild(node);
		}
		this.__hiddenNames[id] = hname;
	}

	this.getHiddenName = function(id) {
		return this.__hiddenNames[id];
	}

	this._isPast = function(d, m, y) {
		today = new Date();

		ty = today.getYear() > 999 ? today.getYear() : today.getYear() + 1900;

		if(y > ty) {
			return false;
		} else if (y < ty) {
			return true;
		} else if(m > today.getMonth()) {
			return false;
		} else if(m < today.getMonth()) {
			return true;
		} else if(d >= today.getDate()) {
			return false;
		} else {
			return true;
		}
	}

	this._makeMonth = function(id) {
		days = parent._getMonthDays(this._getMonth(id), this._getYear(id));

		var nTbl = _el("table");
		nTbl.className = "terminsuche-kalender-container-tabelle";
		var nTHead = _el("thead");
		var nTBody = _el("tbody");

		//Mo-Fr
		nTHead.appendChild(this._getDayRow());

		nTbl.appendChild(nTHead);

		//Tage
		var date = new Date(this._getYear(id), this._getMonth(id), 1);
		full = false;
		var i = 2 - ((date.getDay() == 0) ? 7 : date.getDay());
		while(!full) {
			var nTr = _el("tr");
			for(var j=0; j<7; j++) {
				var nTd = _el("td");
				if(i > 0 && i <= days) {
					text = _text(i);
					if(this._isPast(i, this._getMonth(id), this._getYear(id))) {
						var fid = false;
					} else {
						var fid = id + "|" + i + "|" + this._getMonth(id) + "|" + this._getYear(id);
					}
				} else {
					text = _text(" ");
					var fid = false;
				}
				if(fid) {
					var link = _el("a");
					link.id = fid;
					link.onclick = this.markDate;
					link.appendChild(text);
					if(j >= 5) {
						link.className = "terminsuche-kalender-wochenende ";
					}
					nTd.appendChild(link);
				} else {
					nspan = _el("span");
					nspan.appendChild(text);
					nTd.appendChild(nspan);
				}
				if(i == parent._getMonthDays(this._getMonth(id), this._getYear(id))) {
					full = true;
				}
				nTr.appendChild(nTd);
				i += 1;
			}
			nTBody.appendChild(nTr);
		}
		nTbl.appendChild(nTBody);

		return nTbl;
	}

	this.markDate = function() {	//wird von Link aufgerufen
		var info = this.id.split("|"); //0 - id, 1 - tag, 2 - monat, 3 - jahr

		if(!terminkalender._Cal._HTMLCal._setSelDate(info[0], info[1], info[2], info[3])) {
			return;
		}

		if(!(info[1] == 0 && info[2] == 0 && info[3] == 0)) {
			cssclass = this.className;
			if(cssclass.length == 0) {
				this.className = "terminsuche-kalender-auswahl-rahmen-sichtbar";
			} else {
				newcssclass = cssclass.replace("terminsuche-kalender-auswahl-rahmen-unsichtbar", "terminsuche-kalender-auswahl-rahmen-sichtbar");
				if(newcssclass == cssclass) {
					this.className += " terminsuche-kalender-auswahl-rahmen-sichtbar";
				} else {
					this.className = newcssclass;
				}
			}
		}
	}

	this._outlineSelDate = function(id) {
		fid = this._getSelDateId(id);

 		if(_(fid)) {
			cssclass = _(fid).className;
			if(cssclass.length == 0) {
				_(fid).className = "terminsuche-kalender-auswahl-rahmen-sichtbar";
			} else {
				newcssclass = cssclass.replace("terminsuche-kalender-auswahl-rahmen-unsichtbar", "terminsuche-kalender-auswahl-rahmen-sichtbar");
				if(newcssclass == cssclass) {
					_(fid).className += " terminsuche-kalender-auswahl-rahmen-sichtbar";
				} else {
					_(fid).className = newcssclass;
				}
			}

			return true;
		}
		return false;
	}

	this._turnCalendar = function(id, mode) {
		if(mode.indexOf("earlier") > -1) {
			diff = -1;
		} else if(mode.indexOf("today") > -1) {
			diff = 0;
		} else if(mode.indexOf("further") > -1) {
			diff = 1;
		} else {
			return false;
		}

		if(diff == 0) {
			date = new Date();
			this._setMonth(id, date.getMonth());
			this._setYear(id, date.getYear() > 999 ? date.getYear() : date.getYear() + 1900);
			this._setSelDate(id, date.getDate(), this._getMonth(id), this._getYear(id));
		} else {
			this._stepMonth(id, diff);
		}

		_(id + "_month").innerHTML = "";
		_(id + "_month").appendChild(this._makeMonth(id));
		_(id + "_monthName").innerHTML = "";
		_(id + "_monthName").appendChild(_text(this._getMonthName(id) + " " + this._getYear(id)));

		this._outlineSelDate(id);
	}

	this._checkDate = function(id) {
		if(this._getMonth(id) < 0) {
			this._setMonth(id, 11);
			this._prevYear(id);
		} else if(this._getMonth(id) > 11) {
			this._setMonth(id, 0);
			this._nextYear(id);
		}
	}

	this._setFunc = function(i, m) {
		this.__functions[i] = function() {
			terminkalender._Cal._HTMLCal._turnCalendar(i, m);
		}
	}

	this._getMonthName = function(id) {
		if(!this.__monthnames) {
			this.__monthnames = new Array("Januar", "Februar", unescape("M%E4rz"), "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember");
		}

		return this.__monthnames[this._getMonth(id)];
	}

	this._nextYear = function(id) {
		this._setYear(id, this._getYear(id) + 1);
	}

	this._prevYear = function(id) {
		this._setYear(id, this._getYear(id) - 1);
	}

	this._setYear = function(id, val) {
		if(val < 999) {
			val += 1900;
		}
		this.__years[id] = val;
	}

	this._stepMonth = function(id, step) {
		this.__months[id] = this._getMonth(id) + step;
		this._checkDate(id);
	}

	this._setMonth = function(id, val) {
		if(val >= 0 && val < 12) {
			this.__months[id] = val;
			return true;
		}
		return false;
	}

	this._getMonth = function(id) {
		if(typeof(this.__months[id]) != "undefined") {
			return this.__months[id];
		} else {
			tmp = new Date;
			this.__months[id] = tmp.getMonth();
			return this.__months[id];
		}
	}

	this._getYear = function(id) {
		if(typeof(this.__years[id]) != "undefined") {
			return this.__years[id];
		} else {
			tmp = new Date;
			this.__years[id] = tmp.getYear() < 999 ? tmp.getYear() + 1900 : tmp.getYear();
			return this.__years[id];
		}
	}

	this._getIds = function() {
		var keys = new Array();

		for(key in this.__months) {
			keys.push(key);
		}

		return keys;
	}

	this._deselectDate = function(id) {
		try {
			if(_(this._getSelDateId(id)).nodeName == "A") {
				cssclass = _(this._getSelDateId(id)).className;
				if(cssclass.length == 0) {
					_(this._getSelDateId(id)).className = "terminsuche-kalender-auswahl-rahmen-unsichtbar";
				} else {
					newcssclass = cssclass.replace("terminsuche-kalender-auswahl-rahmen-sichtbar", "terminsuche-kalender-auswahl-rahmen-unsichtbar");
					if(newcssclass == cssclass) {
						_(this._getSelDateId(id)).className += " terminsuche-kalender-auswahl-rahmen-unsichtbar";
					} else {
						_(this._getSelDateId(id)).className = newcssclass;
					}
				}

			} else {
				_(this._getSelDateId(id)).checked = false;
			}
		} catch (ex) {
// 			this._setError("deselect: " + id);
		} finally {
			return;
		}
	}

	this._getSelDateId = function(id) {
		seldate = this._getSelDate(id);

		fid = id + "|" + seldate["day"] + "|" + seldate["month"] + "|" + seldate["year"];

		return fid;
	}

	this._isUnlimitedDate = function(dateObj) {
		if(dateObj["day"] == 0 && dateObj["month"] == 0 && dateObj["year"] == 0) {
			return true;
		}
		return false;
	}

	this._validateSelChange = function(id, newDate) {
		if(!this.__corners[id] || this._isUnlimitedDate(newDate)) {
			return true;
		}

		//id as end
		error = false;
		str = "";
		max = this.__corners[id].starts.length;
		count = 0;
		for(startpoint in this.__corners[id].starts) {
			//Hack für Prototype
			if(count >= max) {
				break;
			}
			count++;
			//End Hack

			startdate = this._getSelDate(this.__corners[id].starts[startpoint]);
			//IE Hack
			if(typeof(startdate) == 'undefined') {
			  count--;
			  continue;
			}
			//end IE Hack

			str += startdate["day"] + "." + startdate["month"] + "." + startdate["year"] + "; ";
			if(this._isUnlimitedDate(startdate)) {
				continue;
			}
			if((parseInt(newDate["year"]) < parseInt(startdate["year"])) ||
				((parseInt(newDate["year"]) == parseInt(startdate["year"])) && (parseInt(newDate["month"]) < parseInt(startdate["month"]))) ||
				((parseInt(newDate["year"]) == parseInt(startdate["year"])) && (parseInt(newDate["month"]) == parseInt(startdate["month"])) && (parseInt(newDate["day"]) < parseInt(startdate["day"]))) ) {
				error = true;
				break;
			}
		}
		if(error) {
			alert("Dieses Datum liegt vor dem Startdatum und kann daher nicht gesetzt werden.");
			return false;
		}

		//id as start
		max = this.__corners[id].ends.length;
		count = 0;
		for(endpoint in this.__corners[id].ends) {
			//Hack für Prototype
			if(count >= max) {
				break;
			}
			count++;
			//End Hack

			var enddate = this._getSelDate(this.__corners[id].ends[endpoint]);
			//IE Hack
			if(typeof(enddate) == 'undefined') {
			  count--;
			  continue;
			}
			//end IE Hack
			str += enddate["day"] + "." + enddate["month"] + "." + enddate["year"] + "; ";
			if(this._isUnlimitedDate(enddate)) {
				continue;
			}
			if((parseInt(newDate["year"]) > parseInt(enddate["year"])) ||
				((parseInt(newDate["year"]) == parseInt(enddate["year"])) && (parseInt(newDate["month"]) > parseInt(enddate["month"]))) ||
				((parseInt(newDate["year"]) == parseInt(enddate["year"])) && (parseInt(newDate["month"]) == parseInt(enddate["month"])) && (parseInt(newDate["day"]) > parseInt(enddate["day"]))) ) {
				error = true;
				break;
			}
		}
		if(error) {
			alert("Dieses Datum liegt nach dem Enddatum und kann daher nicht gesetzt werden.");
			return false;
		}

		return true;
	}

	this._setSelDate = function(id, d, m, y) {
		var seldate = this._getSelDate(id);
		if(typeof(seldate) == "object") {
			if((seldate["day"] == d) &&	(seldate["month"] == m) && (seldate["year"] == y)) {
				return;
			}
		}

		var selDate = {};

		selDate["day"] = d;
		selDate["month"] = m;
		selDate["year"] = y;

		if(!this._validateSelChange(id, selDate)) {
			return;
		}

		this._deselectDate(id);

		this.__selDates[id] = selDate;
// 		if(_(id + "_divcal") != null) {
// 			_(id + "_divcal").date = selDate;
// 			alert("gesetzt");
// 		}
		m = Number(m) + 1;		//f�r einge gute �bergabe, da 0 = Januar
		if(_(id + "_hiddenfield")) {
			if(d < 10) {
				d = "0" + d;
			}
			if(m < 10) {
				m = "0" + m;
			}
			_(id + "_hiddenfield").value = d + "." + m + "." + y;
		}

		return true;
	}

	this._getHumanDate = function(id) {
		dateobj = this._getSelDate(id);
		if(dateobj["day"] < 10) {
			str = "0" + dateobj["day"] + ".";
		} else {
			str = dateobj["day"] + ".";
		}
		month = dateobj["month"] + 1;
		if(dateobj["day"] < 10) {
			str += "0" + month + ".";
		} else {
			str += month + ".";
		}
		str += dateobj["year"];

		return str;
	}

	this._getSelDate = function(id) {
		return this.__selDates[id];
	}

	this._init = function(id) {
		var date = new Date();
		
		this._setYear(id, date.getYear() > 999 ? date.getYear() : date.getYear() + 1900);
		this._setMonth(id, date.getMonth());
		this._setSelDate(id, date.getDate(), this._getMonth(id), this._getYear(id));
// 		alert(id + "|" + date.getDate() + "|" + this._getMonth(id) + "|" + this._getYear(id));
// 		_(id + "|" + date.getDate() + "|" + this._getMonth(id) + "|" + this._getYear(id)).className =  "terminsuche-kalender-auswahl-rahmen-sichtbar";
	}

	this._setError = function(msg) {
		if(this._debug) {
			alert(msg);
		}
	}

	this._debug = false;
	this._parent = parent;
	this._controller = jscontrol;
	this.__days = {};
	this.__months = {};
	this.__years = {};
	this.__functions = {};
	this.__selDates = {};
	this.__corners = {};
	this.__hiddenNames = {};
}
//END CLASS HTMLKALENDER

//BEGIN CLASS TERMINAX
function Terminax() {

	this.getSuggestList = function(section, letters, func) {
		query = "item=" + section + "&input=" + escape(letters);
		this.sendRequest(query);
		this._section = section;
		this._callback = func;
	}

	this.sendRequest = function(get) {
		this.xmlHttp.abort();
		var url = this.ajaxHost + "terminsuche_ajax.php?" + get;
		this.xmlHttp.open("GET", url, true);  //GET or POST, URL, wether request to be handled asynchr.
		this.xmlHttp.onreadystatechange = this.OnReadyStateChange;
		this.xmlHttp.send(null);              //Send the request, parameter is parameters to send is usual style
	}

	this.ajaxInit = function () {
		try {
    		// Firefox, Opera 8.0+, Safari, Konqueror
			this.xmlHttp = new XMLHttpRequest();
		} catch (ex) {
    		// Internet Explorer
			try {
				this.xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (ex) {
				try {
					this.xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (ex) {
					alert("Your browser does not support AJAX!");
					return false;
				}
			}
		}
		return true;
	}

	this.OnReadyStateChange = function() {
		terminkalender._Ajax.CustomOnReadyStateChange();
	}

	this.CustomOnReadyStateChange = function() {
		switch(this.xmlHttp.readyState) {
			case 0:
        		//request not initialized
				break;
			case 1:
				//request has been set up
				break;
			case 2:
				//request has been sent
				break;
			case 3:
				//request in process
				break;
			case 4:
				//request completed
// 				alert(this.xmlHttp.responseText);
				this._callback(this._section, this.xmlHttp.responseText);
				break;
			default:
				break;
		}
	}

	this.detectHost = function() {
		iPos = window.location.href.indexOf("/", 7);
		return window.location.href.substr(0, iPos) + "/ajax/";
	}

	this.xmlHttp = false;
// 	this.ajaxHost = "http://www.hz-online.de/ajax/";
	this.ajaxHost = this.detectHost();
	this.ajaxInit();
}
//END CLASS TERMINAX

