﻿/**
* jQuery.smoothDivScroll - Smooth div scrolling using jQuery.
* This plugin is for turning a set of HTML elements's into a smooth scrolling area.
*
* Copyright (c) 2009 Thomas Kahn - thomas.kahn(at)karnhuset(dot)net
*
* This plugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details. <http://www.gnu.org/licenses/>.
*
* Date: 2009-05-23
* @author Thomas Kahn
* @version 0.8
*
*/

(function($) { 
	jQuery.fn.smoothDivScroll = function(options){

		var defaults = {
			scrollingHotSpotLeft: "div.scrollingHotSpotLeft",
			scrollingHotSpotRight: "div.scrollingHotSpotRight",
			scrollWrapper: "div.scrollWrapper",
			scrollableArea: "div.scrollableArea", 
			hiddenOnStart: false,
			ajaxContentURL: "",
			countOnlyClass: "",
			scrollingSpeed: 30, // 1 = slowest - 100 = fastest
			mouseDownSpeedBooster: 1,
			autoScroll: "",
			autoScrollDirection: "right", 	// left - right - backandforth - endlessloop
			autoScrollSpeed: 1,
			pauseAutoScroll: "",
			visibleHotSpots: "always", //"onstart", // onstart / always
			hotSpotsVisibleTime: 10, 
			startAtElementId: ""
		};

		options = $.extend(defaults, options);
		
		return this.each(function() {

			var $mom = $(this);
			var scrollXpos;
			var booster;
			var motherElementOffset = $mom.offset().left;
			var hotSpotWidth = 0;
			var hasExtended = false;
			
			booster = 1;

			$(window).one("load", function() {
				
				// calculate the width of the scrolling area, resize it to that width
				
				$mom.scrollableAreaWidth = 0;
				$mom.tempStartingPosition = 0;
				
				$mom.find(options.scrollableArea).children((options.countOnlyClass)).each(function() {
				
					// Add the width of the current element in the loop to the total width
					$mom.scrollableAreaWidth = $mom.scrollableAreaWidth + $(this).outerWidth(true);
					
				});
				
				// Set the width of the scrollableArea to the accumulated width
				$mom.find(options.scrollableArea).css("width", $mom.scrollableAreaWidth + "px");
								
				// Set the starting position of the scrollable area. If no startAtElementId is set, the starting position will be the default value (zero)
				$mom.find(options.scrollWrapper).scrollLeft($mom.tempStartingPosition);
				
				// If the user wants to have visible hot spots, here is where it's taken care of
				switch (options.visibleHotSpots) {
					
					case "always":
						makeHotSpotBackgroundsVisible();
						break;
					
					case "onstart":
						makeHotSpotBackgroundsVisible();
						$mom.hideHotSpotBackgroundsInterval = setInterval(hideHotSpotBackgrounds, (options.hotSpotsVisibleTime * 1000));
						break;
					
					default: break;	
				
				}
				
			});
			
			// WINDOW RESIZE
			
			$(window).bind("resize", function() {
				windowIsResized();
			});

			function windowIsResized() {

				// Reset the left offset of the scroll wrapper
				$mom.find(options.scrollWrapper).scrollLeft("0");
				
				// Get the width of the page (body)
				var bodyWidth = $("body").innerWidth();

				if ($mom.scrollableAreaWidth < bodyWidth) {	
				
					hideLeftHotSpot();
					hideRightHotSpot();
				
				} else {
				
					showHideHotSpots();
				
				}
			}
			
			function hideLeftHotSpot() {
				$mom.find(options.scrollingHotSpotLeft).hide();
			}
			
			function hideRightHotSpot() {
				$mom.find(options.scrollingHotSpotRight).hide();
			}
			
			function showLeftHotSpot() {
				$mom.find(options.scrollingHotSpotLeft).show();
				if (hotSpotWidth <= 0) {
					hotSpotWidth = $mom.find(options.scrollingHotSpotLeft).width();
				}
			}
			
			function showRightHotSpot() {
				$mom.find(options.scrollingHotSpotRight).show();
				if (hotSpotWidth <= 0) {
					hotSpotWidth = $mom.find(options.scrollingHotSpotRight).width();
				}
			}
			
			function setHotSpotHeightForIE() {
				jQuery.each(jQuery.browser, function(i, val) {
					if (i=="msie" && jQuery.browser.version.substr(0,1) == "6") {
						$mom.find(options.scrollingHotSpotLeft).css("height", ($mom.find(options.scrollableArea).innerHeight()));
						$mom.find(options.scrollingHotSpotRight).css("height", ($mom.find(options.scrollableArea).innerHeight()));				
					}
				});
			}
			
			
			// SCROLL RIGHT
			
			// Check the mouse X position and calculate the relative X position inside the right hot spot
			$mom.find(options.scrollingHotSpotRight).bind('mousemove',function(e) {
				
				var x = e.pageX - (this.offsetLeft + motherElementOffset);
				scrollXpos = Math.round((x/hotSpotWidth) * options.scrollingSpeed);
				
				if (scrollXpos === Infinity) {
					scrollXpos = 0;
				}

			});

			// mouseover right hot spot
			$mom.find(options.scrollingHotSpotRight).bind('mouseover',function(){
				$mom.rightScrollInterval = setInterval(doScrollRight, 6);
			});	
			
			// mouseout right hot spot
			$mom.find(options.scrollingHotSpotRight).bind('mouseout',function(){
				clearInterval($mom.rightScrollInterval);
				scrollXpos = 0;
			});
			
			// scrolling speed booster right
			$mom.find(options.scrollingHotSpotRight).bind('mousedown',function(){
				booster = options.mouseDownSpeedBooster;
			});
			
			// stop boosting the scrolling speed
			$("*").bind('mouseup',function(){
				booster = 1;
			});
	
			
			// The function that does the actual scrolling right
			var doScrollRight = function() {	
				
				if (scrollXpos > 0) {
				
					$mom.find(options.scrollWrapper).scrollLeft($mom.find(options.scrollWrapper).scrollLeft() + (scrollXpos*booster));
				
				}
				
				showHideHotSpots();
			
			};
			
		
			// SCROLL LEFT
		
			// Check the mouse X position and calculate the relative X position inside the left hot spot
			$mom.find(options.scrollingHotSpotLeft).bind('mousemove',function(e){
				var x = $mom.find(options.scrollingHotSpotLeft).innerWidth() + 215 - (e.pageX - motherElementOffset);
				
				scrollXpos = Math.round((x/hotSpotWidth) * options.scrollingSpeed);

				if (scrollXpos === Infinity) {
					scrollXpos = 0;
				}
			});
			
			// mouseover left hot spot
			$mom.find(options.scrollingHotSpotLeft).bind('mouseover',function() {
				if (options.autoScroll == "onstart") {
					clearInterval($mom.autoScrollInterval);
				}
				
				$mom.leftScrollInterval = setInterval(doScrollLeft, 6);
			});	
			
			// mouseout left hot spot
			$mom.find(options.scrollingHotSpotLeft).bind('mouseout',function() {
				clearInterval($mom.leftScrollInterval);
				scrollXpos = 0;
			});
			
			// scrolling speed booster left
			$mom.find(options.scrollingHotSpotLeft).bind('mousedown',function() {
				booster = options.mouseDownSpeedBooster;
			});
			
			// The function that does the actual scrolling left
			var doScrollLeft = function() {				
				if (scrollXpos > 0) {
					$mom.find(options.scrollWrapper).scrollLeft($mom.find(options.scrollWrapper).scrollLeft() - (scrollXpos*booster));
				}
				showHideHotSpots();
			};
			

			// HOTSPOTS
			
			function showHideHotSpots() {

				if ($mom.find(options.scrollWrapper).scrollLeft() === 0) {

					// When you can't scroll further left, the left scroll hot spot should be hidden and the right hot spot visible
				
					hideLeftHotSpot();
					showRightHotSpot();
				
				} else if (($mom.scrollableAreaWidth) <= ($mom.find(options.scrollWrapper).innerWidth() + $mom.find(options.scrollWrapper).scrollLeft())) {
					
					// When you can't scroll further right the right scroll hot spot should be hidden and the left hot spot visible
					
					hideRightHotSpot();
					showLeftHotSpot();
				
				} else {
					
					// If you are somewhere in the middle of your scrolling, both hot spots should be visible
				
					showRightHotSpot();
					showLeftHotSpot();
				
				}
			}
			
			// Function for making the hot spot background visible
			
			function makeHotSpotBackgroundsVisible() {
				
				// The left hot spot
				$mom.find(options.scrollingHotSpotLeft).addClass("scrollingHotSpotLeftVisible");

				// The right hot spot
				$mom.find(options.scrollingHotSpotRight).addClass("scrollingHotSpotRightVisible");
			
			}

			// Hide the hot spot backgrounds.
			
			function hideHotSpotBackgrounds() {
			
				clearInterval($mom.hideHotSpotBackgroundsInterval);

				// Fade out the left hot spot
				$mom.find(options.scrollingHotSpotLeft).fadeTo("slow", 0.0, function(){
					$mom.find(options.scrollingHotSpotLeft).removeClass("scrollingHotSpotLeftVisible");
				});

				// Fade out the right hot spot
				$mom.find(options.scrollingHotSpotRight).fadeTo("slow", 0.0, function(){
					$mom.find(options.scrollingHotSpotRight).removeClass("scrollingHotSpotRightVisible");
				});
			}			
			
	});
};

})(jQuery);

