/*
 * Date:   26.11.2010
 * Description: Vertical scrollbar with jQuery UI - CSS
 * Author: Matteo Poile
 * Site:   http://www.devsign.it
 * E-mail: matteopoile@gmail.com
 * 
 * Copyright (c) 2010 Matteo Poile (http://www.devsign.it)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * Thanks to: http://www.simonbattersby.com/blog/vertical-scrollbar-using-jquery-ui-slider/ 
 *
 * Version: 0.8
 * 
 * Requires: 1.4+
 */

(function( $ ){
	
	$.fn.scrollgrab = function(options) { 
		  
		var methods = {
		    init : function( options ) {},
		    destroy : function( ) {},
		    hide : function( ) { },
		    update : function( content ) { }
		  };

		
		if(jQuery.fn.slider){
			
			var settings = {
				'orientation'		: 'vertical',
				'width' 			: false,
				'height'			: false,
				'scrollablePadding'	: false,
				'sliderBoxWidth'	: false,
				'sliderHeight' 		: false,
				'sliderWidth'		: 'auto',
				'sliderMin'			: 0,
				'sliderMax'			: 100,
				'sliderValue'		: 100,
				'disabled'			: false,
				'animate'			: false,
				'speed'				: 5,
				'cursor'			: false,
				'debug'				: false
			};
			
			if ( options ) { 
		        $.extend( settings, options );
			}
			
			var $scrollWrapper = this;
			var $scrollable = this.children('.scrollable');
			
			$scrollable.css({ 'position': 'absolute'});
			if(settings.scrollablePadding){
				$scrollable.css({'padding': settings.scrollablePadding });
			}
			$scrollablePaddingTop = parseInt($scrollable.css('padding-top'));
			$scrollablePaddingBottom = parseInt($scrollable.css('padding-bottom'));
			
			
			//set width and height (adding padding top/bottom) of the .scroll-wrapper element and set overflow property to hidden as we can use the slider now
			if(settings.width){
				$scrollWrapper.css({ 'width': settings.width });
			}
			if(settings.height){
				$scrollWrapper.css({ 'height': settings.height + $scrollablePaddingTop + $scrollablePaddingBottom });
			}
			$scrollWrapper.css({ 'overflow': 'hidden' });
					   
			//calculate the height that the scrollbar handle should be
			var difference = $scrollable.height() - $scrollWrapper.height();

			//if the scrollbar is needed, set it up...
			if( difference > 0 )
			{
				
			   var proportion = difference / $scrollable.height();
			   //set the proportional height - round it to make sure everything adds up correctly later on
			   var handleHeight = Math.round((1-proportion) * $scrollWrapper.height());
			   handleHeight -= handleHeight%2;
			   
			   if(settings.sliderHeight){
				   //forced handle height
				   handleHeight = settings.sliderHeight; 
			   }
			   
			   $scrollWrapper.find('.slider-box').remove();
			   //append the necessary divs so they're only there if needed
			   $scrollWrapper.append('<\div class="slider-box"><\div class="slider"><\/div><\/div>');
			   var $sliderBox = this.children('.slider-box');
			   var $slider = this.find('.slider');
			   $sliderBox.css({ 'width': settings.sliderBoxWidth, height: $scrollWrapper.height() });
			   if(settings.disabled){
					$sliderBox.addClass('disabled');
				}
			   
			   function moveScrollable(value){
				   //move the top up (negative value) by the percentage the slider has been moved times the difference in height
				   var topValue = -((100-value)*difference/100);
			         $scrollable.stop().animate({top:topValue}, settings.animate );
			         if( settings.debug ){
			        	 $('#debug span').eq(7).text(value);
					 }
			   }
			   
			   //set up the slider 
			   $slider.slider({
				  disabled: settings.disabled,
			      orientation: settings.orientation,
			      min: settings.sliderMin,
			      max: settings.sliderMaz,
			      value: settings.sliderValue,
			      animate: settings.animate,
			      slide: function(event, ui) {
				   moveScrollable(ui.value);
			      }
			   });
			   
			   moveScrollable(settings.sliderValue);
			   
			   	var $handle = this.find('.ui-slider-handle');
			   	if(settings.sliderWidth == 'auto'){
				   	$handle.outerWidth($slider.width());
				}else{
				   	$handle.outerWidth(settings.sliderWidth);
				}
				if(settings.cursor){
					$handle.css('cursor', settings.cursor); 
				}
				
			   //set the handle height and bottom margin so the middle of the handle is in line with the slider
			   $handle.css({height:handleHeight});
			   outerHandleHeight = $handle.outerHeight(); // this will take care of eventual borders
			   $handle.css({'margin-bottom':-0.5*outerHandleHeight});
				
			   var origSliderHeight = $slider.height();//read the original slider height
			   var sliderHeight = origSliderHeight - outerHandleHeight ;//the height through which the handle can move needs to be the original height minus the handle height
			   var sliderMargin =  (origSliderHeight - sliderHeight)*0.5;//so the slider needs to have both top and bottom margins equal to half the difference
			   this.find(".ui-slider").css({height:sliderHeight,'margin-top':sliderMargin});//set the slider height and margins
			   this.find(".ui-slider-range").css({top:-sliderMargin});//position the slider-range div at the top of the slider container
			
			}//end if
		
			
			//debug
			if( settings.debug ){
				
				var mousewheel = (jQuery.fn.mousewheel) ? 'Loaded' : 'Missing';
				
				var debug = "<div id='debug' style='position:fixed;bottom:10px;left:10px;width:220px;padding:10px;background:#fffda8;border:2px solid #333;z-index:9999;'>" +
								"<b>DEBUG:<\/b><br \/><br \/>" +
					        	".scroll-wrapper height: <span><\/span><br \/>" +
					        	".scrollable height: <span><\/span><br \/>" +
					        	".ui-slider-handle height: <span><\/span><br \/>" +
					        	".ui-slider-handle outerHeight: <span><\/span><br \/>" +
					        	".ui-slider-handle margin: <span><\/span><br \/>" +
					        	"$('.slider').slider('option', 'min'): <span><\/span><br \/>" +
					        	"$('.slider').slider('option', 'max'): <span><\/span><br \/>" +
					        	"$('.slider').slider('value'): <span></span><br \/><br \/>" +
					        	"disabled: " + settings.disabled + "<br \/>" +
					        	"speed: " + settings.speed + "<br \/>" +
					        	"animate: " + settings.animate + "<br \/><br \/>" +
					        	"Mousewheel plugin: " + mousewheel +
					        "</div>";
				$('body').append(debug);
				
				$('#debug span').eq(0).text($scrollWrapper.height());
				$('#debug span').eq(1).text($scrollable.height());
				$('#debug span').eq(2).text(handleHeight);
				if(outerHandleHeight != 'undefined'){
					$('#debug span').eq(3).text(outerHandleHeight);
				}
				$('#debug span').eq(4).text(sliderMargin);
				$('#debug span').eq(5).text($slider.slider('option', 'min'));
				$('#debug span').eq(6).text($slider.slider('option', 'max'));
				$('#debug span').eq(7).text($slider.slider('value'));
			}
			
			//additional code for mousewheel
			if(jQuery.fn.mousewheel && !settings.disabled){
				
				this.bind( 'mousewheel', function(event, delta){
					
			  		var speed = settings.speed;
				    var sliderVal = $slider.slider('value');//read current value of the slider | !!! can't read value setted dragging slider

				    sliderVal += ( delta * speed );//increment the current value
				    
				    var sliderMin = $slider.slider('option', 'min');
				    if ( sliderVal < sliderMin ) sliderVal = sliderMin; //limit sliderMin to $slider option 'min' val
				    var sliderMax = $slider.slider('option', 'max');
				    if ( sliderVal > sliderMax ) sliderVal = sliderMax; //limit sliderMax to $slider option 'max' val
				    
				    //and set the new value of the slider
				    $slider.slider('option','value', sliderVal);  
				    var topValue = -(( 100 - sliderVal ) * difference / 100);//calculate the content top from the slider position
					
					if ( topValue > 0 ) topValue = 0;//stop the content scrolling down too much
					if ( Math.abs( topValue ) > difference ) topValue = (-1) * difference;//stop the content scrolling up too much
					
					$scrollable.stop().animate({top:topValue}, settings.animate );//move the content to the new position
				    event.preventDefault();//stop any default behaviour
				    
				    if( settings.debug ){
				    	$('#debug span').eq(7).text(sliderVal);

				    	//$('#debug').prepend($slider.slider('option','value') + "|" + $slider.slider('value') + "<br \/>");
				    	
				    }
				    
			 	});
				
				
			}
			
			return this;
		
		}else{
			alert('jQuery UI Slider Widget is missing! Visit www.jqueryui.com/download');
			return this;
		}
	}; // end $.fn

})( jQuery );
