Scrollable = Class.create();
Scrollable.prototype =
{
	initialize: function(name, options)
	{
		this.busy = false;
		this.name = name;
		this.element = $(this.name);
		this.initialOffset = 0;
		if (window.location.hash != "") {
			this.initialOffset = $$('a[name="'+window.location.hash.split("#").last()+'"]').first().offsetTop;
		}
		options = options || {};
		this.upButton = options.up || false;
		this.downButton = options.down || false;
		if (this.element == null)
		{
			if (this.upButton)
				$(this.upButton).hide();
			if (this.downButton)
				$(this.downButton).hide();
			return;
		}
		this.realHeight = parseInt($(this.name).offsetHeight);
		this.visibleHeight = parseInt($(this.name).parentNode.offsetHeight);
		if (this.upButton)
			Event.observe(this.upButton, 'mousedown', this.upStart.bindAsEventListener(this), false);
		if (this.downButton)
			Event.observe(this.downButton, 'mousedown', this.downStart.bindAsEventListener(this), false);
		Event.observe(document, 'mouseup', this.unlock.bindAsEventListener(this), false);
		Event.observe(this.name, 'DOMMouseScroll', this.scrollWheel.bindAsEventListener(this), false);
		Event.observe(this.name, 'mousewheel', this.scrollWheel.bindAsEventListener(this), false);
		Event.observe(window, 'resize', this.update.bindAsEventListener(this), false);
		if (this.realHeight <= this.visibleHeight)
		{
			if (this.upButton)
				$(this.upButton).hide();
			if (this.downButton)
				$(this.downButton).hide();
		}
		this.update.bind(this).delay(1);
	},
	
	update: function()
	{
		this.realHeight = parseInt($(this.name).offsetHeight);
		this.visibleHeight = parseInt($(this.name).parentNode.offsetHeight);
		if (this.realHeight <= this.visibleHeight)
		{
			if (this.upButton)
				$(this.upButton).hide();
			if (this.downButton)
				$(this.downButton).hide();
		}
		else
		{
			if (this.upButton)
				$(this.upButton).show();
			if (this.downButton)
				$(this.downButton).show();
		}
		if (this.visibleHeight > this.realHeight)
			this.element.setStyle({top: "0px"})
		else if (this.element.offsetTop < this.visibleHeight - this.realHeight)
			this.element.setStyle({top: (this.visibleHeight - this.realHeight).toString() + "px"})
	},
	
	downStart: function()
	{
		this.lock();
		this.downAction();
	},
	
	upStart: function()
	{
		this.lock();
		this.upAction();
	},
	
	downAction: function()
	{
		this.update();
		distance = parseInt($(this.name).offsetTop - this.initialOffset) /*- parseInt($(this.name).getStyle("margin-top")) - parseInt($(this.name).getStyle("margin-bottom"))*/;
		if (distance - 10 >= this.visibleHeight - this.realHeight /*- parseInt($(this.name).getStyle("margin-top")) - parseInt($(this.name).getStyle("margin-bottom"))*/)
			$(this.name).setStyle({top: (distance + this.initialOffset - 10).toString() + "px"})
		else
			$(this.name).setStyle({top: (this.visibleHeight + this.initialOffset - this.realHeight /*- parseInt($(this.name).getStyle("margin-top"))*/).toString() + "px"})
		if (this.isLocked())
			this.downAction.bind(this).delay(0.05);
	},
	
	upAction: function()
	{
		this.update();
		distance = parseInt($(this.name).offsetTop - this.initialOffset);
		if (distance + 10 <= 0)
			$(this.name).setStyle({top: (distance + this.initialOffset + 10).toString() + "px"})
		else
			$(this.name).setStyle({top: this.initialOffset + "px"})
		if (this.isLocked())
			this.upAction.bind(this).delay(0.05);
	},
	
	lock: function()
	{
		this.busy = true;
	},
	
	unlock: function()
	{
		this.busy = false;
	},
	
	isLocked: function()
	{
		return this.busy;
	},
	
	handleWheel: function(delta)
	{
		this.newPosition = this.element.offsetTop + delta*10;
		if (this.newPosition <= this.visibleHeight + this.initialOffset - this.realHeight)
			this.newPosition = this.visibleHeight + this.initialOffset - this.realHeight;
		else if (this.newPosition >= this.initialOffset)
			this.newPosition = this.initialOffset;
		this.element.style.top = this.newPosition.toString() + "px";
	},
	
	scrollWheel: function(event)
	{
		var delta = 0;
		if (!event) event = window.event;
		if (event.wheelDelta)
		{
			delta = event.wheelDelta/120; 
			if (window.opera)
				delta = -delta;
		}
		else if (event.detail)
			delta = -event.detail/3;
		if (delta)
			this.handleWheel(delta);
		if (event.preventDefault)
			event.preventDefault();
		event.returnValue = false;
	}
};

