/*
 Rod Dines 06 Nov 2006

 schillmania.com - 2006 edition: lots of style.

 Not complete, unfortunately. Must balance life
 and work and everything in-between. ;)

*/

var nAV = navigator.appVersion.toLowerCase();
var nUA = navigator.userAgent.toLowerCase();
var nP = navigator.platform.toLowerCase();
var isIE = nAV.indexOf('msie')!=-1;
var isIE6 = (nAV.indexOf('msie 6')!=-1 || nAV.indexOf('msie 5')!=-1);
var isFirefox = (nUA.indexOf('firefox')!=-1);
var isOpera = (nUA.indexOf('opera')!=-1);
var isSafari = (nUA.indexOf('safari')!=-1);
var isWin32 = (nP.indexOf('win')!=-1);
var isMac = (nP.indexOf('mac')!=-1);
if (isOpera) {
  isIE = false;
  isIE6 = false;
}


function $(id) {
  //used to simplify coding
  return document.getElementById(id); // thanks, prototype.
}

var oDebug = null;
var tStart = new Date();

function writeDebug(x) {
  if (!oDebug) {
    if (document.getElementsByTagName('p').length) oDebug = document.getElementsByTagName('p')[document.getElementsByTagName('p').length-1];
    if (document.body) {
      document.body.appendChild(oDebug);
      oDebug.style.display = 'block';
    }
  }
  var o = document.createElement('span'); // can't put block-level elements under P tags
  o.style.display = 'block';
  c = document.createTextNode((new Date()-tStart)+': '+x);
  o.appendChild(c);
  if (!oDebug) return false;
  try {
    if (!oDebug.getElementsByTagName('span').length) {
      oDebug.appendChild(o);
    } else {
      oDebug.insertBefore(o,oDebug.getElementsByTagName('span')[0]);
    }
  } catch(e) {
    window.status = 'Warning: writeDebug failed.';
    setTimeout("window.status=''",1000);
  }
}

if (window.location.href.indexOf('debug=1')==-1)  writeDebug = function(x) {} // disable

function removeChildNodes(o) {
  // remove children from bottom up
  var nodes = o.childNodes;
  if (!nodes || !o) {
    writeDebug('removeChildNodes('+(o||'null')+'): no nodes to remove.');
    return false;
  }
  writeDebug('removeChildNodes('+o.nodeName+'): removing '+nodes.length+' node'+(nodes.length>1?'s':''));
  for (var i=nodes.length-1; i>=0; i--) {
    o.removeChild(nodes[i]);
  }
}

//+++++++++++++++++++++++++ ANIMATOR  CLASS +++++++++++++++++++++++++

function Animator() {
  var self = this;
  this.timer = null;
  this.active = null;
  this.methods = [];
  this.tweenStep = [1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2];
  
  this.start = function() {
    if (self.active==true) return false;
    self.active = true;
    self.timer = window.setInterval(self.animate,20);
  }

  this.stop = function() {
    if (self.timer) {
      window.clearInterval(self.timer);
      self.timer = null;
      self.active = false;
    }
  }

  this.reset = function() {
    self.methods = [];
  }

  this.addMethod = function(oMethod,oncomplete) {
    for (var i=self.methods.length; i--;) {
      if (self.methods[i] == oMethod) {
        if (oncomplete) {
          self.methods[i]._oncomplete = oncomplete;
        }
        return false;
      }
    }
    self.methods[self.methods.length] = oMethod;
    self.methods[self.methods.length-1]._oncomplete = oncomplete||null;
  }

  this.createTween = function(start,end) {
    var start = parseInt(start);
    var end = parseInt(end);
    var tweenStepData = self.tweenStep;
    var tween = [start];
    var tmp = start;
    var diff = end-start;
    var j = tweenStepData.length;
    var isAscending = end>start;
    // alert('start, end, isAscending: '+start+','+end+','+isAscending);
    for (var i=0; i<j; i++) {
      tmp += diff*tweenStepData[i]*0.01;
      tween[i] = parseInt(tmp);
      // floor/ceiling checks (rounding errors?)
      if (isAscending) {
        if (tween[i]>end) tween[i] = end;
      } else {
        if (tween[i]<end) tween[i] = end;
      }
    }
    if (tween[i] != end) tween[i] = end;
    return tween;
  }
  
  this.animate = function(e) { 
    if (!self.active) return false;
    var active = false;
    for (var i=self.methods.length; i--;) {
      if (self.methods[i]) {
        if (self.methods[i]()) {
          active = true;
        } else {
          if (self.methods[i]._oncomplete) {
            self.methods[i]._oncomplete();
            self.methods[i]._oncomplete = null;
          }
          self.methods[i] = null;
        }
      }
    }
    if (!active) {
      self.stop();
      self.reset();
    }
  }

}

