var elements; // (new SettignsElements()) присваивается в onBodyStart; SettignsElements объявляется на странице
var createdElements = {};

function HoverMenu(data) {
	// выпадающее меню
	var dublicate = this;
	var ul = data.ul;
	var hoverClass = data.hoverClass;
	var hoverWithULClass = "hover-with-ul";
	var stopEvent = data.stopEvent;
	var curNodes = [];
	var frames = [];
	
	this.init = function() {
		dom.addListener(ul, { mouseover: onMouseOver, mouseout: onMouseOut, mousedown: dom.stopEvent });
		dom.braceNL(ul);
		if (!dom.ie6 && !dom.ie7) {
			// подкладывать iframe под раскрывающийся список не потребуется
			createFrame = function() { return true; };
			removeFrame = function() { return true; };
			removeFrameLI = function() { return true; };
		} else {
			// а тут много чего требуется
			var subUl = dom.get(ul, "ul");
			var frames = [];
			for (var i=0, l=subUl.length, prev; i<l; i++) {
				// удаляем white-space между a и ul, иначе перед третьим уровнем меню появляется 3px бага (нет, zoom уже стоит)
				prev = subUl[i].previousSibling;
				subUl[i].style.zIndex = 1200 +l - i;
				dom.get(dom.ancestors(subUl[i]), "li")[0].style.zIndex = 1100 +l - i;
				if (/\s/.test(prev.nodeValue)) {
					prev.parentNode.removeChild(prev);
				}
				// создаем скрытый iframe для каждой ul, т.к. эта процедура подтормаживает
				frames.push(createFrame(subUl[i], true));
			}
			delete subUl;
		}
		if (dom.ie) {
			// при первом mousedown происходит mouseout...
			dom.addListener(ul, { mousedown: onMouseDown });
		}
		dom.addListener(window, {blur: dublicate.hide})
	};
	
	this.hide = function() {
		while(curNodes.length) {
			var li = curNodes.pop();
			if (li) hideLi(li, curNodes.length);
		}
	};
	
	this.show = function(li, level) {
		if (!li) return;
		if (curNodes[level] == li) return;
		if (curNodes[level]) {
			hideLi(curNodes[level], level);
			removeFrameLI(curNodes[level]);
			//frames[level] = null;
		}
		curNodes[level] = li;
		showLi(li, level);
		level++;
		while(curNodes[level]) {
			hideLi(curNodes[level], level);
			curNodes.splice( level -1, 1 );
		}
		/*
		//if (dom.ie) {
		//	var ul = dom.get(li, "ul")[0];
		//	if (ul) dom.zoomZoom(ul);
		//}
		*/
	};
	
	function hideLi(li, level) {
		if (!li) return;
		var childUl = dom.get(li, "ul")[0]
		removeFrameLI(li);
		//frames[level] = null;
		if (childUl) childUl.style.display = "none";
		dom.remClass(li, hoverClass);
		dom.remClass(li, hoverWithULClass);
		/*
		//if (childUl && dom.ie) {
		//	dom.zoomZoom(li);
		//}
		*/
	}
	
	function showLi(li, level) {
		if (!li) return;
		var childUl = dom.get(li, "ul")[0]
		if (childUl) {
			childUl.style.visibility = "hidden";
			childUl.style.display = "block";
			var maxX = dom.xy(ul)[0] + ul.offsetWidth;
			var x = dom.xy(childUl)[0] + childUl.offsetWidth;
			if (x>maxX) childUl.style.left = ( parseInt(childUl.style.left) || 0 ) - 1 - (x - maxX) +"px";
			childUl.style.visibility = "visible";
		}
		dom.addClass(li, hoverClass);
		if (childUl) {
			dom.addClass(li, hoverWithULClass);
			if (!childUl._HoverMenu_normalWidth) {
				// всем li'шкам надо выставить одинаковую ширину:
				// для ie6/7 - всегда
				// для ff2 - для последнего пункта меню, если он "вылазит" за меню
				var subLi = dom.get(childUl.childNodes, "li");
				/*if (subLi.length>1) {*/
					// конечно, если у нас хотя бы две li'шки
					var maxWidth = li.offsetWidth -1;
					for (var i=0, l=subLi.length; i<l; i++) {
						maxWidth = Math.max(maxWidth, subLi[i].offsetWidth);
					}
					for (i=0; i<l; i++) {
						subLi[i].style.width = maxWidth +"px";
					}
				/*}*/
				childUl._HoverMenu_normalWidth = true;
			}
			createFrame(childUl);
		}
	}
	
	function onMouseDown(evt) {
		// только ie6/7
		var evt = evt || window.event;
		var el = evt.target || evt.srcElement;
		var ancestors = [el].concat(dom.ancestors(el));
		var a = dom.get(ancestors, "a")[0];
		if (a) a.click(); // переходим на страничку
	}
	
	function onMouseOver(evt) {
		var evt = evt || window.event;
		var from = evt.fromElement || evt.relatedTarget;
		var to = evt.toElement || evt.target;
		onMouse(from, to);
	}
	
	function onMouseOut(evt) {
		var evt = evt || window.event;
		var from = evt.fromElement || evt.target;
		var to = evt.toElement || evt.relatedTarget;
		onMouse(from, to);
	}
	
	function onMouse(from, to) {
		if (!from || !to) return;
		var toAncestors = [to].concat(dom.ancestors(to));
		var toOutside = !dom.nodesetHasNode(toAncestors, ul); // мышь передвинута за пределы меню
		if (toOutside) {
			dublicate.hide();
		} else {
			var ancestorsLi = dom.get(toAncestors, "li");
			dublicate.show( ancestorsLi[0], ancestorsLi.length -1 );
		}
	}
	
	function createFrame(forUl, hidden) {
		// только для ie6/7
		var xy = dom.xy(forUl);
		var frame = forUl._HoverMenu_hasFrame || dom.cr("iframe", "substrate", false, {frameBorder: "0", scrolling: "no" });
		if (!forUl._HoverMenu_hasFrame) {
			frame.style.display = "none";
			if (true) {
				ul.parentNode.insertBefore(frame, ul);
			} else {
				forUl.parentNode.insertBefore(frame, forUl);
			}
			forUl._HoverMenu_hasFrame = frame;
		}
		if (!hidden) {
			frame.style.width = forUl.offsetWidth -1 +"px";
			frame.style.height = forUl.offsetHeight +"px";
			frame.style.left = xy[0]+1 +"px";
			frame.style.top = xy[1] +"px";
			forUl._HoverMenu_hasFrame.style.display = "block";
		}
		return forUl._HoverMenu_hasFrame;
	}
	
	function removeFrame(frame) {
		// только для ie6/7
		if (frame && frame.style) frame.style.display = "none";
	}
	
	function removeFrameLI(li) {
		// только для ie6/7
		var ul = dom.get(li, "ul")[0];
		if (ul) removeFrame(ul._HoverMenu_hasFrame);
	}
}

