<!--
/**
 * mps mediaworks 
 * mailto:info@mps-mediaworks.de
 *
 * navigation_lib.js
 * NAVIGATION FUNKTION Version 0.9.1 cw/mps/fecla 2001-10-13, 25.10.2001 
 * umgestellt auf Objektorientierung 01.04.2003 
 */

/**
 * class NavigationLink
 * 
 * This class represents a link/a row in the navigation
 *
 * Navigation.addLink is called using a NavigationLink-Object
 * as parameter.
 * To provide visibility of the row NavigationLink::write() is called.
 * This should always be done by using Navigation::write()
 * 
 * Parameters:
 * integer navLevel:	hirarchy level of the item in the navigation
 *						(0: root, 1: toplevel)
 * string linkUrl:		relative link to the page or #
 *						(uses Navigation::basePath as base)
 * string linkOnClick:	provide a javascript to handle clicks
 *						e.g. oNav.getJsOnClickLink('oNav') to expand/collapse nodes
 * string linkText:		shown text for this navigation link
 * variant linkImage:	reserved for an optional Image used for this link
 * string linkStyle:	name of a the css stylesheet used for this link
 *						(depending on the write method() there should also be a 
 * 						version with the suffixes "-curr", "-anc", "-cld")
 */
function NavigationLink(navLevel, linkUrl, linkOnClick, linkText, linkStyle) {
	this.navLevel = navLevel;	// level of node as an integer value
	this.linkUrl = linkUrl;		// target url as string
	this.linkOnClick = linkOnClick; // javascript e.g. to explode/collapse subtrees
	this.linkStyle = linkStyle;
	this.linkText = linkText;
	this.isVisibleOld = false;
	this.isExpanded = false;	// shows if this node is expanded or collapsed
	this.oChildLinks = new Array();
	this.oParentLink = undefined;
	this.LayerName = 'navlayer';	// LayerID of the div-tag where the navigation is displayed
}
NavigationLink.prototype.NavigationLink = NavigationLink;
// the direct syntax (NavigationLink.prototype.NavigationLink = function NavigationLink) isn't accepted by mozialla 1.5


/**
 * update state and presentation of current node
 * to ensure correct output
 * This Method id always called before getHtml().
 * It controls behaviour and design of the 
 * navigation during execution by setting
 * the property NavigationLink::linkCurrentSuffix
 * to either 
 *  -cur current link
 *  -anc ancestor
 *  -cld child
 *  ''   else
 * this is also added to the linkStyle property
 * to define the linkStyleWithSuffix property
 *
 * e.g.
 *  CurrentPage: 
 *  linkCurrentSuffix ='-cur'
 *  linkStyle = 'navlink1'
 *  linkStyleWithSuffix = 'navlink1-cur'
 */
NavigationLink.prototype.update = function () {
	if (this.isCurrentPage()) {
		this.linkCurrentSuffix = "-cur";
	}
	else if (this.isAncestor(this.oNav.oCurrentPage) >= 0) {
		this.linkCurrentSuffix = "-anc";
	}
	else if (this.isChild(this.oNav.oCurrentPage)) {
		this.linkCurrentSuffix = "-cld";
	}
	else {
		this.linkCurrentSuffix = "";
	}

	this.linkStyleWithSuffix = this.linkStyle+this.linkCurrentSuffix;

}

/**
 * initialise a link
 * In difference to the update method, this
 * method is only called before the first time
 * write() is executed. It is used to provide the
 * initial look of the navigation. 
 * (Especially to expand or collapse nodes)
 */
NavigationLink.prototype.init = function () {
	if (this.isCurrentPage()) {
		// the following line ensures, that the 
		// children of the current link are visible
		this.expandLink();
	}
	else if (this.isAncestor(this.oNav.oCurrentPage) >= 0) {
		// the following line ensures, that all 
		// ancestors of the current link are expanded
		this.expandLink();
	}
}

/**
 * NavigationLink.getHtml()
 *
 * This method actualy creates the HTML code 
 * representing the navigation link.
 * It's responsible for look and feel and for so 
 * has to be overwritten in a derived class (see navigation_custom.js)
 */
