/*

FREESTYLE MENUS v1.0 RC (c) 2001-2004 Angus Turnbull, http://www.twinhelix.com
Altering this notice or redistributing this file is prohibited.

*/

  
  //MENU INITIALIZATION
  var divMenu = new FSMenu('divMenu', false, 'visibility', 'visible', 'hidden');
  divMenu.showDelay = 0;
  divMenu.switchDelay = 0;
  divMenu.hideDelay = 500;
  divMenu.cssLitClass = 'highlighted';
  

// *** COMMON CROSS-BROWSER COMPATIBILITY CODE ***
var isDOM=document.getElementById?1:0,
 isIE=document.all?1:0,
 isNS4=navigator.appName=='Netscape'&&!isDOM?1:0,
 isOp=self.opera?1:0,
 isDyn=isDOM||isIE||isNS4;

function getRef(i, p)
{
 p=!p?document:p.navigator?p.document:p;
 return isIE ? p.all[i] :
  isDOM ? (p.getElementById?p:p.ownerDocument).getElementById(i) :
  isNS4 ? p.layers[i] : null;
};

function getSty(i, p)
{
 var r=getRef(i, p);
 return r?isNS4?r:r.style:null;
};

if (!self.LayerObj) var LayerObj = new Function('i', 'p',
 'this.ref=getRef(i, p); this.sty=getSty(i, p); return this');
function getLyr(i, p) { return new LayerObj(i, p) };

function LyrFn(n, f)
{
 LayerObj.prototype[n] = new Function('var a=arguments,p=a[0],px=isNS4||isOp?0:"px"; ' +
  'with (this) { '+f+' }');
};
LyrFn('x','if (!isNaN(p)) sty.left=p+px; else return parseInt(sty.left)');
LyrFn('y','if (!isNaN(p)) sty.top=p+px; else return parseInt(sty.top)');

if (!self.page) var page = { win:self, minW:0, minH:0, MS:isIE&&!isOp };

page.elmPos=function(e,p)
{
 var x=0,y=0,w=p?p:this.win;
 e=e?(e.substr?(isNS4?w.document.anchors[e]:getRef(e,w)):e):p;
 if(isNS4){if(e&&(e!=p)){x=e.x;y=e.y};if(p){x+=p.pageX;y+=p.pageY}}
 else if (e && e.focus && e.href && this.MS && navigator.platform.indexOf('Mac')>-1)
 {
  e.onfocus = new Function('with(event){self.tmpX=clientX-offsetX;' +
   'self.tmpY=clientY-offsetY}');
  e.focus();x=tmpX;y=tmpY;e.blur()
 }
 else while(e){x+=e.offsetLeft;y+=e.offsetTop;e=e.offsetParent}
 return{x:x,y:y};
};

// *** CORE MENU OBJECT AND FUNCTIONS ***
function FSMenu(myName, nested, cssProp, cssVis, cssHid)
{
 this.myName = myName;
 this.nested = nested;
 this.cssProp = cssProp;
 this.cssVis = cssVis;
 this.cssHid = cssHid;
 this.cssLitClass = '';
 this.menus = { root: new FSMenuNode('root', this) };
 this.menuToShow = [];
 this.mtsTimer = null;
 this.showDelay = 0;
 this.switchDelay = 125;
 this.hideDelay = 500;
};

FSMenu.prototype.show = function(mN) { with (this)
{
 menuToShow = arguments;
 clearTimeout(mtsTimer);
 mtsTimer = setTimeout(myName + '.menus.root.over()', 10);
}};

FSMenu.prototype.hide = function(mN) { with (this)
{
 clearTimeout(mtsTimer);
 if (menus[mN]) menus[mN].out();
}};

function FSMenuNode(id, obj)
{
 this.id = id;
 this.obj = obj;
 this.lyr = this.child = this.args = this.par = this.timer = null;
 var node = this;

 this.over = function(evt) { with (node) with (obj)
 {
  if (isNS4 && evt && lyr.ref) lyr.ref.routeEvent(evt);
  clearTimeout(timer);

  if (menuToShow)
  {
   clearTimeout(mtsTimer);
   var a = menuToShow, m = a[0];
   menuToShow = null;
   if (!menus[m] || !menus[m].lyr.ref) menus[m] = new FSMenuNode(m, obj);
   var c = menus[m];
   if (c == node) return;
   // Stop any impending show/hide of the child menu.
   clearTimeout(c.timer);
   if (c != child && c.lyr.ref)
   {
    c.args = a;
    c.par = node;

    var delay = child ? switchDelay : showDelay;

    if (delay) c.timer = setTimeout(myName + '.menus["' + c.id + '"].show()', delay);
    else c.show();
   }
  }

  if (!nested && par) par.over();
 }};

 this.out = function(evt) { with (node) with (obj)
 {
  // Basically the same as over(), this cancels impending events and sets a hide timer.
  if (isNS4 && evt && lyr && lyr.ref) lyr.ref.routeEvent(evt);
  clearTimeout(timer);
  timer = setTimeout(myName + '.menus["' + id + '"].hide()', hideDelay);
  if (!nested && par) par.out();
 }};

 if (id != 'root') with (this) with (lyr = getLyr(id)) if (ref)
 {
  if (ref.addEventListener)
  {
   ref.addEventListener('mouseover', this.over, false);
   ref.addEventListener('mouseout', this.out, false);
  }
  else
  {
   if (isNS4) ref.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT);
   ref.onmouseover = this.over;
   ref.onmouseout = this.out;
  }
 }
};