function CloseContent(data) {
	// внутри dl скрывает/показывает dt при нажатии на dd
	var dublicate = this;
	var dl = data.dl;
	var hoverClass = data.hoverClass;
	var openClass = data.openClass;
	
	this.init = function() {
		dom.addListener(dl, { mouseover: onMouseOver, mouseout: onMouseOut, click: onClick });
		/*
		for (var i=0, dd = dom.get(dl, "dd"), l=dd.length; i<l; i++) {
			if (!isOpenDD(dd[i])) dd[i].style.display = "none";
		}
		*/
		for (var i=0, dt = dom.get(dl, "dt"), l=dt.length; i<l; i++) {
			if (!isOpenDT(dt[i])) {
				dublicate.hide(dt[i]);
			} else {
				dublicate.show(dt[i]);
			}
		}
	};
	
	this.hide = function(dt) {
		dom.remClass(dt, openClass);
		var dd = getRelDD(dt);
		if (dd) dom.remClass(dd, openClass);
		dom.batSignal();
	};
	
	this.show = function(dt) {
		dom.addClass(dt, openClass);
		var dd = getRelDD(dt);
		if (dd) dom.addClass(dd, openClass);
		dom.batSignal();
	};

	function isOpenDT(dt) {
		return dom.hasClass(dt, openClass);
	}
	
	function isOpenDD(dd) {
		var dt = getRelDT(dd);
		return dom.hasClass(dt, openClass);
	}
	
	function getRelDT(dd) {
		var dt = dd;
		while(dt && (dt.tagName || "").toLowerCase() != "dt") {
			dt = dt.previousSibling;
			if (!dt || (dd.tagName || "").toLowerCase() == "dd") return null;
		}
		return dt || null;
	}
	
	function getRelDD(dt) {
		var dd = dt;
		while(dd && (dd.tagName || "").toLowerCase() != "dd") {
			dd = dd.nextSibling;
			if (!dd || (dd.tagName || "").toLowerCase() == "dt") return null;
		}
		return dd || null;
	}
	
	function hover(dt) {
		dom.addClass(dt, hoverClass);
		var dd = getRelDD(dt);
		if (dd) dom.addClass(dd, hoverClass);
	}
	
	function unhover(dt) {
		dom.remClass(dt, hoverClass);
		var dd = getRelDD(dt);
		if (dd) dom.remClass(dd, hoverClass);
	}
	
	function onMouseOver(evt) {
		var evt = evt || window.event;
		var from = evt.fromElement || evt.relatedTarget;
		var to = evt.toElement || evt.target;
		var fromDT = from ? dom.get([from].concat(dom.ancestors(from)), "dt")[0] : null;
		var toDT = to ? dom.get([to].concat(dom.ancestors(to)), "dt")[0] : null;
		if (fromDT!=toDT && toDT)
			hover(toDT)
	}
	
	function onMouseOut(evt) {
		var evt = evt || window.event;
		var from = evt.fromElement || evt.target;
		var to = evt.toElement || evt.relatedTarget;
		var fromDT = from ? dom.get([from].concat(dom.ancestors(from)), "dt")[0] : null;
		var toDT = to ? dom.get([to].concat(dom.ancestors(to)), "dt")[0] : null;
		if (fromDT!=toDT && fromDT)
			unhover(fromDT)
	}
	
	function onClick(evt) {
		var evt = evt || window.event;
		var to = evt.srcElement || evt.target;
		var toDT = dom.get([to].concat(dom.ancestors(to)), "dt")[0];
		if (toDT) {
			if (isOpenDT(toDT)) {
				dublicate.hide(toDT);
			} else {
				dublicate.show(toDT);
			}
		}
	}
}

