function Carousel(node) {
	// настройки:
	var animLength = 576; // продолжительность анимации, ms
	// ноды:
	var overflow = getByClassName("overflow"), 
		container = getByClassName("container"), 
		prev = getByClassName("prev"), 
		next = getByClassName("next"),
		pager = document.getElementById("pager");
	var pages = pager.getElementsByTagName("a");

	// состояние:
	var animating = false;
	var hover = [];
	var currentPage = 1;
	
	prev.onclick = prevPage;
	next.onclick = nextPage;
	
	for (var i = 0; i < pages.length; i++) {
		pages[i].onclick = pageByNumber;
	}

	
	updateButtonsVisibility();
	
	
	function prevPage() { page(-1); return false; }
	function nextPage() { page(1); return false; }

	function pageByNumber() {
		p = parseInt(this.innerHTML);
		page(p - currentPage);
	}
		
	function page(shift) {
		// перематать страницу
		if (animating) return;
		//var shift = shift || 1;
		var points = getPoints();
		
		var needLeft = Math.min(points.maxLeft, Math.max(0, points.curLeft + points.viewPort * shift));
		if (needLeft===points.curLeft) return;

		currentPage += shift;
		var pages = pager.getElementsByTagName("a");
		for (var i = 0; i < pages.length; i++) {
			pages[i].className = (i == currentPage - 1 ? 'active' : '');
		}
		
		anim(container, points.curLeft, needLeft);
	}
	
	function updateButtonsVisibility() {
		// скрыть или показать кнопки prev/next в зависимоти от степени прокрутки
		var points = getPoints();
		prev.style.display = points.curLeft==0 ? "none" : "block";
		next.style.display = points.maxLeft==points.curLeft ? "none" : "block";
	}
	
	function getPoints() {
		// получение данных по габаритам элементов
		var viewPort = overflow.offsetWidth + 3;
		var curLeft = Math.abs(parseInt(container.style.left) || 0);
		
		var lastNode = container.getElementsByTagName("div");
			lastNode = lastNode[lastNode.length -4];
		var maxLeft = lastNode.offsetLeft + lastNode.offsetWidth - viewPort;
		
		return {
			viewPort: viewPort, // видимая часть
			curLeft: curLeft, // текущий сдвиг 0+
			maxLeft: maxLeft // максимальный сдвиг 0+
		};
	}
	
	function anim(node, val1, val2) {
		// запуск анимации сдвига от val1 до val2 - оба положительные, "-" и "px" добавятся сами
		if (animating) return;
		animating = true;
		
		var steps = Math.round(Math.abs(Math.max(val1, val2), Math.min(val1, val2)) / 2);
		var values = interpolate(val1, val2, steps);
		var stepCost = animLength / steps; // кол-во ms, отводимое для показа одного кадра
		var startAt = Number(new Date()); // время начала анимации
		var timer = window.setInterval(iter, 1);
		var curStep = -1;
		
		function iter() {
			var newStep = Math.round((Number(new Date()) - startAt) / stepCost); // номер текущего шага
			if (newStep>curStep) {
				if (newStep>steps) {
					node.style.left = values[steps];
					afterAnim();
				} else {
					node.style.left = values[newStep];
				}
				curStep = newStep;
			}
		}
		
		function afterAnim() {
			// вызывается по завершению анимации
			window.clearInterval(timer);
			timer = null;
			animating = false;
			updateButtonsVisibility();
		}
		
		function interpolate(from, to, steps) {
			// (1, 3, 4) > [1, 1.66, 2.32, 3] > ["1px", "2px", "2px", "3px"]
			var ret = [ "-"+ Math.round(from) +"px" ];
			var d = (to - from) / steps;
			for (var i=0, l=steps-1; i<l; ++i) {
				ret.push( "-"+ Math.round(from +d*i) +"px" ); // ["1px", "2px", "2px", "3px"]
			}
			ret.push( "-"+ Math.round(to) +"px" );
			return ret;
		}
	}
	
	function getByClassName(className) {
		// получение первой ноды с нужным классом
		for (var ar=node.getElementsByTagName("*"), i=0, l=ar.length, reg = new RegExp("(^|\\s)"+ className +"(\\s|$)"); i<l; i++) {
			if (reg.test(ar[i].className || "")) return ar[i];
		}
	}

}
