///////Скроллер////////
var scrollers=new Array(); //Массив всех скроллеров
var bodyMouseUp=function(){}; //функция body.onmouseup
var bodyMouseOut=function(){}; //функция body.onmouseout
var bodyMouseMove=function(){}; //функция body.onmousedown
var bodyLoad=function(){}; //функция body.onload
var windowResize=function(){}; //функция body.onresize
//Создание скроллера
function createScroller(scrollerName)
{
	scrollers[scrollerName]=new contentScroller(scrollerName);
}
contentScroller=function(objName)
{
	//Переменные DOM
	this.scrollObject; //Блок с контентом
	this.scrollerButtonNegative; // Кнопка "влево" или "вверх", 
	this.scrollerButtonPositive; // Кнопка "вправо" или "вниз", 
	this.scrollerThumb; // Ползунок
	//Переменные объекта body и window (функции)
	//Общие переменные скроллинга
	this.scrollOrd="Y"; // Направление скроллирования ("x" или "y"). К регистру нечувствительно.
	var scrollRatio=1; // Соотношение видимой и невидимой области скроллируемого блока
	var thumbRatio=1;
	this.hideBar=true; // 
	this.scrollTime=50; // Таймаут скроллинга(в мс)
	this.scrollStep=15; // Шаг скроллера
	this.scrollMode=false;
	this.scrollButtonEvent="mousedown"; // Тип скроллинга. Варианты: "mousedown", "mousemove", "click"
	this.scrollerThumbMarg=0; // 
	//Переменные drag'n'drop
	this.inDragin=false;
	this.mousePos=null;
	//Переменные для колёсика мыши
	this.scrollWheel=true; // Применение колёсика мыши
	this.wheelStep=3; // количество шагов скроллинга на шаг колёсика мыши
	this.wheelMax=3; // Максимаьный холостой ход колёсика
	var wheelCount=0;
	//Переменные ошибок
	this.errors=new Array(); // массив ошибок
	this.errorHandler="alert"; // обработчик ошибок
	
	//Инициализация скроллера
	this.initScroller=function(scrollObject,scrollerButtonPositive,scrollerButtonNegative,scrollerThumb)
	{
		try
		{
			var ord,ordNegative,item,thumbPlace;
			var startEvent=null, extStartEvent=null, stopEvent=null,eventTout=true;
			this.scrollObject=document.getElementById(scrollObject);
			if(!this.scrollObject) return false;
			this.scrollerButtonPositive=document.getElementById(scrollerButtonPositive);
			this.scrollerButtonNegative=document.getElementById(scrollerButtonNegative);
			this.scrollerThumb=document.getElementById(scrollerThumb);
			if(this.scrollerThumb) thumbPlace=this.scrollerThumb.parentNode;
			else
			{
				if(this.scrollerButtonPositive) thumbPlace=this.scrollerButtonPositive.parentNode;
				else if(this.scrollerButtonNegative) thumbPlace=this.scrollerButtonNegative.parentNode
			}
			switch(this.scrollOrd.toLowerCase())
			{
				case 'x':
					ord="Left";
					ordNegative="right";
					item="Width";
				break;
				case 'y':
					ord="Top";
					ordNegative="bottom";
					item="Height";
				break;
			}
			scrollRatio=(this.scrollObject['scroll'+item]!=0)?this.scrollObject['client'+item]/this.scrollObject['scroll'+item]:1;
			if(scrollRatio>=1)
			{
				if(this.hideBar && thumbPlace) thumbPlace.style.visibility='hidden';
				scrollRatio=1;
			}
			else
			{
				if(this.hideBar && thumbPlace) thumbPlace.style.visibility='visible';
			}
			switch(this.scrollButtonEvent)
			{
				case 'mousedown':
					startEvent="mousedown";
					stopEvent="mouseup";
				break;
				case 'mousemove':
					startEvent="mousemove";
					extStartEvent="mouseover";
					stopEvent="mouseup";
				break;
				case 'click':
					startEvent="click";
					eventTout=false;
				break;
				default:
					startEvent="mousedown";
					stopEvent="mouseup";
				break;
			}
				if(this.scrollerButtonPositive && startEvent) this.scrollerButtonPositive['on'+startEvent]=function()
				{
					scrollers[objName].scrollContent(true,ord.toLowerCase(),eventTout);
				}
				if(this.scrollerButtonPositive && extStartEvent) this.scrollerButtonPositive['on'+extStartEvent]=function()
				{
					scrollers[objName].scrollContent(true,ord.toLowerCase(),eventTout);
				}
				if(this.scrollerButtonPositive && stopEvent) this.scrollerButtonPositive['on'+stopEvent]=function()
				{
					scrollers[objName].scrollContent(false);
				}
				if(this.scrollerButtonNegative && startEvent) this.scrollerButtonNegative['on'+startEvent]=function()
				{
					scrollers[objName].scrollContent(true,ordNegative.toLowerCase(),eventTout);
				}
				if(this.scrollerButtonNegative && extStartEvent) this.scrollerButtonNegative['on'+extStartEvent]=function()
				{
					scrollers[objName].scrollContent(true,ordNegative.toLowerCase(),eventTout);
				}
				if(this.scrollerButtonNegative && stopEvent) this.scrollerButtonNegative['on'+stopEvent]=function()
				{
					scrollers[objName].scrollContent(false);
				}
			if(this.scrollerThumb)
			{
				this.scrollerThumb.onmouseout=function(){return true;}
				this.scrollerThumb.onmousemove=function(event)
				{
					scrollers[objName].startDrag(event);
					return false;
				}
				this.scrollerThumb.onmouseup=function()
				{
					scrollers[objName].inDragin=false;
					scrollers[objName].mousePos=null;
					return false;
				}
				this.scrollerThumb.onmousedown=function()
				{
					scrollers[objName].inDragin=true;
					return false;
				}
				document.body.onmouseup=function()
				{
					bodyMouseUp();
					for(i in scrollers)
					{
						scrollers[i].inDragin=false;
						scrollers[i].mousePos=null;
					}
					return false;
				}
				
				document.body.onmousemove=function(event)
				{
					var ret=true;
					bodyMouseMove();
					for(i in scrollers)
					{
						scrollers[i].startDrag(event);
						if(ret) ret=!scrollers[i].inDragin;
					}
					return ret;
				}
				
				window.onload=function(event)
				{
					bodyLoad();
					for(i in scrollers)
					{
						scrollers[i].recheckScroller();
						
					}
				}
				
				window.onresize=function()
				{
					windowResize();
					for(i in scrollers)
					{
						scrollers[i].recheckScroller();
					}
				}
				if (thumbPlace.addEventListener)
	 			{
	 				thumbPlace.addEventListener('DOMMouseScroll',scrollers[objName].wheel, false);
	 			}
	 			thumbPlace.onmousewheel =function(event){scrollers[objName].wheel(event)};
			}
			
			if(this.scrollWheel)
			{
				if (this.scrollObject.addEventListener)
	 			{
	 				this.scrollObject.addEventListener('DOMMouseScroll',scrollers[objName].wheel, false);
	 			}
	 			this.scrollObject.onmousewheel =function(event){scrollers[objName].wheel(event)};
 			}
			if(this.scrollerThumb)
			{
				thumbRatio=this.scrollerThumb.parentNode['client'+item]/this.scrollObject['scroll'+item];
				this.scrollerThumb.style[ord.toLowerCase()]=thumbRatio*this.scrollObject['scroll'+ord]+"px";
				tH=Math.round(scrollRatio*this.scrollerThumb.parentNode['client'+item])-this.scrollerThumbMarg;
				this.scrollerThumb.style[item.toLowerCase()]=(tH>0)?tH+"px":"40px";
			}
		}
		catch(e){ this.setError(prepareException(e));}
	}
	this.recheckScroller=function()
	{
		try
		{
			var ord,ordNegative,item;
			var thumbPlace;
			if(this.scrollerThumb) thumbPlace=this.scrollerThumb.parentNode;
			switch(this.scrollOrd.toLowerCase())
			{
				case 'x':
					ord="Left";
					ordNegative="right";
					item="Width";
				break;
				case 'y':
					ord="Top";
					ordNegative="bottom";
					item="Height";
				break;
			}
			if(this.scrollObject['scroll'+ord]+this.scrollObject['client'+item]>this.scrollObject['scroll'+item]) this.scrollObject['scroll'+ord]=this.scrollObject['scroll'+item]-this.scrollObject['client'+item];
			scrollRatio=(this.scrollObject['scroll'+item]!=0)?this.scrollObject['client'+item]/this.scrollObject['scroll'+item]:1;
			if(this.scrollerThumb) thumbRatio=this.scrollerThumb.parentNode['client'+item]/this.scrollObject['scroll'+item];
			if(scrollRatio>=1)
			{
				if(this.hideBar && this.scrollerThumb) thumbPlace.style.visibility='hidden';
				scrollRatio=1;
			}
			else
			{
				if(this.hideBar && this.scrollerThumb){ thumbPlace.style.visibility='visible';}
			}
			if(this.scrollerThumb)
			{
				thumbRatio=this.scrollerThumb.parentNode['client'+item]/this.scrollObject['scroll'+item];
				this.scrollerThumb.style[ord.toLowerCase()]=thumbRatio*this.scrollObject['scroll'+ord]+"px";
				tH=Math.round(scrollRatio*this.scrollerThumb.parentNode['client'+item])-this.scrollerThumbMarg;
				this.scrollerThumb.style[item.toLowerCase()]=(tH>0)?tH+"px":"40px";
			}
		}
		catch(e){ this.setError(prepareException(e));}
	}
	//Основная функция скроллинга блока. Переменные mode(bool) - скроллить или нет, dest(string) - направление скроллинга, tOut(bool) - рекурсивность с таймаутом, step(float) - шаг скроллига(по умолчанию берётся из переменной this.scrollStep)
	this.scrollContent=function(mode,dest,tOut,step)
	{
		try
		{
			if(step==null) step=this.scrollStep;
			this.scrollMode=mode;
			if(this.scrollMode)
			{
				
				var ord,item;
				var listMarg;
				var r;
				switch(dest)
				{
					case 'left':
						ord="Left";
						item="Width";
						r=-1;
					break;
					case 'top':
						ord="Top";
						item="Height";
						r=-1;
					break;
					case 'right':
						ord="Left";
						item="Width";
						r=1;
					break;
					case 'bottom':
						ord="Top";
						item="Height";
						r=1;
					break;
				}
				listMarg=this.scrollObject['scroll'+ord];
				if(listMarg+r*step<=0)
				{
					this.scrollObject['scroll'+ord]=0;
					if(this.scrollerThumb) this.scrollerThumb.style[ord.toLowerCase()]="0px";
					return !(listMarg<=0);
				}
				if(listMarg + r* step>=this.scrollObject['scroll'+item]-this.scrollObject['client'+item])
				{
					this.scrollObject['scroll'+ord]=this.scrollObject['scroll'+item]-this.scrollObject['client'+item];
					if(this.scrollerThumb) this.scrollerThumb.style[ord.toLowerCase()]=this.scrollObject['scroll'+ord]*thumbRatio+"px";
					return !(listMarg>=this.scrollObject['scroll'+item]-this.scrollObject['client'+item]);
				}
				this.scrollObject['scroll'+ord]=listMarg+r*step;
				if(this.scrollerThumb) this.scrollerThumb.style[ord.toLowerCase()]=this.scrollObject['scroll'+ord]*thumbRatio+"px";
				
				if(tOut) setTimeout("scrollers['"+objName+"'].timeoutContScrll('"+dest+"',true)",this.scrollTime);
				return true;
			}
		}
		catch(e){ this.setError(prepareException(e));}
	}
	// Функция вызова рекурсии скроллинга по таймауту
	this.timeoutContScrll=function(dest,tOut)
	{
		if(this.scrollMode) this.scrollContent(this.scrollMode,dest,tOut);
	}
	//Обработка метода drag'n'drop.
	this.startDrag=function(e)
	{
		try
		{
			var dest,item;
			if(!e) e=window.event;
			if(this.inDragin)
			{
				if(this.mousePos==null) this.mousePos=e['client'+this.scrollOrd.toUpperCase()];
				m=e['client'+this.scrollOrd.toUpperCase()]-this.mousePos;
				this.mousePos=e['client'+this.scrollOrd.toUpperCase()];
				if(this.scrollOrd.toUpperCase()=='X')
				{
					dest=(m>0)?'right':'left';
					item="Width";
				}
				else
				{
					dest=(m>0)?'bottom':'top';
					item="Height";
				}
				//this.scrollerThumb.style.top=parseFloat(this.scrollerThumb.style.top)+m+"px";
				this.scrollContent(true,dest,false,Math.abs(m/thumbRatio));
				//this.scrollContent(true,dest,false,m);
				return false;
			}
			else return true;
		}
		catch(e){ this.setError(prepareException(e));}
	}
	//Обработка колёсика мыши
	this.wheel=function(event)
	{
		try
		{
			var wheelDelta;
			var dest='';
			if (!event) event = window.event;
			if (event.wheelDelta) wheelDelta = -event.wheelDelta/120;
			else if (event.detail) wheelDelta = event.detail/3;
			if(scrollers[objName].scrollOrd.toUpperCase()=="X") dest=(wheelDelta>0)?'right':'left';
			if(scrollers[objName].scrollOrd.toUpperCase()=="Y") dest=(wheelDelta>0)?'bottom':'top';
			if(scrollers[objName].scrollContent(true,dest,false,scrollers[objName].wheelStep*scrollers[objName].scrollStep))
			{
				wheelCount=0;
				if (event.preventDefault) event.preventDefault();
				event.returnValue = false;
			}
			else
			{
				wheelCount+=Math.abs(wheelDelta);
				if(wheelCount<=scrollers[objName].wheelMax)
				{
					if (event.preventDefault) event.preventDefault();
					event.returnValue = false;
				}
				else wheelCount=scrollers[objName].wheelMax;
			}
		}
		catch(e){ scrollers[objName].setError(prepareException(e));}
	}
	//Обработка ошибок
	function prepareException(e)
	{
		filename=(e.fileName)?e.fileName.substring(7,e.fileName.length):'';
		return filename+': '+e.name+' at line '+e.lineNumber+': '+e.message;
	}
	this.printErrors=function()
	{
		if(this.errors.length!=0){for(i=0;i<this.errors.length;i++){eval(this.errorHandler+"('"+this.errors[i]+"')");}}
	}
	this.setError = function(eType)
	{
		switch(eType)
		{
			default:this.errors.push("Object: "+objName+". Error "+eType);break;
		}
		this.printErrors();
	}
	//Уничтожение объекта
	this.destruct=function()
	{
		try
		{
			if(this.scrollerButtonPositive)
			{
				this.scrollerButtonPositive.onmousedown="";
				this.scrollerButtonPositive.onmouseup="";
			}
			if(this.scrollerButtonNegative)
			{
				this.scrollerButtonNegative.onmousedown="";
				this.scrollerButtonNegative.onmouseup="";
			}
			if(this.scrollerThumb)
			{
				this.scrollerThumb.onclick="";
				this.scrollerThumb.onmouseout="";
				this.scrollerThumb.onmousemove="";
				this.scrollerThumb.onmouseup="";
				this.scrollerThumb.onmousedown="";
				document.body.onmouseup=function(event){bodyMouseUp()};
				document.body.onmousemove=function(event){bodyMouseMove()};
				window.onresize=function(event){windowResize()};
				if (this.scrollerThumb.parentNode.parentNode.addEventListener)
	 			{
	 				this.scrollerThumb.parentNode.parentNode.removeEventListener('DOMMouseScroll',scrollers[objName].wheel, false);
	 			}
	 			this.scrollerThumb.parentNode.parentNode.onmousewheel = "";
			}
			
			if(this.scrollWheel)
			{
				if (this.scrollObject.removeEventListener)
	 			{
	 				this.scrollObject.removeEventListener('DOMMouseScroll',scrollers[objName].wheel, false);
	 			}
	 			this.scrollObject.onmousewheel ="";
				}
				
			delete scrollers[objName];
		
		}
		catch(e){ this.setError(prepareException(e));}
	}
}