function RealisedProjects(data) {
	// реализованные проэкты
	var dublicate = this;
	var container = data.container;
	var title = data.title;
	var groups = [];
	var curGroupIndex = null;
	var expandText = data.expandText || "Раскрыть все";
	var expandHeaderText = data.expandHeaderText || "Все объекты";
	var expandLink = null;
	var expandNode = null;
	
	this.init = function() {
		var ancs = container.getElementsByTagName("a");
		for (var i=0, l=ancs.length, parsedAnc; i<l; i++) {
			parsedAnc = parseAncer(ancs[i]);
			if (!parsedAnc) continue;
			groups.push( new Group( ancs[i], parsedAnc.content, parsedAnc.text ) );
		}
		if (groups.length) {
			for (var i=1, l=groups.length; i<l; i++) {
				groups[i].hide();
			}
			groups[0].show();
			curGroupIndex = 0;
		}
		dom.addListener(container, { click: onClick });
		
		expandLink = dom.cr("a", "expand-link", expandText);
		expandLink.onclick = dublicate.expand;
		//container.appendChild( expandLink );
	};
	
	this.expand = function() {
		if (expandNode) return;
		expandLink.style.visibility = "hidden";
		var node = dom.cr("div");
		for (var i=0, l=groups.length; i<l; i++) {
			node.appendChild( groups[i].cloneContent() );
		}
		for (var i=0, l=groups.length; i<l; i++) {
			groups[i].hide();
		}
		for (var i=0, ch=node.childNodes, cn, node_html, t=[]; cn=ch[i]; cn=ch[i++]) {
			node_html = cn.innerHTML;
			for (var i2=t.length; i2; i2--) {
				if (node_html==t[i2]) {
					node.removeChild(cn);
					i--;
					break;
				}
			}
			t.push(node_html);
		}
		title.innerHTML = expandHeaderText +": "+ node.childNodes.length +"";
		curGroupIndex = null;
		expandNode = title.parentNode.appendChild( dom.cr("div", groups[0].getContent().className +" expand-realised-objects", node) );
	};
	
	this.collapse = function() {
		if (!expandNode) return;
		expandLink.style.visibility = "visible";
		title.innerHTML = '';
		expandNode.parentNode.removeChild(expandNode);
		expandNode = null;
	};
	
	function parseAncer(anc) {
		var href = anc.href;
		if (!href) return;
		
		var id = href.substring( href.indexOf("#") +1 );
		var content = document.getElementById(id);
		if (!content) return;
		
		var img = anc.getElementsByTagName("img")[0];
		if (!img) return;
		var text = img.alt +"";
		
		return { content: content, text: text };
	}
	
	function onClick(evt) {
		var evt = evt || window.event;
		var el = evt.srcElement || evt.originalTarget;
		var anc = dom.get( [el].concat(dom.ancestors( el )), "a" )[0];
		if (!anc) return;
		var ind = getGroupIndexByAncer(anc);
		if (typeof(ind)!="number") return;
		if (ind!==curGroupIndex) {
			dublicate.collapse();
			if (typeof(curGroupIndex)=="number") groups[curGroupIndex].hide();
			groups[ind].show();
			curGroupIndex = ind;
			dom.zoomZoom(groups[ind].getContent())
		}
		return dom.stopEvent(evt);
	}
	
	function getGroupIndexByAncer(ancer) {
		for (var i=0, l=groups.length; i<l; i++) {
			if (groups[i].getAncer()==ancer) return i;
		}
	}
	
	function Group(link, content, text) {
		
		this.show = function() {
			dom.addClass(link, "cur");
			content.style.display = "";
			if (title) title.innerHTML = text.substring(0, 1).toUpperCase() + text.substring(1); // ie6 bug
		};
		
		this.hide = function() {
			dom.remClass(link, "cur");
			content.style.display = "none";
			if (title) title.innerHTML = "";
		};
		
		this.cloneContent = function() {
			// создать заголовок, раскрыть содержимое, убрать выделение пункта меню
			var ret = document.createDocumentFragment();
			// ret.appendChild( dom.cr("h2", "h", text) );
			for (var ch = content.childNodes, i=0, l=ch.length; i<l; i++) ret.appendChild( ch[i].cloneNode(true) );
			//var cont = content.cloneNode(true);
			//cont.style.display = "block";
			//ret.appendChild( cont );
			return ret;
		};
		
		this.getContent = function() {
			return content;
		};
		
		this.getAncer = function() {
			return link;
		};
	}
}

