/*
 * iCMS JavaScript Extension
 * 
 * Copyright (c) 2006-2010 i-deal Studio
 */

// function returns element by ID
var ge = (document.all) ? function(id){ return document.all[id]; } : function(id){ return document.getElementById(id); };
window.ge = ge;

// class for events
var CEvents = function() {
	return this;
};
// add handler for element event
CEvents.prototype.Add = function(el, ev, handler) {
	if (el) {
		if (el.addEventListener) el.addEventListener(ev, handler, false);
		else if (el.attachEvent) el.attachEvent("on" + ev, handler);
		else el["on" + ev] = handler;
	};
};
// delete handler of element event
CEvents.prototype.Del = function(el, ev, handler) {
	if (el) {
		if (el.removeEventListener) el.removeEventListener(ev, handler, false);
		else if (el.detachEvent) el.detachEvent("on" + ev, handler);
		else el["on" + ev] = null;
	};
};

// class for DOM
var CDOM = function() {
	return this;
};
// assign inner text for element
CDOM.prototype.SetText = function(el, text) {
	if (el) {
		if (el.innerText != void 0) el.innerText = text;
		else el.textContent = text;
	};
};
// return inner text of element
CDOM.prototype.GetText = function(el) {
	if (!el) return;
	else if (el.innerText != void 0) return el.innerText;
	else return el.textContent;
};
// add class name in element class
CDOM.prototype.ClassAdd = function(el, cl) {
	if (el && cl != void 0) {
		if (!(cl instanceof Array)) cl = [cl];
		var c = el.className ? el.className : '', n;
		for (var i = 0, L = cl.length; i < L; i++) {
			n = c.indexOf(cl[i]), ns = /\S/;
			if (n == -1 || (n > 0 && ns.test(c.SubStr(n - 1, 1))) || ns.test(c.SubStr(n + cl[i].length, 1))) c += " " + cl[i];
		};
		if (el.className != c) el.className = c;
	};
};
// delete class name from element class
CDOM.prototype.ClassDel = function(el, cl) {
	if (el && cl != void 0) {
		var c = el.className;
		if (c) {
			c = c.Trim().Split( /\s+/ );
			if (!(cl instanceof Array)) cl = [cl];
			var i = c.length, f = false;
			while (--i >= 0) {
				if (cl.Search(c[i]) != -1) {
					c[i] = "";
					f = true;
				};
			};
			if (f) el.className = c.join(" ").Replace( /  +/g, " ").Trim();
		};
	};
};
// check if element has class name
CDOM.prototype.ClassHave = function(el, cl) {
	if (el) {
		var c = el.className;
		if (c) {
			c = c.Trim().Split( /\s+/ );
			return c.Search(cl) != -1;
		};
	};
	return false;
};
// enumerate each child nodes of element and call a function with each of them; if not function specified, returns array or found elements
CDOM.prototype.EachChildNode = function(el, func, obj) {
	if (!el) return;
	var r = [], f = func;
	if (!f) f = function(n) { r.Push(n); return true; };
	for (var o = el.firstChild; o; o = o.nextSibling) {
		if (o.nodeType == 1) {
			if (f.call(obj || o, o) === false) break;
		};
	};
	if (!func) return r;
};
// insert node after reference node into parent node of reference
CDOM.prototype.InsertAfter = function(node, ref) {
	var parent, n;
	if (node && ref && (parent = ref.parentNode)) {
		if (n = ref.nextSibling) parent.insertBefore(node, n);
		else parent.appendChild(node);
	};
};
// insert node before reference node into parent node of reference
CDOM.prototype.InsertBefore = function(node, ref) {
	var parent;
	if (node && ref && (parent = ref.parentNode)) {
		parent.insertBefore(node, ref);
	};
};
// set multiple styles to element
CDOM.prototype.SetStyles = function(el, st) {
	if (el && el.style && st) {
		var v;
		for (var n in st) {
			v = ('' + st[n]).Trim();
			if (n == 'opacity') this.SetOpacity(el, parseFloat(v));
			else el.style[n] = v;
		};
	};
};
// helper for opacity
CDOM.prototype.GetOpacityProperty = function() {
	if (typeof document.body.style.opacity == 'string') // CSS3 compliant (Moz 1.7+, Safari 1.2+, Opera 9)
		return 'opacity';
	else if (typeof document.body.style.MozOpacity == 'string') // Mozilla 1.6-, Firefox 0.8 
		return 'MozOpacity';
	else if (typeof document.body.style.KhtmlOpacity == 'string') // Konqueror 3.1, Safari 1.1
		return 'KhtmlOpacity';
	else if (document.body.filters && navigator.appVersion.match(/MSIE ([\d.]+);/)[1]>=5.5) // Internet Exploder 5.5+
		return 'filter';
	
	return false; //no opacity
};
// remembered value of GetOpacityProperty()
CDOM.prototype.OpacityProperty = void 0;
// real set opacity
CDOM.prototype.SetOpacity = function(el, val) {
	if (this.OpacityProperty == void 0) this.OpacityProperty = this.GetOpacityProperty();
	if (!el || !this.OpacityProperty) return;
	
	if (this.OpacityProperty == "filter") {	// Internet Exploder 5.5+
		val *= 100;
			// if opacity already set, then change it with filters collection, otherwise add opacity in style.filter
		var oAlpha;
		try {
			oAlpha = el.filters['DXImageTransform.Microsoft.alpha'] || el.filters.alpha;
		}
		catch (e) {
			oAlpha = false;
		};
		if (oAlpha) oAlpha.opacity = val;
		else el.style.filter += "progid:DXImageTransform.Microsoft.Alpha(opacity="+val+")"; // use += to keep other filters
	}
	else {	// other browsers
		el.style[this.OpacityProperty] = val;
	};
};

