// ??????????? ?? ??????
function SetScrollOperator(obid,sizes,step) {
	var sop=this;
	this.obid=obid;
	this.wid=sizes[0];
	this.hei=sizes[1];
	sop.qscrollInterval=null;
	sop.interval=null;
	sop.step=step;

	//////////////////////////////////////////////////////////////////
	// ????? ?? ????????? ? ???????
	sop.minDraggerHeight=5; // ????????? ???????? ?? ??????? (dragger)
	sop.arrHei=11; // ???????? ?? ?????????

	sop.box=document.getElementById(obid);
	if(!sop.box) return;

	var obDivs=sop.box.getElementsByTagName('DIV');

	// ????????? ?? ???????????
	sop.box.innerHTML='<div>'+sop.box.innerHTML+'<\/div>'; // ??????????
	sop.obj=sop.box.getElementsByTagName('DIV')[0]; // ????? - ???????
	sop.navPanel=document.createElement('DIV'); // ????????? ?? ????????
	sop.innerPanel=document.createElement('DIV'); // ???? ?? ????????
	sop.dragger=document.createElement('SPAN'); // ??????
	sop.arrup=document.createElement('SPAN'); // ??????? "??????"
	sop.arrdown=document.createElement('SPAN'); // ??????? "??????"
	sop.navPanel.className='NavPanel';
	sop.dragger.className='dragger';
	sop.arrdown.className='arrdown';
	sop.arrup.className='arrup';

	// ????????? ?? ???????????
	sop.navPanel.appendChild(sop.innerPanel);
	sop.navPanel.appendChild(sop.arrup);
	sop.navPanel.appendChild(sop.dragger);
	sop.navPanel.appendChild(sop.arrdown);
	sop.box.appendChild(sop.navPanel);

	// ?????? ?????
	sop.box.style.paddingRight='20px';
	sop.box.style.position='relative';

	// ???????? ????
	sop.obj.style.overflow='hidden';
	sop.obj.style.position='relative';
	sop.obj.id=sop.obid+'scr';

	// navPanel
	sop.navPanel.onselectstart=function() {return false;}
	sop.navPanel.onmousedown=function(event) {
		var myElement=(window.event ? window.event.srcElement : event.target);
		if(myElement.tagName!='DIV')
			return false;
	}

	// ???????? ?? ???????
	sop.setScales();

	// Arrow Up
	sop.arrup.onmouseout=function() {sop.clearIntervals();}
	sop.arrup.onmouseover=function() {sop.Scroll('up',sop.step);}
	sop.arrup.onmousedown=function() {sop.obj.step=step+5;}
	sop.arrup.onmouseup=function() {sop.obj.step=step}

	// Arrow Down
	sop.arrdown.onmouseout=function() {sop.clearIntervals();}
	sop.arrdown.onmouseover=function() {sop.Scroll('down',sop.step);}
	sop.arrdown.onmousedown=function() {sop.obj.step=step+5;}
	sop.arrdown.onmouseup=function() {sop.obj.step=step;}

	// ?????????? ???? ??????????? ?? ???????
	sop.dragger.onmousedown=function(e) {
		sop.clearIntervals();
		var y=e?e.pageY:window.event.clientY;
		y-=sop.box.offsetTop;
		sop.dragger.cursorOffset=y-sop.dragger.offsetTop-sop.arrHei;

		document.onmouseup=function() {document.onmousemove=null;}

		var
			ind=true,
			constant1=sop.obj.scrollHei/(sop.obj.offsetHeight-(sop.arrHei*2+2)),
			constant2=sop.obj.offsetHeight-sop.dragger.offsetHeight-sop.arrHei,
			ToBotMax=sop.obj.offsetHeight - sop.dragger.offsetHeight - sop.arrHei
		;

		document.onmousemove=function(e) {
			var y=e?e.pageY:window.event.clientY; y-=sop.box.offsetTop+sop.arrHei;
			var coffsetpos=y-sop.dragger.cursorOffset;

			if(sop.dragger.offsetTop >= sop.arrHei && sop.dragger.offsetTop <= constant2) {
				if(coffsetpos<=sop.arrHei) {coffsetpos=sop.arrHei; sop.obj.scrollTop=0; ind=false;}
				if(coffsetpos>=ToBotMax) {coffsetpos=ToBotMax; sop.obj.scrollTop=sop.obj.scrollHei; ind=false;}
				sop.dragger.style.top=(coffsetpos)+'px';
				if(ind) sop.obj.scrollTop=(sop.dragger.offsetTop-(sop.arrHei-1))*constant1;
				ind=true;
			}
		}
	}

	// ?????????? ???? ???????? ???? ?? ????????
	sop.navPanel.onmouseup=function(e) {
		var myElement=(window.event ? window.event.srcElement : e.target);
		if(myElement.tagName!='SPAN') {
			sop.clearIntervals();
			var y=e?e.pageY:window.event.clientY-2;
			y-=sop.box.offsetTop;

			if(window.event)
				y+=document.documentElement.scrollTop?
					document.documentElement.scrollTop:
					document.body.scrollTop
				;

			// ???????? ?? ??????? ???????? ??????????
			if(y<sop.arrHei || y>sop.obj.offsetHeight-sop.arrHei) return;

			// ??????????
			var QHei=sop.dragger.offsetHeight;
			var flag=(sop.dragger.offsetTop<y)?1:-1;
			sop.qscrollInterval=window.setInterval(
				function() {
					var Top=sop.dragger.offsetTop;
					if(Top+QHei>=y && flag>0) return sop.clearIntervals();
					if(Top<=y && flag<0) return sop.clearIntervals();

					// ????????? ?? ?????????
					var qstep=2;
					if(QHei<=flag*(y-Top)/2) qstep=3;
					if(QHei<=flag*(y-Top)/3) qstep=4;
					sop.dragger.style.top=(Top+qstep*flag)+'px';
					sop.obj.scrollTop=(Top-(sop.arrHei-1))*sop.obj.scrollHei/(sop.obj.offsetHeight-(sop.arrHei*2+2));
				}
			,1);
		}
	}

	// ?????????? ???? MouseWheel
	sop.mWheel=function(e) {
		sop.clearIntervals();
		var e=(!e)?window.event:e;
		var opera = ( window.opera );
		var delta=false;

		if(e.wheelDelta) delta=e.wheelDelta/120*opera;
		else if(e.detail) delta=e.detail/-3;

		if(delta) {
			if(e.preventDefault)
				e.preventDefault();
			e.returnValue=false;
	
			sop.obj.scrollTop+=-delta*20;
			if(sop.obj.scrollTop==0)
				sop.dragger.style.top=sop.arrHei+'px';
			else
				sop.dragger.style.top=(Math.ceil(sop.obj.scrollTop*(sop.obj.offsetHeight-(sop.arrHei*2+2))/sop.obj.scrollHei)+(sop.arrHei-1))+'px';
		}
	}

	if(window.addEventListener)
		sop.box.addEventListener('DOMMouseScroll',sop.mWheel,false);
	sop.box.onmousewheel=sop.mWheel;

	// ???????????? ??? ????? ????????
	sop.imgs=sop.box.getElementsByTagName('IMG');
	for(var i=0; i<sop.imgs.length; i++)
		sop.imgs[i].onload=function() { sop.setScales(); }
}