FSMenuNode.prototype.show = function() { with (this) with (obj)
{
 if (!par) return;
 if (par.child && par.child != this) par.child.hide();
 par.child = this;

 var offR = args[1], offX = args[2], offY = args[3], lX = 0, lY = 0,
  doX = ''+offX!='undefined', doY = ''+offY!='undefined';
 if (offR && (doX||doY))
 {
  with (page.elmPos(offR, par.lyr ? par.lyr.ref : 0)) lX = x, lY = y;
  if (doX) lyr.x(lX + eval(offX));
  if (doY) lyr.y(lY + eval(offY));
 }

 if (offR && cssLitClass && !isNS4) offR.className += (offR.className?' ':'') + cssLitClass;
 if (obj.onshow) obj.onshow(id);
 lyrVis(1);
}};

FSMenuNode.prototype.hide = function() { with (this) with (obj)
{
 if (!par) return;
 if (isNS4 && self.isMouseIn && isMouseIn(lyr.ref)) return show();
 if (args[1] && cssLitClass && !isNS4)
  args[1].className = args[1].className.replace(new RegExp('\\s*' + cssLitClass + '$'), '');
 if (lyr)
 {
  if (obj.onhide) obj.onhide(id);
  lyrVis(0);
 }
 if (child) child.hide();
 if (par && par.child == this) par.child = null;
 par = null;
}};

FSMenuNode.prototype.lyrVis = function(sh) { with (this) with (obj)
{
 lyr.sty[cssProp] = sh ? cssVis : cssHid;
}};



// ANIMATION:  Here's an optional replacement for the lyrVis() function above.
// Uncomment it by removing the /* and */ lines to try it out :).


/*
FSMenuNode.prototype.lyrVis = function(sh) { with (this) with (obj)
{
 lyr.timer |= 0;
 lyr.counter |= 0;
 with (lyr)
 {
  clearTimeout(timer);
  if (sh) sty[cssProp] = cssVis;
  //sty.zIndex = 10000 + sh;

  // CLIPPING ANIMATION: Use the next two lines. N.B: Not well suited to nested lists.
  //var cP = Math.pow(Math.sin(Math.PI*counter/200),0.75);
  //if (!isNS4) sty.clip = 'rect(0px, '+ref.offsetWidth+'px, '+(ref.offsetHeight*cP)+'px, 0px)';

  // ALPHA ANIMATION: Use this, and uncommment the LyrFn('alpha'....) lines below too.
  lyr.alpha(counter==100 ? null : counter);
  counter += 10*(sh?1:-1);

  counter += 10*(sh?1:-1);
  if (counter>100) { counter = 100 }
  else if (counter<0) { counter = 0; sty[cssProp] = cssHid }
  else timer = setTimeout(myName + '.menus["' + id + '"].lyrVis(' + sh + ')', 80);
 }
}};

LyrFn('alpha','var f=ref.filters,d=(p==null),o=d?"inherit":p/100; if (f) {' +
 'if (!d&&sty.filter.indexOf("alpha")==-1) sty.filter+=" alpha(opacity="+p+")"; ' +
 'else if (f.length&&f.alpha) with(f.alpha){if(d)enabled=false;else{opacity=p;enabled=true}} }' +
 'else if (isDOM)sty.opacity=sty.MozOpacity=o');
*/

// NS4 compatibility
if (isNS4)
{
 var fsmMouseX, fsmMouseY, fsmOR=self.onresize, nsWinW=innerWidth, nsWinH=innerHeight;
 document.fsmMM=document.onmousemove;

 self.onresize = function()
 {
  if (fsmOR) fsmOR();
  if (nsWinW!=innerWidth || nsWinH!=innerHeight) location.reload();
 };

 document.captureEvents(Event.MOUSEMOVE);
 document.onmousemove = function(e)
 {
  fsmMouseX = e.pageX;
  fsmMouseY = e.pageY;
  return document.fsmMM?document.fsmMM(e):document.routeEvent(e);
 };

 function isMouseIn(sty)
 {
  with (sty) return ((fsmMouseX>left) && (fsmMouseX<left+clip.width) &&
   (fsmMouseY>top) && (fsmMouseY<top+clip.height));
 };
}