NavigationLink.prototype.getHtml = function () {
	/*
	 * classes we need from the css style sheet:
	 * a.navigation:	defines navigation links (this depends on the linkStyle parameter to the constructor)
	 * a.navigationakt:	defines highlighted navigation links to show current path
	 * 
	 * images we need:
	 * navigation_mark:			Marker/bullet point for link entries
	 * navigation_mark-cur:		highlighted version of above to mark current path
	 * navigation_mark_over:	highlighted version of above for roll over effect
	 * navigation_mark_over-cur:	highlighted version of above to mark current path
	 * navigation_mark-anc, navigation_mark_over-anc, navigation_mark-cld, navigation_mark_over-cld
	 * navigation_mark_transp:	transparent version of above as (??)
	 * (rem: if you don't really need as much images, just copy them on each other)
	 *
	 * members to use for html output (in order of preference):
	 * int navLevel:		level of navigation (1=toplevel)
	 * string linkStyleWithSuffix:	class name for css style sheet notation (e.g. navigation, navigation-akt)
	 * string linkText:		text to display for the link
	 * string linkHref:		complete url for the navigation link for the href attribute
	 *						(This should always be adapted to current host or filesystem-drive)
	 * string zaehler:		counter for creating image id for later reference (e.g. for MouseOver-Event)
	 * string linkCurrentSuffix:	suffix "-cur" when in current navigation path or "" else
	 *						used to modify styles e.g. image filenames
	 */
	 
	if (this.navLevel==1) {
		 document.write('<tr><td bgcolor="#B4B4CC" height="20"></td><td colspan="4"><img src="/images/pixel_weiss.gif" width="192" height="1" hspace="" vspace="0" border="0" alt=""></td></tr>');
	}
	sHtmlLink = '<tr><td bgcolor="#B4B4CC" height="21"></td>'
				// indent navigation level navlevel-steps
				+ '<td valign="top" colspan="' + this.navLevel + '" ></td>'
				// space for the marker
				+ '<td class="'+this.linkStyleWithSuffix+'" valign="top" ><img class="'+this.linkStyleWithSuffix+'" src="/images/all/nav/navigation_mark'+this.linkCurrentSuffix+'.gif" border="0" name="nav_mark_'+this.zaehler+'"></td>'
				// the link itself
				+ '<td class="navlevel'+ this.navLevel +'" valign="top" align="left" colspan="'+(3-this.navLevel)+'">'
				+ '<a class="'+this.linkStyleWithSuffix+'" href="'+ this.linkHref +'" onMouseOver="RolloverOnMouseOver(\'nav_mark_'+this.zaehler+'\',\'/images/all/nav/navigation_mark_over'+this.linkCurrentSuffix+'.gif\');" onMouseOut="RolloverOnMouseOut(\'nav_mark_'+this.zaehler+'\');">'+this.linkText+'</a>'
				+ '<br></td>'
				+ '</tr>\n';
	return(sHtmlLink);
	
	//oDebug.writeVar(this.navLevel, "navLevel"); // hierarchiestufe des links (1:hauptnavigation)
	//oDebug.writeVar(this.linkStyle, "linkStyle");
	//oDebug.writeVar(this.linkStyleWithSuffix, "linkStyleWithSuffix");
	//oDebug.writeVar(this.zaehler, "zaehler");
	//oDebug.write(sHtmlLink);
}


/**
 * register parent/calling object of class Navigation
 * and get properties
 */
NavigationLink.prototype.setNavigation = function (oNavigation) {
	// oNavigation: calling object of class Navigation
	this.oNav = oNavigation;
	this.zaehler = this.oNav.zaehler;
	//alert((new String(this.linkUrl)).substr(0,1));
	if ((new String(this.linkUrl)).substr(0,1) == '/')
		// this is a relative link in the current site
		this.linkHref = this.oNav.currentLocationHost + this.oNav.basePath + this.linkUrl;
	else
		// this is an absolute link
		this.linkHref = this.linkUrl;
	 
}


/**
 * Collapse a Node of the tree
 */
NavigationLink.prototype.collapseLink = function () {
	// perhaps we should avoid collapsing the current path,
	// so that the current link/page is always visible
	if (this.isAncestor(this.oNav.oCurrentPage) == -1)
		this.isExpanded = false;
}

/**
 * Collapse a node and all subnodes/children of the tree
 */
