// jQuery Carousel with Scrollbar
// Plugin written by Radoslav Georgiev
// c4xpl0siv3@gmail.com

var car;
$.fn.scrollcarousel = function(options) { 
	var defaults = {  
		navigation :          "scroll",
		buttonPrev:           false,
		buttonNext:           false,
		start:                1,
		auto:                 0,
		displayIndex:         false,
		easing:               null,
		speed:                "fast",
		wrap: 	             "both",
		maxScroll:            1,
		autoAlign:            true,
		handleHTML:           "<span>&nbsp;</span>",
		scrollStrings:        null,
		scrollType:           "normal", // Couldbe normal or cool
		carouselLoadedCallback: null,
		carouselScrolledCallback: null,
		itemLoadCallback:      null,
		itemVisibleCallback:   null
	};  
	var options = $.extend(defaults, options);  
	
	var mouse = function(){
		this.left = 0;
		this.top = 0;
	}
	
	var IE = document.all?true:false
	// If NS -- that is, !IE -- then set up for mouse capture
	if (!IE) document.captureEvents(Event.MOUSEMOVE)
	// Set-up to use getMouseXY function onMouseMove
	
	// Temporary variables to hold mouse x-y pos.s
	mouse.left = 0;
	mouse.top = 0;
	
	
	return this.each(function() {  
		car = this;
		var obj = $(this);
		var htmlObj = this;
		var carouselList =  $("ul:eq(0)", obj);
		
		var current = options.start-1;
		
		var element = new function(){
			this.width = $("li:eq(0)", carouselList).outerWidth();
			this.height = $("li:eq(0)", carouselList).outerHeight();
			this.count = carouselList.children("li").size();
		}		
		
		// Setting ul's width - all li's shoudle be in one row
		carouselList.css("width", element.width * element.count);
		carouselList.css("left" , -((options.start-1)*element.width));
		
		var scrollContainer = null;
		if(options.navigation == "scroll")
		{
			var newHTML = document.createElement("div");
			$(newHTML).attr("class", "carousel-scroll");
			obj.append(newHTML);
			scrollContainer = $(".carousel-scroll", obj);
		}
		var scrollHandle = null;
		var scrollRatio;
		var scrollSpacing;
		var setScrollData;
		
		if(scrollContainer)
		{
			var newHTML = document.createElement("div");
			$(newHTML).attr("class", "scrollcarousel-handle");
			scrollContainer.append(newHTML);
			scrollHandle = $(".scrollcarousel-handle" ,scrollContainer);
			scrollHandle.css("width", scrollContainer.width()/element.count);
			scrollSpacing = (scrollContainer.width() - scrollHandle.outerWidth()*(element.count))/(element.count -1);
			if(scrollHandle.outerWidth()==scrollContainer.width()/element.count) scrollSpacing = 0;
			scrollRatio = (scrollHandle.outerWidth() + scrollSpacing)/element.width;
			scrollHandle.css("left", current*scrollHandle.outerWidth() + current*scrollSpacing);
			scrollHandle.html(options.handleHTML);
		
			setScrollData = function(num){
				if(!options.displayIndex) return;
				
				if(options.scrollStrings)
				{
					if(options.scrollType == "normal")
					{
						if(options.scrollStrings[num-1])
							$("span", scrollHandle).html(options.scrollStrings[num-1]);
						else
							$("span", scrollHandle).html(num);
					}
				}
				else
					$("span", scrollHandle).html(num);
			}
			
			if(options.scrollType == "cool")
			{
				var list = document.createElement("ul");
				scrollContainer.append(list);
				scrollList = $("ul", scrollContainer);
				for(i=0; i<options.scrollStrings.length; i++)
				{
					var li = document.createElement("li");
					if(typeof(options.scrollStrings[i]) == "string")
					{
						var li = document.createElement("li");
						$(li).html(options.scrollStrings[i]);
						scrollList.append(li);
					}
					else
					{
						for(k=0; k<options.scrollStrings[i]; k++)
						{
							var li = document.createElement("li");
							$(li).html("&nbsp;");
							scrollList.append(li);								
						}
					}
				}
				$("li", scrollList).width(scrollHandle.outerWidth()+scrollSpacing);
			}
			
			 setScrollData(options.start);
		}
		var buttonNext = null;
		var buttonPrev = null;
		
		var navigationDiv, navigationList;
		var updateNavigationDot;
		
		if(options.navigation == "dots")
		{
			var div = document.createElement("div");
			$(div).attr("class", "slider-navigation");
			obj.append(div);
			navigationDiv = $(".slider-navigation", obj);
			
			navigationList = document.createElement("ul");
			navigationDiv.append(navigationList);
			navigationList = $(".slider-navigation ul", obj);
			
			for(var i=0; i<element.count; i++)
			{
				var lItem = document.createElement("li");
				var lLink = document.createElement("a");
				$(lLink).attr("href", "#");
				$(lLink).html("&nbsp;");
				if(i==current) $(lLink).addClass("active");
				$(lItem).append(lLink);
				navigationList.append(lItem);
				
				var thisLink = $(".slider-navigation ul li a", obj).eq(i);
				thisLink.click(function(){
					scrollTo($(this).parent().index()+1);					
					$("a", navigationList).removeClass("active");
					$(this).addClass("active");
				});
			}
			
			updateNavigationDot = function()
			{
				$("a", navigationList).removeClass("active");
				$("li", navigationList).eq(current-1).find("a").addClass("active");
			}
		}
		
		if(options.buttonNext)
		{
			obj.append("<div class=\"scrollcarousel-next\">Next</div>");
			buttonNext = $(".scrollcarousel-next", obj);	
		}
		
		if(options.buttonPrev)
		{
			obj.append("<div class=\"scrollcarousel-prev\">Prev</div>");
			buttonPrev = $(".scrollcarousel-prev", obj);	
		}
		
		
		var scrollNextCount = 0;
		var carouselTimeout;
		
		function next(){
			if(!carouselList.is(":animated"))
			{
				clearTimeout(carouselTimeout);
				
				var currentX = carouselList.position().left;
				currentX = currentX - (currentX % element.width);
				var currEl = currentX / element.width;
				
				
				if(currentX != -(element.width*(element.count-1)))
				{	
					var nextX = (currEl-1)*element.width;
					carouselList.animate({ left: nextX}, options.speed, options.easing);
					if(scrollContainer)
					{
						scrollNextX = (-currEl+1)*(scrollHandle.outerWidth()+scrollSpacing);
						scrollHandle.animate({left: scrollNextX }, options.speed, options.easing);
						setScrollData(-currEl+2);
						if(options.itemLoadCallback)
							options.itemLoadCallback(htmlObj, -currEl+2, element.count, options);
						if(options.itemVisibleCallback)
							options.itemVisibleCallback(htmlObj,-currEl+2,  element.count, options);
							
					}
					current = -currEl + 2;
				}
				else if(options.wrap=="both" || options.wrap == "right")
				{
					carouselList.animate({left:0}, options.speed, options.easing);
					if(scrollContainer)
					{
						scrollHandle.animate({left:0}, options.speed, options.easing);
						setScrollData(1);
						if(options.itemLoadCallback)
							options.itemLoadCallback(htmlObj, 1, element.count, options);
						if(options.itemVisibleCallback)
							options.itemVisibleCallback(htmlObj, 1, element.count, options);
					}
					current = 1;
				}				
				
				if(options.navigation == "dots") updateNavigationDot();
				
				scrollNextCount--;	
					
				if(options.auto)
				{
					carouselTimeout = setTimeout(next, options.auto * 1000);
				}				
			}
			else
			{
				if(scrollNextCount) carouselTimeout = setTimeout(next ,0.5);
			}
		}
		
		this.next = next;
		
		if(options.auto)
		{
			carouselTimeout = setTimeout(next, options.auto * 1000);
		}
		
		if(options.buttonNext)
		{
			buttonNext.click(function(){
				if(scrollNextCount<options.maxScroll) scrollNextCount++;
				next();
				return false;
			});
		}
		
		
		var scrollPrevCount = 0;
		
		function prev(){
			if(!carouselList.is(":animated"))
			{
				clearTimeout(carouselTimeout);
				
				var currentX = carouselList.position().left;
				currentX = currentX - (currentX % element.width);
				
				var currentX = carouselList.position().left;
				currentX = (!(currentX % element.width)) ? currentX: currentX - (currentX % element.width) - element.width;
				var currEl = currentX / element.width;
				
				if(currentX < 0)
				{	
					var nextX = (currEl+1)*element.width;
					carouselList.animate({ left: nextX }, options.speed, options.easing);
					if(scrollContainer)
					{
						scrollNextX = (-currEl-1)*scrollHandle.outerWidth() + (-currEl-1)*scrollSpacing;
						scrollHandle.animate({left: scrollNextX}, options.speed, options.easing);
						setScrollData(-currEl);
						if(options.itemLoadCallback)
							options.itemLoadCallback(htmlObj, -currEl, element.count, options);
							
						if(options.itemVisibleCallback)
							options.itemVisibleCallback(htmlObj,-currEl, element.count, options);
					}
					current = -currEl;
				}
				else if(options.wrap=="both" || options.wrap == "left")
				{
					carouselList.animate({left: -(carouselList.width()-element.width)}, options.speed, options.easing);
					if(scrollContainer)
					{
						nextScrollX = (element.count-1)*scrollHandle.outerWidth() + (element.count-1)*scrollSpacing;
						scrollHandle.animate({left: nextScrollX }, options.speed, options.easing);
						setScrollData(element.count);
						if(options.itemLoadCallback)
							options.itemLoadCallback(htmlObj, element.count, element.count, options);
						if(options.itemVisibleCallback)
							options.itemVisibleCallback(htmlObj,element.count,  element.count, options);
					}
					current = element.count;
				}				
				
				if(options.navigation == "dots") updateNavigationDot();
				
				scrollPrevCount--;	
				
				if(options.auto) carouselTimeout = setTimeout(next, options.auto * 1000)				
			}
			else
			{
				if(scrollPrevCount) carouselTimeout = setTimeout(prev ,0.5);
			}
		}
		
		this.prev = prev;
		
		if(options.buttonPrev)
		{
			buttonPrev.click(function(){
				if(scrollPrevCount<options.maxScroll) scrollPrevCount++;
				prev();
				return false;
			});
		}
		
		function scrollTo(smtg, settimeout)
		{
			settimeout = (typeof(settimeout)!='undefined') ? settimeout : true;
			if(smtg != null && (smtg<1 || smtg>element.count)) return;
			
			clearTimeout(carouselTimeout);
			
			var m_current;
			if(smtg)
			{
				m_current = smtg;
				if(options.navigation == "scroll") setScrollData(smtg);
				if(options.itemLoadCallback)
					options.itemLoadCallback(htmlObj, smtg, element.count, options);
				if(options.itemVisibleCallback)
					options.itemVisibleCallback(htmlObj,smtg, element.count, options);
			}
			else m_current = current;
			carouselList.animate({ 
				left: -( (m_current-1) * element.width)
			} , options.speed, options.easing)
			if(options.navigation == "scroll") 
				scrollHandle.animate({
					left: (m_current-1)*(scrollHandle.outerWidth() + scrollSpacing)
			}, options.speed, options.easing);
				
			if(options.navigation == "dots") updateNavigationDot();
			
			current = m_current;
			
			if(options.navigation == "dots") updateNavigationDot();
			
			
			if(options.auto && settimeout && !scrollFocused) carouselTimeout = setTimeout(next, options.auto * 1000);
		}
		this.goTo = scrollTo;
		
		function pause()
		{
			clearTimeout(carouselTimeout);	
		}
		this.pause = pause;
		
		function resume()
		{
			if(options.auto)
			carouselTimeout = setTimeout(next, options.auto * 1000);	
		}
		this.resume = resume;
		
		this.setAuto = function(interval)
		{
			options.auto = interval;
		}
		
		var scrollFocused;
		
		// Scroller Stuff
		if(options.navigation == "scroll")
		{
			
			var mouseMoveTimeOut, initLeft, initMouseLeft, scrollEnabled, mouseWasDown = false;
		
			var clickedButton;
			
			scrollContainer.click(function(){
				setTimeout(directClick, 1);							   
			});
			
			scrollContainer.hover(function(){
				scrollFocused = true;
				pause();							   
			}, function(){
				scrollFocused = false;
				resume();	
			});
			
			function directClick()
			{
				if(!clickedButton)
				{
					if(carouselList.is(":animated")) return;
					clearTimeout(carouselTimeout);
					
					var left = mouse.left - scrollContainer.offset().left;
					var top = mouse.top - scrollContainer.offset().top;
					
					var stepW = scrollHandle.width() + scrollSpacing;
					for(i=0; i<element.count; i++)
					{
						if(left > i*stepW - scrollSpacing/2 && left < (i+1)*stepW - scrollSpacing/2  )
							scrollTo(i+1);
					}
					
					clickedButton = false;
				}
				else clickedButton = false;
			}
				
			function moveScroll()
			{
				if(!scrollEnabled) return;
				clearTimeout(carouselTimeout);
				
				var newPos = (mouse.left-initMouseLeft) + initLeft;
				if(newPos>=0 && newPos <= scrollContainer.width()-scrollHandle.outerWidth())
				{
					scrollHandle.css("left", newPos);
					carouselList.css("left", -newPos/scrollRatio);
					var temp = carouselList.width()+(-newPos/scrollRatio);
					temp = element.count - (temp-((temp-(element.width/2))%element.width))/element.width;
					var temp2 = temp - (temp%1) +1;
					current = temp2;
					if(scrollHandle.html()!=temp2) setScrollData(temp2);
					if(options.itemVisibleCallback)
							options.itemVisibleCallback(htmlObj,temp2, element.count, options);
				}
				else if(newPos<0)
				{
					scrollHandle.css("left", 0);
					carouselList.css("left", 0);
				}
				else if(newPos > scrollContainer.width()-scrollHandle.outerWidth())
				{
					scrollHandle.css("left", scrollContainer.width()-scrollHandle.outerWidth());
					carouselList.css("left", -(carouselList.width()-element.width))
				}
			}
			
			scrollHandle.mousedown(function(){
				initLeft = scrollHandle.position().left;
				initMouseLeft = mouse.left;
				scrollEnabled = true;
				clickedButton = true;
				clearTimeout(carouselTimeout)
				
				return false;
			});
			
			$(document).mouseup(function(){
				
				if(scrollEnabled)
				{
					scrollEnabled = false;
											
					if(options.auto)
					{
						//carouselTimeout = setTimeout(next, options.auto * 1000);
					}
					
					if(options.autoAlign)
					{
						scrollTo(current, false);	
					}
				}
				
			});
			
			
			$(document).mousemove(function getMouseXY(e) {
			  if (IE) { // grab the x-y pos.s if browser is IE
				mouse.left = event.clientX + document.body.scrollLeft;
				mouse.top = event.clientY + document.body.scrollTop;
			  } else {  // grab the x-y pos.s if browser is NS
				mouse.left = e.pageX;
				mouse.top = e.pageY;
			  }  
			  // catch possible negative values in NS4
			  if (mouse.left < 0){mouse.left = 0};
			  if (mouse.top < 0){mouse.top = 0};
			  // show the position values in the form named Show
			  // in the text fields named MouseX and MouseY
			  
			  moveScroll();
							  
			  
			  return true;
			});
		
			scrollHandle.disableSelection();
	
		}
		
		options.buttonPrev && buttonPrev.disableSelection();
		options.buttonNext && buttonNext.disableSelection();
		
		if(options.carouselLoadedCallback)
			options.carouselLoadedCallback(this, current, element.count, options);
		
	});  
};  

jQuery.fn.extend({ 
        disableSelection : function() { 
                return this.each(function() { 
                        this.onselectstart = function() { return false; }; 
                        this.unselectable = "on"; 
                        jQuery(this).css('user-select', 'none'); 
                        jQuery(this).css('-o-user-select', 'none'); 
                        jQuery(this).css('-moz-user-select', 'none'); 
                        jQuery(this).css('-khtml-user-select', 'none'); 
                        jQuery(this).css('-webkit-user-select', 'none'); 
                }); 
        } 
});