function LyteboxInPage(data) {
	// просмотр lytebox-фотографий не в отдельном а-ля pop'up диве, а "прямо на странице"
	var dublicate = this;
	var nodes = {
		container: data.node,
		bracing: null,
		img: null,
		prev: null,
		next: null,
		linksContainer: data.linksContainer
	}
	var defaultHeight = data.height;
	var text = {
		prev: data.prev,
		next: data.next
	};
	var lyteboxData = {
		instance: null,   // ссылка на myLytebox :)
		imageNum: null,   // номер активной каркинки
		lastImgNum: null, // нужен, чтобы отслеживать необходимость смены картинки
		imagesURL: [],    // массив URL'ов картинок
		hasNext: null,    // имеется след. картинка
		hasPrev: null,    // имеется пред. картинка
		ancNodes: []      // ссылки, которые будет обрабатывать LyteBox
	}
	
	this.init = function() {
		// создаем ноды
		nodes.container.innerHTML = "<div style='height: "+ defaultHeight +"px;'><img /><a href='#' class='prev'>"+ text.prev +"</a><a href='#' class='next'>"+ text.next +"</a></div>";
		nodes.bracing = nodes.container.getElementsByTagName("div")[0];
		nodes.img = nodes.container.getElementsByTagName("img")[0];
		nodes.img.onload = resizeImg;
		nodes.prev = nodes.container.getElementsByTagName("a")[0];
		nodes.next = nodes.container.getElementsByTagName("a")[1];
		
		// привешиваемся к переделанному LyteBox'у
		nodes.linksContainer.lyteboxOnFindAnc = dublicate.onLyteboxFindAncer;
		nodes.linksContainer.lyteboxBreak = dublicate.onLyteboxShowImg;
		nodes.linksContainer.lyteboxAfterInit = dublicate.onLyteboxInit;
		
		// вешаем onclick'и
		nodes.prev.onclick = function() {
			if (lyteboxData.hasPrev) {
				var anc = lyteboxData.ancNodes[lyteboxData.imageNum-1];
				lyteboxData.instance.start(anc, false, false);
			}
			return false;
		};
		nodes.next.onclick = function() {
			if (lyteboxData.hasNext) {
				var anc = lyteboxData.ancNodes[lyteboxData.imageNum+1];
				lyteboxData.instance.start(anc, false, false);
			}
			return false;
		};
	};
	
	function resizeImg() {
		var navHeight = Math.max(nodes.prev.offsetHeight, nodes.next.offsetHeight);
		var contentHeight = defaultHeight-navHeight;
		if (contentHeight>nodes.img.height) {
			nodes.img.style.top = (defaultHeight-Math.max(nodes.prev.offsetHeight, nodes.next.offsetHeight))/2 - nodes.img.height/2 +"px";
			nodes.bracing.style.height = defaultHeight+"px";
		} else {
			nodes.img.style.top = "0px";
			nodes.bracing.style.height = nodes.img.height + navHeight +"px";
		}
		nodes.img.style.left = Math.floor(nodes.bracing.offsetWidth/2 - nodes.img.width/2) +"px";
		dom.remClass(nodes.bracing, "load");
		dom.batSignal();
		
		var lightgreyBlock = dom.get(dom.ancestors( nodes.container ), "div", "lightgrey-block")[0];
		if (lightgreyBlock) {
			var h = dom.get(lightgreyBlock, "*", "h")[0];
			if (h) {
				dom.zoomZoom(h.parentNode);
			}
		}
	}
	
	this.onLyteboxFindAncer = function(anc, lytebox) {
		lyteboxData.instance = lytebox;
		for (var i=0, ancs = lyteboxData.ancNodes, l=ancs.length; i<l; i++) {
			if (anc==ancs[i]) break;
		}
		if (i==l) {
			lyteboxData.ancNodes.push(anc);
		}
	};
	
	this.onLyteboxShowImg = function(anc, lytebox) {
		var imageNum = lytebox.imageNum;
		var images = [];
		for (var i=0, l=lytebox.imageArray.length; i<l; i++) {
			images[i] = lytebox.imageArray[i][0];
		}
		lyteboxData.instance = lytebox;
		lyteboxData.imageNum = imageNum;
		lyteboxData.imagesURL = images;
		lyteboxData.hasNext = imageNum < images.length -1;
		lyteboxData.hasPrev = imageNum;
		
		if (lyteboxData.lastImgNum===lyteboxData.imageNum) return;
		
		nodes.img.src = lyteboxData.imagesURL[lyteboxData.imageNum];
		nodes.prev.style.display = lyteboxData.hasPrev ? "" : "none";
		nodes.next.style.display = lyteboxData.hasNext ? "" : "none";
		
		dom.addClass(nodes.bracing, "load");
		var lastAnc = lyteboxData.ancNodes[lyteboxData.lastImgNum];
		if (lastAnc) dom.remClass(lastAnc, "cur");
		var curAnc = lyteboxData.ancNodes[lyteboxData.imageNum];
		if (curAnc) dom.addClass(curAnc, "cur");
		lyteboxData.lastImgNum = lyteboxData.imageNum;
	};
	
	this.onLyteboxInit = function() {
		if (lyteboxData.ancNodes.length)
			lyteboxData.instance.start(lyteboxData.ancNodes[0], false, false);
	};
}

