function Node(fdescription, flink, ftarget, fseq) //constructor 
{ 
  //constant data
  this.desc = fdescription;
  this.link = flink;
  this.target = ftarget;
  this.seq = fseq;
  this.parentObj = null;
  this.id = -1;
  this.children = new Array;
  this.nChildren = 0;
  this.level = 0;
  this.levelcss = 0;
  this.navObj = 0;
  this.iconSrc = 0;
  this.iconSrcClosed = 0;
  this.iconSrcHover = 0;
  this.iconSrcActive = 0;
  this.iconSrcOpenActive = 0;
  this.iconImg = 0;
    
  //dynamic data
  this.isOpen = false;
  this.isRendered = 0;
  
  //methods
  this.esconde = escondeBlock;
  this.initialize = initializeNode;
  this.addChild = addChild;
  this.renderOb = drawNode;
  this.blockStartHTML = blockStartHTML;
  this.blockEndHTML = blockEndHTML;
  this.createIndex = createEntryIndex;
  this.setState = setStateNode;
  this.subEntries = folderSubEntries;
  this.folderMstr = folderMstr;
  this.iconImageSrc = iconImageSrc;
} 
/*
 * $Log: ua.js,v $
 * Revision 1.9  2002/07/22 14:06:21  bc6ix
 * fix license path, change version reporting to use 2 digits for each level
 *
 * Revision 1.8  2002/07/07 08:23:07  bc6ix
 * fix line endings
 *
 * Revision 1.7  2002/05/14 16:52:52  bc6ix
 * use CVS Log for revision history
 *
 *
 */

/* ***** BEGIN LICENSE BLOCK *****
 * Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
 * Full Terms at http://bclary.com/lib/js/license/mpl-tri-license.txt
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Netscape code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Corporation.
 * Portions created by the Initial Developer are Copyright (C) 2001
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s): Bob Clary <bclary@netscape.com>
 *
 * ***** END LICENSE BLOCK ***** */

function xbDetectBrowser()
{
  var oldOnError = window.onerror;
  var element = null;

  window.onerror = null;
  
  // work around bug in xpcdom Mozilla 0.9.1
  window.saveNavigator = window.navigator;

  navigator.OS    = '';
  navigator.version  = parseFloat(navigator.appVersion);
  navigator.org    = '';
  navigator.family  = '';

  var platform;
  if (typeof(window.navigator.platform) != 'undefined')
  {
    platform = window.navigator.platform.toLowerCase();
    if (platform.indexOf('win') != -1)
      navigator.OS = 'win';
    else if (platform.indexOf('mac') != -1)
      navigator.OS = 'mac';
    else if (platform.indexOf('unix') != -1 || platform.indexOf('linux') != -1 || platform.indexOf('sun') != -1)
      navigator.OS = 'nix';
  }

  var i = 0;
  var ua = window.navigator.userAgent.toLowerCase();
  
  if (ua.indexOf('safari') != -1)
  {
    i = ua.indexOf('safari');
    navigator.family = 'safari';
    navigator.org = 'safari';
    navigator.version = parseFloat('0' + ua.substr(i+7), 10);
  }
  else if (ua.indexOf('opera') != -1)
  {
    i = ua.indexOf('opera');
    navigator.family  = 'opera';
    navigator.org    = 'opera';
    navigator.version  = parseFloat('0' + ua.substr(i+6), 10);
  }
  else if ((i = ua.indexOf('msie')) != -1)
  {
    navigator.org    = 'microsoft';
    navigator.version  = parseFloat('0' + ua.substr(i+5), 10);
    
    if (navigator.version < 4)
      navigator.family = 'ie3';
    else
      navigator.family = 'ie4';
  }
  else if (ua.indexOf('gecko') != -1)
  {
    navigator.family = 'gecko';
    var rvStart = ua.indexOf('rv:');
    var rvEnd   = ua.indexOf(')', rvStart);
    var rv      = ua.substring(rvStart+3, rvEnd);
    var rvParts = rv.split('.');
    var rvValue = 0;
    var exp     = 1;

    for (var z = 0; i < rvParts.length; i++)
    {
      var val = parseInt(rvParts[z]);
      rvValue += val / exp;
      exp *= 100;
    }
    navigator.version = rvValue;

    if (ua.indexOf('netscape') != -1)
      navigator.org = 'netscape';
    else if (ua.indexOf('compuserve') != -1)
      navigator.org = 'compuserve';
    else
      navigator.org = 'mozilla';
  }
  else if ((ua.indexOf('mozilla') !=-1) && (ua.indexOf('spoofer')==-1) && (ua.indexOf('compatible') == -1) && (ua.indexOf('opera')==-1)&& (ua.indexOf('webtv')==-1) && (ua.indexOf('hotjava')==-1))
  {
    var is_major = parseFloat(navigator.appVersion);
    
    if (is_major < 4)
      navigator.version = is_major;
    else
    {
      i = ua.lastIndexOf('/');
      navigator.version = parseFloat('0' + ua.substr(i+1), 10);
    }
    navigator.org = 'netscape';
    navigator.family = 'nn' + parseInt(navigator.appVersion);
  }
  else if ((i = ua.indexOf('aol')) != -1 )
  {
    // aol
    navigator.family  = 'aol';
    navigator.org    = 'aol';
    navigator.version  = parseFloat('0' + ua.substr(i+4), 10);
  }
  else if ((i = ua.indexOf('hotjava')) != -1 )
  {
    // hotjava
    navigator.family  = 'hotjava';
    navigator.org    = 'sun';
    navigator.version  = parseFloat(navigator.appVersion);
  }

  window.onerror = oldOnError;
}

