var scrollTopPosition = 0;
var autoScrolling = false;
var scrollerElement = document.body; //document.documentElement;
var scrollSpeed = 0;

// Functions
function ScrollBody(e)
{
	if(e == null) e = event;
	
    var wheelDelta = ScrollDelta(e) * 30;
	wheelDelta = (wheelDelta > 0) ? 70 : -70;
	
	if(autoScrolling == false)
	{
		scrollerElement = DetectBodyElement(wheelDelta / Math.abs(wheelDelta)); // it should pass 1 or -1
		if(scrollerElement.scrollTop > 0) scrollTopPosition = scrollerElement.scrollTop;
	}
	
    scrollTopPosition += wheelDelta;
    
    if(scrollTopPosition < 0) scrollTopPosition = 0;
    
    if(!autoScrolling)
    {
        autoScrolling = true;
        ProcessVScroll();
    }
}

function ProcessVScroll()
{
    if(scrollTopPosition > scrollerElement.scrollTop - 1 && scrollTopPosition < scrollerElement.scrollTop + 1)
    {
        scrollerElement.scrollTop = scrollTopPosition;
        autoScrolling = false;
    }
    else
    {
		var speed = (Math.abs(scrollTopPosition - scrollerElement.scrollTop) / 10 > 0.1) ? (Math.max(scrollTopPosition, scrollerElement.scrollTop) - Math.min(scrollTopPosition, scrollerElement.scrollTop)) / 10 : 1;
        scrollSpeed = (speed > scrollSpeed) ? scrollSpeed + 1 : speed;
		
		var lastScrollTop = scrollerElement.scrollTop;
        
        scrollerElement.scrollTop = (scrollTopPosition > scrollerElement.scrollTop) ? scrollerElement.scrollTop + scrollSpeed : scrollerElement.scrollTop - scrollSpeed;
        
        if(lastScrollTop != scrollerElement.scrollTop)
        {
            setTimeout(ProcessVScroll, 10);
        }
        else
        {
            autoScrolling = false;
			scrollSpeed = 0;
        }
    }
}

function DetectBodyElement(dir)
{
	// Method 1
	if(document.body.scrollTop > 0 || document.documentElement.scrollTop > 0)
	{
		return (document.body.scrollTop > document.documentElement.scrollTop) ? document.body : document.documentElement;
	}
	
	// Method 2
	document.body.scrollTop += 1;
	document.documentElement.scrollTop += 1;
	
	return (document.body.scrollTop != document.documentElement.scrollTop) ? DetectBodyElement(dir) : document.body;
}

function RegisterWheelScrollEvent()
{
    // register event
    AddEventHandler(document.documentElement, "MouseScroll", ScrollBody, true);
    AddEventHandler(document.body, "MouseScroll", ScrollBody, true);
}

var AddEventHandler = function(obj, eventType, func, useEventCapture)
{
	try
	{
	    if(eventType.toLowerCase() == "mousescroll") eventType = "mousewheel";
	    
		if (obj.addEventListener)
		{
		    if(!obj.addEventListener(eventType, func, useEventCapture))
		    {
		        var eventName = eventType;
		        if(eventName.toLowerCase() == "mousewheel") eventName = "MouseScroll";
		        
		        if(!obj.addEventListener("DOM"+eventName, func, useEventCapture))
		        {
		            //obj["on" + eventType] = func;
		        }
		    }
		}
		else if(obj.attachEvent)
		{
			obj.attachEvent("on" + eventType, func);
		}
		else
		{
		    obj["on" + eventType] = func;
		}
	}
	catch(exception)
	{
		window.title = exception + " in AddEventHandler()";
	}
}

var ScrollDelta = function(e)
{
    var wheelDelta = 0;

    if (!e) e = window.event;

    if(e.detail) 
    {         
        wheelDelta = e.detail;
        
        // reduce because Opera is giving too large numbers
        if(wheelDelta > 1) wheelDelta = Math.ceil(wheelDelta / 3);
    }
    else if(e.wheelDelta)
    {
        wheelDelta = Math.floor(-e.wheelDelta / 30);
    }

    BlockEvent(e);
    
    return wheelDelta;
}

var BlockEvent = function(e)
{
    if(e.stopPropagation) e.stopPropagation();
    else e.cancelBubble = true;
    if(e.preventDefault) e.preventDefault();
    else e.returnValue = false;
}

RegisterWheelScrollEvent();