// ???????? ?? ??????? ?????????
SetScrollOperator.prototype.setScales=function() {
	var sop=this;

	// ?????? ?????
	sop.box.style.width=sop.wid+'px';
	sop.box.style.height=sop.hei+'px';

	// ???????? ????
	sop.obj.style.width=sop.wid+'px';
	sop.obj.scrollHei=sop.obj.scrollHeight;
	sop.obj.style.height=sop.hei+'px';

	// ??????
	sop.dragger.id=sop.obid+'dragger';
	if(sop.obj.scrollHei<=sop.hei)
		sop.navPanel.style.display='none';
	else {
		sop.dragger.style.height=Math.ceil(sop.hei*(sop.hei-(sop.arrHei*2+2))/sop.obj.scrollHei)+'px';
		if(sop.dragger.offsetHeight<sop.minDraggerHeight)
			sop.dragger.style.height=sop.minDraggerHeight+'px';
	}
	sop.dragger.style.top=sop.arrHei+'px';
}

// ?????????? ???? ?????????
SetScrollOperator.prototype.Scroll=function(dir,step) {
	var sop=this;

	sop.obj.step=step;
	sop.clearIntervals();
	sop.interval=window.setInterval(
		function() {
			switch(dir) {
				case 'up': sop.obj.scrollTop-=sop.obj.step; break;
				case 'down': sop.obj.scrollTop+=sop.obj.step; break;
			}
			if(sop.obj.scrollTop==0)
				sop.dragger.style.top=sop.arrHei+'px';
			else
				sop.dragger.style.top=(Math.ceil(sop.obj.scrollTop*(sop.obj.offsetHeight-(sop.arrHei*2+2))/sop.obj.scrollHei)+(sop.arrHei-1))+'px';
		}
	,1);
}

// ?????????? ?? ?????????
SetScrollOperator.prototype.clearIntervals=function() {
	window.clearInterval(this.qscrollInterval);
	window.clearInterval(this.interval);
	return true;
}