var animator = new Animator();


//+++++++++++++++++++++++++ HEADER  CLASS +++++++++++++++++++++++++

function Header(o) {
  writeDebug('Header()');
  var self = this;
  this.o = o;
  this.oShade = null;       //set in this.init() to $('photo-shade');
  this.oHeader = null;      //set in this.init() to $('header');
  this.oNav = null;         //set in this.init() to $('col2');
  this.oContainer = null;   //set in this.init() to $('container');
  this.oHAI = null;         //set in this.init() to $('hai');
  this.oToggle = null;      //set in this.init() to $('header-toggle');
  this.tweens = [];
  this.frame = 0;
  this.frameCount = 0;
  this.shades = [];

  //Added by Rod Dines for IE hover support
  this.toggleMouseOver = function(bHighlight) {
	//All this just cause IE doesnt handle the CSS image:hover pseudo class or .png files
	if ( bHighlight==true && ( isIE || isIE6) ) {
		if ( classContains(self.oToggle,'inverted') ) {
			self.oToggle.innerHTML='<img src="/ne/layout/button-down-1.gif" border=0 />';
		} else {
			self.oToggle.innerHTML='<img src="/ne/layout/button-up-1.gif" border=0 />';
		}
	} else {
		self.oToggle.innerHTML='';
	}
  }

  this.animate2 = function() {
    self.o.style.backgroundColor = '#'+self.shades[0][self.frame]+self.shades[1][self.frame]+self.shades[2][self.frame];
    return (++self.frame<self.frameCount);
  }

  this.animate = function() {
    var posY = self.tweens[2][self.frame]+'px';
    self.oHAI.style.backgroundPosition = '50% '+posY; // 50% ?
    $('empty-left').style.marginTop = $('empty-right').style.marginTop = posY;
    self.o.style.backgroundColor = '#'+self.shades[0][self.frame]+self.shades[1][self.frame]+self.shades[2][self.frame];
    return (++self.frame<self.frameCount);
  }

  this.animateComplete = function() {
    self.frame = 0;
    // self.oHAI.style.backgroundPosition = '50% 0px';
    // if (isMac && !isSafari) window.setTimeout(self.move2,20);
    // window.setTimeout(self.move2,20);
    // test
//REMOVED BY ROD DINES SINCE WE NOT USING NAV CLASS
    //setTimeout(navTest,500);
  }

  this.animateComplete2 = function() {
    self.frame = 0;
    // generate tween for new height
    self.tweens[2] = animator.createTween(parseInt(self.o.offsetHeight)+8,0);
  }

  this.setColor = function(cEnd) {
    var cStart = hex2decArray(getRGBArray(getBackgroundColor(self.o,true)));
    cEnd = hex2decArray(cEnd);
    if (cStart.join('') == cEnd.join('')) return false; // exit if no change
    self.shades = [animator.createTween(cStart[0],cEnd[0]),animator.createTween(cStart[1],cEnd[1]),animator.createTween(cStart[2],cEnd[2])];
    self.shades = [dec2hexArray(self.shades[0]),dec2hexArray(self.shades[1]),dec2hexArray(self.shades[2])];
    animator.addMethod(self.animate2,self.animateComplete2);
    animator.start();
  }

  this.move = function() {
    animator.addMethod(self.animate,self.animateComplete);
    animator.start();
  }

  this.move2 = function() {
    animator.addMethod(self.animate2,self.animateComplete2);
    animator.start();
  }

  this.animateMaximize = function() {
    // expand to full height
	//These 3 values must correspond to the differences in starting position in the CSS for the three DIV objects
	var iToggleDiff = -8;  //e.g. header-toggle.style.top: 248px - top.style.height: 256px
	var iHeaderDiff = 64;  //e.g. header.style.top: 320px - top.style.height: 256px
	var iNavDiff = 180;    //e.g. col2.style.top: 436px: - top.style.height: 256px
	self.o.style.height = self.tweens[0][self.frame]+'px';
	self.oToggle.style.top = (self.tweens[0][self.frame]+iToggleDiff)+'px';
	self.oHeader.style.top = (self.tweens[0][self.frame]+iHeaderDiff)+'px';
	self.oNav.style.top = (self.tweens[0][self.frame]+iNavDiff)+'px';
	if (isIE || isSafari) self.oShade.style.top = self.tweens[0][self.frame]+'px'; // some browsers are dumb with bottom:0px;
	return (++self.frame<self.frameCount);    
  }

  this.animateMaximizeComplete = function() {
    self.tweens[0].reverse();
    self.frame = 0;
    // generate tween for new height
    self.tweens[2] = animator.createTween(parseInt(self.o.offsetHeight)+8,0);
    if (classContains(self.oToggle,'inverted')) {
      removeClass(self.oToggle,'inverted');
    } else {
      addClass(self.oToggle,'inverted');
    }
  }

  this.maximize = function() {
    animator.addMethod(self.animateMaximize,self.animateMaximizeComplete);
    animator.start();
  }

  this.toggle = function() {
    for (var i=self.tweens.length; i--;) {
      self.tweens[i].reverse();
    }
    for (i=self.shades.length; i--;) {
      self.shades[i].reverse();
    }
    animator.addMethod(self.animate,self.animateComplete);
    animator.start();
  }

  this.init = function() {
    writeDebug('header.init()');

    self.oShade = $('photo-shade');
    self.oHeader = $('header');
    self.oNav = $('col2');
    self.oContainer = $('container');
    self.oHAI = $('hai');
    self.oToggle = $('header-toggle');

    var wWidth = parseInt(window.innerWidth||document.body.clientWidth);
    var iWidth = parseInt($('hai-image').offsetWidth);
    var wHalfWidth = parseInt(wWidth/2)-parseInt(iWidth/2);

    self.oHAI.style.backgroundImage = 'url('+$('hai-image').src+')';
    self.oHAI.style.backgroundPosition = '50% 256px';
    self.oHAI.style.backgroundRepeat = 'no-repeat'; // safari is dumb.

    // Mouseover :HOVER replacement for IE
    //if (isIE)  if (isIE6)
    //self.oToggle.onmouseover = "header.toggleMouseOver(true);";
    //self.oToggle.onmouseout  = "header.toggleMouseOver(false);";

    // $('empty-left').style.marginTop = $('empty-right').style.marginTop = '0px';

    // set offset of "middle" image for shadows
    $('empty').style.width = (iWidth-2)+'px';
    if (!isOpera) $('shades').style.display = 'block'; // Opera is dumb here for some reason.
    $('shades').style.marginLeft = -(Math.floor(iWidth/2)+16)+'px'; // include shadow

    // create RGB pair arrays
    var cStart = getBackgroundColor(self.o);
    cStart = hex2decArray(cStart);
    var cEnd = hex2decArray(getRGBArray(getBackgroundColor($('hai-image'),true)));
    self.shades = [animator.createTween(cStart[0],cEnd[0]),animator.createTween(cStart[1],cEnd[1]),animator.createTween(cStart[2],cEnd[2])];
    self.shades = [dec2hexArray(self.shades[0]),dec2hexArray(self.shades[1]),dec2hexArray(self.shades[2])];

    self.tweens = [animator.createTween(parseInt(self.o.offsetHeight),495),animator.createTween(-(iWidth),wHalfWidth),animator.createTween(parseInt(self.o.offsetHeight)+8,0)]; // animator.createTween(parseInt(self.o.offsetHeight)+8,0)
    self.frameCount = self.tweens[0].length;
    self.move();

  }

  this.destructor = function() {
    self.o = null;
    self.oNav = null;
    self.oShade = null;
    self.oContainer = null;
    self.oHAI = null;
    // if (isIE) self.oToggle.onmouseover = self.oToggle.onmouseout = null;
    self.oToggle = null;
    self = null;
  }

}