NavigationLink.prototype.collapseBranch = function () {
	// first collapse this node
	this.collapseLink();

	// the following code could serve to collapse
	// all child nodes to (this will only make a difference
	// when these are expanded afterwards)
	for (var i = 0 ; i < this.oChildLinks.length ; ++i) {
		this.oChildLinks[i].collapseLink(); 	
	}
}


/**
 * Expand a Node of the tree
 */
NavigationLink.prototype.expandLink = function () {
	this.isExpanded = true;
}

/* 
 * is the current node visible on the
 * screen?
 */
NavigationLink.prototype.isVisible = function () {
	//oDebug.write('\n\nthis.linkText='+this.linkText);
	//oDebug.write('\nthis.oNav.oCurrentPage.linkText='+this.oNav.oCurrentPage.linkText);
	//oDebug.write('\nthis.isAncestor()='+this.isAncestor(this.oNav.oCurrentPage));
	//oDebug.write('\nthis.isDescendant()='+this.isDescendant(this.oNav.oCurrentPage));

	// the top level is always visible
	// expand navigation right from start up to level x
	if (this.navLevel <= this.oNav.gesamtnavbis)
		return true;
	
	// this node can only be visible if its
	// parent is visible and Expanded as well
	if (this.oParentLink != null)
		if (! this.oParentLink.isVisible()
			|| ! this.oParentLink.isExpanded)
		return false;
	
	// all other nodes are unvisible by default
	var lIsVisible = false;
	// show all ancestors of current page
	//if (this.isAncestor(this.oNav.oCurrentPage) >= 0)
	//	lIsVisible = true;
	
	// show expanded nodes
	if (this.oParentLink.isExpanded)
		lIsVisible = true;
	
	return lIsVisible;
}

/*
 * get an ancestor of this Link. The parameter specifies the level
 * of the preceding generation (e.g. 1 = parent link)
 */
NavigationLink.prototype.getAncestor = function (iAncestor) {
	if (iAncestor == 0) {
		return this;
	}
	else if (this.oParentLink == undefined) {
		return null;
	}
	else {
		return (this.oParentLink).getAncestor(iAncestor - 1);
	}
}

/*
 * is this node the current page (window.location) of the 
 * browser?
 */
NavigationLink.prototype.isCurrentPage = function () {
	//oDebug.write('\nisCurrentPage:'+this.oNav.currentLocationPath+'=='+ this.linkUrl);
	if (this.oNav.currentLocationPath == this.oNav.basePath+this.linkUrl) {
		//oDebug.write('=true');
		return true
	}
}

/**
 * get the generation distance from this
 * link to current location
 * 0: same generation
 * >0: this link is a descendant of the current page/location
 * <0: this link is an ancestor
 * -1: the parent generation of links
 */
Navigation.prototype.getGeneration = function (oNavLink) {
	return(this.navLevel - oNavLink.navLevel);
}
 
/**
 * is this node a descendant of the current location
 * returns the level
 * 1 for child
 * 2 for grandchild
 * 0 for self 
 * -1 not a descendant
 */
NavigationLink.prototype.isDescendant = function (oNavLink) {
	//oDebug.write('\n\t'+this.linkText+'=='+oNavLink.linkText);
	if (this==oNavLink) {
		return 0;
	}
	else if (this.oParentLink == null || this.oParentLink == undefined) {
		return -1;
	}
	else {
		//alert('oParentLink='+this.oParentLink);
		var vReturn = this.oParentLink.isDescendant(oNavLink)
		if (vReturn == -1)
			return -1;
		else
			return vReturn + 1;
	}
}

NavigationLink.prototype.isParent = function (oNavLink) {
	return (this.isAncestor(oNavLink) == 1);
}

/**
 * is this node an ancestor of the current location
 * returns the level
 * 1 for parent
 * 2 for grandparent...
 * 0 for self (false)
 * -1 not an ancestor
 */
NavigationLink.prototype.isAncestor = function (oNavLink) {
	if (oNavLink != undefined && oNavLink != null)
		return oNavLink.isDescendant(this);
	else
		return -1;
}

NavigationLink.prototype.isChild = function (oNavLink) {
	return (this.isDescendant(oNavLink) == 1);
}

NavigationLink.prototype.isSibling = function (oNavLink) {
	return (this.getAncestor(1) != null && this.getAncestor(1) == oNavLink.getAncestor(1));
}

