/* cbyScrollbarH plugin (vertical scrollbar for iPad/android/desktop computers) */
(function($){
	/* OO jquery based on http://www.virgentech.com/blog/2009/10/building-object-oriented-jquery-plugin.html */
	$.fn.cbyScrollbarH = function(options) {
		return this.each(function() {
			var element = $(this);
			// Return early if this element already has a plugin instance
			if (element.data('cbyScrollbarH')) return;
			// pass options to plugin constructor
			var cbyScrollbarH = new cbyScrollbarHClass(this, options);
			// Store plugin object in this element's data
			element.data('cbyScrollbarH', cbyScrollbarH);
		});
	};
	
	var cbyScrollbarHClass = function(element,options) {
		// Start declaration (don't forget to put 'var' before every variables/functions!)
		// Default settings
		var settings = jQuery.extend({
			step: 40,
			thumbsize: 2.5,
			thumbcolor: "#000000",
			thumbopac: 0.3,
			thumbmargin: 10
		}, options);
		var container=$(element);				// The object
		var iScroll=0;							// The scrolling value (positive, 100 to move up 100px)
		var iScrollTo=0;						// The scrolling to value
		var mouseIn=0;							// Tells if the mouse is inside the container
		// The element MUST contain a div embedding the content!
		if (container.children().get(0).nodeName.toUpperCase()!="DIV") { alert("cbyScrollbarH error: firstChild is not a DIV");return false;}
		container.css("overflow","hidden");
		var viewport=container.find("div").eq(0);
		viewport.css({position:"absolute",width:"98%"});
		var height=container.height();
		var maxScroll=viewport.height();
		//container.find('img').eq(0).bind('load',function(){alert($(this).attr("src"));doResize()});
		var timeout=false;
		if (container.find(".thumb").length)
			var thumb=container.find(".thumb").eq(0);
		else {
			var thumb=$("<div>").css("margin-top",settings.thumbmargin+"px")
				.css({position:"absolute",right:0*settings.thumbsize,width:0,height:height*height/maxScroll-2*settings.thumbsize-2*settings.thumbmargin,top:0,cursor:"pointer",display:"none",opacity:settings.thumbopac})
				.css("border",settings.thumbsize+"px solid "+settings.thumbcolor).css("border-radius",settings.thumbsize+"px").addClass("thumb");
			container.append(thumb);
		}
		container.bind("mouseenter",function(){mouseIn=1;if (maxScroll>height) thumb.fadeIn();/*container.focus()*/});		// Mouseover fires to many event!
		container.bind("mouseleave",function(){mouseIn=0;thumb.fadeOut()});
		thumb.bind("mousedown", function(event){if (maxScroll>height) mouse(event),false});
		container.bind("mousewheel",function(event,delta){if (maxScroll>height) wheel(event,delta)});
		container.bind("touchstart",function(event){if (maxScroll>height) touch(event),false});
		// Set a tabindex to allow keyboard focus, but remove ouline if object focused
		container.attr("tabindex","0").css("outline","none").bind("keydown",function(event){if (maxScroll>height) keyboard(event),true});
		
		var move = {mode: 0, y0:0, y1:0, y2:0, y3:0, d:0, anim: 0}

		var mouse = function(event) {
			event.preventDefault();
			event.stopPropagation();
			switch (event.type) {
				case "mousedown":	// init, set 
					move.mode=1;
					move.y0 = event.pageY-iScroll/maxScroll*height;
					$(document).bind("mousemove mouseup", function(event){mouse(event),false});
					container.unbind("mouseleave");
					break;
				case "mouseup":
					move.mode=0;
					$(document).unbind("mousemove mouseup");
					container.bind("mouseleave",function(){thumb.fadeOut()});
					break;
				case "mousemove":
					if (move.mode) {
						iScroll=(event.pageY-move.y0)*maxScroll/height;
						doScroll();
					}
					break;
			}
		}
		
		var touch = function(event) {
			var e = event.originalEvent;
			event.preventDefault();
			event.stopPropagation();
			switch (event.type) {
				case "touchstart":	// init, set 
					thumb.show();
					if (move.anim) {
						viewport.stop();
						thumb.stop();
						thumb.show();
						move.anim=0;
						move.d=0;
						iScroll=-parseInt(viewport.css("top"));
					}
					move.mode=2;
					move.y0 = iScroll+e.targetTouches[0].pageY;
					move.y1 = e.targetTouches[0].pageY;
					move.y2 = e.targetTouches[0].pageY;
					move.y3 = e.targetTouches[0].pageY;
					$(document).bind("touchmove touchend", function(event){touch(event),false});
					if (timeout) clearTimeout(timeout);
					break;
				case "touchend":
					timeout=setTimeout(function(){thumb.fadeOut()},2000);
					move.mode=0;
					$(document).unbind("touchend touchmove");
					var target=event.target;
					if (Math.abs(move.y3-move.y2)<30) {
						while (target) {			// If user clicked on a A (or a children of a A), make the action
							if (target.nodeName=="A") {$(event.target).click();return false;}
							target=target.parentNode;
						}
					}
					if (move.d>100) move.d=100;
					if (move.d<-100) move.d=-100;
					doAnimate(move.d);
					break;
				case "touchmove":
					if (move.mode) {
						move.d=move.y2-e.targetTouches[0].pageY;
						iScroll=(move.y0-e.targetTouches[0].pageY);
						move.y2 = e.targetTouches[0].pageY;
						doScroll();
					}
					break;
			}
		}
		
		var wheel = function(event,delta) {
			iScroll=iScroll-settings.step*delta;
			doScroll();
			event.preventDefault();
		}

		var keyboard = function(event) {
			switch (event.which) {
				case 38:		// key up
					iScroll=iScroll-settings.step;
					break;
				case 40:		// key down
					iScroll=iScroll+settings.step;
					break;
				case 33:		// page up
					iScroll=iScroll-height;
					break;
				case 34:		// page down
					iScroll=iScroll+height;
					break;
			}
			doScroll();
			//event.preventDefault();   key event must go further 
		}

		
		var doScroll = function() {		// move the viewport and thumb to the right position (and check if not out of boundaries)
			if (move.mode!=2) {		// moving with mouse/wheel, can't go outside boundaries
				if (iScroll<0) {iScroll=0;}
				if (iScroll>(maxScroll-height)) {iScroll=maxScroll-height;}
			} else { // moving with touch panel, decrease iScrool if ouside boundaries
				if (iScroll<0) {iScroll=iScroll/2;}
				if (iScroll>(maxScroll-height)) {iScroll=maxScroll-height-(maxScroll-height-iScroll)/2;}
			}
			viewport.css("top",-iScroll);
			thumb.css({top:height*(iScroll/maxScroll)});
			//$('#debug').html("current="+iScroll);
		}
		
		var doAnimate = function(d) {
			move.anim=0;		// 0: no anim, >0: speed of animation
			move.d=d;
			if (iScroll<0) {
				move.anim=200;
				iScrollTo=0;
			} else {
				if (iScroll>(maxScroll-height)) {
					move.anim=200;
					iScrollTo=maxScroll-height;
				} else 
				if (Math.abs(d)>10) {
					move.anim=800;
					iScrollTo=iScroll+12*(d);
					if (iScrollTo<0) {iScrollTo=-30;move.anim=200}
					if (iScrollTo>(maxScroll-height)) {iScrollTo=maxScroll-height+30;move.anim=200}
				}
			}
			//$('#debug').html("d= "+d+" to="+iScrollTo+" current="+iScroll);
			
			if (move.anim) {
				viewport.animate({top: -iScrollTo}, move.anim, 'quadEaseOut', function(){iScroll=iScrollTo;move.anim=0;doAnimate(0)});
				thumb.animate({top: height*(iScrollTo/maxScroll)}, move.anim, 'quadEaseOut');
			}
		}
		
		var doResize = function() {
			height=container.height();
			maxScroll=viewport.height();
			thumb.css({height:height*height/maxScroll-2*settings.thumbsize-2*settings.thumbmargin});
			if (maxScroll>height) {
				doScroll(); 
				if (mouseIn) thumb.fadeIn();
			} else thumb.hide();
		}
		
		this.resize = function(){
			doResize();
		}
	}
})(jQuery);