//+++++++++++++++++++++++++ AUXILLARY STUFF +++++++++++++++++++++++++

function getRGBArray(sColor) {
  // return string array
  if (sColor.length==3) sColor = sColor+''+sColor;
  return [sColor.substr(0,2),sColor.substr(2,2),sColor.substr(4,2)];
}

function getBackgroundColor(o,asString) {
  var cStr = getStyle(o,isIE?'backgroundColor':'background-color');
  if (!cStr) return getRGBArray('#ffffff'); // backup
  if (cStr.indexOf('#')+1) {
    // hex format - "#xxyyzz"
    cStr = cStr.substr(1);
    if (cStr.length==3) cStr = cStr+''+cStr; // "double" string if only 3 characters
    if (!asString) cStr = getRGBArray(cStr);
  } else {
    // rgb format - "rgb (x,y,z)"
    // split into rgb, parse and return
    var rgb = cStr.split(',');
    rgb[0] = rgb[0].substr(4); // remove "rgb("
    for (var i=rgb.length; i--;) {
      rgb[i] = dec2hex(parseInt(rgb[i],10));
    }
    cStr = asString?rgb.join(''):rgb;
  }

  return cStr;
}

function getBorderColor(o,asString) { // holy dupe, batman! (Needs to be cleaned up.)
  var cStr = getStyle(o,isIE?'borderLeftColor':'border-left-color');
  if (!cStr) return '#6699cc'; // backup
  if (cStr.indexOf('#')+1) {
    // hex format - "#xxyyzz"
    cStr = cStr.substr(1);
    if (cStr.length==3) cStr = cStr+''+cStr; // "double" string if only 3 characters
    if (!asString) cStr = getRGBArray(cStr);
  } else {
    // rgb format - "rgb (x,y,z)"
    // split into rgb, parse and return
    var rgb = cStr.split(',');
    rgb[0] = rgb[0].substr(4); // remove "rgb("
    for (var i=rgb.length; i--;) {
      rgb[i] = dec2hex(parseInt(rgb[i],10));
    }
    cStr = asString?rgb.join(''):rgb;
  }

  return cStr;
}