xbDetectBrowser();

// Simulating inserAdjacentHTML on NS6
// Code by thor@jscript.dk
// ******************************************

if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement){
	HTMLElement.prototype.insertAdjacentElement = function (where,parsedNode)
	{
		switch (where){
		case 'beforeBegin':
			this.parentNode.insertBefore(parsedNode,this);
			break;
		case 'afterBegin':
			this.insertBefore(parsedNode,this.firstChild);
			break;
		case 'beforeEnd':
			this.appendChild(parsedNode);
			break;
		case 'afterEnd':
			if (this.nextSibling) 
				this.parentNode.insertBefore(parsedNode,this.nextSibling);
			else this.parentNode.appendChild(parsedNode);
			break;
		}
	}

	HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
	{
		var r = this.ownerDocument.createRange();
		r.setStartBefore(this);
		var parsedHTML = r.createContextualFragment(htmlStr);
		this.insertAdjacentElement(where,parsedHTML);
	}
}

function getElById(idVal) {
  if (document.getElementById != null)
    return document.getElementById(idVal);
  if (document.all != null)
    return document.all[idVal];
  
  alert("Problem getting element by id");
  return null;
}

//Used with NS4 and STARTALLOPEN
function renderAllTree(nodeObj, parent) {
	var i=0;
	nodeObj.renderOb(parent);
	if (nodeObj.nChildren > 0){
		nodeObj.isOpen = true;
		nodeObj.iconImg.src = nodeObj.iconImageSrc();
	}
  if (supportsDeferral)
	for (i=nodeObj.nChildren-1; i>=0; i--)
      renderAllTree(nodeObj.children[i], nodeObj.navObj);
  else
    for (i=0 ; i < nodeObj.nChildren; i++)
      renderAllTree(nodeObj.children[i], null);
}


function findObj(id)
{
  var i=0;
  var nodeObj;
  if (typeof foldersTree.xID != "undefined") {
    nodeObj = indexOfEntries[i];
    for(i=0;i<nEntries&&indexOfEntries[i].xID!=id;i++) //may need optimization
      ;
    id = i;
  }
  if (id >= nEntries)
    return null;
  else
    return indexOfEntries[id];
}
function findObjBySeq(id)
{
	var i=0;
	var nodeObj;
	for(i=0;i<nEntries&&indexOfEntries[i].seq!=id;i++) //may need optimization
		;
	id = i;

	if (id >= nEntries)
		return null;
	else
		return indexOfEntries[id];
}
function createEntryIndex() 
{ 
  this.id = nEntries;
  indexOfEntries[nEntries] = this;
  nEntries++;
}
function addChild(childNode) 
{ 
  this.children[this.nChildren] = childNode;
  childNode.parentObj = this;
  this.nChildren++;
  return childNode;
}
// functions
function createNode(fdescription, flink, ftarget, fseq) 
{ 
  newNode = new Node(fdescription, flink, ftarget, fseq);
  return newNode;
}
function insNode(parentNode, childNode)
{
  return parentNode.addChild(childNode);
}


function openBySeq(seq)
{
	var nodeObj = null;
	nodeObj = findObjBySeq(seq);
	if (nodeObj){
		if (nodeObj.parentObj) {
		openParentNode(nodeObj.parentObj);
	}
	setActiveNodeObj(nodeObj);
	clickOnNodeObj(nodeObj);
	}
	
}
function openParentNode(nodeObj)
{
	if (nodeObj.parentObj)
	{
		openParentNode(nodeObj.parentObj);
		clickOnNodeObj(nodeObj);
	}
}