/* easing for cbyScrollbar */
jQuery.extend( jQuery.easing, {
	quadEaseOut: function(p, n, firstNum, diff) {
            var c=firstNum+diff;
            return -c *(p/=1)*(p-2) + firstNum;
	}
});


/* mousewheel plugin */
(function($) {
	var types = ['DOMMouseScroll', 'mousewheel'];
	$.event.special.mousewheel = {
		setup: function() {
			if ( this.addEventListener )
				for ( var i=types.length; i; )
					this.addEventListener( types[--i], handler, false );
			else
				this.onmousewheel = handler;
		},
		
		teardown: function() {
			if ( this.removeEventListener )
				for ( var i=types.length; i; )
					this.removeEventListener( types[--i], handler, false );
			else
				this.onmousewheel = null;
		}
	};

	$.fn.extend({
		mousewheel: function(fn) {
			return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
		},
		
		unmousewheel: function(fn) {
			return this.unbind("mousewheel", fn);
		}
	});


	function handler(event) {
		var args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true;
		
		event = $.event.fix(event || window.event);
		event.type = "mousewheel";
		
		if ( event.wheelDelta ) delta = event.wheelDelta/120;
		if ( event.detail     ) delta = -event.detail/3;
		
		// Add event and delta to the front of the arguments
		args.unshift(event, delta);

		return $.event.handle.apply(this, args);
	}

})(jQuery);