var header = null;

// hex -> dec / dec -> hex
// http://www.southwest.com.au/~jfuller/binary/converter.htm

function dec2hex(cval) {
  if (cval > 255) cval = 255;
  var hexascii = "0123456789ABCDEF";
  var cval0 = Math.floor(cval/16);
  var cval1 = cval-(cval0*16);
  var c1 = hexascii.charAt(cval0);
  var c2 = hexascii.charAt(cval1);
  return (c1+c2);
}

function hex2dec(cval) {
  cval = cval.toUpperCase();
  var tval = 0;
  var hexascii = "0123456789ABCDEF";
  var mychar, ch;
  for (var c=0; c<cval.length; c++) {
    mychar = cval.charAt(c);
    for (ch=0; ch<16; ch++) {
      if (mychar == hexascii.charAt(ch)) {
        tval += ch;
	if (c<cval.length-1) tval *= 16;
      }
    }
  }
  return tval;
}

function hex2decArray(hArray) {
  var result = [];
  for (var i=0,j=hArray.length; i<j; i++) {
    result[i] = hex2dec(hArray[i]);
  }
  return result;
}

function dec2hexArray(dArray) {
  var result = [];
  for (var i=0,j=dArray.length; i<j; i++) {
    result[i] = dec2hex(dArray[i]);
  }
  return result;
}

