// todo: rewrite parse method of Url with Regexp

//
function zero() {
}

function isRightMouseButton(button)
{
	if (posLib.moz) {
		return (button == 2);
	} else {
		return (button != 1);
	}
}

function isLeftMouseButton(button)
{
	if (posLib.moz) {
		return (button != 2);
	} else {
		return (button == 1);
	}
}

//
function onKeyDown(manager) {
	if (!isUndefined(manager)) {
		try {
			manager.onKeyDown();
		} catch (e) {
		}
	}
}

//
function getSrcElement(e) {
    var targetElm = (e.target) ? e.target : e.srcElement;
    if (targetElm.nodeType == 3) {
      targetElm = targetElm.parentNode;
    }
    return targetElm;
}

//
function onSelectStart() {
	if (getSrcElement(event).tagName == "INPUT") {
		return true;
	} else {
		return false;
	}
}

//
function onContextMenu(e) {
	if (getSrcElement(e).tagName == "INPUT") {
		return true;
	} else {
		return false;
	}
}

//
function cancelEventPropagation(e) {
	e.cancelBubble = true;
	if (e.stopPropagation) {
		e.stopPropagation();
	}
	return false;
}

//
function getEventSrcElement(e) {
	return posLib.moz ? e.target : e.srcElement;
}

// params: e - event, w - window to close
function onDialogKeyDown(e, w) {
	if (isUndefined(w))	w = window;
	if (e.keyCode == 13) {
		if (!isUndefined(w.onOKClick)) {
			w.onOKClick();
		} else if (!isUndefined(w.onCloseClick)) {
			w.onCloseClick();
		}
		return false;
	} else if (e.keyCode == 27) {
		if (!isUndefined(w.onCancelClick)) {
			w.onCancelClick();
		} else if (!isUndefined(w.onCloseClick)) {
			w.onCloseClick();
		}
		return false;
	}
	return true;
}

//
function onDialogListKeyDown(e, w) {
	var r = window.lm.onKeyDown(e);
	if (!r) return false;
	return onDialogKeyDown(e, w);
}

//
function doServerAction(url) {
	var result = xmlHelper.loadData(url.toString());
	if (isUndefined(result)) {
		alert("No response from server");
		return false;
	}
	if (result != "") {
		if (result.indexOf("<html>") != -1) {
			callLogout();
			return false;
		}
		alert(result);
		return false;
	}
	return true;
}

//
function checkResponse(response) {
	if (isUndefined(response)) {
		alert("No response from server");
		return false;
	}
	if (response.indexOf("<html>") != -1) {
		callLogout();
		return false;
	}
	return true;
}

//
function __e(el, w) {
	if (isUndefined(w)) w = window;
	return w.document.all[el];
}

//
function isUndefined(value) {
	return typeof(value) == 'undefined' || (value == null);
}

//
function getParentElement(el, tagName) {
	if (isUndefined(el)) return null;
	while (el.tagName != tagName) {
		el = el.parentNode;
		if (isUndefined(el)) return null;
	}
	return el;
}

//
function getChildElements(el, tagName) {
	var children = [], childTagName;
	for (var i = 0; i < el.childNodes.length; i++) {
		// nodeType:
		// 1 - element node
		// 3 - text node
		childTagName = el.childNodes[i].tagName;
		if (isUndefined(childTagName)) continue;
		if (childTagName.toLowerCase() == tagName.toLowerCase()) {
			children.push(el.childNodes[i]);
		}
	}
	return children;
}

//
function concatArrays(arr1, arr2) {
	for (var i = 0; i < arr2.length; i++) {
		arr1.push(arr2[i]);
	}
}

//
function getElementsById(elParent, id) {
	var elements = new Array(), ch;
	for (var i = 0; i < elParent.childNodes.length; i++) {
		if (elParent.childNodes[i].id == id) {
			elements.push(elParent.childNodes[i]);
		}
		concatArrays(elements, getElementsById(elParent.childNodes[i], id));
	}
	return elements;
}

//
function getFirstElementById(elParent, id) {
	for (var i = 0; i < elParent.childNodes.length; i++) {
		if (elParent.childNodes[i].id == id) {
			return elParent.childNodes[i];
		} else {
			var childEl = getFirstElementById(elParent.childNodes[i], id);
			if (childEl != null) {
				return childEl;
			}
		}
	}
	return null;
}

//
function getElementByName(name, doc) {
	var elements;
	if (isUndefined(doc)) {
		elements = document.getElementsByName(name);
	} else {
		elements = doc.getElementsByName(name);
	}
	return elements.length > 0 ? elements[0] : null;
}

// examine 'display' style property of a row itself
// and all of its parent TR elements
function isRowVisible(row) {
	if (isUndefined(row)) return false;
	if (row.style.display == "none") {
		return false;
	}
	var outer = getParentElement(row.parentNode, "TR");
	while (!isUndefined(outer)) {
		if (outer.style.display == "none") {
			return false;
		}
		outer = getParentElement(outer.parentNode, "TR");
	}
	return true;
}

//
function getDefaultWindowFeatures() {
	var s = "menubar=0,titlebar=0,toolbar=0,status=1,resizable=1";
	return s;
}

//
function getWindowFeatures(left, top, width, height) {
	// IE shows window in invalid place if left or top < 0
	if (left < 0) left = 0;
	if (top < 0) top = 0;
	var s = "left=" + left + "px, top=" + top +  "px, " +
			"width=" + width + "px, height=" + height + "px";
	return s + "," + getDefaultWindowFeatures();
}

