/* classes */
	function Scrollbar(bar, area, margin, padding) {
		/* events */
			var self = this;
			addEvent(window, "mousemove", false, function(event) {
				if (self.dragging) self.scrollBar(event.clientY - self.offset - self.click);
			});
			addEvent(window, "mouseup", false, function(event) {
				self.dragging = false;
				self.tracking.on = false;
				if (self.tracking.timer != null) {
					clearInterval(self.tracking.timer);
					self.tracking.timer = null;
				}
			});
			addEvent(window, "keypress", false, function(event) {
				if (self.focused && !(event.shiftKey || event.metaKey || event.altKey || event.ctrlKey)) {
					var handled = true;
					switch (event.keyIdentifier) {
						case "Up":
							self.scrollArea(self.area.scrollTop - 10);
							break;
						case "Down":
							self.scrollArea(self.area.scrollTop + 10);
							break;
						case "PageUp":
							self.scrollArea(self.area.scrollTop - self.area.clientHeight);
							break;
						case "PageDown":
							self.scrollArea(self.area.scrollTop + self.area.clientHeight);
							break;
						case "Home":
							self.scrollBar(0);
							break;
						case "End":
							self.scrollBar(self.max);
							break;
						default:
							handled = false;
					}
					if (handled) event.stopPropagation();
				}
			});
			addEvent(area, "mouseover", false, function(event) { self.focused = true; });
			addEvent(area, "mouseout", false, function(event) { self.focused = false; });
			addEvent(area, "mousewheel", false, function(event) { self.scrollArea(self.area.scrollTop - ((event.wheelDelta / 120) * 10)); });
			addEvent(bar, "mouseover", false, function(event) { self.focused = true; });
			addEvent(bar, "mouseout", false, function(event) { self.focused = false; });
			addEvent(bar, "mousedown", false, function(event) {
				self.tracking.on = true;
				if (scrollTracking(event)) {
					self.tracking.timer = setInterval(function() {
						if (scrollTracking(event)) {
							clearInterval(self.tracking.timer);
							startTracking(event);
						}
					}, 500);
				}
			});
			addEvent(bar, "mousemove", false, function(event) {
				if (self.tracking.on && self.tracking.timer == null)
					startTracking(event);
			});
			addEvent(bar, "mousewheel", false, function(event) { self.scrollArea(self.area.scrollTop - ((event.wheelDelta / 120) * 10)); });
			addEvent(bar.childNodes[0], "mousedown", false, function(event) { event.preventDefault(); });
			addEvent(bar.childNodes[1], "mousedown", false, function(event) { event.preventDefault(); });
			addEvent(bar.childNodes[2], "mousedown", false, function(event) { event.preventDefault(); });
			addEvent(bar.childNodes[3], "mousedown", false, function(event) {
				self.click = event.clientY - self.offset - self.position;
				self.dragging = true;
				event.stopPropagation();
			});
			addEvent(bar.childNodes[3].childNodes[0], "mousedown", false, function(event) { event.preventDefault(); });
			addEvent(bar.childNodes[3].childNodes[1], "mousedown", false, function(event) { event.preventDefault(); });
			addEvent(bar.childNodes[3].childNodes[2], "mousedown", false, function(event) { event.preventDefault(); });
		
		/* functions */
			function startTracking(event) {
				self.tracking.timer = setInterval(function() {
					if (!scrollTracking(event)) {
						clearInterval(self.tracking.timer);
						self.tracking.timer = null;
					}
				}, 125);
			}
			
			function scrollTracking(event) {
				self.click = event.clientY - self.offset;
				if (self.click >= self.position && self.click <= self.position + self.widgetSize)
					return false;
				if (self.click < self.position)
					self.scrollArea(self.area.scrollTop - self.area.clientHeight);
				else
					self.scrollArea(self.area.scrollTop + self.area.clientHeight);
				return true;
			}
		
		/* variables */
			this.bar = bar;
			this.area = area;
			this.margin = margin * 2;
			this.padding = padding;
			
			this.offset = margin;
			this.scrollRatio = 0;
			this.trackSize = 0;
			this.trackRatio = 0;
			this.widgetSize = 0;
			this.max = 0;
			this.click = 0;
			this.position = 0;
			this.tracking = {on: false, timer: null};
			this.focused = false;
		
		/* code */
			var node = bar;
			do {
				if (node.offsetTop != null) this.offset += node.offsetTop;
				node = node.parentNode;
			}
			while (node != null);
			this.refresh();
	}
	
	Scrollbar.prototype.refresh = function() {
		this.scrollRatio = this.area.scrollHeight / (this.area.clientHeight - 10);
		this.trackSize = this.area.clientHeight - this.margin;
		this.trackRatio = this.area.clientHeight / this.trackSize;
		this.widgetSize = this.trackSize / this.scrollRatio;
		this.max = this.trackSize - this.widgetSize;
		this.area.childNodes[1].style.marginRight = this.widgetSize + 10 < this.trackSize ? "1.7em" : 0;
		this.bar.style.display = this.widgetSize + 10 < this.trackSize ? "block" : "none";
		this.bar.childNodes[1].style.height = ((this.trackSize - 20) / 10) + "em";
		this.bar.childNodes[3].childNodes[1].style.height = ((this.widgetSize - 17) / 10) + "em";
		this.scrollArea(this.area.scrollTop);
		//this.area.innerHTML = this.area.innerHTML;
	}
	
	Scrollbar.prototype.scrollBar = function(to) {
		if (to < 0) this.position = 0;
		else if (to > this.max) this.position = this.max;
		else this.position = to;
		this.area.scrollTop = (this.position * this.trackRatio) * this.scrollRatio;
		this.bar.childNodes[3].style.top = (this.position / 10) + "em";
	}
	
	Scrollbar.prototype.scrollArea = function(to) {
		this.scrollBar((to / this.scrollRatio) / this.trackRatio);
	}