function getStyleMethod1(el,styleProp) {
  writeDebug('getStyleMethod1()');
  var x = typeof(el)=='string'?$(el):el;
  // IE/firefox method
  return (x.currentStyle?x.currentStyle[styleProp]:(window.getComputedStyle?document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp):null)); // window.getComputedStyle
}

function getStyleMethod2(el,styleProp) {
  // based on http://www.quirksmode.org/dom/getstyles.html
  writeDebug('getStyleMethod2()');
  var x = typeof(el)=='string'?$(el):el;
  // Safari method
  return (x.currentStyle?x.currentStyle[styleProp]:(document.defaultView.getComputedStyle?document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp):null)); // window.getComputedStyle
}

getStyle = (isSafari?getStyleMethod2:getStyleMethod1); // Super-lame, but apparently how it has to be. (Safari blows up on window.getComputedStyle - IE chokes on document.defaultView.getComputedStyle.)


// CONTENT MANAGER - re-re-hashed from 2005, re-hashed from 2004 site

function ContentManager() {
  writeDebug('ContentManager()');
  var self = this;
  this.xmlhttp = null;
  this.oLast = null;

  if (typeof window.XMLHttpRequest != 'undefined') {
    try {
      this.xmlhttp = new XMLHttpRequest();
    } catch(e) {
      // d'oh
    }
  }

  if (!self.xmlhttp) {
    try {
      this.xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
      try {
        this.xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
      } catch(E) {
        this.xmlhttp = null;
      }
    }
  }

  this.readystatechangeHandler = function() {
    if (self.xmlhttp.readyState == 4) {
      if (self.onloadHandler) {
        self.onloadHandler();
      }
    }
  }

  this.load = function(url) {
    url = url.toString();
    writeDebug('ContentManager.load('+url+')');
    if (url.indexOf('.xml')>=0 || (url.indexOf('webpad')>=0)) return true;
    if (url.indexOf('#')>=0) {
      return false;
    }

    // haaaack
    // url = url.replace('2006/','');
    url = url.replace('../','');

//MODIFIED BY ROD DINES 12/DEC/2006
return true;
//alert('url:' + url)
//MODIFIED BY ROD DINES 12/DEC/2006

    if (self.xmlhttp) {
      try {
        target = $('col1');
        url = url.toString();
        if (APP_XHTML||(window.location.href.indexOf('test')>=0)) {
          file = 'index.php?xml=true&r='+parseInt(Math.random()*1048576);
        } else {
          file = 'content.html';
        }
        //self.xmlhttp.open('GET',url+file,true); // "true" - don't hold up browser
        //self.xmlhttp.onreadystatechange = self.readystatechangeHandler;
        //self.xmlhttp.setRequestHeader('Content-Type', 'text/xml');
        //self.xmlhttp.send(null); // xmlDoc
      } catch(e) {
        // something blew up - d'oh!
        // alert('something blew up');
        // writeDebug('contentManager.load(): error @ '+e.lineNumber+','+e.message);
        return true;
      }
    } else {
      // no XMLHTTP support.
      return true;
    }
    return false;
  }

  this.onloadHandler = function() {
    writeDebug('ContentManager.onloadHandler()');
    if (soundManager) soundManager.play('b4');
    c = $('col1');
    if (APP_XHTML==true) {
      removeChildNodes(c);
      c.appendChild(document.importNode(self.xmlhttp.responseXML.documentElement.getElementsByTagName('div')[0],true));
    } else {
      // Internet explorer etc. get to do it the non-standards way
      c.innerHTML = '';
      c.innerHTML = self.xmlhttp.responseText;
    }
  }

  this.assignHandlers = function() {
    // intercept onclick and load via XMLHTTP where supported
    var o = $('nav').getElementsByTagName('ul')[0];
    var oItems = null;
    for (var i=0; i<o.childNodes.length; i++) {
      if (o.childNodes[i].nodeType != 3) { // non-text
        oItems = o.childNodes[i].getElementsByTagName('a');
        for (var j=oItems.length; j--;) {
          oItems[j]._class = o.childNodes[i].getElementsByTagName('a')[0].title;
          oItems[j].onclick = self.clickHandler;
        }
      }
    }
    var a = $('nav').getElementsByTagName('a');
    for (var i=0; i<a.length; i++) {
      a[i].onclick = self.clickHandler;
//alert('href:' + a[i].href)
    }
  }

  this.clickHandler = function(o) {
    // writeDebug('ContentManager.clickHandler('+o+')');
    o = (o&&o.href?o:this); // event firing either direct assignment or .clickHandler(this) - test for .href property as Mozilla transparently passes event argument by default
    // soundManager.play(null,'click0');
    // setEntryHighlight(o.id);

    if (o.href.indexOf('#'+o._class)==-1) {
      o.parentNode.className = 'selected';
      if (self.lastSelected && self.lastSelected != o.parentNode) {
        self.lastSelected.className = '';
      }
      self.lastSelected = o.parentNode;
      $('col1').className = o._class;
      var cColor = getBorderColor(parentNode(this));
      header.setColor(cColor);
    }

    o.blur();

//MODIFIED BY ROD DINES 12/DEC/2006
    var winRef = null;
    if (self.load(o)) {
        //don't open a window as we are just expanding or shrinking a menu heading
	return false;
    } else {
        //open a new url in this window as user has chosen a menu item
	winRef = window.open( o.href, '_self');
	return true;
    }
//MODIFIED BY ROD DINES 12/DEC/2006

    //return self.load(o);
    
  }

}