//
function getDialogFeatures(left, top, width, height, resizable) {
	if (posLib.moz) {
		var s = "left=" + left + "px, top=" + top +  "px, " +
				"width=" + width + "px, height=" + height + "px, " +
				"help=no, status=no, resizable=" + (!isUndefined(resizable) ? resizable : "yes");
		return s;
	} else {
		var s = "dialogLeft: " + left + "px; dialogTop: " + top +  "px;" +
				"dialogWidth: " + width + "px;dialogHeight: " + height + "px;" +
				"help: no; status: no; modal: yes; resizable: " + (!isUndefined(resizable) ? resizable : "yes") + ";";
		return s;
	}
}

//
function getPropertiesDialogFeatures(w,h) {
	if(isUndefined(w)) w = 600;
	if(isUndefined(h)) h = 600;
	return getDialogFeatures((screen.width - w) / 2, (screen.height - h) / 2, w, h);
}

//
function getDefaultDialogFeatures(resizable) {
	var w = screen.width / 3 * 2;
	var h = screen.height / 2;
	return getDialogFeatures((screen.width - w) / 2, (screen.height - h) / 2, w, h, resizable);
}

//
function Cooler(label) {
	this.window = window; // window
	this.label = label;   // label
	this.window.cooler = this; // registration in window

	//
	this.coolerMarks = ['|', '/', '-', '\\'];
	this.currentMark = 0;
	this.coolerTimerID = 0;

	//
	this.update = function() {
		if (this.coolerTimerID != -1) {
			this.currentMark = this.currentMark < 3 ? this.currentMark + 1 : 0;
			this.label.innerHTML = this.coolerMarks[this.currentMark];
			this.start();
		}
	}

	//
	this.start = function() {
		this.coolerTimerID = this.window.setTimeout("window.cooler.update()", 200);
	}

	//
	this.stop = function() {
		if (this.coolerTimerID != -1) {
			this.label.innerHTML = '';
			window.clearTimeout(this.coolerTimerID);
			this.coolerTimerID = -1;
		}
	}
}

// ping object
function Pinger() {
	this.window = window.top;

	//
	this.init = function() {
		if (isUndefined(this.window.pinger)) {
			this.window.pinger = this;
			this.initPinger();
		} else alert('Error: Pinger already defined');
	}

	//
	this.initPinger = function() {
		if (window.ping_time != -1) {
			this.serverPingerTimer = this.window.setTimeout("window.top.pinger.keepAlive()", window.ping_time * 1000);
		} else alert('ping is turned off');
	}

	//
	this.stopPinger = function() {
		if (!isUndefined(this.serverPingerTimer)) {
			this.window.clearTimeout(this.serverPingerTimer);
			this.serverPingerTimer = null;
		}
	}

	//
	this.pingServer = function() {
		var url = urlHelper.get("/secure/session.do").add("action", "ping");
		var data = xmlHelper.loadData(url.toString(), new PingerResponseHandler(this));
	}

	//
	this.keepAlive = function() {
		this.pingServer();
	}
}

//
function PingerResponseHandler(pp) {
	this.pp = pp;

	//
	this.handleResponse = function(obj, httpStatus) {
		if (httpStatus == 200) {
			pp.initPinger();
		} else {
			pp.stopPinger();
		}
		this.pp = null;
	}
}


// helper for communication with dialog windows
function DialogParams() {
	this.params = [];

	//
	this.get = function(name) {
		return this.params[name];
	}

	//
	this.set = function(name, value) {
		this.params[name] = value;
		return this;
	}
}

//
function isFieldOnForm(name) {
	var formElements = document.forms["panelForm"].elements;
	for (i = 0; i < formElements.length; i++) {
		if (formElements[i].name == name)
			return true;
	}
	return false;
}

//
function ModalDialog(url, params, features) {
	this.window = window;
	this.url = url;
	this.params = params;
	this.features = features;

	//
	this.show = function() {
		if (isUndefined(this.params)) this.params = new DialogParams();
		this.params.set("opener", window.top.self);
		if (isUndefined(this.features)) this.features = getDefaultDialogFeatures();
		if (posLib.moz)	{
			try {
				var win = this.window.open(url.toString(), "_blank", this.features);
				win.params = this.params;
				return null;
			} catch(e) {
				return null;
			}
		} else {
			try {
				var r = this.window.showModalDialog(url.toString(), this.params, this.features);
			} catch (e) {
				r = "cancel";
			}

			// forceLogout
			if (r == "forceLogout") {
				// am i itself a dialog?
				if (!isUndefined(this.window.top.dialogArguments)) {
					this.window.top.returnValue = r;
					this.window.top.close();
				} else {
					this.window.setTimeout("forceLogout();", 100);
				}
			}

			//
			return r;
		}
	}

	//
	this.getResult = function(name) {
		return this.params.get(name);
	}
}

//
function openWaitDialog() {
	var url = urlHelper.get("/secure/util/block_wait.vm");
	var w = 200, h = 50;
	var dialogFeatures = getDialogFeatures((screen.width - w) / 2, (screen.height - h) / 2, w, h);
	var md = new ModalDialog(url, null, dialogFeatures);
	md.show();
}

//
function getOpener() {
	if (isModal()) {
		return window.top.dialogArguments.get("opener");
	} else {
		return window.top.opener;
	}
}