// class for HTTP routines
var CHTTP = function() {
	return this;
};
// value of signature header
CHTTP.prototype.VERSION = "i-CMS/2.0 AJAX";
// request types
CHTTP.prototype.METHOD_POST = 1;
CHTTP.prototype.METHOD_GET = 2;
// function return new instance of XMLHTTP object
CHTTP.prototype.NewXMLHTTP = function() {
	var xmlHttp = null;
	try {
		xmlHttp = new XMLHttpRequest();	// Firefox, Opera 8.0+, Safari
	}
	catch (e) {	// Internet Explorer
		try {
			xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");	// IE 6.0+
		}
		catch (e) {
			try {
				xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");	// IE 5.5+
			}
			catch (e) {
			};
		};
	};
	return xmlHttp;
};
// make HTTP request
CHTTP.prototype._Request = function(method, url, args, onresponce, obj) {
	var xmlHttp = this.NewXMLHTTP();
	if (!xmlHttp) return false;
	xmlHttp.onreadystatechange = function() {
		/* 0 - The request is not initialized; 1 - The request has been set up; 2 - The request has been sent; 3 - The request is in process; 4 - The request is complete */
		if (xmlHttp.readyState == 4) onresponce.call(obj || xmlHttp, xmlHttp.responseText, xmlHttp);
	};
	var params = [], key;
	if (args) for (key in args) params.Push(key + "=" + escape(args[key].toUTF8()));
	params = params.join("&");
	
	if (typeof method == typeof "") method = method.toUpperCase();
	switch (method) {
		case this.METHOD_POST:
		case "POST":
			xmlHttp.open("POST", url, true);
			xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			xmlHttp.setRequestHeader("Content-Length", params.length);
			xmlHttp.setRequestHeader("X-Requested-With", this.VERSION);
			xmlHttp.setRequestHeader("Connection", "close");
			xmlHttp.send(params);
			break;
		case this.METHOD_GET:
		case "GET":
			if (params) url += '?';
			xmlHttp.open("GET", url + params, true);
			xmlHttp.setRequestHeader("X-Requested-With", this.VERSION);
			xmlHttp.send(null);
			break;
		default:
			return false;
	};
	return true;
};

// class for debugging
var CDebug = function() {
	return this;
};
// return text dump of a value
CDebug.prototype.Dump = function(o, recurs) {
	if (o === null) return "null";
	else if (o === void 0) return "undefined";
	else if (typeof o == typeof 1 || typeof o == typeof true) return o.toString();
	else if (typeof o == typeof "") return o.length ? "String[" + o.length + "]" + (recurs ? "" : ": " + o) : '""';
	else if (typeof o == "function") return recurs ? "Function" : o.toString();
	else if (typeof o == "object") {
		var a = o instanceof Array;
		var r;
		if (!recurs) {
			r = a ? "Array(" : "Object {";
			var items = [], k, L;
			if (a) for (k = 0, L = o.length; k < L; k++) items.Push("\n    " + k + ": " + this.Dump(o[k], true));
			else {
				var x;
				for (k in o) {
					try {
						x = o[k];
						x = this.Dump(x, true);
					}
					catch(e) {
						x = "* Error";
					};
					items.Push("\n    " + k + ": " + x);
				};
			};
			r += items.join(",");
			if (items.length) r += "\n";
			r += a ? ")" : "}";
		}
		else {
			if (a) r = "Array(" + o.length + ")";
			else {
				try {
					r = (o.toString) ? o.toString() : "[Object]";
				}
				catch(e) {
					r = "[Object]";
				};
				r = r.Replace( /^\[/ , '' ).Replace( /\]$/ , '' );
			};
		};
		return r;
	}
	else return typeof o;
};