var contentManager = new ContentManager();


//Auxillary Stuff

function getOffX(o) {
  // thank-you, PPK.
  // http://www.quirksmode.org/js/findpos.html
  var curleft = 0;
  if (obj.offsetParent)	{
    while (o.offsetParent) {
      curleft += o.offsetLeft;
      o = o.offsetParent;
    }
  } else if (o.x) {
    curleft += o.x;
  }
  return curleft;
}

function getOffY(o) {
  var curtop = 0;
  if (o.offsetParent) {
    while (o.offsetParent) {
      curtop += o.offsetTop;
      o = o.offsetParent;
    }
  } else if (o.y) {
    curtop += o.y;
  }
  return curtop;
}

function parentNode(o) {
  if (!o.parentNode) return o;
  o = o.parentNode;
  while (o.nodeType == 3 && o.parentNode) {
    o = o.parentNode;
  }
  return o;
}

function classContains(o,sClass) {
  if (typeof(o.className)=='undefined' || !o.className) return false;
  var sC = o.className;
  return (sC==sClass || sC.indexOf(sClass+' ')+1 || sC.indexOf(' '+sClass)+1);
}

function addClass(o,sClass) {
  if (classContains(o,sClass)) return false;
  o.className = (o.className?o.className+' ':'')+sClass;
}

function removeClass(o,sClass) {
  if (!classContains(o,sClass)) return false;
  // need to use regexp
  o.className = o.className.replace(sClass+' ','');
  o.className = o.className.replace(' '+sClass,'');
  o.className = o.className.replace(sClass,'');
}

//+++++++++++++++++++++++++ NAVIGATOR - NavElement & NavController Classes +++++++++++++++++++++++++