//
function linkWithOpener() {
	if (isModal()) {
		var opener = window.top.dialogArguments.get("opener");
		opener.setModalDialog(window.top);

		//
		if (opener.pinger) {
			var pinger = new Pinger();
			pinger.init();
		}
	} else {
		window.top.opener.setModalDialog(window.top);
	}
}

function removeLinkWithOpener() {
	if (isModal()) 
	{
		var opener = window.top.dialogArguments.get("opener");
		opener.removeModalDialog();
	} 
	else 
	{
		if (!isUndefined(window.top.opener) && !window.top.opener.closed && window.top.opener.removeModalDialog) {
			window.top.opener.removeModalDialog();
		}
	}
}

//
function setModalDialog(modalDialog) {
	window.top.modalDialog = modalDialog;
}

//
function removeModalDialog() {
	window.top.modalDialog = null;
}

//
function closeDialogs(w) {
	if(isUndefined(w)) return;
	w = w.top;
	if (w.modalDialog != null) {
		if (!w.modalDialog.closed) {
			w.modalDialog.closeDialogs(w.modalDialog);
			w.modalDialog.close();
		}
	}
	w.modalDialog = null;
}

//
function forceLogout() {
	if (!isUndefined(window.top.wm)) {
		if (!window.top.wm.closeOtherWindows()) return;
	}
	var xUrl=urlHelper.get("/login.do").add("logout", "true")
	window.top.location.replace(xUrl.toString());
}

//
function isModal() {
	return !isUndefined(window.top.dialogArguments);
}

// checks that window is modal dialog or usual window
// and does corresponding actions to force logout
function callLogout() {
	if (isModal()) {
		window.top.returnValue = "forceLogout";
		window.top.close();
	} else {
		if (posLib.moz) {
			if (!isUndefined(window.top.params)) {
				// !isUndefined(window.top.params) means that this is 'modal' dialog
				var wOpener = window.top.params.get("opener");
				if (!isUndefined(wOpener)) {
					wOpener.callLogout();
					window.top.close();
					return;
				}
			}
		}
		if (!window.top.wm) {
			iwm = new AddWindowsManager();
			iwm.init();
		}
		forceLogout(true);
	}
}

//
function StrUtil() {

	//
	this.isEmpty = function(value) {
		return isUndefined(value) || (value == null) || (value.length == 0);
	}

}
strUtil = new StrUtil();

// URL parser
function Url(url) {
	//
	this.init = function(url) {
		if (url) {
			this.parse(url);
		}
	}

	// full clean
	this.clean = function() {
		this.url = null;
		this.params = [];
		this.values = [];
	}

	// parsing
	this.parse = function(url) {
		//
		var p = url.indexOf("?");
		if (p != -1) {
			this.url = url.substring(0, p);
			var params = url.substring(p + 1, url.length);

			//
			var a = params.split("&"), i, l = 0;
			for (i = 0; i < a.length; i++) {
				p = a[i].split("=");
				if (p.length == 2) {
					this.params[l] = p[0];
					this.values[l] = p[1];
					l++;
				}
			}
		} else {
			this.url = url;
		}

		//
		return this;
	}

	//
	this.set = function(url, bIsRelative) {
		if (isUndefined(bIsRelative)) bIsRelative = true;

		//
		if (bIsRelative) this.url = window.app_id + url;
		else this.url = url;

		//
		return this;
	}

	// params only clean
	this.clear = function() {
		this.params = [];

		//
		return this;
	}

	//
	this.getParamIndex = function(id) {
		var index = -1, i, l = this.params.length;
		for (i = 0; i < l; i++) {
			if (this.params[i] == id) {
				index = i;
				break;
			}
		}
		return index;
	}

	// adding param
	this.add = function(id, value) {
		if ((value == null) || (isUndefined(value))) {
			this.del(id);
		} else {
			var index = this.getParamIndex(id);
			if (index == -1) {
				var l = this.params.length;
				this.params[l] = id;
				this.values[l] = value;
			} else {
				this.values[index] = value;
			}
		}

		//
		return this;
	}

	//
	this.addFromForm = function(oForm) {
		//
		var formElements = oForm.elements, elType, value;
		for (i = 0; i < formElements.length; i++) {
			value = formElements[i].value;
			if (isUndefined(formElements[i].name) || value == "") {
				continue;
			}
			elType = formElements[i].type;
			if (elType == "checkbox") {
				if (formElements[i].checked) {
					this.add(formElements[i].name, "on");
				} else {
					this.add(formElements[i].name, "off");
				}
			} else if (elType == "radio") {
				if (formElements[i].checked) {
					this.add(formElements[i].name, formElements[i].value);
				}
			} else if ((elType != "submit") && (elType != "button") && (formElements[i].tagName != "button")) {
				this.add(formElements[i].name, formElements[i].value);
			}
		}
		return this;
	}

	// remove param
	this.del = function(id) {
		var index = this.getParamIndex(id);
		if (index != -1) {
			var i, l = this.params.length - 1;
			for (i = index; i < l; i++) {
				this.params[i] = this.params[i + 1];
				this.values[i] = this.values[i + 1];
			}
			this.params.length = l;
			this.values.length = l;
		}

		//
		return this;
	}

	// getter
	this.get = function(id) {
		var index = this.getParamIndex(id);
		return index == -1 ? null : this.values[index];
	}

	// to string
	this.toString = function() {
		var url = this.url;
		var l = this.params.length, i, p, v, b = false;
		for (i = 0; i < l; i++) {
			p = this.params[i];
			v = this.values[i];

			//
			if (!strUtil.isEmpty(p) && !strUtil.isEmpty(v)) {
				if (!b) url = url + "?";
				else url = url + "&";
				url = url + p + "=" + encodeURIComponent("" + v);
				b = true;
			}
		}

		//
		return url.replace("#", "");
	}
	//
	this.clean();
	this.init(url);
}