// main iCMS class
var CiCMS = function() {
	this.LoadFuncs = [];
	this._onLoad = function() {
		this.Load = function(func) {
			func();
		};
		for (var i = 0, L = this.LoadFuncs.length; i < L; i++) {
			try {
				(this.LoadFuncs[i])();
			}
			catch(e) {};
		};
		this.LoadFuncs.length = 0;
	};
	// add a function to document onload event
	this.Load = function(func) {
		this.LoadFuncs.Push(func);
	};
	
	var o = this;
	this.Events.Add(window, 'load', function(){ o._onLoad(); });
	return this;
};
// create class for events
CiCMS.prototype.Events = new CEvents();
// create class for DOM
CiCMS.prototype.DOM = new CDOM();
// create class for debugging
CiCMS.prototype.Debug = new CDebug();
// create class for HTTP
CiCMS.prototype.HTTP = new CHTTP();
// function makes request for HTML
CiCMS.prototype.AJAH = function(method, url, args, onresponce, obj) {
	return this.HTTP._Request(method, url, args, onresponce, obj);
};
// function makes request for JavaScript (may be it should have name AJAJ ?)
CiCMS.prototype.AJAX = function(method, url, args, onresponce, obj) {
	return this.HTTP._Request(method, url, args, function(s, o) {
		var r;
		try {
			if (typeof s != typeof "" || !s.length) s = "void 0";
			eval("r = " + s + ";"); // @bug some browsers stores objects sorted by keys (Opera 10, Chrome)
		}
		catch (e) {
			//alert('Error: ' + e.message + '\r\n----\r\n' + s);
			r = void 0;
		};
		//alert(iCMS.Debug.Dump(r.groups[0]));
		onresponce.call(obj || o, r, o);
	});
};

// create main iCMS class
var iCMS = new CiCMS();
window.iCMS = iCMS;

// delete all options from a Select and fill it from directories
CDOM.prototype.SelectFromDirs = function(select, link, lng, skipfirst) {
	if (!select) return;
	var o = this.EachChildNode(select);
	for (var i = skipfirst ? 1 : 0; o && i < o.length; i++) {
		select.removeChild(o[i]);
		o[i] = null;
	};
	o = null;
	var f = function() {	// IE7 strange bug
		var c = select.className;
		select.className = '';
		select.className = c;
	};
	if (link) {
		iCMS.AJAX("POST", "/fnc/ajaxdirsq.php", {l:lng, g:link}, function(items){
			if (items && typeof items == typeof {}) {
				for (var i in items) {
					o = document.createElement('option');
					o.value = i;
					this.SetText(o, items[i].t);
					select.appendChild(o);
				};
			};
			f();
		});
	}
	else f();
};

// iform renaming fields
var iFormRenamingField = function(o) {
	this.fd = ge(o.id + "_title");
	this.fh = ge(o.id + "_help");
	this.d = o.d;
	this.h = o.h;
	return this;
};
var iFormRenaming = function(ids, value, fields) {
	var i, L, o;
	
	this.Fields = [];
	for (i = 0, L = fields.length; i < L; i++) this.Fields.Push( new iFormRenamingField(fields[i]) );
	
	this.Items = [];
	for (i = 0, L = ids.length; i < L; i++) {
		o = ge(ids[i]);
		o._i_renaming = this;
		iCMS.Events.Add(o, 'click', this.OnClick);
		this.Items.Push(o);
	};
	this.Rename(value);
	return this;
};
iFormRenaming.prototype.Rename = function(value) {
	for (var i = 0, L = this.Fields.length; i < L; i++) {
		if (this.Fields[i].fd && this.Fields[i].d) iCMS.DOM.SetText(this.Fields[i].fd, this.Fields[i].d[value]);
		if (this.Fields[i].fh && this.Fields[i].h) iCMS.DOM.SetText(this.Fields[i].fh, this.Fields[i].h[value]);
	};
};
iFormRenaming.prototype.OnClick = function(e) {
	e = e ? e : window.event;
	var o, obj;
	if (e && (o = e.target ? e.target : e.srcElement) && (obj = o._i_renaming)) {
		obj.Rename(o.value);
	};
};