NavigationLink.prototype.isCousin = function (oNavLink) {
	return (this.getAncestor(2) != null && this.getAncestor(2) == oNavLink.getAncestor(2));
}

/**
 * is this node an uncle of the current location
 * returns the level
 * 1 uncle
 * 2 second uncle
 * 0 for self (false)
 * false else
 */
NavigationLink.prototype.isUncle = function (oNavLink) {
	return (this.getAncestor(1) != null && this.getAncestor(1) == oNavLink.getAncestor(2));
}

/**
 * class Navigation
 * handles structure and behaviour of navigation
 */
function Navigation() {
	
	this.sHtmlHeader = '<table>';
	this.sHtmlFooter = '</table>';
	
	// root node: top level link (navlevel=0)
	this.oRootLink = null;
	
	// the Link which represents the current page location
	this.oCurrentPage = null;

	// an array to save all nodes, Levels and targets
	this.oNavLinks = new Array();
	
	// indicator will be reset on first call
	// of write() method to provide initialising
	this.lWriteNotCalled = true;
	
	// Laufende Nummer der Menupunkte (ausgeblendete mitgerechnet)
	this.zaehler = 0;

	// get base-url and path on server
	//oDebug.write(location+'\n');
	if (location.protocol != 'file:') {
		this.currentLocationHost = location.protocol +"//"+ location.host + location.port;
		this.currentLocationPath = location.pathname + location.search + location.hash;
	}
	else {
		// this page is loaded from a file source
		// if the site resides on a file server there must 
		// be done some changes
		// e.g. IE 6:
		// location bar in browser window: W:\epoweb\site\en\index.php
		// window.location == 'file:///W:/epoweb/site/en/index.php';
		// location.protocol == 'file:'; 
		// location.pathname == '/W:\epoweb\site\en\index.php';
		
		// get the path after the drive spezification
		var aSplit = String(window.location).split(':');
		if (aSplit.length != 3)
			alert("assertion failed.");
		//oDebug.write(aSplit);
		// aSplit = file,///W,/epoweb/site/en/index.php
		this.currentLocationHost = location.protocol + aSplit[1]+':';
		this.currentLocationPath = aSplit[2]; // location.pathname + location.search + location.hash;
	}
	
}
Navigation.prototype.Navigation = Navigation;


/**
 * Method Navigation.addLink
 *
 */
Navigation.prototype.addLink = function (oNavigationRow) {
	// register this object as parent/caller
	//this.navlevel = navlevel;
	this.zaehler++;
	
	// save nodes for later use (sequential without regard to their hirarchy)
	this.oNavLinks[this.zaehler] = oNavigationRow;
	
	// save nodes as tree structure 
	// this is tricky because the assignment only provides levels and not parents themselves
	if (this.navLevel == 0) {
		this.oRootLink = this.oNavLinks[this.zaehler];
		// this is superceeded code, which could provide several root nodes
		// still it's not according to KISS
		//this.oRootLink[this.oRootLink.length] = this.oNavLinks[this.zaehler];
	}
	else {
		// search the parent node
		//alert('[zaehler].navLevel:'+this.oNavLinks[this.zaehler].navLevel);
		for (i = this.zaehler-1; i > 0 && this.oNavLinks[this.zaehler].navLevel <= this.oNavLinks[i].navLevel; --i) {
			;
		}
		if (i > 0) {
			var oParentNode = this.oNavLinks[i];
			oParentNode.oChildLinks[oParentNode.oChildLinks.length] = this.oNavLinks[this.zaehler];
			//alert('zaehler:'+this.zaehler+'\n[zaehler].navLevel:'+this.oNavLinks[this.zaehler].navLevel+'\n i:'+i +'\n[i].navLevel:'+this.oNavLinks[i].navLevel +'\n n childs:'+this.oNavLinks[i].oChildLinks.length);
			this.oNavLinks[this.zaehler].oParentLink = oParentNode;
		}
	}
		
	this.oNavLinks[this.zaehler].setNavigation(this);
	if (this.oNavLinks[this.zaehler].isCurrentPage()) {
		this.oCurrentPage = this.oNavLinks[this.zaehler];
		//oDebug.write('\nthis.oCurrentPage.linkText='+this.oCurrentPage.linkText);
	}

	return true;
}

/**
 * return the Html-code for the Navigation as a String
 */