// helper for URL manipulations
function UrlHelper() {

	//
	this.parse = function(sUrl) {
		var url = new Url(sUrl);
		return url;
	}

	//
	this.get = function(sUrl) {
		return this.parse().set(sUrl);
	}
}
var urlHelper = new UrlHelper();

// Implementation of dynamic form
function Form(id) {
	this.id = id;
	this.window = window;
	this.fields = [];
	this.values = [];

	//
	this.getFieldIndex = function(id) {
		var index = -1, i, l = this.fields.length;
		for (i = 0; i < l; i++) {
			if (this.fields[i] == id) {
				index = i;
				break;
			}
		}
		return index;
	}

	//
	this.getFieldsCount = function() {
		return this.fields.length;
	}

	// remove param
	this.del = function(id) {
		var index = this.getFieldIndex(id);
		if (index != -1) {
			var i, l = this.fields.length - 1;
			for (i = index; i < l; i++) {
				this.fields[i] = this.fields[i + 1];
				this.values[i] = this.values[i + 1];
			}
			this.fields.length = l;
			this.values.length = l;
		}

		//
		return this;
	}

	//
	this.add = function(id, value) {
		if (isUndefined(value)) {
			this.del(id);
		} else {
			var index = this.getFieldIndex(id);
			if (index == -1) {
				var l = this.fields.length;
				this.fields[l] = id;
				this.values[l] = replaceLongSpaces(value);
			} else {
				this.values[index] = replaceLongSpaces(value);
			}
		}

		//
		return this;
	}

	//
	this.get = function(id) {
		var l = this.fields.length, i;
		for (i = 0; i < l; i++) {
			if (this.fields[i] == id) {
				return this.values[i];
			}
		}
		return null;
	}

	//
	this.addFromForm = function(oForm) {
		//
		var formElements = oForm.elements, elType, value;
		for (i = 0; i < formElements.length; i++) {
			value = formElements[i].value;
			if (isUndefined(formElements[i].name) || value == "") {
				continue;
			}
			elType = formElements[i].type;
			if (elType == "checkbox") {
				if (formElements[i].checked) {
					this.add(formElements[i].name, "on");
				} else {
					this.add(formElements[i].name, "off");
				}
			} else if (elType == "radio") {
				if (formElements[i].checked) {
					this.add(formElements[i].name, formElements[i].value);
				}
			} else if ((elType != "submit") && (elType != "button") && (formElements[i].tagName != "button")) {
				this.add(formElements[i].name, formElements[i].value);
			}
		}
		return this;
	}

	//
	this.createFields = function(frm, doc) {
		var l = this.fields.length, el;
		var inputs = frm.getElementsByTagName("INPUT");
		for (var i = 0; i < l; i++) {
			el = null;
			for (var j = 0; j < inputs.length; j++) {
				if (inputs[j].name == this.fields[i] && inputs[j].type == "hidden") {
					el = inputs[j];
					break;
				}
			}
			if (el != null) {
				el.value = this.values[i];
			} else {
				el = doc.createElement("INPUT");
				el.type = "hidden";
				el.name = this.fields[i];
				el.value = this.values[i];
				frm.appendChild(el);
			}
		}
	}

	//
	this.submit = function(sUrl, srcDoc) {
		if (isUndefined(this.id)) {
			this.id = "_action";
		}
		var doc;
		if (isUndefined(srcDoc)) {
			doc = window.document;
		} else {
			doc = srcDoc;
		}
		frm = doc.forms[this.id];
		if (isUndefined(frm)) return;
		this.createFields(frm, doc);
		frm.method = "POST";
		frm.action = sUrl;
		frm.submit();
	}
}

