// Scrollbar handler module

// Last edited: 15-08-2007
// Version: 0.1.dev
// Revision: 1

// This module is responsible for handling scrollbar behavior

var _scrollBars = new Array();

var _scrollQueue = new Array();
var _scrollEngine = window.setInterval(_scrollCore,50);

var _captureMouseY = 0;

document.onmouseup = function() {
	// On mouse up - clear queue
	_scrollQueue = new Array();
}

document.onmousemove = function(ev) {
	_captureMouseY = (typeof ev == "undefined")?(document.body.scrollTop + event.clientY):ev.pageY;
}

function _classScrollBar(n,bu,bd,p,s,c)  {

	// Scroll bar class
	this._name = n;
	this._buttonUp = document.getElementById(bu);
	this._buttonDown = document.getElementById(bd);
	this._path = document.getElementById(p);
	this._scroller = document.getElementById(s);
	this._content = document.getElementById(c);
	this._pathHeight = parseInt(this._path.getAttribute("myheight"));
	this._viewportHeight = this._content.offsetHeight;
	this._scrollHeight = this._content.scrollHeight;
	// Calculate the initial values
	this._scrollerHeight = 21; //Math.round(this._viewportHeight / this._scrollHeight * this._pathHeight);
	this._scroller.style.height = this._scrollerHeight + "px";
	this._scrollerPosition = 0;
	// Create service functions
	this._updateScrollerByContent = function() {
		// Recalculate dimensions
		this._scrollerHeight = 21; //Math.round(this._viewportHeight / this._scrollHeight * this._pathHeight);
		if (this._scrollerHeight > this._pathHeight) this._scrollerHeight = this._pathHeight
		this._scroller.style.height = this._scrollerHeight + "px";
		// Recalculate position
		var scrolled = this._content.scrollTop / (this._content.scrollHeight - this._content.offsetHeight);
		var remains = this._pathHeight - this._scrollerHeight;
		this._path.style.paddingTop = Math.round(remains * scrolled) + "px";
		this._scrollerPosition = Math.round(remains * scrolled);
	}
	this._updateContentByScroller = function() {
		// Recalculate scroll amount
		var scrolled = this._scrollerPosition / (this._pathHeight - this._scrollerHeight);
		this._content.scrollTop = Math.round(scrolled * (this._content.scrollHeight - this._content.offsetHeight));
	}
	// Assign handlers
	this._buttonUp._myObj = this;
	this._buttonUp.onmousedown = function() {
		// Scroll Up - add to engine
		_scrollQueue.push(new _classScrollAction("button",this._myObj,-1,5));
	}
	this._buttonDown._myObj = this;
	this._buttonDown.onmousedown = function() {
		// Scroll Down - add to engine
		_scrollQueue.push(new _classScrollAction("button",this._myObj,1,5));
	}
	this._scroller._myObj = this;
	this._scroller.onmousedown = function(ev) {
		if (typeof ev == "undefined") var origin = (document.body.scrollTop + event.clientY); else var origin = ev.pageY;
		// Start drag
		_scrollQueue.push(new _classScrollAction("drag",this._myObj,origin,0,this._myObj._scrollerPosition));
	}
	this._content._myObj = this;
	if (document.all) {
		this._content.onmousewheel = HandleWheel;
	} else {
		this._content.addEventListener('DOMMouseScroll', HandleWheel, false);
	}
	
}

function HandleWheel(ev) {
	if (typeof ev == "undefined") {
		var delta = event.wheelDelta/40;
		event.cancelBubble = true;
	} else {
		var delta = -ev.detail;
		ev.stopPropagation();
		ev.preventDefault();
	}
	this._myObj._content.scrollTop -= 5*delta;
	this._myObj._updateScrollerByContent();
	return false;
}

function _classScrollAction(type,sobj,direction,rate) {
	this._type = type;					// text type "BUTTON" for button click&hold, "DRAG" for drag
	this._object = sobj;				// Scroll object reference
	this._direction = direction;		// used as reference point of drag origin in case of drag event
	this._rate = rate;					// used as reference point of the original position of the scroller at the moment of drag init
}

// Active functions

function regScrollBar(sbprefix) {
	var tempsb = new _classScrollBar(sbprefix,sbprefix+"_btnup",sbprefix+"_btndown",sbprefix+"_path",sbprefix+"_scroller",sbprefix+"_contents");
	_scrollBars.push(tempsb);
}

// Service functions

function _scrollCore() {
	for (var i=0;i<_scrollQueue.length;i++) {
		var thisScroll = _scrollQueue[i];
		switch (thisScroll._type.toUpperCase()) {
			case "BUTTON":
				thisScroll._object._content.scrollTop += (thisScroll._direction * thisScroll._rate);
				thisScroll._object._updateScrollerByContent();
				break;
			case "DRAG":
				var diffy = thisScroll._direction - _captureMouseY;
				var newpos = thisScroll._rate - diffy;
				if (newpos < 0) newpos = 0;
				if ((newpos + thisScroll._object._scrollerHeight) > thisScroll._object._pathHeight) newpos = (thisScroll._object._pathHeight - thisScroll._object._scrollerHeight);
				thisScroll._object._path.style.paddingTop = newpos + "px";
				thisScroll._object._scrollerPosition = newpos;
				thisScroll._object._updateContentByScroller();
				try { document.selection.empty(); }
				catch(eee) {
					window.getSelection().removeAllRanges();
				}
				break;
		}
	}
}


function _getRealX(obj) {
	var thisobj = obj;
	var pos = obj.offsetLeft;
	while (1>0) {
		if (thisobj == document.body) break;
		thisobj = thisobj.offsetParent;
		pos += thisobj.offsetLeft;
	}
	return pos;
}

function _getRealY(obj) {
	var thisobj = obj;
	var pos = obj.offsetTop;
	while (1>0) {
		if (thisobj == document.body) break;
		thisobj = thisobj.offsetParent;
		pos += thisobj.offsetTop;
	}
	return pos;
}

// Positioning

function _getRealX(obj) {
	var thisobj = obj;
	var pos = obj.offsetLeft;
	while (1>0) {
		if (thisobj == document.body) break;
		thisobj = thisobj.offsetParent;
		pos += thisobj.offsetLeft;
	}
	return pos;
}

function _getRealY(obj) {
	var thisobj = obj;
	var pos = obj.offsetTop;
	while (1>0) {
		if (thisobj == document.body) break;
		thisobj = thisobj.offsetParent;
		pos += thisobj.offsetTop;
	}
	return pos;
}

