//
// Monitor scrolling in the web page, by setting a ScrollSpy
// Version 0.9.2
// By Willem Broekema, <willem@pastelhorn.com>
//
// More info and latest release:
// <http://pastelhorn.com/project/js/scrollspy>
//
// Licensed under the GNU LGPL
// <http://www.gnu.org/copyleft/lesser.html>
//
//// if you want to strip the comments, please keep the lines above /////
//
// License:
//
//  This script is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  See <http://www.gnu.org/copyleft/lesser.html> for the license.
//
//
//
// Inspired by:
//
//   "Drifting Layers:  Keeping Important Elements Visible"
//   -- Michael Bostock
//      http://developer.netscape.com/docs/technote/dynhtml/drift/
//
// History:
//
//  version 0.9.3, November 4, 2002
//   - Added fix for IE4/MacOS (thanks Jeroen Visser)
//
//  January 24, 2002
//   - Licensed under the LGPL (it had no license)
//
//  version 0.9.2, November 12, 2001
//   - Added "document.documentElement.scrollTop", used by IE 6.
//     (thanks Peter Zagler)
//
//  version 0.9.1, January 13, 2001:
//   -  Added conditional code for Opera to work around
//      "Anchor - setInterval bug"
//      (see <http://pastelhorn.com/project/js/scrollspy/operabug>).
//
//  version 0.9.0 -- January 5, 2000:
//   - First release.
//


// Part of browser detection script copied from 
// http://developer.netscape.com/docs/examples/javascript/browser_type.html
//
// This following Opera detection code is used to work around the
// "Anchor - setInterval" bug in (at least) Opera 5 
// -- see <http://pastelhorn.com/project/js/scrollspy/operabug>

var agt = navigator.userAgent.toLowerCase();
var isOperaSpy = (agt.indexOf("opera") != -1) ? 1 : 0;

/// the following browser detection code is not currently used, but
/// appears to be working:
//
// var isNav4Spy = (document.layers && !isOperaSpy) ? 1 : 0;
// var isIE4Spy  = (document.all && !isOperaSpy) ? 1 : 0;
// var isMozSpy  = (document.getElementById && !(isNav4Spy || isIE4Spy || isOperaSpy)) ? 1 : 0;
// var isOpera5IE5Spy = (document.all && (window.pageYOffset || window.pageYOffset == 0) ) ? 1 : 0;
//
// window.alert('op: ' + isOperaSpy + '; nav4: ' + isNav4Spy + '; isIE4: ' + isIE4Spy + '; moz: ' + isMozSpy + '; O5IE5: ' + isOpera5IE5Spy);

//
/// If (isMozSpy == 1), assume it's one of:
///  - Mozilla;
///  - Opera 5, set to be identified as 'Mozilla X',
///    with X one of (5.0; 4.76; 3.0).
//
/// If (isOpera5IE5Spy == 1), then assume browser is Opera set to
/// identify as 'MSIE 5' although it does not support all properties of it
//



function scrollSpy(theFunction) {

//
// First, set window.RANDOMNAME to this Spy object, so the outside world
// can refer to it.
//
// Although ugly, it's needed, if we want "setInterval()" to apply a method
// on our object:  when using "setInterval("this...", ..)", the
// "this" will refer to the window, because that's the object running
// the function "setInterval".
//
// Another solution would be, passing the object's name as parameter to
// the constructor:
//
//   S = new scrollSpy('S', func)
//
// and use the first parameter to build the "setInterval()" command line.
//

  var NameOfThisSpy = generateSpyInternalName();
  
  eval('window.' + NameOfThisSpy + ' = this;'); // window.RANDOMNAME = <this_spy>
  eval('this.name = "' + NameOfThisSpy + '";'); // <this_spy>.name = "RANDOMNAME"

  this.changeFunction = theFunction;
  this.intervalTime = 10;   // by default 200 milliseconds
  this.enabled = 0;
  this.monitor = monitorScrolling;

  this.getWindowYOffset = getWindowYOffsetSpy;
  this.prevWindowYOffset = 0;

 /// public interface:  

  this.start = startSpy;
  this.stop = stopSpy;
  this.isRunning = isRunningSpy;
  
  this.getIntervalTime = getIntervalTimeSpy;
  this.setIntervalTime = setIntervalTimeSpy;

 /////
}



function startSpy() {
  if (!this.enabled) { // not already running?

    var cmdstring = 'window.' + this.name + '.monitor()';
    
    if (!isOperaSpy)
      this.interval = window.setInterval( cmdstring, this.intervalTime );
    else // work around bug
      this.interval = window.setTimeout( cmdstring, this.intervalTime );

    this.enabled = 1;
  }
}

function stopSpy() {
  if (this.enabled) { // really running?
    window.clearInterval(this.interval);
    this.enabled = 0;
  }
}

function isRunningSpy() {
  return this.enabled;
}

    

function getIntervalTimeSpy() {
  return this.intervalTime;
}

function setIntervalTimeSpy(newValue) {
  var wasRunning = (this.enabled) ? 1 : 0;
  this.stop();
  this.intervalTime = newValue;
  if (wasRunning)
    this.start();
}