function HorizontalScroll(data) {
	var speed = dom.ie6 ? data.speed.ie6 : dom.ie7 ? data.speed.ie7 : data.speed.browser;
	var nodes = {
		container: data.container,
		content: data.content,
		prev: data.prev.normal,
		prevDisabled: data.prev.disabled,
		next: data.next.normal,
		nextDisabled: data.next.disabled
	};
	if (dom.ie8) {
		nodes.content.style.width = "10000px";
		nodes.content.style.left = "0px";
		nodes.content.style.top = "0px";
	}
	var checkButtonInAnimation = data.checkButtonInAnimation;
	var timer, step, needOffset;
	
	this.init = function() {
		var imgNodes = [nodes.prev, nodes.prevDisabled, nodes.next, nodes.nextDisabled];
		var nextNode = nodes.content.nextSibling;
		if (nextNode) {
			for (var i=0, l=imgNodes.length; i<l; i++) {
				nextNode.parentNode.insertBefore(imgNodes[i], nextNode)
			}
		} else {
			for (var i=imgNodes.length-1; i>-1; i--) {
				nodes.container.appendChild(imgNodes[i], nextNode)
			}
		}
		nodes.prev.onclick = prevPage;
		nodes.next.onclick = nextPage;
		nodes.prev.onmouseover = function() { dom.addClass(nodes.prev, "prev-hover"); };
		nodes.next.onmouseover = function() { dom.addClass(nodes.next, "next-hover"); };
		nodes.prev.onmouseout = function() { dom.remClass(nodes.prev, "prev-hover"); };
		nodes.next.onmouseout = function() { dom.remClass(nodes.next, "next-hover"); };
		if (dom.ie8) {
			nodes.next.style.position = nodes.nextDisabled.style.position = "absolute";
			nodes.next.style.right = nodes.nextDisabled.style.right = "10px";
			nodes.next.style.bottom = nodes.nextDisabled.style.bottom = "6px";
			nodes.prev.style.position = nodes.prevDisabled.style.position = "absolute";
			nodes.prev.style.left = nodes.prevDisabled.style.left = "3px";
			nodes.prev.style.bottom = nodes.prevDisabled.style.bottom = "3px";
		}
		checkPrevPage();
		checkNextPage();
	};
	
	this.prevPage = prevPage;
	this.nextPage = nextPage;
	this.hasPrevPage = hasPrevPage;
	this.hasNextPage = hasNextPage;
	
	function prevPage() {
		if (timer) return;
		var pageSize = nodes.container.offsetWidth;
		var curOffset = getCurOffset(); // <= 0
		needOffset = Math.min(0, curOffset + pageSize);
		if (Math.abs(needOffset) - Math.abs(curOffset) == 0) return;
		step = Math.floor(needOffset / speed[0]);
		timer = window.setInterval(addOffset, speed[1]);
	}
	
	function nextPage() {
		if (timer) return;
		var pageSize = nodes.container.offsetWidth;
		var curOffset = getCurOffset(); // <= 0
		var maxOffset = getMaxOffset(); // <= 0
		needOffset = Math.max(maxOffset, curOffset - pageSize);
		if (Math.abs(needOffset) - Math.abs(curOffset) == 0) return;
		step = Math.floor(needOffset / speed[0]);
		timer = window.setInterval(remOffset, speed[1]);
	}
	
	function remOffset() {
		var newOffset = Math.max(needOffset, getCurOffset() - speed[0]);
		nodes.content.style[ dom.ie8 ? "marginLeft" : "left" ] = newOffset +"px";
		if (checkButtonInAnimation) {
			checkPrevPage();
			checkNextPage();
		}
		if (needOffset==newOffset || !--step) stopTimer();
	}
	
	function addOffset() {
		var newOffset = Math.min(needOffset, getCurOffset() + speed[0]);
		// nodes.content.style.left = newOffset +"px";
		nodes.content.style[ dom.ie8 ? "marginLeft" : "left" ] = newOffset +"px";
		if (checkButtonInAnimation) {
			checkPrevPage();
			checkNextPage();
		}
		if (needOffset==newOffset || !--step) stopTimer();
	}
	
	function stopTimer() {
		nodes.content.style.left = needOffset +"px";
		window.clearInterval(timer);
		timer = false;
		checkPrevPage();
		checkNextPage();
	}
	
	function getCurOffset() {
		return dom.ie8 ? parseInt(nodes.content.style.marginLeft) : parseInt(nodes.content.style.left) || 0;
	}
	
	function getMaxOffset() {
		var lastChild = dom.get(nodes.content.childNodes, "*");
		lastChild = lastChild[lastChild.length-1];
		var abs = (lastChild.offsetLeft + lastChild.offsetWidth) - nodes.container.offsetWidth;
		if (dom.ie8) abs += Math.abs(getCurOffset());
		return abs * -1;
	}
	
	function hasPrevPage() {
		var pageSize = nodes.container.offsetWidth;
		var curOffset = getCurOffset(); // <= 0
		var n = Math.min(0, curOffset + pageSize);
		return Math.abs(n) - Math.abs(curOffset) != 0;
	}
	
	function hasNextPage() {
		var pageSize = nodes.container.offsetWidth;
		var curOffset = getCurOffset(); // <= 0
		var maxOffset = getMaxOffset(); // <= 0
		var n = Math.max(maxOffset, curOffset - pageSize);
		return n<=0 && Math.abs(n) - Math.abs(curOffset) != 0;
	}
	
	function checkPrevPage() {
		if (hasPrevPage()) {
			nodes.prev.style.display = "";
			nodes.prevDisabled.style.display = "none";
		} else {
			nodes.prevDisabled.style.display = "";
			nodes.prev.style.display = "none";
		}
	}

	function checkNextPage() {
		if (hasNextPage()) {
			nodes.next.style.display = "";
			nodes.nextDisabled.style.display = "none";
		} else {
			nodes.nextDisabled.style.display = "";
			nodes.next.style.display = "none";
		}
	}
}