// tabs
var TabPagesItem = function(a, index, parent) {
	this.oTab = ge(a[0]);
	this.oPage = ge(a[1]);
	this.Show(false);
	this.Index = index;
	this.Parent = parent;
	this.oTab._i_TabItem = this;
	iCMS.Events.Add(this.oTab, 'click', this.OnClick);
	return this;
};
TabPagesItem.prototype.Show = function(b) {
	if (b) iCMS.DOM.ClassAdd(this.oTab, 'selected');
	else iCMS.DOM.ClassDel(this.oTab, 'selected');
	this.oPage.style.display = b ? 'block' : 'none';
};
TabPagesItem.prototype.OnClick = function(e) {
	e = e ? e : window.event;
	var obj;
	if (e && (obj = e.target ? e.target : e.srcElement) && (obj = obj._i_TabItem)) {
		obj.Parent.Select(obj.Index);
	};
};
var TabPages = function(aItems) {
	this.Items = [];
	this.Selected = -1;
	for (var i = 0, L = aItems.length; i < L; i++) {
		this.Items.Push( new TabPagesItem(aItems[i], i, this) );
	};
	this.Select(0);
	return this;
};
TabPages.prototype.Select = function(index) {
	if (index != this.Selected) {
		if (this.Selected >= 0) this.Items[this.Selected].Show(false);
		this.Items[this.Selected = index].Show(true);
	};
};

// path selector
var PathSelectorItem = function(parent,R) {
	this.Parent = parent;
	this.ID = R.i;
	this.Link = (R.l != void 0) ? R.l : R.i;
	this.Title = R.t;
	this.oOption = document.createElement('option');
	this.oOption.value = this.ID;
	iCMS.DOM.SetText(this.oOption, this.Title);
	this.Parent.appendChild(this.oOption);
	return this;
};
PathSelectorItem.prototype.Free = function() {
	this.Parent.removeChild(this.oOption);
	this.oOption = null;
	this.Parent = null;
};

var PathSelector = function(parent, item, parentDiv, onEnd, modulePath, langSelect, langLoad, path) {
	this.ModulePath = modulePath;
	this.Lang_SelectArea = langSelect;
	this.Lang_Loading = langLoad;
	this.Path = path || modulePath;
	this.Parent = parent;
	this.Area = item ? item.ID : 0;
	this.ParentDiv = parentDiv;
	this.Child = null;
	this.OnEnd = onEnd;
	
	this.oSelect = document.createElement('select');
	this.oOptionDef = document.createElement('option');
	this.oOptionDef.value = 0;
	iCMS.DOM.SetText(this.oOptionDef, this.Lang_Loading);
	this.oSelect.appendChild(this.oOptionDef);
	if (this.Area) this.oSelect.style.display = 'none';
	this.ParentDiv.appendChild(this.oSelect);
	this.oSubDiv = document.createElement('div');
	this.ParentDiv.appendChild(this.oSubDiv);
	this.Items = {};
	
	var o = this;
	iCMS.Events.Add(this.oSelect, 'change', function(){ o.OnChange(); });
	
	iCMS.AJAX("POST", this.ModulePath + "/list", { id : this.Area.toString() }, this.OnResponce, this);
	return this;
};
PathSelector.prototype.GetPath = function() {
	var r = '', id, item;
	if ((id = this.oSelect.value) && (item = this.Items[id]) && item.oOption) {
		r = '/' + item.Link;
	};
	return this.Path + r;
};
PathSelector.prototype.GetID = function() {
	if (this.Child) return this.Child.GetID();
	var id, item;
	if ((id = this.oSelect.value) && (item = this.Items[id]) && item.oOption) return id;
	else return this.Area;
};
PathSelector.prototype.GetItem = function() {
	var id, item;
	if (this.Child) item = this.Child.GetItem();
	if (!item && (id = this.oSelect.value)) item = this.Items[id];
	return item;
};
PathSelector.prototype.OnChange = function() {
	if (this.Child) {
		this.Child.Free();
		this.Child = null;
	};
	var id, item;
	if ((id = this.oSelect.value) && (item = this.Items[id]) && item.oOption) {
		this.Child = new PathSelector(this, item, this.oSubDiv, this.OnEnd, this.ModulePath, this.Lang_SelectArea, this.Lang_Loading, this.GetPath());
	};
};
PathSelector.prototype.OnResponce = function(items, o) {
	var id, L = items ? items.length : 0;
	if (L) {
		for (var i = 0; i < L; i++) {
			id = items[i].i;
			this.Items[id] = new PathSelectorItem(this.oSelect, items[i]);
		};
		iCMS.DOM.SetText(this.oOptionDef, this.Lang_SelectArea);
		this.oSelect.style.display = 'block';
	}
	else {
		if (this.Area) this.oSelect.style.display = 'none';
		if (this.OnEnd) this.OnEnd(this);
	}
};
PathSelector.prototype.Free = function() {
	if (this.Child) {
		this.Child.Free();
		this.Child = null;
	};
	for (var id in this.Items) {
		this.Items[id].Free();
		this.Items[id] = null;
	};
	this.Items = null;
	this.ParentDiv.removeChild(this.oSubDiv);
	this.oSubDiv = null;
	this.oSelect.removeChild(this.oOptionDef);
	this.oOptionDef = null;
	this.ParentDiv.removeChild(this.oSelect);
	this.oSelect = null;
};