//
function DateFormatter() {
	this.patterns = [];
	this.monthNames = [];
	this.weekDayNames = [];

	// patterns must be in following order: SHORT, MEDIUM, FULL
	this.setPatterns = function(patterns) {
		var i;
		for (i = 0; i < 3; i++) {
	        // don't need day of week name
			patterns[i] = patterns[i].replace("EEEE, ", "");

			// with the following code formatting may don't work correctly,
			// if pattern contains format literals in '..' block
	        while (patterns[i].search("'") != -1) {
		        patterns[i] = patterns[i].replace("'", "");
			}
		}
		this.patterns["short"] = patterns[0];
		this.patterns["medium"] = patterns[1];
		this.patterns["full"] = patterns[2];
	}

	//
	this.getPattern = function(type) {
		return this.patterns[type];
	}

	//
	this.setMonthNames = function(monthNames) {
		this.monthNames = monthNames;
	}

	//
	this.setWeekDayNames = function(weekDayNames) {
		this.weekDayNames = weekDayNames;
	}

	//
	this.getMonthNumber = function(monthName, num) {
		var result = -1, i, s1, s2;
		for (i = 0; i < this.monthNames.length; i++) {
			s1 = num ? this.monthNames[i].toLowerCase().substring(0,num) : this.monthNames[i].toLowerCase();
			s2 = num ? monthName.toLowerCase().substring(0,num) : monthName.toLowerCase();
			if (s1 == s2) {
				return i;
			}
		}
		return result;
	}

	//
	this.fmt = function(date, r) {
		var y100 = date.getYear()%100;
		var prev = r;
		r = r.replace("yyyy", "" + date.getYear());
		r = r.replace("yy", (y100<10 ? "0" : "") + y100);
		if (r == prev) {
			r = r.replace("y", (y100 < 10 ? "0" : "") + y100);
		}
		prev = r;
		r = r.replace("MMMM", this.monthNames[date.getMonth()]);
		r = r.replace(/M{3}/, this.monthNames[date.getMonth()].substring(0,3));
		r = r.replace("MM", (date.getMonth() < 9 ? "0" : "") + (date.getMonth() + 1));
		if (r == prev) {
			r = r.replace("M", "" + (date.getMonth() + 1));
		}
		prev = r;
		r = r.replace("dd", (date.getDay()<10?"0":"")+date.getDay());
		if (r == prev) {
			r = r.replace("d", ""+date.getDay());
		}
		return r;
	}

	//
	this.format = function(date, type) {
        if (isUndefined(date) || isUndefined(type)) {
            return '';
		} else {
			var r = this.patterns[type];
			return this.fmt(date, r);
		}
    }

	//
    this.parse = function(src, type) {
		if (!src || ! type) return null;
		src = src.replace(/\u00a0/g," ");
		var srcTokens = src.split(new RegExp("[,. ]"));
		var patternTokens = this.patterns[type].split(new RegExp("[,. ]"));
		var i, date = new DateObject();

		for (i = 0; i < patternTokens.length; i++) {
			if (srcTokens.length < i + 1) break;
			p = patternTokens[i];
			s = srcTokens[i];
			if (s.indexOf('0') == 0) {
				s = s.replace("0", "");
			}
			if (p=='y' || p=='yy' || p=='yyyy')   {
				n = parseInt(s);
				if(isNaN(n) || isUndefined(n)) continue;
				date.setYear(n<50 ? 2000+n : ( n<100 ? 1900+n : n));
			} else if (p=='MMMM') {
				date.setMonth(this.getMonthNumber(s));
			} else if (p=='MMM') {
				date.setMonth(this.getMonthNumber(s,3));
			} else if (p=='M' || p=='MM') {
				n = parseInt(s);
				if(isNaN(n) || isUndefined(n)) continue;
				date.setMonth(n);
			} else if (p=='d' || p=='dd' || p=='den') {
				n = parseInt(s);
				if(isNaN(n) || isUndefined(n)) continue;
				date.setDay(n);
			}
		}

		return date.isValid() ? date : null;
    }

    //
    this.parse2 = function(caption, src, type) {
		d = this.parse(src, type);
		if (d == null) {
			alert(caption + " is invalid");
			return null;
		}
		return d;
    }

    //
    this.getCurrentDate = function() {
    	var d = new Date();
    	return new DateObject(d.getDate(), d.getMonth(), d.getFullYear());
    }

    //
    this.createParamValue = function(src, type) {
    	var date = this.parse(src, type);
    	//if (date == null) return;
    	if (date == null) date = this.getCurrentDate();
    	return "" + date.getYear() + "-" + date.getMonth() + "-" + date.getDay();
    }
}

//
function DateObject(day, month, year) {
	this.day = day;
	this.month = month;
	this.year = year;

	//
	this.setDate = function(day, month, year) {
		this.day = day;
		this.month = month;
		this.year = year;
	}

	//
	this.isValid = function() {
		if (isUndefined(this.day) || isNaN(this.day)) {
			return false;
		} else if (this.day < 1 || this.day > 31) {
			return false;
		}

		//
		if (isUndefined(this.month) || isNaN(this.month)) {
			return false;
		} else if (this.month < 0 || this.month > 11) {
			return false;
		}

		//
		if (isUndefined(this.year) || isNaN(this.year)) {
			return false;
		} else if (this.year < 1950 || this.year > 2050) {
			return false;
		}

		return true;
	}

	//
	this.getDaysOffset = function(date) {
		var millis1 = (new Date(this.year, this.month, this.day)).getTime();
		var millis2 = (new Date(date.year, date.month, date.day)).getTime();
		return Math.floor((millis2 - millis1) / (24 * 60 * 60 * 1000));
	}

	//
	this.addDays = function(nDays) {
		var date = new Date(this.year, this.month, this.day);
		var millis = date.getTime();
		millis += nDays * 24 * 60 * 60 * 1000;
		date.setTime(millis);
		this.year = date.getFullYear();
		this.month = date.getMonth();
		this.day = date.getDate();
	}

	//
	this.getWeekDay = function() {
		return (new Date(this.year, this.month, this.day).getDay());
	}

	//
	this.setDay = function(day) {
		this.day = day;
	}

	//
	this.getDay = function() {
		return this.day;
	}

	//
	this.setMonth = function(month) {
		this.month = month;
	}

	//
	this.getMonth = function() {
		return this.month;
	}

	//
	this.setYear = function(year) {
		this.year = year;
	}

	//
	this.getYear = function() {
		return this.year;
	}
}