function InputWithDefaultText(data) {
	var node = data[0];
	var text = data[1];
	var isPass = data[2];
	
	this.init = function() {
		check();
		node.onfocus = remDefaultValue;
		node.onblur = check;
	};
	
	function check() {
		if (badValue()) { setDefaultValue(); }
	}
	
	function setDefaultValue() {
		dom.addClass(node, "defaultText");
		node.value = text;
		try {
			if (isPass) node.type = "text";
		} catch(er) { }
	}

	function remDefaultValue() {
		dom.remClass(node, "defaultText");
		if (badValue()) node.value = "";
		try {
			if (isPass) node.type = "password";
		} catch(er) { }
	}
	
	function badValue() {
		return node.value=="" || node.value==text;
	}
}

var dom = {
	ie: navigator.userAgent.indexOf("MSIE") > -1,
	ie6: navigator.userAgent.indexOf("MSIE 6") > -1,
	ie7: navigator.userAgent.indexOf("MSIE 7") > -1,
	ie8: navigator.userAgent.indexOf("MSIE 8") > -1,
	opera: navigator.userAgent.indexOf("Opera") > -1,
	fox: navigator.userAgent.indexOf("Firefox") > -1,
	scrollSpeedInPage: .8,
	get: function(parent, tagName, className, attrHash) {
		// parent - родитель, или массивHTML-элементов или нодесет 
		// tagName - строка
		// className - строка или массив
		// attrHash - объект { name: value }
		var tags, ret;
		if (parent.length) {
			ret = dom.nodesetToArray(parent);
			if (tagName=="*") {
				for (var i=0, l=ret.length, r, ok; i<l; i++) {
					if ( ret[i].nodeType!=1 ) {
						ret.splice(i, 1);
						i--;
						l--;
					}
				}
			} else {
				for (var i=0, l=ret.length, r, ok; i<l; i++) {
					if ( (ret[i].tagName || "").toLowerCase() != tagName.toLowerCase() ) {
						ret.splice(i, 1);
						i--;
						l--;
					}
				}
			}
		} else if (parent.constructor==Array) {
			return [];
		} else {
			ret = dom.nodesetToArray( parent.getElementsByTagName( tagName ) );
		}
		if (className) {
			for (var i=0, l=ret.length, r, ok; i<l; i++) {
				r = ret[i];
				ok = true;
				if (className.constructor == Array) {
					for (var i2=0, l2=className.length, c; ok, i2<l2; i2++) {
						c = className[i2];
						ok = true;
						if ( !dom.hasClass( r, c ) ) ok = false;
					}
				} else if (className) {
					if ( !dom.hasClass( r, className ) ) ok = false;
				}
				if (!ok) {
					ret.splice(i, 1);
					i--;
					l--;
				}
			}
		}
		if (attrHash) {
			for (var i=0, l=ret.length, r, ok; i<l; i++) {
				r = ret[i];
				ok = true;
				for (var attrName in attrHash) {
					if ( !dom.hasAttr(r, attrName, attrHash[attrName]) ) ok = false;
				}
				if (!ok) {
					ret.splice(i, 1);
					i--;
					l--;
				}
			}
		}
		return ret || [];
	},
	precedingSiblings: function(node) {
		var ret = [];
		var cur = node;
		while(cur.previousSibling) ret.push(cur = cur.previousSibling);
		return ret;
	},
	followingSiblings: function(node) {
		var ret = [];
		var cur = node;
		while(cur.nextSibling) ret.push(cur = cur.nextSibling);
		return ret.reverse();
	},
	ancestors: function(node) {
		var ret = [];
		while(node = node.parentNode)
         if (node.nodeType == 1) ret.push(node);
		return ret;
	},
	descendants: function(node, nodeType) {
		var ret = [];
		f(ret, node.firstChild);
		if (typeof(nodeType)=="number") {
			var ret2 = [];
			for (var i=0, l=ret.length; i<l; i++) {
				if (ret[i].nodeType == nodeType) ret2.push(ret[i]);
			}
			return ret2;
		} else {
			return ret;
		}
	 
		function f(arr, cur) {
			arr.push(cur);
			if (cur.firstChild) f(arr, cur.firstChild);
			if (cur.nextSibling) f(arr, cur.nextSibling);
		}
	},
	cr: function(tagName, className, inside, attrHash, propHash, listenersHash) {
		var ret = document.createElement( tagName );
		if (className) ret.className = className;
		if (inside) {
			if ( typeof(inside)=="string" ) {
				ret.innerHTML = inside;
			} else if (inside.constructor == Array) {
				for (var i=0, l=inside.length; i<l; i++) {
					if (inside[i].nodeType) ret.appendChild(inside[i]);
				}
			} else if (inside.nodeType) {
				ret.appendChild(inside);
			}
		}
		if (attrHash) {
			for (var name in attrHash) ret.setAttribute(name, attrHash[name]);
		}
		if (propHash) {
			for (var name in propHash) ret[name] = propHash[name];
		}
		if (listenersHash) {
			dom.addListener(ret, listenersHash);
		}
		return ret;
	},
	rem: function(node) {
		return node.parentNode.removeChild( node );
	},
	clear: function(node) {
		while(node.firstChild) node.removeChild(node.firstChild);
		return node;
	},
	text: function(node) {
		return String(node.textContent || node.innerText);
	},
	nodesetToArray: function(nodeset) {
		var ret = [];
		for (var i=0, l=nodeset.length, r, ok; i<l; i++) {
			ret[i] = nodeset[i];
		};
		return ret;
	},
	nodesetHasNode: function(nodeset, node) {
		for (var i=0, l=nodeset.length, r, ok; i<l; i++) {
			if (node == nodeset[i]) return true;
		};
		return false;
	},
	hasClass: function(node, need) {
		return (new RegExp("(^|\\s)"+ (need || "").toLowerCase().replace(/\-/g, "\\-") +"(\\s|$)")).test( (node.className || "").toLowerCase() );
	},
	hasAttr: function(node, name, need) {
		return (new RegExp("(^|\\s)"+ need +"(\\s|$)")).test( node.getAttribute(name) );
	},
	addClass: function(node, name) {
		if (!dom.hasClass(node, name)) node.className += " " + name;
		return node;
	},
	remClass: function(node, name) {
		node.className = node.className.replace( new RegExp("(^|\\s)"+ name +"(\\s|$)"), " ");
		return node;
	},
	style: function(node, styleName, toInt) {
		if ( !document.defaultView && styleName.indexOf("-")>-1) {
			styleName = styleName.replace(/-top/, "Top");
			styleName = styleName.replace(/-right/, "Right");
			styleName = styleName.replace(/-bottom/, "Bottom");
			styleName = styleName.replace(/-left/, "Left");
		}
		var ret = document.defaultView 
			? document.defaultView.getComputedStyle(node, null).getPropertyValue(styleName)
			: node.runtimeStyle[styleName] || node.style[styleName] || node.currentStyle[styleName];
		if (toInt) ret = parseInt(ret);
		return ret;
	},
	xy: function(node) {
		var x = 0, y = 0;
		while(node.offsetParent) {
			x += node.offsetLeft;
			y += node.offsetTop;
			node = node.offsetParent;
		}
		return [x, y];
	},
	whStyle: function(node, toggleVisibility) {
		if (toggleVisibility) {
			node.style.visibility = "hidden";
			node.style.display = "block";
		}
		if (dom.opera) {
			var ret = ret = [ parseInt(dom.style(node, "width")), parseInt(dom.style(node, "height"))];
			ret[0] -= dom.style(node, "border-left", 1) + dom.style(node, "padding-left", 1) + dom.style(node, "padding-right", 1) + dom.style(node, "border-right", 1);
			ret[1] -= dom.style(node, "border-top", 1) + dom.style(node, "padding-top", 1) + dom.style(node, "padding-bottom", 1) + dom.style(node, "border-bottom", 1);
		} else {
			var ret = [ parseInt(dom.style(node, "width")), parseInt(dom.style(node, "height"))];
		}
		if (toggleVisibility) {
			node.style.display = "none";
			node.style.visibility = "visible";
		}
		return ret;
	},
	addListener: function(node, listeners) {
		if (node==="body") node = document.getElementsByTagName("body")[0];
		if (node.addEventListener) {
			for (var name in listeners) {
				node.addEventListener(name, listeners[name], false);
			}
		} else {
			for (var name in listeners) {
				node.attachEvent("on"+ name, listeners[name]);
			}
		}
	},
	remListener: function(node, listeners) {
		if (node==="body") node = document.getElementsByTagName("body")[0];
		if (node.addEventListener) {
			for (var name in listeners) {
				try {
					node.removeEventListener(name, listeners[name], false);
				} catch(er) { ; }
			}
		} else {
			for (var name in listeners) {
				try {
					node.detachEvent("on"+ name, listeners[name]);
				} catch(er) { ; }
			}
		}
	},
	stopEvent: function(evt) {
		var evt = evt || window.event;
		if (evt.stopPropogandation) evt.stopPropogandation();
		if (evt.preventDefault) evt.preventDefault();
		evt.returnValue = false;
		evt.cancelBubble = true;
		return false;
	},
	braceNL: function(ul) {
		var ul = ul || document.getElementById("nl");
		var li = dom.get(ul.childNodes, "li");
		var count = li.length;// li.length -1;
		var lastLi = li[li.length-1];
		if (lastLi.offsetTop != li[0].offsetTop) return; // меню на двух строках
		var x1 = lastLi.offsetLeft + lastLi.offsetWidth;
		var x2 = ul.offsetWidth;
		var d = x2 - x1;
		if (d>0) {
			var dItem = Math.floor(d / count);
			var dItemHalf = Math.floor((d / count) /2);
			for (var i=0, pl, pr; i<count-1; i++) {
				li[i].style.paddingLeft = dom.style(li[i], "padding-left", true) + dItemHalf +"px";
				li[i].style.paddingRight = dom.style(li[i], "padding-right", true) + dItemHalf +"px";
			}
			if (lastLi.offsetTop != li[0].offsetTop) return; // меню на двух строках
			x1 = lastLi.offsetLeft + lastLi.offsetWidth;
			x2 = ul.offsetWidth;
			d = x2 - x1;
			if (d) {
				lastLi.style.paddingLeft = (parseInt(lastLi.style.paddingLeft) || 0) + d - (dom.fox || dom.ie8 ? 1 : 0 ) +"px";
			}
		}
		if (dom.fox) {
			ul.style.display = "none";
			ul.style.display = "block";
		}
	},
	batSignal: function(allBrowsers) {
		if (!allBrowsers && !dom.ie) return;
		var bordersFor = [
			document.getElementById("footer"), // Robin
			document.getElementsByTagName("body")[0] // batmobile
		];
		// Batman ahead
		for (var i=0, l=bordersFor.length; i<l; i++) {
			// Batman fights
			if (!bordersFor[i]) continue;
			bordersFor[i].style.paddingBottom = "1px";
			bordersFor[i].style.paddingBottom = "0px";
		}
		// Batman wins
	},
	zoomZoom: function(node) {
		if (!dom.ie) return;
		for (var c=node.childNodes, i=0, l=c.length; i<l; i++) {
			node.style.zoom = "101%";
		}
		for (var c=node.childNodes, i=0, l=c.length; i<l; i++) {
			node.style.zoom = "100%";
		}
	},
	mediaIs: function(type) {
		// смотрим устройство воспроизведения страницы, не вызывать до открытия тэга body
		if (!type && !dom.media) {
			dom.media = {
				print: dom.mediaIs("print"),
				screen: dom.mediaIs("screen")
			}
		}
		var selector = "#checkMediaType";
		var rule = "display: none";
		var text = selector +" { "+ rule +" } ";
		var props = {type: "text/css", rel: "stylesheet", media: type};
		var style, style2;
		if (dom.ie6 || dom.ie7) {
			style = document.createStyleSheet();
			style.media = type;
			style.cssText = text;
		} else {
			style = dom.cr("style", false, false, props, props);
			style.media = type;
			document.getElementsByTagName("head")[0].appendChild(style);
			if (dom.ie) {
				// ie8
				style2 = document.styleSheets[document.styleSheets.length-1];
				style2.cssText = text;
			} else {
				style.appendChild( document.createTextNode( text ) );
			}
		}
		var node = dom.cr("div", false, " ", {id: "checkMediaType"});
		document.getElementsByTagName("body")[0].appendChild(node);
		// document.getElementById("ro-01").appendChild(node);
		var ret = dom.style( node, "display" ) == "none";
		node.parentNode.removeChild(node);
		try {
			style2.disabled = true;
		} catch(er) {}
		try {
			style.parentNode.removeChild(style);
		} catch(er) {}
		try {
			style2.parentNode.removeChild(style2);
		} catch(er) {}
		return ret;
	}
};