function SelectRegion(id) {
	window.open('/region.php?id='+id, 'region', 'width=400,height=200');
};

// region selector
var RegionSelectorItem = function(parent,R) {
	this.Parent = parent;
	this.ID = R.i;
	this.Title = R.t;
	this.oOption = document.createElement('option');
	this.oOption.value = this.ID;
	iCMS.DOM.SetText(this.oOption, this.Title);
	this.Parent.appendChild(this.oOption);
	return this;
};
RegionSelectorItem.prototype.Free = function() {
	this.Parent.removeChild(this.oOption);
	this.oOption = null;
	this.Parent = null;
};

var RegionSelector = function(parent, item, parentDiv, onEnd, modulePath, langSelect, langLoad) {
	this.ModulePath = modulePath;
	this.Lang_SelectArea = langSelect;
	this.Lang_Loading = langLoad;
	this.Parent = parent;
	this.Level = 1 + (parent ? parent.Level : 0);
	this.Area = item ? item.ID : 0;
	this.ParentDiv = parentDiv;
	this.Child = null;
	this.OnEnd = onEnd;
	
	this.oSelect = document.createElement('select');
	this.oOptionDef = document.createElement('option');
	this.oOptionDef.value = 0;
	iCMS.DOM.SetText(this.oOptionDef, this.Lang_Loading);
	this.oSelect.appendChild(this.oOptionDef);
	if (this.Area) this.oSelect.style.display = 'none';
	this.ParentDiv.appendChild(this.oSelect);
	this.oSubDiv = document.createElement('div');
	this.ParentDiv.appendChild(this.oSubDiv);
	this.Items = {};
	
	var o = this;
	iCMS.Events.Add(this.oSelect, 'change', function(){ o.OnChange(); });
	
	iCMS.AJAX("POST", this.ModulePath + "/list", { id : this.Area.toString(), t : this.Level.toString() }, this.OnResponce, this);
	return this;
};
RegionSelector.prototype.GetID = function() {
	if (this.Child) return this.Child.GetID();
	var id, item;
	if ((id = this.oSelect.value) && (item = this.Items[id]) && item.oOption) return id;
	else return this.Area;
};
RegionSelector.prototype.GetItem = function() {
	var id, item;
	if (this.Child) item = this.Child.GetItem();
	if (!item && (id = this.oSelect.value)) item = this.Items[id];
	return item;
};
RegionSelector.prototype.OnChange = function() {
	if (this.Child) {
		this.Child.Free();
		this.Child = null;
	};
	var id, item;
	if ((id = this.oSelect.value) && (item = this.Items[id]) && item.oOption) {
		this.Child = new RegionSelector(this, item, this.oSubDiv, this.OnEnd, this.ModulePath, this.Lang_SelectArea, this.Lang_Loading);
	};
};
RegionSelector.prototype.OnResponce = function(items, o) {
	var id, L;
	if (items && (L = items.length)) {	// array or null
		for (var i = 0; i < L; i++) {
			id = items[i].i;
			this.Items[id] = new RegionSelectorItem(this.oSelect, items[i]);
		};
		iCMS.DOM.SetText(this.oOptionDef, this.Lang_SelectArea);
		this.oSelect.style.display = 'block';
	}
	else {
		if (this.Area) this.oSelect.style.display = 'none';
		if (this.OnEnd) this.OnEnd(this);
	};
};
RegionSelector.prototype.Free = function() {
	if (this.Child) {
		this.Child.Free();
		this.Child = null;
	};
	for (var id in this.Items) {
		this.Items[id].Free();
		this.Items[id] = null;
	};
	this.Items = null;
	this.ParentDiv.removeChild(this.oSubDiv);
	this.oSubDiv = null;
	this.oSelect.removeChild(this.oOptionDef);
	this.oOptionDef = null;
	this.ParentDiv.removeChild(this.oSelect);
	this.oSelect = null;
};