function NavElement(o,oInner,index) {
  writeDebug('NavElement()');
  var self = this;
  var needsCSSHelp = (isIE || isSafari || isOpera); // these don't handle css { dt:hover + dd } at all, or are buggy in this particular case - handled instead via JS
  this.o = o;
  this.oInner = oInner;
  this.oDTs = [];
  this.oDDs = [];
  this.oHeader = null;
  this.isOpen = false;
  this.tween = null;
  this.tweenOpen = [];
  this.tweenClose = [];
  this.frame = 0;
  this.frameCount = 0;
  this.height = 0;
  this.index = index;
  this.unit = 'px';
  this.lastHover = null;

  this.getHeight = function() {
    self.height = parseInt(self.o.offsetHeight)+(!isOpera?6:0);
  }

  this.createTween = function() {
    self.tweenOpen = animator.createTween(-self.height,0);
    self.tweenClose = animator.createTween(0,-self.height);
    self.tween = self.tweenClose;
    self.frameCount = self.tween.length;
  }

  this.oMouseHandler = function(evt) {
    // support for non-:hover case
    // window.status = event.type;
    var e = evt?evt:window.event;
    if (e.type != 'mouseover' && e.type != 'mouseout') return;
    if (e.type == 'mouseover') {
      if (soundManager) soundManager.play('over');
    }
    if (!needsCSSHelp) return true;
    if (e.type == 'mouseover') {
      // super-lame workaround for Safari - confuses mouseout/:hover or something - must manually remove hover on last element {
      if (isSafari && self.lastHover) {
        removeClass(self.lastHover,'hover');
        removeClass(self.oDDs[self.lastHover._index],'hover');
      }
      addClass(this,'hover');
      addClass(self.oDDs[this._index],'hover');
      self.lastHover = this;
    } else {
      removeClass(this,'hover');
      removeClass(self.oDDs[this._index],'hover');
    }
  }

  this.assignHandlers = function() {
    self.oHeader.onclick = function(){navController.toggle(self.index);animator.start();}
    // if (needsCSSHelp) {
      self.oDTs = self.o.getElementsByTagName('dt');
      self.oDDs = self.o.getElementsByTagName('dd');
      for (var i=self.oDTs.length; i--;) {
        self.oDTs[i].onmouseover = self.oMouseHandler;
        self.oDTs[i].onmouseout = self.oMouseHandler;
        self.oDTs[i]._index = i;
      }
    // }
  }

  this.releaseHandlers = function() {
    self.oHeader.onclick = null;
    // if (needsCSSHelp) {
      for (var i=self.oDTs.length; i--;) {
        self.oDTs[i].onmouseover = null;
        self.oDTs[i].onmouseout = null;
      }
    // }
  }

  this.animate = function() {
    self.oInner.style.marginTop = self.tween[self.frame]+self.unit;
    if (self.tween == self.tweenOpen) {
      // if moving up off-screen, scroll.
      var oY = getOffY(self.oHeader);
      var wY = isIE?document.documentElement.scrollTop:window.scrollY;
      if (wY > oY) {
        // window.scrollTo(0,oY);
        if (isIE) {
          self.oHeader.scrollIntoView();
        } else {
          window.scrollTo(0,oY);
        }
      }
    }
    return (++self.frame<self.frameCount);
  }

  this.oncomplete = function() {
    writeDebug('navElement.oncomplete()');
    // self.o.style.overflow = '';
    // alert(self.tween[self.frame-1]+'px -> '+(self.tween[self.frame-1]/animator.pxEM)+'em');
    // self.oInner.style.marginTop = (self.tween[self.frame-1]/animator.pxEM*1.2)+'em';
    if (soundManager) soundManager.play('b6');
    self.frame = 0;
  }

  this.aniStart = function() {
    // $('nav').className = ''; // test
    // self.o.style.overflow = 'hidden';
    // self.o.style.height = '100%'; // dumb fix
  }

  this.open = function(fOncomplete) {
    writeDebug('navElement.open()');
    if (self.isOpen) return false;
    self.isOpen = true;
    self.tween = self.tweenOpen;
    animator.addMethod(self.animate,fOncomplete||self.oncomplete);
    if (soundManager) soundManager.play('b0');
    self.aniStart();
  }

  this.close = function(fOncomplete) {
    writeDebug('navElement.close()');
    if (!self.isOpen) return false;
    self.isOpen = false;
    self.tween = self.tweenClose;
    animator.addMethod(self.animate,fOncomplete||self.oncomplete);
    if (soundManager) soundManager.play('b0');
    self.aniStart();
  }

  this.init = function() {
    self.oHeader = self.o.parentNode.getElementsByTagName('h2')[0];
    self.assignHandlers();
    self.getHeight();
    self.createTween();
    self.oInner.style.marginTop = self.tweenOpen[0]+self.unit;
  }

  this.destructor = function() {
    self.releaseHandlers();
    self.lastHover = null;
    self.oDTs = null;
    self.oDDs = null;
    self.o = null;
    self.oInner = null;
    self = null;
  }

}