Navigation.prototype.getHtml = function () {

	//alert('nav.write()');

	var sNavigation = this.sHtmlHeader;
	for (var i=1; i < this.oNavLinks.length; ++i) {
		// see where this link is located relative to the current page
		//this.oNavLinks[i].processPosition(this.oCurrentPage);
		//alert(this.oNavLinks[i].isVisibleOld);
		// update each node to ensure correct presentation
		//alert('nav.write():3');
		if (this.lWriteNotCalled)
			this.oNavLinks[i].init();
		this.oNavLinks[i].update();
		if ( (this.oNavLinks[i].isVisible())) {
			sNavigation += this.oNavLinks[i].getHtml() + '\n\n';
		}
	}
	this.lWriteNotCalled = false;
	sNavigation += this.sHtmlFooter;
	
	//alert('nav.write():2');
	return sNavigation;
}


/**
 * output the navigation tree to the layer (<div) with 
 * the specified name
 */
Navigation.prototype.write = function () {

	var sNavigation = this.getHtml();
	
	//alert('nav.write():2');

	// output without a specified layer
	// (a re-write of ths navigation won't work)
	if (this.LayerName == undefined || this.LayerName == '') {
		alert(document.layers.length);
		document.write(sNavigation);
		alert(document.layers.length);
	}
	
	// output browsers (IE 5, 6,...)
	if (document.all != undefined) {
		var oDiv = document.all[this.LayerName]; //document.getElementById('navlayerx');
		//alert('oDiv.innerHTML');
		oDiv.innerHTML = sNavigation;
	}
	// output for netscape 4.*
	//if (parseInt(navigator.appVersion)<5 && navigator.appName=="Netscape") {
	else if (document.layers != undefined) {
		oTemp = document.layers[this.LayerName].document
		//alert(document.layers[this.LayerName].name);
		oTemp.open();
		//oTemp.open("text/html","replace") 
		//document.layers['navlayer'].firstChild.data = 'xxx4';
		oTemp.write(sNavigation);
		oTemp.close();
	}
	// here we go with mozilla
	else if (document.getElementById(this.LayerName) != undefined) {
		var oDiv = document.getElementById(this.LayerName); //document.getElementById('navlayerx');
		//alert('oDiv.innerHTML');
		oDiv.innerHTML = sNavigation;
	}
	else {
		// so we don't know how to display the javascript 
		// navigation in the current browser
	}
	//oDebug.write(sNavigation);
	//document.writeln('</div>');
}

/**
 * write full Navigation Tree as Html-Code to Debug
 * This is a helper to get a static navigation as an
 * alternative to javascript
 */
Navigation.prototype.writeNavigationTree = function () {
	// bei Bedarf muss das Fenster erst geoeffnet werden
	oWindow = window.open("",					// leere URL
									"_blank",	// Name des Debugfensters
									"resizable,status,width=25,height=300,scrollbars"
									);
	//oWindow.document.write("<html><head><title>Debug Javascript</title></head><body><PRE>");
	oDoc = oWindow.document;
	oDoc.write(this.getHtml());
}

/**
 * click on an empty link
 * (normaly toggles visibility of link node)
 */
Navigation.prototype.clickLink = function Navigation_clickLink (iNodeIndex) {
	//alert(this.oNavLinks[iNodeIndex].oChildLinks.length);
	var oLink = this.oNavLinks[iNodeIndex];
	//if (oLink.oChildLinks.length > 0 && oLink.oChildLinks[0].isVisibleOld) {
	if (oLink.isExpanded) {
		oLink.collapseLink();
		//alert('collapse');
	}
	else {
		//alert('expand');
		oLink.expandLink();
	}
	// show navigation
	this.write();
	
	// returning false from the onClick will
	// prevent a reload
	var oReturn = false;
	
	// if there is a URL ensure the execution
	// (this should only have an effect when used with frames)
	if (this.linkUrl != '')
		oReturn = true;
	
	return oReturn;
}

Navigation.prototype.getJsOnClickLink = function Navigation_getJsOnClickLink(sLocalObjectName) {
	//oDebug.write('return '+this+'oNav.clickLink('+(this.zaehler+1)+');');
	return 'return '+sLocalObjectName+'.clickLink('+(this.zaehler+1)+');'
}


//-->