function hoverOverNode(folderId)
{
 hoverOverNodeObj(findObj(folderId));
}
function hoverOutNode(folderId)
{
 hoverOutNodeObj(findObj(folderId));
}
function clickOnNode(folderId) 
{ 
  clickOnNodeObj(findObj(folderId));
}
function setActiveNode(folderId) 
{ 
	setActiveNodeObj(findObj(folderId));
}
function setActiveNodeObj(nodeObj)
{
	if (nodeObj.link != '') {
		lastPageClicked = nodeObj.link;
		tmpLastClicked = lastClicked;
		lastClicked = nodeObj;
		if (tmpLastClicked)
			tmpLastClicked.iconImg.src = tmpLastClicked.iconImageSrc();
	}
}
function setLastNodeClicked(folderId) 
{ 
	setLastNodeObjClicked(findObj(folderId));
}
function setLastNodeObjClicked(nodeObj)
{
	lastCatClicked = nodeObj.seq;
}
function clickOnNodeObj(nodeObj) 
{ 
  var state = 0;
  var currentOpen;
 
  state = nodeObj.isOpen;
  if (nodeObj.parentObj && closecats && !nodeObj.isOpen)
	for (i=0 ; i < nodeObj.parentObj.nChildren; i++)  
		{
			nodeObj.parentObj.children[i].setState(0);
		}
  nodeObj.setState(!state); //open<->close
}
function hoverOverNodeObj(nodeObj) 
{ 
	if (nodeObj.nChildren == 0 && nodeObj != lastClicked)
  nodeObj.iconImg.src = nodeObj.iconSrcHover;
}
function hoverOutNodeObj(nodeObj) 
{ 
	if (nodeObj.nChildren == 0 && nodeObj != lastClicked)
  nodeObj.iconImg.src = nodeObj.iconImageSrc();
}

function setStateNode(isOpen) 
{ 
  var subEntries;
  var totalHeight;
  var fIt = 0;
  var i=0;
  var currentOpen;
  if (isOpen == this.isOpen) 
    return;
 
  if (browserVersion == 2)  
  { 
	totalHeight = 0;
    for (i=0; i < this.nChildren; i++) 
      totalHeight = totalHeight + this.children[i].navObj.clip.height;
       subEntries = this.subEntries();
    if (this.isOpen) 
      totalHeight = 0 - totalHeight;
    for (fIt = this.id + subEntries + 1; fIt < nEntries; fIt++) 
      indexOfEntries[fIt].navObj.moveBy(0, totalHeight);
  }  
  this.isOpen = isOpen;

  propagateChangesInState(this);
}
function folderSubEntries() 
{ 
  var i = 0;
  var se = this.nChildren;
 
  for (i=0; i < this.nChildren; i++){ 
    if (this.children[i].children) //is a folder 
      se = se + this.children[i].subEntries();
  } 
 
  return se;
}
function propagateChangesInState(folder) 
{   
  var i=0;
  folder.iconImg.src = folder.iconImageSrc();
  
  //Propagate changes
  for (i=folder.nChildren-1; i>=0; i--) 
	{
	if (folder.isOpen) 
      folder.children[i].folderMstr(folder.navObj);
    else
      folder.children[i].esconde();
    }
}
function escondeBlock() 
{
  if (browserVersion == 1 || browserVersion == 3) { 
    if (this.navObj.style.display == "none") 
      return;
    this.navObj.style.display = "none";
  } else {
	if (this.navObj.visibility == "hidden") 
      return;
    this.navObj.visibility = "hidden";
  }
  this.setState(0);
} 
 
function folderMstr(domObj) 
{ 
  if (!this.isRendered)
     this.renderOb(domObj);
  else
    if (browserVersion == 1 || browserVersion == 3) 
      this.navObj.style.display = "block";
    else 
      this.navObj.visibility = "show";
} 

function hideWholeTree(nodeObj, hideThisOne, nodeObjMove) {
  var i=0;
  var heightContained=0;
  var childrenMove=nodeObjMove;
  nodeObj.isOpen = false;
  nodeObj.iconImg.src = nodeObj.iconImageSrc();
  if (hideThisOne)
    nodeObj.esconde();
  if (browserVersion == 2 && nodeObj.navObj)
  	nodeObj.navObj.moveBy(0, 0-nodeObjMove);
  for (i=0 ; i < nodeObj.nChildren; i++) {
	heightContainedInChild = hideWholeTree(nodeObj.children[i], true, childrenMove);
	if (browserVersion == 2) {
		heightContained = heightContained + heightContainedInChild + nodeObj.children[i].navObj.clip.height;
		childrenMove = childrenMove + heightContainedInChild;
	}
  }
  return heightContained;
}

var doc = document;
var indexOfEntries = new Array;
var nEntries = 0;
var lastClicked = null;
var lastCatClicked = null;
var lastPageClicked = null;
doc.yPos = yposition;

