
function scroller() {
	var clip_size=328
	var speed=5
	var d=document
	var bar=d.getElementById('scrollbar')
	var sc=d.getElementById('scrolled')
	var buttonUp=d.getElementById('scrollup')
	var buttonDown=d.getElementById('scrolldown')
	var clip_top=0
	var bar_offset=0
	var scrolled_top=sc.offsetTop
	var limit_top=buttonUp.offsetTop+buttonUp.offsetHeight
	var limit_bottom=buttonDown.offsetTop-bar.offsetHeight
	buttonUp.onmouseup=buttonDown.onmouseup=scrollStop
	buttonUp.onmousedown=buttonDown.onmousedown=scrollButton
	d.onmousemove=scrollBar
	d.onmouseup=cast
	bar.onmousedown=take
	bar.onselectstart=stop
	
	function stop() {
		return false;
	}
	
	function scrollStop() {
		clearTimeout(sc.timer);
	}
	
	function scrollButton(e) {
		// determine speed and direction
		if (e=eventIE(e)) {
			current_speed = speed;
			if (e.target.id == buttonDown.id) {
				current_speed = -speed;
			}
		}
		if (clip_top-current_speed<0) {
			limitTop();
			return;
		}
		if (clip_top+clip_size-current_speed > sc.offsetHeight) {
			limitDown();
			return;
		}
		clip_top -= current_speed;
		bar.style.top = (parseInt(getStyle(bar, "top").replace("px", "")) - current_speed) + "px";
		move();
		args = arguments;	// can't refer to 'arguments' directly in setTimeout()
		sc.timer=setTimeout('args.callee()', 1);
	}
	
	function scrollBar(e) {
		if (!bar_offset) {
			return;
		}
		e=eventIE(e)
		if (e.pageY-bar_offset<limit_top) {
			limitTop();
			return;
		}
		if (e.pageY>limit_bottom+bar_offset) {
			clip_top=sc.offsetHeight-clip_size;
			limitDown();
			return;
		}
		bar.style.top = (e.pageY-bar_offset) + 'px';
		move();
	}
	
	function move() {
		position = (bar.offsetTop-limit_top)/(limit_bottom-limit_top);
		sc.style.top = (scrolled_top-(Math.floor(sc.offsetHeight-clip_size) * position))+'px';
		clip_top=Math.floor((sc.offsetHeight-clip_size)*position);
		sc.style.clip='rect('+clip_top+'px '+sc.offsetWidth+'px '+(clip_top+clip_size)+'px 0px)';
	}
	
	function limitTop() {
		clip_top=0;
		bar.style.top=limit_top+'px';
		sc.style.top=scrolled_top+'px';
		sc.style.clip='rect(0px '+sc.offsetWidth+'px '+clip_size+'px 0px)';
	}
	
	function limitDown() {
		bar.style.top=limit_bottom+'px';
		sc.style.top=scrolled_top+clip_size-sc.offsetHeight+'px';
		sc.style.clip='rect('+(sc.offsetHeight-clip_size)+'px '+sc.offsetWidth+'px '+sc.offsetHeight+'px 0px)';
	}
	
	
	function take(e) {
		e=eventIE(e);
		bar_offset=e.pageY-bar.offsetTop;
	}
	
	function cast() {
		bar_offset=0
	}
	
	function eventIE(e) {
		// map IE event handling to Gecko mode
		if (window.event && !window.opera) {
			e=window.event;
			e.pageY=window.event.y;
			e.target=window.event.srcElement;
		}	
		return e;
	}
	function getStyle(el, property) {
		if (el.currentStyle) {
			// IE needs camelCase here
			var matches = property.match(/\-[a-z]/g);
			if (matches) {
				for (var i = 0; i < matches.length; i++) {
					property = property.replace(new RegExp(matches[i]), matches[i].substr(1, 1).toUpperCase());
				}
			}
			return eval('el.currentStyle.' + property);
		} else {
			return d.defaultView.getComputedStyle(el, "").getPropertyValue(property);
		}
	}
}