var CClickHint = function(id) {
	this.oDiv = ge(id);
	if (!this.oDiv) this.IsVisible = this.Show = this.Toggle = function(){};
	return this;
};
CClickHint.prototype.oDiv = null;
CClickHint.prototype.IsVisible = function() {
	return this.oDiv.style.display != 'none';
};
CClickHint.prototype.Show = function(b) {
	this.oDiv.style.display = b ? 'block' : 'none';
};
CClickHint.prototype.Toggle = function() {
	this.Show(!this.IsVisible());
};

var NumberFieldValidator = 
{
	Init : function() {
		var inp = document.getElementsByTagName('INPUT'), o, h;
		if (!inp) return;
		var c, s;
		for (var k = 0, N = inp.length; k < N; k++) {
			o = inp[k];
			if (!(s = o.type || o.getAttribute('type')) || s.toLowerCase() != 'text') continue;
			c = o.className;
			if (!c) continue;
			c = c.Trim().toLowerCase().Split( /\s+/ );
			if (c.Search('number') != -1 && !o._i_number) {
				var min = void 0, max = void 0, dec = void 0, typ = void 0, req = false, intr = false;
				for (var i = 0, L = c.length; (min == void 0 || max == void 0 || dec == void 0 || typ == void 0) && i < L; i++) {
					if (c[i] == 'interval') intr = true;
					s = c[i].SubStr(0, 4);
					if (s == 'max-') max = 0 + Number(c[i].SubStr(4));
					else if (s == 'min-') min = 0 + Number(c[i].SubStr(4));
					else if (s == 'dec-') dec = 0 + Number(c[i].SubStr(4));
					else if (s == 'typ-') typ = c[i].SubStr(4);
					else if (s == 'req') req = true;
				};
				if (min == void 0 || max == void 0) min = max = false;
				
				h = document.createElement('SPAN');
				h.className = 'number';
				
				if (intr) {
					for (intr = o.nextSibling; intr && (!intr.tagName || intr.tagName.toUpperCase() != 'INPUT'); intr = intr.nextSibling);
				};
				if (intr && intr.tagName && intr.tagName.toUpperCase() == 'INPUT') {
					iCMS.DOM.ClassAdd(intr, ['number', 'err']);
					intr._i_number = {required:req, type:typ, decimals:dec, min:min, max:max, hint:h, interval:o, from:false};
					this.DoValidate(intr);
					iCMS.Events.Add(intr, 'change', this.OnChange);
					iCMS.Events.Add(intr, 'keydown', this.OnChange);
					iCMS.Events.Add(intr, 'keypress', this.OnChange);
					iCMS.Events.Add(intr, 'keyup', this.OnChange);
					iCMS.Events.Add(intr, 'blur', this.OnBlur);
				};
				// iCMS.DOM.SetText(h, '');
				iCMS.DOM.InsertAfter(h, intr ? intr : o);
				
				o._i_number = {required:req, type:typ, decimals:dec, min:min, max:max, hint:h, interval:intr, from:true};
				this.DoValidate(o);
				iCMS.Events.Add(o, 'change', this.OnChange);
				iCMS.Events.Add(o, 'keydown', this.OnChange);
				iCMS.Events.Add(o, 'keypress', this.OnChange);
				iCMS.Events.Add(o, 'keyup', this.OnChange);
				iCMS.Events.Add(o, 'blur', this.OnBlur);
			};
		};
	},
	OnChange : function(e) {
		e = e || window.event;
		var obj = e.target ? e.target : e.srcElement, c;
		if (obj && (c = obj._i_number)) {
			NumberFieldValidator.DoValidate(obj);
		};
	},
	OnBlur : function(e) {
		e = e || window.event;
		var obj = e.target ? e.target : e.srcElement, c;
		if (obj && (c = obj._i_number)) {
			if (c.value != void 0) obj.value = c.value;
		};
	},
	DoValidate : function(obj) {
		var v = obj.value, error, n, c = obj._i_number;
		do {
			if (v == '' && !c.required) break;
			if (c.type == 'int') {
				if (! /^[-+]?\d+$/.test(v) ) {
					error = 'Введите целое число.';
					break;
				};
			}
			else if (c.type == 'float') {
				v = v.Replace(/,/, '.');
				var m = v.match(/^[-+]?\d+(?:[,\.](\d*))?$/);
				if (!m) {
					error = 'Введите число.';
					break;
				};
				if (m[1] && m[1].length > c.decimals) {
					error = 'Допустимы только ' + c.decimals + ' цифр после запятой.';
					break;
				};
			}
			else break;
			
			n = Number(v);
			if (c.min !== false && c.max !== false && (n < c.min || n > c.max)) {
				n = void 0;
				error = 'Число находится вне допустимого диапазона.';
				break;
			};
		} while (0);
		c.value = n;
		if (error) {
			c.error = error;
			iCMS.DOM.ClassAdd(obj, 'err');
			iCMS.DOM.SetText(c.hint, error);
			iCMS.DOM.ClassAdd(c.hint, 'err');
		}
		else {
			c.error = void 0;
			iCMS.DOM.ClassDel(obj, 'err');
			iCMS.DOM.SetText(c.hint, '');
			iCMS.DOM.ClassDel(c.hint, 'err');
		};
		
		if (c.interval && c.interval._i_number) {
			error = [];
			var f1, f2, c1, c2;
			f1 = f2 = obj;
			c1 = c2 = c;
			if (c.from) {
				c2 = c.interval._i_number;
				f2 = c.interval;
			}
			else {
				c1 = c.interval._i_number;
				f1 = c.interval;
			};
			if (c1.error != void 0) error.Push(c1.error);
			if (c2.error != void 0) error.Push(c2.error);
			if (!error.length) {
				var has1 = c1.value != void 0, has2 = c2.value != void 0;
				if (has1) {
					if (has2) {
						if (c1.value > c2.value) error.Push('Интервал задан неверно.');
					}
					else error.Push('Укажите второе число.');
				}
				else {
					if (has2) error.Push('Укажите первое число.');
					else {
						if (c1.required) error.Push('Укажите второе число.', 'Укажите первое число.');
					};
				};
			};
			if (error.length) {
				iCMS.DOM.SetText(c1.hint, error.join(' '));
				iCMS.DOM.ClassAdd(c1.hint, 'err');
			}
			else {
				iCMS.DOM.SetText(c1.hint, '');
				iCMS.DOM.ClassDel(c1.hint, 'err');
			};
		};
	}
};