function NavController() {
  writeDebug('NavController()');
  var self = this;
  this.navElements = [];
  this.lastOpen = -1;

  this.init = function() {
    writeDebug('navController.init()');
    var oUL = $('nav').getElementsByTagName('ul')[0].getElementsByTagName('ul');
    for (var i=oUL.length; i--;) {
      self.navElements[i] = new NavElement(oUL[i],oUL[i].getElementsByTagName('li')[0],i);
      self.navElements[i].init();
    }
  }

  this.toggle = function(i) {
    (self.navElements[i].isOpen)?self.navElements[i].close():self.navElements[i].open();
    if (self.lastOpen>-1 && self.lastOpen != i) self.navElements[self.lastOpen].close();
    self.lastOpen = i;
  }

  this.destructor = function() {
    for (var i=self.navElements.length; i--;) {
      self.navElements[i].destructor();
      delete self.navElements[i];
    }
    self.navElements = null;
    self = null;
  }

}

var navController = new NavController();

function navTest() {
  // navController.open(0);
}

//+++++++++++++++++++++++++ MAIN INIT / LOAD / UNLOAD +++++++++++++++++++++++++


function unload() {
  header.destructor();
  header = null;
}

function init() {
  writeDebug('init()');
  header = new Header($('top'));
  // window.setTimeout(function(){header.init();},1000); // navController.toggle(0);
  // header.init();
  header.init();
  //contentManager.assignHandlers();
  contentManager.assignHandlers();

  navController.init();

  window.onload = null;
  window.onunload = unload;
  writeDebug('init() - end');
}

// shades.reverse();

function preInit() {
  if (document.getElementById) {
    writeDebug('preInit()');
    window.onload = init;
  } else {
    return false;
  }
  if (isIE && isIE6) { // silly IE, web standards are for good browsers!
    //adds an IE6 class to the HTML object so we can use HTML.ie6 to determine if IE6 in CSS
    writeDebug('Appending IE6 HTML class');
    addClass(document.getElementsByTagName('html')[0],'ie6');
  }
  writeDebug('hiding nav..');
  // hide nav
  $('nav').className = 'closed';
  writeDebug('preInit() - end');
}

var imageData = {
  'music' : 7,
  'people' : 4,
  'places' : 12,
  'things' : 10
}

var imageIndices = ['music','people','places','things'];

function imageInit() {
  if (!document.getElementById) return false;
  writeDebug('imageInit()');
  var i = parseInt(Math.random()*imageIndices.length);
  var n = parseInt(Math.random()*imageData[imageIndices[i]]);
  // document.getElementsByTagName('img')[document.getElementsByTagName('img').length-1].src = '2006/image/banner/'+imageIndices[i]+'/'+n+'.jpg';
  //Use a javascript variable "topinitialimageurl" so that the initial image can be defined in the document construction ASP code
  document.getElementsByTagName('img')[document.getElementsByTagName('img').length-1].src = topinitialimageurl;
  writeDebug('imageInit() - end');
}


// ++++++++++++++++++++++++++  ERROR HANDLING ++++++++++++++++++++++++
function debugError(msg,url,line) {
  writeDebug('Error: '+msg+' | ' +url+' | '+line);
  window.onerror = null;
  return true;
}

//window.onerror = debugError;