//
function NumberFormatter() {
	//
	this.fractionDigits = null;
	this.decimalSeparator = null;
	this.groupingSeparator = null;

	//
	this.parseFormatInfo = function(info) {
		this.fractionDigits = parseInt(info.charAt(0));
		this.decimalSeparator = info.charAt(1);
		info.length > 2 ? this.groupingSeparator = info.charAt(2) : null;
	}

	//
	this.format = function(n,digits) {
		if (isNaN(n)) return null;

		//
		var nWhole = Math.floor(n);
		var nFract = n - nWhole;
		var pow = Math.pow(10, this.fractionDigits);
		nFract = Math.round(nFract * pow) / pow;
		var sign = nWhole < 0 ? "-" : "";

		// divide number on groups
		var result = "", group;
		if (this.groupingSeparator != null) {
			//
			while (nWhole / 1000 != 0) {
				nWhole /= 1000;
				if (result != "") {
					result = this.groupingSeparator + result;
				}
				group = Math.round((nWhole - Math.floor(nWhole)) * 1000);
				result = group + result;
				nWhole = Math.floor(nWhole);
			}

			//
			if (result == "") {
				result = "0";
			}

			result = sign + result;

		} else {
			//
			result = result + nWhole;
		}

		//
		result += this.decimalSeparator;
		var sFract = "" + nFract;
		//if (sFract == "0") {
		//	result += "0";
		//} else {
			result += this.padFractWithDigits(sFract.substring(2, sFract.length),digits);
		//}

		return result;
	}

	//
	this.parse = function(sValue) {
		if (this.groupingSeparator != null) {
			sValue = sValue.replace(this.groupingSeparator, "");
		}
		sValue = sValue.replace(this.decimalSeparator, ".");

		// TODO: check fraction digits
		return parseFloat(sValue, 10);
		//return isNaN(sValue) ? null : parseFloat(sValue, 10);
	}
	
	this.padFractWithDigits = function(n,digits)
	{
		var retVal = n;
		for (i = 0; i < digits - n.length; i++) {
			retVal += "0";	
		}
		return retVal;
	}
}
var numberFormatter = new NumberFormatter();

//
function confirmDialog(msgID, params, paramTypes, actionOnConfirm, actionOnCancel) {
	// possible values for paramTypes array:
	// text, node, user, group, datasource

	if (posLib.moz) {
		if (!isUndefined(actionOnConfirm)) {
			window.top.actionOnConfirm = actionOnConfirm;
		}
		if (!isUndefined(actionOnCancel)) {
			window.top.actionOnCancel = actionOnCancel;
		}
	}

	var url = urlHelper.get("/secure/confirm.do");
	url.add("msgid", msgID);

	//
	if (!isUndefined(params)) {
		var i;
		for (i = 0; i < params.length; i++) {
			url.add("p"+ i, paramTypes[i]+"."+params[i]);
		}
	}

	//
	var w = 480, h = 150;
	var dialogFeatures = getDialogFeatures((screen.width - w) / 2, (screen.height - h) / 2, w, h, "no");
	var md = new ModalDialog(url, null, dialogFeatures);
	return md.show();
}

//
function divider(caption) {
	with (document) {
		write("<table border='0' style='margin:20px 0px 5px 0px;' width='100%' cellspacing='0' cellpadding='0'>");
			write("<tr>");
				write("<td width='3%'><hr></td>");
				write("<td style='white-space:nowrap;'>" + caption + "</td>");
				write("<td width='100%'><hr></td>");
			write("</tr>");
		write("</table>");
	}
}

//
function smallColorButton(name, color) {
	var doc = document;
	doc.write("<td>");
		doc.write("<input type='hidden' name='" + name + "' value='" + color + "'>");
		doc.write("<button id='colorCell' style='width:20px; height:20px; background-color:" + color + ";' name='b" + name + "' onclick='window.top.selectColor(this, window, " + window.comp_id + "); return false;'/>");
	doc.write("</td>");
}

//
function colorButton(name, color) {
	var doc = document;
	doc.write("<td style='padding: 0px 0px 5px 5px;'>");
		doc.write("<input type='hidden' name='" + name + "' value='" + color + "'>");
		doc.write("<button name='b" + name + "' onclick='window.top.selectColor(this, window); return false;'>");
			doc.write("<table cellpadding='0' cellspacing='0'>");
				doc.write("<tr>");
					doc.write("<td id='colorCell' class='colorCell' style='background-color:" + color + ";'>");
					doc.write("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>");
					doc.write("<td>");
						doc.write("<img src='" + window.app_id + "/images/dialog/sepdown.gif'>");
					doc.write("</td>");
				doc.write("</tr>");
			doc.write("</table>");
		doc.write("</button>");
	doc.write("</td>");
}

//
function lineButton(name, line) {
	with (document) {
		write("<td style='padding: 0px 0px 5px 5px;'>");
			write("<input type='hidden' name='" + name + "' value='" + line + "'>");
			write("<button name='b" + name + "' onclick='window.top.selectLine(this, window); return false;'>");
				write("<table cellpadding='0' cellspacing='0' width='60px'>");
					write("<tr>");
						write("<td id='lineCell' class='lineCell' style='background-color:#ffffff;'>");
							write("<center>");
								write("<table id='line' cellpadding='0' cellspacing='0' width='40px' height='" + line + "px'>");
									write("<tr>");
										write("<td style='background-color:#000000;'/>");
									write("</tr>");
								write("</table>");
							write("</center>");
						write("</td>");
						write("<td>");
							write("<img src='" + window.app_id + "/images/dialog/sepdown.gif'>");
						write("</td>");
					write("</tr>");
				write("</table>");
			write("</button>");
		write("</td>");
	}
}

