/* Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
 * 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://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 *
 * Version: 3.0.2
 * 
 * Requires: 1.2.2+
 */
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);


(function($) {

	$.fn.scrollify = function(options) {
		
		$("<div id='sb_scrollbar'><div id='sb_topbutton'></div><div id='sb_slider'></div><div id='sb_botbutton'></div></div>").appendTo("body");
		
		var settings = {
			'width':34
		};
		
		if (options) $.extend(settings,options);
		
		var scrollbar = $("#sb_scrollbar"), tbutton = $("#sb_topbutton"), bbutton = $("#sb_botbutton"), slider = $("#sb_slider");
		
		var el_border = this.outerHeight() - this.innerHeight();
		var sb_border = scrollbar.outerHeight() - scrollbar.innerHeight();
		var borderdiff = el_border - sb_border;
		
		$.log("el border: " + scrollbar.outerWidth());
		
		scrollbar.css({
			'position':'absolute',
			'width':settings.width,
			'height':this.height() + borderdiff,
			'top':this.offset().top
		});
		
		this.width(this.width() - scrollbar.outerWidth());
		
		/*Find the actual height and desired height. Save both. Find the ratio of desired and natural height to determine the length of the scrollbar.*/
		var cssheight = this.height();
		this.height('auto');
		var contentheight = this.height();
		this.css("overflow","hidden");
		this.height(cssheight);
		
		/*Multiply the scrollbar length by this number to find the actual slider length*/
		var ratiovisible = cssheight / contentheight;
		
		/*let the scrollbar be located in the rightmost part of the original div*/
		scrollbar.css("left", this.outerWidth() + this.offset().left);
		
		/*define top button*/
		tbutton.css({
			'position':'absolute',
			'top':'0px',
			'width':scrollbar.width() - (tbutton.outerWidth() - tbutton.innerWidth())
		});
		
		/*define bottom button*/
		bbutton.css({
			'position':'absolute',
			'bottom':'0px',
			'width':scrollbar.width() - (bbutton.outerWidth() - bbutton.innerWidth())
		});
		
		/*create the slideableArea object, which controls the slider function - start by finding top and bottom pixel.*/
		var slideableArea = {
			top:tbutton.outerHeight(),
			bottom:scrollbar.innerHeight() - bbutton.outerHeight()
		};
		
		slideableArea.height = slideableArea.bottom - slideableArea.top;
		settings.sliderHeight ? slideableArea.slidershare = settings.sliderHeight : slideableArea.slidershare = (slideableArea.bottom - slideableArea.top) * ratiovisible;
		
		slider.css({
			'position':'absolute',
			'height':slideableArea.slidershare - (slider.outerHeight() - slider.innerHeight()),
			'width':scrollbar.width() - (slider.outerWidth() - slider.innerWidth()),
			'top':tbutton.outerHeight()
		});
		
		/*min is the same as top, but max is the bottom minus slider height*/
		slideableArea.minPixel = slideableArea.top;
		slideableArea.maxPixel = slideableArea.bottom - slider.outerHeight();
		
		/*there is a doc length, but it can't scroll to doc length - only to doc length minus 1 page*/
		slideableArea.docLength = contentheight;
		slideableArea.maxDocScroll = contentheight - this.outerHeight() + 20; /*magic number*/
		
		/*the slider is the #sb_slider div*/
		slideableArea.slider = slider;
		
		/*the controlArea is the original div that called the function, equal to this in current context*/
		slideableArea.controlArea = this;
		
		/*the initial position is the top or minPixel*/
		slideableArea.currentPosition = slideableArea.minPixel;
		
		slideableArea.translatePosition = function(pxPos) {
			var scrollLength = this.maxPixel - this.minPixel;
			var thisPos = pxPos - this.minPixel;
			var relPos = thisPos / scrollLength;
			
			return this.maxDocScroll * relPos;
		};
		
		slideableArea.translateStep = function() {
			return (this.maxPixel - this.minPixel) / (this.maxDocScroll / 20);
		}
		
		slideableArea.moveSlider = function(diff) {
			$.log(sliderstartposition);
			var dpos = sliderstartposition + diff;
			
			if (dpos < this.minPixel) dpos = this.minPixel;
			if (dpos > this.maxPixel) dpos = this.maxPixel;
			
			this.slider.css("top",dpos);
			this.controlArea.scrollTop(this.translatePosition(dpos));
		}
		
		slideableArea.pushSlider = function(add) {
			var newPos = this.currentPosition + add;
			
			if (newPos < this.minPixel) {
				newPos = this.minPixel;
			} else if (newPos > this.maxPixel) {
				newPos = this.maxPixel;
			}
			
			this.slider.css("top",newPos);
			this.controlArea.scrollTop(this.translatePosition(newPos));
			this.currentPosition = newPos;
		}
		
		var isscrolling = false;
		var mousetriggerpixel;
		var sliderstartposition;
		
		slider.mousedown(function(e) {
			e.stopPropagation();
			isscrolling = true;
			mousetriggerpixel = e.pageY;
			sliderstartposition = slideableArea.currentPosition;
			return false;
		});

		$("body").mouseup(function(e) {
			isscrolling = false;
			slideableArea.currentPosition = parseInt($("#sb_slider").css("top"));
		});

		$("body").mousemove(function(e) {
			e.preventDefault();
			if (isscrolling) {
				slideableArea.moveSlider(e.pageY-mousetriggerpixel);
			}
		});
		
		tbutton.click(function(e) {
			e.stopPropagation();
			slideableArea.pushSlider(-slideableArea.translateStep());
		});
		
		bbutton.click(function(e) {
			e.stopPropagation();
			slideableArea.pushSlider(slideableArea.translateStep());
		});
		
		scrollbar.click(function(e) {
			e.stopPropagation();
			if (e.pageY > (slider.offset().top + slider.outerHeight())) {
				slideableArea.pushSlider(slider.outerHeight());
			} else if (e.pageY < slider.offset().top) {
				slideableArea.pushSlider(-slider.outerHeight());
			}
		});
		
		this.mousewheel(function(e,delta) {
			e.preventDefault();
			e.stopPropagation();
			if (delta == 1) {
				slideableArea.pushSlider(slideableArea.translateStep() * -4);
			} else if (delta == -1) {
				slideableArea.pushSlider(slideableArea.translateStep() * 4);
			}
		});
		
		return this;
	};
	
	$.log = function(message) {
		$("#log").empty();
		$("<p>" + message + "</p>").appendTo("#log");
	};

})(jQuery);