//=========================================================
// custom scroller developed for 2027.org by aaron boodman
//
// some sections based on ypSimpleScroll.js.
//
// www.youngpup.net
// 3/28/2001 (3 hours before site launch!)
//
// updated 
// - 8/29/02 : fixed performance issues related to using
//   background images
//=========================================================
// code is art!
//=========================================================

var gsScroll = null;

function Scroller()
{
    this.name        = "";
    this.speed       = 100;
  	this.aniLen      = 1000;
  	this.clipH       = 0;
  	this.thumbMax    = 0;
  	this.thumbH      = 11;
  	this.scrollbarH  = 0;
  	this.scrollTop   = 0;
  	this.scrollLeft  = 0;
  	this.minRes      = 0;
  	this.ie4         = navigator.appName == "Microsoft Internet Explorer" && !document.getElementById;
  	this.ns4         = document.layers ? 1 : 0;
  	this.dom         = document.getElementById ? 1 : 0;
  	this.mac         = navigator.platform == "MacPPC";
  	this.mo5         = navigator.userAgent.indexOf("Gecko") != -1;
  	this.dir         = 0;
    this.lastTime    = 0;
    this.aniTimer    = 0;
    this.dragActive  = 0;
    this.dragLastY   = 0;
    this.dragStartOffset = 0;
  	this.startPos    = 0;
    this.startTime   = 0;
    this.accel       = 0;
    this.endPos      = 0;
    this.dist        = 0;
    this.lyrFrame, this.lyrScrollbar, this.lyrScrollbarGlobal, this.lyrThumb, this.lyrMarker, this.lyrElevUp, this.lyrElevDn, this.lyrContainer, this.lyrContent; 
  
  this.init = function()
  {
  		// gather pieces
  		this.lyrFrame           = this.getLyr("scroller"+this.name, document)
  		this.lyrScrollbar       = this.getLyr("scrollbar"+this.name, this.lyrFrame)
  		this.lyrScrollbarGlobal = this.getLyr("scrollbarGlobal"+this.name, this.lyrFrame)
  		this.lyrThumb           = this.getLyr("thumb"+this.name, this.lyrScrollbar)
  		this.lyrMarker          = this.getLyr("marker"+this.name, this.lyrScrollbar)
  		this.lyrElevUp          = this.getLyr("elevUp"+this.name, this.lyrScrollbar)
  		this.lyrElevDn          = this.getLyr("elevDn"+this.name, this.lyrScrollbar)
  		this.lyrContainer       = this.getLyr("container"+this.name, this.lyrFrame)
  		this.lyrContent         = this.getLyr("content"+this.name, this.lyrContainer)
  		
  		this.clipH = this.lyrFrame.offsetHeight;
  		this.scrollbarH = this.lyrScrollbarGlobal.clientHeight-6;
  		this.thumbMax = this.lyrScrollbarGlobal.clientHeight-50;
  		
  		// calculate some values
  		this.docH            = Math.max(this.ns4 ? this.lyrContent.document.height : this.lyrContent.offsetHeight, this.clipH)
  		this.scrollH         = this.docH - this.clipH
  		
  		if (this.docH > this.clipH)
      {
  			// hook events
  			this.lyrElevUp.onmousedown   = this.slideTo
  			this.lyrElevDn.onmousedown   = this.slideTo
  			this.lyrThumb.onmousedown    = this.startDrag
  			this.lyrThumb.ondragstart    = function() { return false; }
  			this.lyrElevUp.onmouseover   = function() { this.sObj.toggleElev(this.sObj.lyrElevUp, 2) }
  			this.lyrElevUp.onmouseout    = function() { this.sObj.toggleElev(this.sObj.lyrElevUp, 1) }
  			this.lyrElevDn.onmouseover   = function() { this.sObj.toggleElev(this.sObj.lyrElevDn, 2) }
  			this.lyrElevDn.onmouseout    = function() { this.sObj.toggleElev(this.sObj.lyrElevDn, 1) }
  			
  			// initialize some settings
  			this.lyrThumb.s.top = "0px";
  
  			// ns4 bullshit.
  			if (document.layers)
        	{ 
  				this.lyrThumb.captureEvents(Event.MOUSEDOWN)
  				this.lyrElevDn.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE)
  				this.lyrElevUp.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE)
  			}
  
  			// mozilla5 bullshit.
  			if (this.mo5) document.getElementById("scrollerMo5Shim").style.height = this.docH
  			this.jumpTo(0);
  		} 
  		else 
  		{
  			this.lyrScrollbarGlobal.s.visibility = 'hidden';
  		}
  
  		// all done!
  		this.loaded = true
  }

  this.startScroll = function(dir) {
  	if (this.aniTimer) window.clearTimeout(this.aniTimer)
  	this.dir		  = dir
  	this.lastTime	= (new Date()).getTime() - this.minRes
  	this.startPos	= this.scrollTop
  	this.aniTimer	= window.setTimeout("Scroller.scroll()", this.minRes)
  }

  this.scroll = function() {
  	this.aniTimer	= window.setTimeout("Scroller.scroll()", this.minRes)
  	var now			  = (new Date()).getTime()
  	var elapsed		= now - this.lastTime
  	var ny			  = eval(this.scrollTop + this.dir + (elapsed * this.speed / 1000))
  	this.lastTime	= now
  	if (ny > this.scrollH && this.dir == "+" || ny < 0 && this.dir == "-") {
  		this.endScroll()
  		this.jumpTo(this.dir == "+" ? this.scrollH : 0)
  	}
  	else this.jumpTo(ny)
  }

  this.endScroll = function() {
  	if (this.aniTimer) this.aniTimer = window.clearTimeout(this.aniTimer)
  }

  this.startDrag = function(e) {
  	if (!e) e = window.event
  	if (this.sObj.aniTimer) window.clearTimeout(this.sObj.aniTimer)
  	var ey = e.clientY ? e.clientY : e.y
  	this.sObj.dragLastY = ey
  	this.sObj.dragStartOffset = ey - parseInt(this.sObj.lyrThumb.s.top)
  	this.sObj.dragActive = true
  	if (this.sObj.ns4) window.document.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP)
  	gsScroll = this.sObj;
    window.document.onmousemove = gsScroll.doDrag
  	window.document.onmouseup = gsScroll.stopDrag
  	//this.sObj.lyrFrame.onmousemove = this.sObj.doDrag;
    //this.sObj.lyrFrame.onmouseup = this.sObj.stopDrag;
    return false
  }

  this.doDrag = function(e) {
    if (!e) e = window.event
  	var ey = (e.clientY ? e.clientY : e.y)
  	var dy = ey - gsScroll.dragLastY
  	var ny = parseInt(gsScroll.lyrThumb.s.top) + dy
  	// constrain
  	if (ny >= gsScroll.thumbMax) gsScroll.dragLastY = gsScroll.thumbMax + gsScroll.dragStartOffset
  	else if (ny < 0) gsScroll.dragLastY = gsScroll.dragStartOffset
  	else gsScroll.dragLastY = ey
  	ny = Math.min(Math.max(ny, 0), gsScroll.thumbMax)
  	gsScroll.jumpTo(ny * gsScroll.scrollH / gsScroll.thumbMax)
  	return false;
  }

  this.stopDrag = function() {
  	//gsScroll = this.sObj;
    gsScroll.dragActive = false
  	if (gsScroll.ns4) window.document.releaseEvents(Event.MOUSEMOVE | Event.MOUSEUP)
  	window.document.onmousemove = null
  	window.document.onmouseup   = null
    //this.sObj.lyrFrame.onmousemove = null;
    //this.sObj.lyrFrame.onmouseup = null;
  }

  // slideTo gets called in the scope of lyrElevUp or lyrElevDn
  this.slideTo = function(e) {
  	if (!e) e = window.event
  	var ey = e.offsetY ? e.offsetY : e.layerY
  	if (typeof ey == "undefined") ey = 0
  	var ny = (this.id == "elevDn") ? ey-5 : ey
  	ny += this.s.top == "" ? 0 : parseInt(this.s.top)
  	ny *= this.sObj.scrollH / this.sObj.thumbMax
  	ny = Math.min(ny, this.sObj.scrollH)
  	this.sObj.startTime = (new Date()).getTime()
  	this.sObj.startPos = this.sObj.scrollTop
  	this.sObj.endPos = ny;
  	this.sObj.dist = this.sObj.endPos - this.sObj.startPos
  	this.sObj.accel = this.sObj.dist / 1000 / 1000
  	if (this.sObj.aniTimer) this.sObj.aniTimer = window.clearInterval(aniTimer)
  	gsScroll = this.sObj;
    this.sObj.aniTimer = window.setInterval("gsScroll.slide()", 10)
  }

  this.slide = function() {
  		var now = (new Date()).getTime()
  		var elapsed = now - this.startTime
  		if (elapsed > 1000) this.endScroll()
  		else {
  			var t = 1000 - elapsed
  			var ny = this.endPos - t * t * this.accel
  			this.jumpTo(ny)
  	}
  }

  this.jumpTo = function(ny) {
  	var thumbTop = Math.round(ny * this.thumbMax / this.scrollH);
  	this.lyrElevUp[document.layers ? "clip" : "style"].height = thumbTop + 'px';
    this.lyrElevDn[document.layers ? "clip" : "style"].height = this.scrollbarH - thumbTop + 'px';
  	this.lyrElevDn.s.top = thumbTop + 'px';
  	this.lyrThumb.s.top = thumbTop + 'px';
  	this.lyrContent.s.top = -ny + 'px';
  	this.scrollTop = ny;
  }

  this.toggleElev = function(lyr, iState) {
  	var img = this["imgElevBack" + iState];
  	if (document.layers) lyr.document.images[0].src = img.src;
  	//else lyr.firstChild.src = img.src;
  	lyr.onmousemove = iState == 2 ? this.moveMarker : null
  	if (iState == 1) this.lyrMarker.s.visibility = "hidden"
  }

  this.moveMarker = function(e) {
  	if (!this.sObj.lyrThumb.active) {
  			if (!e) e = window.event
  			var ey = e.layerY ? e.layerY : e.offsetY
  			if (isNaN(ey)) ey = 0
  			var ny = Math.round(ey / 2) * 2
  			ny += (this.s.top == "" ? 0 : parseInt(this.s.top))
  			ny -= 1
  			this.sObj.lyrMarker.s.top = ny
  			this.sObj.lyrMarker.s.visibility = "visible"
  	}
  }

  this.toggleButton = function(suffix, iState) {
  	var lyr = eval("Scroller.lyrScroll" + suffix)
  	var img = this.getFirstImage(lyr)
  	img.src = "scroll"+suffix+iState+".gif"
  }

  this.getLyr = function(sLyrId, oNestRef) {
  	var o
  	if (document.all) o = oNestRef.all[sLyrId]
  	else if (document.layers) o = oNestRef.layers[sLyrId]
  	else o = this.recursiveNs6Get(sLyrId, oNestRef)
  	o.s = document.layers ? o : o.style
  	o.sObj = this;
  	return o
  }

  // this is kinda slow for ns6 -> 
  // but best way I could think of w/o totally bloating the code.
  this.recursiveNs6Get = function(id, p) {
  	if (p.childNodes) {
  		for (var i = 0; i < p.childNodes.length; i++) {
  			if (p.childNodes[i].id == id) return p.childNodes[i]
  			else if (p.childNodes[i].childNodes.length > 0) {
  				var obj = this.recursiveNs6Get(id, p.childNodes[i])
  				if (obj && obj != null) return obj
  			}
  		}
  	}
  	return false
  }

  this.getFirstImage = function(lyr) {
  	return document.layers ? lyr.document.images[0] : document.all ? lyr.all.tags("IMG")[0] : lyr.getElementsByTagName("IMG")[0]
  }

}

function ypImage(s) {
	var oImg  = new Image()
	oImg.src = s
	return oImg
}

function dbg(obj) {
	var s = ""
	for (prop in obj) s += prop + ":" + obj[prop] + "\n"
	alert(s)
}

