// valzSideScroll.js

// Side-scrolling and unobtrusive link substitution

var animLength = .7; // number of seconds for the transition
var fps = 60; // # frames per second (may not be honoured depending on browser speed)
var mouseWheelScrollDistance = 10;
var mouseWheelAcceleration = 1.5;

addLoadEvent(valzSideScroll); // auto-run once page loads

if (navigator.appName.match("Microsoft")) animLength/=1.5;


function valzSideScroll(){
	if (document.getElementsByTagName) {
		// first off, let's get a list of all the named anchors on this page
		var namedAnchorsObj = new Object();		
		
		var linksAry = document.getElementsByTagName("a");
		for (var i=0; i<linksAry.length; ++i){
			if (linksAry[i].name) namedAnchorsObj[linksAry[i].name] = linksAry[i];;
		}

		// now, let's go through all the links on this page that actually link to named anchors on this page
		var matchLocalLinks = new RegExp("#([^.]+)$");
		for (var i=0; i<linksAry.length; ++i){
			if (linksAry[i].href.match(matchLocalLinks)){
				if (namedAnchorsObj[RegExp.$1]) {
					var thisLink = linksAry[i];
					var namedAnchor = namedAnchorsObj[RegExp.$1];
					
					var linkClickHandler = function(a){ return(function(e){return localLinkClick(e,a)})}(namedAnchor); // encapsulate namedAnchor
					
					if (thisLink.addEventListener){
						thisLink.addEventListener("click", linkClickHandler , false); // correct DOM way
					} else {
						thisLink.onclick = linkClickHandler;
					}
				}
			}
		}
	} // else we're in a load of trouble
}



function localLinkClick(evt, anchorObj){
	//window.scrollTo(findPos(anchorObj).x, window.scrollY); // the quick and dirty (transitionless) way

	beginX = findScrollPos().x;
	endX = findPos(anchorObj).x; 
	deltaX = endX - beginX;
	time = 0;
	
	if (timerID) clearInterval(timerID); // not sure whether this is even necessary
	timerID = setInterval(enterFrame, 1000/fps);

	
	// and now cancel the click so we don't jump straight there using the old HTML way
	if (evt && evt.preventDefault) evt.preventDefault(); // correct DOM approach to cancelling the event
	if (evt) evt.returnValue = false;
	return false; // oldskool IE way of cancelling the event
}

function enterFrame(){
	time++;

	window.scrollTo(easeInOut(time, beginX, deltaX, animFrames), window.scrollY);

	if (time >= animFrames){
		clearInterval(timerID);
	}
}






// Mousewheel Handling
if (window.addEventListener){
	window.addEventListener('DOMMouseScroll', wheelScroll, false); // FF
	window.addEventListener('mousewheel', wheelScroll, false); // Safari
} else {
	document.onmousewheel = wheelScroll;
}


var lastScroll = new Date();
var scrollMultiplier = 1;

function wheelScroll(e){
	e = e || window.event;
	
	// figure out the direction of the wheel scroll
	var d = 0;
	if (e.wheelDelta) { /* IE/Opera. */
		d = e.wheelDelta / 120;
		if (window.opera) {	
			d = - d; // Opera is whacked
		} else if (navigator.userAgent.match(/chrome/i)) {
			d /=10; // you wouldn't want Google Chrome to be perfect, would you?
		}
	} else if (e.detail) {
		d = - e.detail / 10; // Firefox
	}
	d = - d; // (down is positive)
	
	
	// add acceleration
	var t = new Date();
	if (t - lastScroll < 150){
		scrollMultiplier += mouseWheelAcceleration;
	} else {
		scrollMultiplier = 1;
	}
	lastScroll = t;
	
	// now scroll the screen
	window.scrollTo(findScrollPos().x + (mouseWheelScrollDistance * d * scrollMultiplier), findScrollPos().y);


	if (e.preventDefault) e.preventDefault();
	e.returnValue = false;
	return false;
}

var animFrames = animLength * fps; // total number of frames for the animation
var beginX;
var endX;
var deltaX;
var time = 0;

var timerID; // timer variable














// utility functions adapted from quirksmode.org. Thanks, PPK, as always!
function findPos(obj) {
	var left = !!obj.offsetLeft ? (obj.offsetLeft-32) : 0;
	var top = !!obj.offsetTop ? obj.offsetTop : 0;

	while((obj = obj.offsetParent)){
		left += !!obj.offsetLeft ? obj.offsetLeft : 0;
		top += !!obj.offsetTop ? obj.offsetTop : 0;
	}

	return{x:left, y:top};
}

function findScrollPos(){
	var x,y;
	if (self.pageYOffset) // all except Explorer
	{
		x = self.pageXOffset;
		y = self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop)
		// Explorer 6 Strict
	{
		x = document.documentElement.scrollLeft;
		y = document.documentElement.scrollTop;
	}
	else if (document.body) // all other Explorers
	{
		x = document.body.scrollLeft;
		y = document.body.scrollTop;
	}

		return {x:x, y:y};
}

function easeInOut (t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	}


// unused, but really cool...................
function createEventHandler(obj, evt, func){
	if(obj[evt]){
		obj[evt]=function(f,g){
			return function(){
				f.apply(this,arguments);
				return g.apply(this,arguments);
			};
		}(func, obj[evt]);
	} else  obj[evt]=func;
}




// Unobtrusive Load of MAIN script :-----------------------------------------------------------------



// Run code when the page loads.
function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}