//
function ComponentManager() {
	//
	this.getURL = function() {
		var url = urlHelper.parse(this.window.location.href);
		return url;
	}

	//
	this.setURL = function(url) {
		this.window.location.href = url.toString();
	}
}

//
function disableButton(oBtn) {
	oBtn.disabled = true;
	var oImg = oBtn.getElementsByTagName("IMG").item(0);
	if (posLib.moz) {
		oImg.style.MozOpacity = 0.3;
	} else {
		oImg.style.filter = "gray()";
	}
}

//
function enableButton(oBtn) {
	oBtn.disabled = false;
	var oImg = oBtn.getElementsByTagName("IMG").item(0);
	if (posLib.moz) {
		oImg.style.MozOpacity = 1;
	} else {
		oImg.style.filter = "";
	}
}

//
function disableSelection() {
	if (!posLib.moz) return;
	document.body.style.MozUserSelect = "none";
	var inputs = document.getElementsByTagName("INPUT");
	for (var i = 0; i < inputs.length; i++) {
		if (inputs[i].type == "text" || inputs[i].type == "password") {
			inputs[i].style.MozUserSelect = "normal";
			if (!isUndefined(inputs[i].onfocus)) {
				inputs[i]._onfocus = inputs[i].onfocus;
			}
			inputs[i].onfocus = function() {
				if (!isUndefined(this._onfocus)) this._onfocus();
				window.focusInTextfield = true;
				document.body.style.MozUserSelect = "";
			}
			if (!isUndefined(inputs[i].onblur)) {
				inputs[i]._onblur = inputs[i].onblur;
			}
			inputs[i].onblur = function() {
				if (!isUndefined(this._onblur)) this._onblur();
				window.focusInTextfield = false;
				document.body.style.MozUserSelect = "none";
			}
			inputs[i].onmouseover = function() {
				document.body.style.MozUserSelect = "";
			}
			inputs[i].onmouseout = function() {
				if (!window.focusInTextfield) {
					document.body.style.MozUserSelect = "none";
				}
			}
		}
	}
	// prevent submitting of panelForm on Enter key press
	var pForm = document.getElementById("panelForm");
	if (!isUndefined(pForm)) pForm.onsubmit = function() {return false;};
}

//
function equalizeButtonsSize(containerCell) {
	var childs;
	if (!isUndefined(containerCell)) {
		childs = getChildElements(containerCell, "INPUT");
	} else {
		childs = document.getElementsByTagName("INPUT");
	}
	var buttons = new Array();
	var maxWidth = 0, maxHeight = 0;
	for (var i = 0; i < childs.length; i++) {
		if (childs[i].type == "button") {
			buttons.push(childs[i]);
			if (childs[i].clientWidth > maxWidth) maxWidth = childs[i].clientWidth;
			//if (childs[i].clientHeight > maxHeight) maxHeight = childs[i].clientHeight;
		}
	}
	for (var i = 0; i < buttons.length; i++) {
		buttons[i].style.width = maxWidth;
		//buttons[i].height = maxHeight + 10;
	}
}

//
function getElementLeft(eElement) {
	var nLeftPos = eElement.offsetLeft;
	var eParElement = eElement.offsetParent;

	while (eParElement != null) {
		if(!posLib.moz) {
			if (eParElement.tagName == "TD") {
				nLeftPos += eParElement.clientLeft;
			}
		} else {
			if(eParElement.tagName == "TABLE") {
				var nParBorder = parseInt(eParElement.border);
				if(isNaN(nParBorder)) {
					var nParFrame = eParElement.getAttribute('frame');
					if(nParFrame != null) {
						nLeftPos += 1;
					}
				} else if(nParBorder > 0) {
					nLeftPos += nParBorder;
				}
			}
		}
		nLeftPos += eParElement.offsetLeft;
		eParElement = eParElement.offsetParent;
	}
	return nLeftPos;
}

//
function getElementTop(eElement, container) {
	var nTopPos = eElement.offsetTop;
	var eParElement = eElement.offsetParent;

	while (eParElement != null) {
		if (!isUndefined(container) && eParElement == container) break;
		if(!posLib.moz) {
			if(eParElement.tagName == "TD") {
				nTopPos += eParElement.clientTop;
			}
		} else {
			if(eParElement.tagName == "TABLE") {
				var nParBorder = parseInt(eParElement.border);
				if(isNaN(nParBorder)) {
					var nParFrame = eParElement.getAttribute('frame');
					if(nParFrame != null) {
						nTopPos += 1;
					}
				} else if(nParBorder > 0) {
					nTopPos += nParBorder;
				}
			}
		}
		nTopPos += eParElement.offsetTop;
		eParElement = eParElement.offsetParent;
	}
	return nTopPos;
}

//
function getFrameLeft(wFrame) {
	var nLeftPos = 0, elFrame;
	while (wFrame != wFrame.top) {
		elFrame = wFrame.frameElement;
		nLeftPos += getElementLeft(elFrame);
		if (elFrame.tagName == "FRAME" && !posLib.moz) return nLeftPos + 2;
		wFrame = wFrame.parent;
	}
	return nLeftPos;
}

//
function getFrameTop(wFrame) {
	var nTopPos = 0, elFrame;
	while (wFrame != wFrame.top) {
		elFrame = wFrame.frameElement;
		nTopPos += getElementTop(elFrame);
		if (elFrame.tagName == "FRAME" && !posLib.moz) return nTopPos + 2;
		wFrame = wFrame.parent;
	}
	return nTopPos;
}