/* defer */
// 0. onBodyStart вызывается инлайновым скриптом или из onDOMContentLoaded
// 1. document.readyState > (timer/native) 
// 2. onDOMContentLoaded > (timer) 
// 4. pageInit
// 5. afterPageLoaded (if exist)

function onBodyStart() {
	// вызывается инлайновым скриптом со страницы, когда открывается body или чуть позже
	dom.mediaIs();
	if (dom.media.print) return;
	elements = new SettignsElements();
	var body = document.getElementsByTagName("body")[0];
	body.className = (body.className || "") +" js"; // добавляем к body в класс " js"
	dom.braceNL();
}


function pageInit() {
	if (dom.media.print) return;
	checkElements();
	
	try {
		if (typeof(afterPageLoaded)=="function") afterPageLoaded();
	} catch(er) { }
	try {
		if (typeof(initLytebox)=="function") initLytebox();
		var e = createdElements["lyteboxInPage"];
		if (e) {
			for (var i=0, l=e.length; i<l; i++) {
				e[i].onLyteboxInit();
			}
		}
	} catch(er) { }
}

function onDOMContentLoaded(root) {
	// верстка загружена
	onBodyStart(); // могла не вызваться из HTML 
	pageInit();
}

function checkElements(root) {
	if (dom.media.print) return;
	var ret = {}, count = 0;
	var nodes = (root && root.getElementsByTagName ? root : document).getElementsByTagName("*");
	
	// создаем элементы
	for (var name in elements) {
		element = elements[name];
		ret[name] = [];
		for (var i=0, l=nodes.length, node, tagName, element, check; i<l; i++) {
			node = nodes[i];
			tagName = node.tagName.toLowerCase();
			if (element.tag == tagName) {
				check = element.checkNode(node);
				if (check && typeof(element.c)=="function") {
					ret[name].push( new element.c(check) );
				}
			}
		}
		if ( !ret[name].length ) delete ret[name];
	}
	
	// запускаем .init на каждом элементе
	for (var name in ret) {
		for (var i=0, l=ret[name].length; i<l; i++) {
				ret[name][i].init();
		}
	}

	// сохраняем результат
	if (typeof(createdElements)!="undefined") {
		for (var i in ret) {
			if (!createdElements[i]) createdElements[i] = [];
			createdElements[i] = createdElements[i].concat(ret[i]);
		}
	}
	
	return ret;
}

if (typeof(document.readyState)!="undefined") {
	var _timer = setInterval(function() {
		if (/loaded|complete/.test(document.readyState)) {
			clearInterval(_timer);
			delete _timer;
			onDOMContentLoaded();
		}
	}, 10);
} else if (window.addEventListener) {
    window.addEventListener('DOMContentLoaded', onDOMContentLoaded, false);
} else {
	onDOMContentLoaded();
}

/* / defer */

// запрещаем ие6 перезагружать фоновые картинки при a:hover
try{ if (typeof(document.execCommand && !window.XMLHttpRequest)!="undefined") document.execCommand("BackgroundImageCache", false, true) }
catch(er) { }