// Smoothscroll v0.4

var frame=false;
var noscrollframe=false;

var scrollup=true;
var scrolldown=true;
var delta = 0;

var yoff=0;
var initdone=false;

// tweakables
var framerate = 50;  // hz
var animtime = 600;  // faster than picasa
var scrollsz = 120;  // pixels

// less tweakables
var PulseScale = 8;		// ratio of 'tail' to 'acceleration'
var PulseNormalize = 1;

function init() {
	// Checks if this script is running in a frame
	if (top != self)  {
		frame=true;

		/* The following is a quick fix for non scrollable frames
		Normally there is an attribute scrolling=no for
		the frame/iframe, but i have no idea how
		to access this inside that frame. 
		Help me please if you know that */

		if (document.body.scrollHeight <= (document.body.clientHeight+10)) {
		noscrollframe=true;
		}
	}
	if (frame != true) {
		/* This fixes a bug where the areas left and right 
		to the content does not trigger the onmousewheel event 
		on some pages */
		if ((document.body.offsetHeight + 10) < document.body.scrollHeight)
			document.body.style.height = document.body.scrollHeight + "px";
	}
	initdone=true;
}

function wheel(event){
	// console.log(window.event.srcElement);

	if (initdone==false) init();
	/* This fixes a bug where sometimes the window.onload event is
 	never called. It happens very often in google ads. */

	var scroll=true;
	var src = window.event.srcElement;
	
	// for (var i=0; i<7; i++) {
	do {
		if (document.body.scrollHeight == src.scrollHeight) { 
			// console.log("Nothing todo here anymore");
			scroll=true;
			break;
		}	
		else {
			if (src.style) {
				if (src.clientHeight + 10 < src.scrollHeight) {
				// The "+10" fixes various bugs
				// console.log(i);
				// console.log(src);
				// console.log("different Heights");
				overflow = 
		document.defaultView.getComputedStyle(src,"").getPropertyValue("overflow");
					if (overflow=="scroll" || overflow=="auto") {
						scroll = false;
						break;
					
					}
				}
			}
		}
	} while(src = src.parentElement)
	
	if (frame==true) {
		if (noscrollframe==true) { 
			scroll=false;
		}
		else {
			if ((yoff==window.pageYOffset) && (delta<0)) {
				//The last scroll downwards did nothing
				scrollup=true;
				scrolldown=false;
			}
			if ((yoff==window.pageYOffset) && (delta>0)) {
				//The last scroll upwards did nothing
				scrollup=false;
				scrolldown=true;
			}
		yoff = window.pageYOffset;	
		}
	}

	

	if (scroll==true) {
		delta = 0;
    if (event.wheelDelta) { 
			delta = event.wheelDelta/120;
		}
		
		/* Currently scrollup/down are used for special cases in
		frames but later they will be also used  for smooth 
		scrolling of scrollable elements, i think */

		if ((scrolldown==true && delta < 0) || (scrollup==true && delta > 0)) {
			scrollup=true;
			scrolldown=true;
			handle(delta);
			if (event.preventDefault)
			event.preventDefault();
			event.returnValue = false;
		}
	}
}

window.onload = init;
window.onmousewheel = wheel;

var scrolls = setupScrolls();

// viscous fluid with a pulse for part and decay for the rest
function Pulse_(x)
{
  var val;

  // test
  x = x * PulseScale;
  if (x < 1) {val = x - (1 - Math.exp(-x));} 
  else {
    // the previous animation ended here:
    var start = Math.exp(-1);

    // simple viscous drag
    x -= 1;
    var expx = 1 - Math.exp(-x);
    val = start + (expx * (1.0 - start));
  }

  return val * PulseNormalize;
}

function ComputePulseScale()
{
  PulseNormalize = 1 / Pulse_(1);
}

// viscous fluid with a pulse for part and decay for the rest
function Pulse(x)
{
  if (x >= 1) return 1;
  if (x <= 0) return 0;

  if (PulseNormalize == 1) {
    ComputePulseScale();
  }

  return Pulse_(x);
}

ComputePulseScale();

function setupScrolls() {

	scrolls = new Array();
	
	var last = 0;
	var frm = parseInt(framerate * animtime / 1000);
	
	for (var i = 0; i < frm; i++) {

    // scroll is [0, 1]
    var scroll = (i + 1) / frm;
    // transform [0, 1] -> [0, 1]:
    scroll = Pulse(scroll);

    // scale and quantize to int so our pixel difference works:
    var iscroll = parseInt(scrollsz * scroll + 0.99);
    
    scrolls.push(iscroll - last);
    last = iscroll;
	}
	
	return scrolls;
}

function handle(delta) {

	if (!scrolls)
		setupScrolls();

  // be super-linear with "delta"
  // if you hit the mousewheel hard, you want to scroll a bunch
  // $$$ note: this doesn't do much on fast machines, should revisit:
  var moredelta = delta * delta;
  if (delta < 0) moredelta = -moredelta;

  //document.title = moredelta;

	for (var i=0; i < scrolls.length; i++) {
    if (scrolls[i]) 
      setTimeout ('window.scrollBy( 0 ,' + -moredelta * scrolls[i] + ');', i * 1000 / framerate + 1);
	}
}

/****************************************************
 Contact me at patrickb1991@ gmail . com
*****************************************************/