/*
 * string title	Dialog title
 * bool   noClose	No close button
 * array  elems	Array of element-or-text
 * string elems	HTML code of all elements
 * string left	CSS left for dialog window
 * string top	CSS top for dialog window
 * string right	CSS right for dialog window
 * string bottom	CSS bottom for dialog window
 * string width	CSS width for dialog window
 * string height	CSS height for dialog window
 */
function iDialog(param) {
	if (param == void 0) return this;
	if (!param) param = {};
	this.Param = param;
	this.CreateBackground();
	
	var _T = this;
	
	// window
	this.oWindow = document.createElement('DIV');
	this.oWindow.className = 'idialog';
	this.oWindow.style.display = 'none';
	if (param.left != void 0) this.oWindow.style.left = param.left;
	if (param.top != void 0) this.oWindow.style.top = param.top;
	if (param.right != void 0) this.oWindow.style.right = param.right;
	if (param.bottom != void 0) this.oWindow.style.bottom = param.bottom;
	if (param.width != void 0) this.oWindow.style.width = param.width;
	if (param.height != void 0) this.oWindow.style.height = param.height;
	this.oWindow._iDialog = this;
	document.body.appendChild(this.oWindow);
	
	// title bar
	var t = document.createElement('DIV');
	t.className = 'title';
	if (!param.noClose) {
		// [X]
		var o = document.createElement('DIV');
		o.className = 'close';
		o.innerHTML = "&#215;";
		iCMS.Events.Add(o, 'click', function(){
			_T.Show(false);
		});
		t.appendChild(o);
	};
	// caption
	var o = document.createElement('SPAN');
	o.className = 'caption';
	if (param.title != void 0) iCMS.DOM.SetText(o, param.title);
	t.appendChild(o);
	this.oWindow.appendChild(t);
	
	// client area
	this.oClient = document.createElement('DIV');
	this.oClient.className = 'client';
	this.oWindow.appendChild(this.oClient);
	this.SetContent(param.elems);
};
iDialog.prototype.Background = null;
iDialog.prototype.CreateBackground = function() {
	if (!this.Background) {
		iDialog.prototype.Background = document.createElement('DIV');
		this.Background.className = 'idialog_back';
		iCMS.DOM.SetStyles(this.Background, {
			display : 'none',
			backgroundColor : '#fff',
			opacity : '0.5'
		});
		document.body.appendChild(this.Background);
	};
};
iDialog.prototype.ShowBackground = function(b) {
	if (b === void 0 || b === null) b = this.Background.style.display == 'none';
};
iDialog.prototype.Show = function(b) {
	if (b === void 0 || b === null) b = this.oWindow.style.display == 'none';
	this.oWindow.style.display = this.Background.style.display = b ? 'block' : 'none';
	return b;
};
iDialog.prototype.SetContent = function(elems) {
	if (elems) {
		if (elems instanceof Array) {
			for (var i = 0, L = elems.length; i < L; i++) {
				if (typeof elems[i] != typeof {}) {
					var o = document.createElement('DIV');
					iCMS.DOM.SetText(o, elems[i]);
					elems[i] = o;
				};
				this.oClient.appendChild(elems[i]);
			};
		}
		else if (typeof elems == typeof '') this.oClient.innerHTML = elems;
	};
};