//
function hideCalendar() {
	if (!isUndefined(window.top.calendar)) {
		if (window.top.calendar.visible) {
			window.top.calendar.hide();
		}
	}
}

//
function isValidFloat(value) {
	if (isUndefined(value) || value == "") return false;
	var v = value.charAt(0) == '-' ? value.substring(1) : value;
	v = "1" + v.replace(",", ".").concat("1");
	if (isNaN(v)) return false;
	if (parseFloat(v, 10).toString(10) != v) return false;
	return true;
}

//
function isValidInt(value) {
	if (isUndefined(value) || value == "") return false;
	if (isNaN(value)) return false;
	if (parseInt(value, 10).toString(10) != value) return false;
	return true;
}

//
function getNodeName(nodeID) {
	var url = urlHelper.get("/secure/session.do").add("action", "getNodeName").add("node", nodeID);
	var response = xmlHelper.loadData(url.toString());
	checkResponse(response);
	return response;
}

//
function formatMsg(pattern, param) {
	return pattern.replace("{0}", param);
}

//
function getResourceString(id) {
	var cache = window.top.resourcesCache;
	if (isUndefined(cache)) {
		cache = new Url();
		window.top.resourcesCache = cache;
	}
	var s = cache.get(id);
	if (isUndefined(s)) {
		var url = urlHelper.get("/secure/session.do").add("action", "getResourceString").add("id", id);
		s = xmlHelper.loadData(url.toString());
		checkResponse(s);
		cache.add(id, s);
	}
	return s;
}

//
function loadNewWindowIndex(panelType) {
	var url = urlHelper.get("/secure/session.do");
	url.add("action", "newWindowIndex").add("panelType", panelType);

	var index = xmlHelper.loadData(url.toString());
	if (isUndefined(index)) {
		alert("No response from server");
		return 1000;
	}
	if (index.indexOf("<html>") == -1) {
		return index + "_" + panelType.toLowerCase();
	} else {
		return 1000;
	}
}

//
function storeValuesToArray(names) {
	var el;
	var values = new Array();
	for (var i = 0; i < names.length; i++) {
		el = getElementByName(names[i]);
		if (el.type == "checkbox") {
			if (el.parentNode.style.backgroundColor != "") {
				values[names[i]] = "";
			} else {
				values[names[i]] = el.checked ? "on" : "off";
			}
		} else {
			values[names[i]] = el.value;
		}
	}
	return values;
}

//
function setControlValue(name, value) {
	var el = getElementByName(name);
	if (el.type == "checkbox") {
		if (value == "") {
			el.parentNode.style.backgroundColor = "#bbbbbb";
			el.onclick = function() {
				el.parentNode.style.backgroundColor = "";
			}
		} else {
			el.parentNode.style.backgroundColor = "";
			el.checked = value == "on";
		}
	} else if (el.type == "hidden") {
		el.value = value;
		var button = getElementByName("b" + name);
		var cells = getElementsById(button, "colorCell");
		if (cells.length > 0) {
			cells[0].style.backgroundColor = value;
		} else {
			cells = getElementsById(button, "line");
			if (value == "") {
				getElementsById(button, "lineCell")[0].style.backgroundColor = "#cccccc";
			} else {
				getElementsById(button, "lineCell")[0].style.backgroundColor = "#ffffff";
				cells[0].style.height = "" + value + "px";
			}
		}
	} else if (el.tagName == "SELECT") {
		if (value == "") {
			el.selectedIndex = -1;
		} else {
			el.value = value;
		}
	} else {
		el.value = value;
	}
}

//
function setControlsValues(names, values) {
	for (var i = 0; i < names.length; i++) {
		setControlValue(names[i], values[names[i]]);
	}
}

//
function commonValuesToArray(array1, array2, names) {
	for (var i = 0; i < names.length; i++) {
		if (array1[names[i]] != array2[names[i]]) {
			array1[names[i]] = "";
		}
	}
}

//
function copyTextToClipboard(copytext) {
	if (posLib.moz) {
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
			if (!clip) return;

			var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
			if (!trans) return;
			trans.addDataFlavor('text/unicode');

			var str = new Object();
			var len = new Object();
			var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
			str.data = copytext;
			trans.setTransferData("text/unicode", str, copytext.length * 2);
			var clipid = Components.interfaces.nsIClipboard;
			if (!clip) return false;

			clip.setData(trans, null, clipid.kGlobalClipboard);
		} catch (e) {
			alert("To enable copying to clipboard you need to set\n" +
				"the property 'signed.applets.codebase_principal_support'\n" +
				"at the 'about:config' page to true.");
			return false;
		}
	} else {
		window.clipboardData.setData("Text", copytext);
	}
	return true;
}

// 160 = &nbsp;
function replaceLongSpaces(s) {
	var r;
	if (typeof(s) == "string") {
		r = "";
		var i;
		for (i = 0; i < s.length; i++) {
			if (s.charCodeAt(i) == 160) {
				r += ' ';
			} else {
				r += s.charAt(i);
			}
		}
	} else {
		r = s;
	}
	return r;
}

//
function decodeHTML(s) {
	return s.replace(/&quot;/g, "\"").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&#160;/g, " ");
}

function encodeHTML(s) {
	return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/ /g, "&#160;");
}
