/**
 * zudolab jqTinyscrolling
 *
 * @version    1  (updated: 2008/12/16)
 * @author     Takeshi Takatsudo (http://zudolab.net/)
 * @license    MIT (http://www.opensource.org/licenses/mit-license.php)
 * original idea by Marco Rosella (http://lab.centralscrutinizer.it/the-tiny-scrollings/)
 */

(function($){
	
	var currentSpeed;
	var currentMaxStep;
	var currentBrakeK;
	var currentAddHash;
	var currentTarget;
	var currentHash;
	var currentRequestedY;
	var currentScrollTimer;

	jqTinyscrolling = function(settings)
	{
		this.speed = settings && settings.speed ? settings.speed : 20;
		this.maxStep = settings && settings.maxStep ? settings.maxStep : 200;
		this.maxStepWhenLongDoc = settings && settings.maxStepWhenLongDoc ? settings.maxStepWhenLongDoc : 1000;
		this.brakeK = settings && settings.brakeK ? settings.brakeK : 3;
		this.addHash = settings && settings.addHash===false ? false : true;
		this.anchors = [];
		
		/* exec setup when onload */
		var self = this;
		$(function(){ self.setup(); });
	}
	
	jqTinyscrolling.prototype.setup = function()
	{
		this.prepareAnchors();
		if(!this.anchors) return;
		this.setEvents();
	}
	jqTinyscrolling.prototype.prepareAnchors = function()
	{
		var allAnchors = $("a[href^=#]");
		for(var i=0,anchor; anchor=allAnchors[i]; i++){
			if($(anchor).hasClass("avoidScroll")) continue;
			this.anchors.push(anchor);
		}
	}
	jqTinyscrolling.prototype.setEvents = function()
	{
		var self = this;
		for(var i=0,anchor; anchor=this.anchors[i]; i++){
			$(anchor).click(function(){
				if(currentRequestedY) releaseCurrentScrollInfo();
				if(setCurrentScrollInfo(this)) {
					// If the element being scrolled to is an owc-ui expandoSection component
					//	and it is in a closed state - toggle it open
					var scrollToElementId = '#' + $(this).attr('href').substring(1);
					var scrollToElement = jQuery(scrollToElementId);
					if ($(scrollToElement).data('owc-ui-type') && $(scrollToElement).data('owc-ui-type') == 'expandoSection') {
						var scrollToContentElement = jQuery(scrollToElementId + ' .showMoreLessContentElement');
						var scrollToControlElement = jQuery(scrollToElementId + ' .showMoreLessControlElement');
						if(scrollToContentElement.css('display') == 'none')
							scrollToControlElement.click();
					}
					scroll();
				}
				return false;
			});
		}
		function setCurrentScrollInfo(anchor)
		{
			var $anchor = $(anchor);
			var hash = $anchor.attr("href").replace("#","");
			var target = document.getElementById(hash);
			if(!target) return false;
			currentTarget = target;
			currentHash = hash;
			currentRequestedY = $(target).offset().top;
			currentSpeed = self.speed;
			currentMaxStep = ($(document).height()>2500) ? self.maxStepWhenLongDoc : self.maxStep;
			currentBrakeK = self.brakeK;
			currentAddHash = self.addHash;
			return true;
		}
	}
	function scroll()
	{
		var top = $(document).scrollTop();
		if(currentRequestedY > top){
			var endDistance = 
				Math.round(($(document).height() - (top + $(window).height())) / currentBrakeK);
			endDistance = 
				Math.min(Math.round((currentRequestedY-top)/ currentBrakeK), endDistance);
			var offset = 
				Math.max(2, Math.min(endDistance, currentMaxStep));
			if(Math.round((currentRequestedY-top)/ currentBrakeK)<10)
				offset = 2;
		}else{
			var offset =
				- Math.min(Math.abs(Math.round((currentRequestedY-top)/ currentBrakeK)), currentMaxStep);
		}
		window.scrollTo(0, top + offset);
		if(Math.abs(top-currentRequestedY) <= 1 || $(document).scrollTop() == top){
			window.scrollTo(0, currentRequestedY);
			if(currentAddHash && (!document.all || window.opera)) location.hash = currentHash;
			releaseCurrentScrollInfo();
		}else{
			currentScrollTimer = setTimeout(scroll, currentSpeed);
		}
	}
	function releaseCurrentScrollInfo()
	{
		currentSpeed = null;
		currentMaxStep = null;
		currentBrakeK = null;
		currentAddHash = null;
		currentTarget = null;
		currentHash = null;
		currentRequestedY = null;
		clearTimeout(currentScrollTimer);
		currentScrollTimer = null;
	}
	
	/* override opera 9.5 jQuery height problem */
	(function(){
		if(!$.browser.opera || $.browser.version < 9.5) return;
		$.each([ 'Height', 'Width' ], function(i, name){
			var type = name.toLowerCase();
			var originalMethod = $.fn[ type ];
			$.fn[ type ] = function( size ) {
				return this[0] == window
					? document.documentElement[ 'client' + name ] 
					: originalMethod.call(this,size);
			};
		});
	})();
	
})(jQuery);

new jqTinyscrolling;
