//Custom Vertical Scroller based on jquery
//Requires jquery-ui draggable interface and jquery.dimensions plugin

(function($) {


	$.scroller = function(scrollable_div, inner_div, options) {
		
		var $scrollable_div = $(scrollable_div);
		
		if ($scrollable_div.attr("hasscroll") == "true") {
			return false;
		}
		
		//Initializing global variables
		var $scrollable_div_add = $scrollable_div.find(".scroll_add");
		var $inner_div = $scrollable_div.find(inner_div);
		var containerHeight = options.contentHeightToScroll;
		$scrollable_div.prepend("<div style='display:none' class='scrollbar'><div class='scrollwrap'><div class='scrollbar_toparrow'></div><div class='thumb_area' ><div class='scrollbar_thumb'></div></div><div class='scrollbar_bottomarrow' ></div></div></div>");					
		var $scroller = $scrollable_div.find(".scrollbar");			
		$scroller.height(options.contentHeightToScroll+"px");				
		var $buttonTop = $scroller.find(".scrollbar_toparrow");
		var $buttonBottom = $scroller.find(".scrollbar_bottomarrow");		
		var thumbAreaHeight = options.contentHeightToScroll - 2*options.buttonHeight;		
		var $thumbArea = $scroller.find(".thumb_area").height(thumbAreaHeight + "px");
		var $thumb =  $scroller.find(".scrollbar_thumb");

		switchScroll();

		//Managing Events		
		$thumb.draggable({axis:"y",containment:"parent",drag:thumbDrag});
		
		function setInitScroll()
		{
			if ($inner_div.find("li.active").length)
			{
				try {
					var curTop = $inner_div.find("li.active").position().top;
					var curHeight = $inner_div.get(0).offsetHeight;					
					setScroll(curTop/curHeight);
				} catch (ex){}
			}
		}
		
		function makeScroll(direction)	{
			var step = thumbAreaHeight / (Math.ceil($scrollable_div_add.get(0).scrollHeight/containerHeight));
			step = step / 3;
			var thumbY = $thumb.position().top;			
			switch (direction) {
				case "up":
				{
					thumbY -= step;
					thumbY = (thumbY>=0)?thumbY:0;					
					break;
				}
				case "down":
				{
					var maxY = thumbAreaHeight - options.thumbHeight;
					thumbY +=  step ;			
					thumbY = (thumbY<maxY)?thumbY:maxY;
					break;
				}
			}
			$thumb.css("top",thumbY+"px");
			var ratio = thumbY / (thumbAreaHeight - options.thumbHeight);
			setScroll(ratio);			
		}
		
		var timeOutHandler;
		
		$buttonTop.mousedown(
			function () {
				makeScroll("up");
				timeOutHandler = setInterval(function () {makeScroll("up")} , 200);
				setTimeout( function () {clearInterval(timeOutHandler)} ,1000);
				return false;
			}
		);	
		
		$buttonBottom.mousedown(
			function ()	{
				makeScroll("down");	
				timeOutHandler = setInterval(function () {makeScroll("down")} , 200);
				return false;
			}
		);			
		$thumbArea.mousedown(			
			function (evt) {
				if (evt.target!=this) return;
				clearInterval(timeOutHandler);
				var areaTop = $(this).offset().top;
				
				var thumbY = $thumb.position().top;
				var delta =  - (thumbY - evt.pageY + areaTop);
				if (delta<0) { makeScroll("up"); } else {makeScroll("down");}		
				
				timeOutHandler = setInterval(function () {					
					var thumbY = $thumb.position().top;					
					var delta =  - (thumbY - evt.pageY + areaTop);					
					if ((delta<0)&&(Math.abs(delta)>options.thumbHeight/2)) { makeScroll("up"); } 
					if ((delta>0)&&(Math.abs(delta)>options.thumbHeight)) {makeScroll("down");}															   
				}, 200);
				
				return false;
			}			
		);	
		$(document).mouseup(
			function () {
				clearInterval(timeOutHandler);
			}
	   	);
		
		
		//Checking content height 
		$inner_div.mouseup(function(evt) {
			switchScroll();	
			recalcThumbPosition();
		} );
		
		//Recalculating thumb position
		function recalcThumbPosition () {
			if ($scrollable_div.attr("hasscroll")=="false"){return;}
			var curScrollTop = $scrollable_div_add.get(0).scrollTop;
			var curScrollHeight = $scrollable_div_add.get(0).scrollHeight;
			var newRatio = curScrollTop / (curScrollHeight - options.contentHeightToScroll)  ;
			var maxY = thumbAreaHeight - options.thumbHeight;
			if (newRatio<=1) {
				$thumb.css("top",Math.round(maxY*newRatio)+"px");	
			} else {
				$thumb.css("top",maxY+"px");
				$scrollable_div_add.get(0).scrollTop = curScrollHeight - options.contentHeightToScroll;
			}
		}
		
		//Showing scroll if needed
		function switchScroll()	{
			var innerHeight = $scrollable_div_add.get(0).scrollHeight;
			if (innerHeight>options.contentHeightToScroll)
			{attachScroll();}
			else
			{detachScroll();}
		}		
		
		function attachScroll()	{
			if ($scrollable_div.attr("hasscroll")=="true"){return;}
			$scrollable_div.attr("hasscroll", "true");
			$scroller.show();
			$scrollable_div_add.css({height:options.contentHeightToScroll+"px"});
			//var addPadding = $scrollable_div_add.width() - $scrollable_div.width() + options.fullScrollbarWidth;
			var addPadding = 72;
			$inner_div.css({marginRight:addPadding+"px"});
			return false;
		}
		
		function detachScroll()	{
			if ($scrollable_div.attr("hasscroll")=="false"){return;}
			$scrollable_div.attr("hasscroll", "false");
			$inner_div.get(0).scrollTop = 0;			
			$scroller.hide();
			$scrollable_div_add.css({height:"auto"});
			//var addPadding = $scrollable_div_add.width() - $scrollable_div.width();
			var addPadding = 72;
			$inner_div.css({marginRight:addPadding+"px"});
			return false;
		}		
		
		//Recalculating inner div scroll height
		function thumbDrag() {
			var thumbY = $(this).position().top;
			var ratio = thumbY / (thumbAreaHeight-options.thumbHeight);
			setScroll(ratio);
		}		
		
		function setScroll(ratio) {
			$scrollable_div_add.get(0).scrollTop = Math.round(ratio*(-containerHeight+$scrollable_div_add.get(0).scrollHeight));
		}
		
		function setScrollHandler()
		{
			$scrollable_div_add.scroll(	function () {
				recalcThumbPosition();
			});
		}
		
		switchScroll();	
		setTimeout(function(){setInitScroll()},100);
		setTimeout(function(){recalcThumbPosition()},150);
		setTimeout(function(){setScrollHandler()},1000);
		

	}
	
	$.fn.scroller = function(source,inner_div,options) {			
		options = options || {};				
		options.contentHeightToScroll = options.contentHeightToScroll || 300;
		options.buttonWidth = options.buttonWidth || 16;
		options.buttonHeight = options.buttonHeight || 16;
		options.thumbHeight = options.thumbHeight || 39;
		options.fullScrollbarWidth = options.fullScrollbarWidth || 18;
		this.each(function() {
			new $.scroller(this, inner_div, options);
		});
		return this;		
	};	
	
})(jQuery);