function getWindowYOffsetSpy() {

  if ( window.pageYOffset || window.pageYOffset == 0 )
    return window.pageYOffset;

  if ( document.body ) {
    if ( document.body.scrollTop || document.body.scrollTop == 0 ) {

      if ( document.documentElement ) {
        if ( document.documentElement.scrollTop || document.documentElement.scrollTop == 0 ) {
          // IE 6 uses document.documentElement.scrollTop instead of
          // document.body.scrollTop. Has to do with viewpoints -
          // see some w3 spec ;-)
          return document.body.scrollTop + document.documentElement.scrollTop;
        }

      } else {
        return document.body.scrollTop;
      }
    }
  }
}
  
function monitorScrolling() {

  var newWinYOffset = getWindowYOffsetSpy();
  var Scrolled = (newWinYOffset != this.prevWindowYOffset);

  this.prevWindowYOffset = newWinYOffset;

  if (Scrolled)
    eval( 'this.changeFunction(' + newWinYOffset + ')' );

  if (isOperaSpy) {  // work around bug
    var cmdstring = 'window.' + this.name + '.monitor()';
    this.interval = window.setTimeout( cmdstring, this.intervalTime);
  }
    
}



function generateSpyInternalName() {
  var now = new Date();
  var rand = Math.floor(  1000000 * Math.random(now.getTime())  );
  return ('spy' + rand + 's');
}

/// Part of Opera browser detection script copied from 
/// http://developer.netscape.com/docs/examples/javascript/browser_type.html

var agt = navigator.userAgent.toLowerCase();
var isOpera = ( (agt.indexOf("opera") != -1) && document.getElementById   ) ? 1 : 0;
var isNav4 = (document.layers && !isOpera) ? 1 : 0;
var isIE4  = (document.all && !isOpera) ? 1 : 0;
var isMoz  = ( document.getElementById && !(isNav4 || isIE4 || isOpera) ) ? 1 : 0;

/// Netscape 4 Resize Fix
/// Copied from Dan Steinman's "Dynamic Duo" site:
/// http://www.dansteinman.com/dynduo/en/widthheight.html

if (isNav4) {
  widthCheck = window.innerWidth;
  heightCheck = window.innerHeight;
  window.onResize = resizeFix;
}

function resizeFix() {
  if ( widthCheck != window.innerWidth || heightCheck != window.innerHeight )
    document.location.href = document.location.href;
} 

var smooth_timer;

function setSmoothTop(cur_abs_top, target_rel_top, scrolled, timeout) {
  layer = smooth_layer;
  target_abs_top = scrolled + target_rel_top;
  diff = target_abs_top - cur_abs_top;
  
  if (diff != 0) {
    diff_part = lookup_diff(diff);
    new_abs_top = cur_abs_top + diff_part;
    setTop(layer, new_abs_top);
    cmdstring = "setSmoothTop(" + new_abs_top + "," + target_rel_top + "," + scrolled + "," + timeout + ")";

    if (smooth_timer) {
      // When the user didn't wait for the div to reposition itself but has scrolled
      // before the div was ready, a timeout for the scrolling will be active. Remove
      // it, otherwise the div will never finish positioning itself, as the two timeouts
      // work against each other.
      window.clearTimeout(smooth_timer);
    }
    smooth_timer = window.setTimeout( cmdstring, timeout );
  }
}

function getTop(layer) {
  if (isNav4)  t = layer.top;
  else  if (isIE4) t = layer.style.pixelTop;
    else if (isMoz) {t = layer.style.top;}
      else if (isOpera) t = layer.style.top;
  i = parseInt(t); // remove '..px' if present
  return i;
}

function setTop(layer, t) {
 if (isNav4) layer.top = t;
  else if (isIE4) layer.style.pixelTop = t;
    else if (isMoz) {var p = '' + t + 'px';layer.style.top = p;}
      else if (isOpera) layer.style.top = t;
}

function getDiv(divname) {
	// given name 'divname', return div object
	// if div is within otherdiv, use 'otherdivname.divname' format as parameter
	divs = divname.split('.'); 
	//if (isNav4) {
	//	s = '';
	//	for (i = 0; i < divs.length; i++) {
	//		s += 'document.layers.' + divs[i];
	//		if (i < divs.length - 1) 
	//			s += '.';
	//	}		
	//	return  eval(s);
	//}
	//if (isIE4) return eval( 'document.all.' + divs[ divs.length-1 ] );
	//if (isMoz || isOpera) return document.getElementById(divs[ divs.length-1 ] );
	//alert(isMoz);
	return document.getElementById(divs[ divs.length-1 ] );
}

var do_smooth = 1;
var smooth_timeout = 30;

function lookup_diff(i) { // undefined for i=0
  if (i > 0) {n = 0.10 * i;
	    if (n > 3) n++;
  	  return Math.ceil(n)
  } 
  if (i < 0) {n = 0.10 * i;
    if (n < -3) n--;
    return Math.floor(n)
  }
  if (i == 0) return 'error';
}

var moving_layer;
var smooth_layer;
function update(scrollPos) {
if (do_smooth) setSmoothTop( getTop(smooth_layer), 10, scrollPos,smooth_timeout);
  else {setTop(moving_layer, scrollPos+10);}
}
var S;
function initSpy() {moving_layer = getDiv("arrow");smooth_layer = moving_layer;S = new scrollSpy(update);S.start();
}