var CClickHint = function(id) {
	this.oDiv = ge(id);
	if (!this.oDiv) this.IsVisible = this.Show = this.Toggle = function(){};
	return this;
};
CClickHint.prototype.oDiv = null;
CClickHint.prototype.IsVisible = function() {
	return this.oDiv.style.display != 'none';
};
CClickHint.prototype.Show = function(b) {
	this.oDiv.style.display = b ? 'block' : 'none';
};
CClickHint.prototype.Toggle = function() {
	this.Show(!this.IsVisible());
};
var SettingsBlock, LoginBlock;

var iCalendar =
{
	reDateTime : /^(\d{4})-(\d{1,2})-(\d{1,2})(?:\s+\d{1,2}:\d{1,2}(?::\d{1,2})?)?$/ ,
	Add : function(btn, tx, t, min, max) {
		if (!Calendar) return;
		// http://www.dynarch.com/projects/calendar/doc/
		var conf =
		{
			showTime : !!t,
			dateFormat : t ? '%Y-%m-%d %H:%M' : '%Y-%m-%d',
			onSelect : function(cal) { cal.hide(); },
			trigger : btn,
			inputField : tx
		};
		var m;
		if (typeof min == typeof '' && (m = min.match(this.reDateTime)) && +m[1] >= 1700 && +m[1] <= 9999 && +m[2] >= 1 && +m[2] <= 12 && +m[3] >= 1 && +m[3] <= 31) {
			conf.min = m[1] * 10000 + m[2] * 100 + m[3] * 1;
		}
		else {
			conf.min = 17000101;
		};
		if (typeof max == typeof '' && (m = max.match(this.reDateTime)) && +m[1] >= 1700 && +m[1] <= 9999 && +m[2] >= 1 && +m[2] <= 12 && +m[3] >= 1 && +m[3] <= 31) {
			conf.max = m[1] * 10000 + m[2] * 100 + m[3] * 1;
		}
		else {
			conf.max = 99991231;
		};
		Calendar.setup(conf);
	}
};

iCMS.Load(function(){
	NumberFieldValidator.Init();
	SettingsBlock = new CClickHint('settings_menu');
	LoginBlock = new CClickHint('login_form');
	
	// add Ctrl+Enter to comment form
	var t = ge('id_comment_teaxarea'), f;
	if (t) {
		// search form for posting a comment
		for (f = t; f && f.tagName.toUpperCase() != 'FORM'; f = f.parentNode);
		// if find valid form
		if (f && f.submit) {
			iCMS.Events.Add(t, 'keydown', function(e) {
				e = e || window.event;
				if (e.keyCode == 13 && e.ctrlKey) {
					f.submit();
				};
			});
		};
	};
});


