/* 
Version : 0.2b
Last update : 22 october 2004

HISTORY

0.1b : first beta relase
0.2b :
	* Two new methodes have been added to anchor and span objects, highlighParents and unhighlightparents.
	* There is a new option to request the highlight of the parents of the selected entry. New option name : trackParents
	* The CSS class a.expand is now added to a node when it's expanded.
	* The CSS class a.breadcrumb is now added to the parents of the selected entry if the option trackParents is set to true;

KNOWN ISSUES
	* Overlay of select form object is not implemented.
	* Vertical positioning of absolute ul are not well understand by IE but correctly set in Mozilla in popup mode.
	* Horizontal positioning of absolute ul are not well understand by IE but correctly set in Mozilla in horizontal mode.
	* When icons are used with node, where is a layout problem in case the font size is too small.
	* The mouseover event seems to be slown down for unknown reason.
	* LI separators have an unexpected extra line with IE
	* Transparency is only working at level 1 with IE, but is working fine on every level with Mozilla
	* Popup UL positioning is currently not tested to be sure the UL is not displayed out of the visible area.
*/

// NAME : Poulli_addIcon
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : add an icon to an anchor object or to a span object
// PARAMETERS : 
//		anchorObj : the nachor object that will be updated
// CALL :
//		<poulli object>.addIcon(<anchor obj>)
function Poulli_addIcon(anchorObj) {
	var	entryIcon = anchorObj.getElementsByTagName('img');
	if (anchorObj.myType == 'node') {
		if (entryIcon.length!=0) {
			entryIcon[0].id = 'icon_' + anchorObj.id;
			if (this.positionIcon != 'right') {
				anchorObj.style.textIndent= -(entryIcon[0].width+2)+"px";
			}
		}
		else {
			// if no picture is set for a node and if the automatic correction is activated the picture is added automaticaly
			if (this.modeAuto && this.nodeIconOpenSrc != '') {
				var newIMG = document.createElement("img");
				newIMG.setAttribute("border","0");
				newIMG.setAttribute("alt","");
				newIMG.setAttribute("src",this.nodeIconOpenSrc);
				newIMG.setAttribute("width",this.nodeIconW);
				newIMG.setAttribute("height",this.nodeIconH);
				anchorObj.insertBefore(newIMG,anchorObj.firstChild);
				if (this.positionIcon != 'right') {
					anchorObj.style.textIndent= -(this.nodeIconW+2)+"px";
				}
			}
		}
	}
	else {
		// entry is a leaf and there is no icon
		if (entryIcon.length==0) {
			if (this.modeAuto && this.leafIconSrc != '') {
				var newIMG = document.createElement("img");
				newIMG.setAttribute("border","0");
				newIMG.setAttribute("alt","");					
				newIMG.setAttribute("src",this.leafIconSrc);
				newIMG.setAttribute("width",this.leafIconW);
				newIMG.setAttribute("height",this.leafIconH);
				anchorObj.insertBefore(newIMG,anchorObj.firstChild);
				if (this.positionIcon != 'right') {
					anchorObj.style.textIndent= -(this.leafIconW+2)+"px";
				}
			}
		}
		else {
			if (this.positionIcon != 'right') {
				anchorObj.style.textIndent= -(entryIcon[0].width+2)+"px";
			}
		}
	}
}

// NAME : Poulli_initNode
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : set the new methodes of an anchor object
// PARAMETERS : 
//		anchorObj : the nachor object that will be updated
// CALL :
//		<poulli object>.iniNode(<anchor obj>)
function Poulli_initNode(anchorObj) {
	this.addIcon(anchorObj);
	anchorObj.className = "node";
	anchorObj.expandCollapse = Poulli_expandCollapse;//   ----------------------------------------------
	anchorObj.expand = Poulli_expand;
	anchorObj.collapse = Poulli_collapse;
	anchorObj.popup = Poulli_popup;
	anchorObj.displayStatus = 'open';				// by default nodes are opened
	anchorObj.closeChildren = Poulli_closeChildren;	// close the children of the node
	anchorObj.subLevel = document.getElementById('node_' + anchorObj.id); // a direct access to the UL element associated to this anchor object
	if (anchorObj.subLevel)
		anchorObj.childrenEntries = anchorObj.subLevel.getElementsByTagName('a'); // a direct access to children anchors
	else 
		anchorObj.childrenEntries = null;
	// anchor without href
	if (anchorObj.href.lastIndexOf('#') == anchorObj.href.length-1)
		if (this.layout == 'tree')
			anchorObj.className += ' nohref';
		else
			anchorObj.className += ' nohrefnocursor';

	anchorObj.timer = null;

	if (anchorObj.parentNode.parentNode.parentNode.tagName != 'LI') {
		anchorObj.father = null;
		anchorObj.level = 0;
	}
	else {
		anchorObj.father = anchorObj.parentNode.parentNode.parentNode.getElementsByTagName('a')[0]; // a direct access to the father
		anchorObj.level = anchorObj.father.level + 1;
	}
	
//	anchorObj.selected = false;			// by default every anchor is not selected
	anchorObj.navigation = this;
	anchorObj.getAnchor = Poulli_getAnchor;
	anchorObj.getBreadcrumb = Poulli_getBreadcrumb;
	anchorObj.selectEntry = Poulli_selectEntry;
	anchorObj.switchIcon = Poulli_switchIcon;
	anchorObj.expandParents = Poulli_expandParents;
	anchorObj.highlightParents = Poulli_highlightParents;
	anchorObj.unhighlightParents = Poulli_unhighlightParents;
	
	/// The TITLE is set
	if (!anchorObj.title && anchorObj.lastChild && this.autoTitle) {	
		var entryTitle = new String(anchorObj.lastChild.nodeValue);
		// in IE the <br> is interprated
		entryTitle = entryTitle.replace(/<br>/ig," ");
		anchorObj.title = entryTitle;	
	}
	
	// This is the best way to access to the first picture of the link because sometime the icon have no ID in case it has been added manually by the user.
	anchorObj.icon = anchorObj.getElementsByTagName('img')[0];

	anchorObj.onClick = Poulli_onClick;
	anchorObj.onOver = Poulli_onOver;	
	anchorObj.onOut = Poulli_onOut;	
	// inharited EVENT
	anchorObj.onclick = function(){return this.onClick();};
	anchorObj.onmouseover = function(){return this.onOver();};
	anchorObj.onmouseout = function(){return this.onOut();};
}


// NAME : Poulli_initLeaf
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : set the new methodes of leaf(an anchor) object
// PARAMETERS : 
//		anchorObj : the anchor object that will be updated
// CALL :
//		<poulli object>.initLeaf(<anchor obj>)
function Poulli_initLeaf(anchorObj) {
	this.addIcon(anchorObj);
		anchorObj.displayStatus = '';	// leafs have no displayStatus
		anchorObj.subLevel = null;		// leafs have no sub level

	if (anchorObj.parentNode.parentNode.parentNode.tagName != 'LI') {
		anchorObj.father = null;
		anchorObj.level = 0;		
	}
	else {
		anchorObj.father = anchorObj.parentNode.parentNode.parentNode.getElementsByTagName('a')[0]; // a direct access to the father
		anchorObj.level = anchorObj.father.level + 1;
	}
	
//	anchorObj.selected = false;			// by default every anchor is not selected
	anchorObj.navigation = this;
	anchorObj.getBreadcrumb = Poulli_getBreadcrumb;
	anchorObj.selectEntry = Poulli_selectEntry;
	anchorObj.switchIcon = Poulli_switchIcon;
	anchorObj.expandParents = Poulli_expandParents;
	anchorObj.highlightParents = Poulli_highlightParents;
	anchorObj.unhighlightParents = Poulli_unhighlightParents;

	/// The TITLE is set
	if (!anchorObj.title && anchorObj.lastChild && this.autoTitle) {	
		var entryTitle = new String(anchorObj.lastChild.nodeValue);
		// in IE the <br> is interprated
		entryTitle = entryTitle.replace(/<br>/ig," ");
		anchorObj.title = entryTitle;	
	}
	
	// This is the best way to access to the first picture of the link because sometime the icon have no ID in case it has been added manually by the user.
	anchorObj.icon = anchorObj.getElementsByTagName('img')[0];
	anchorObj.getAnchor = Poulli_getAnchor;
	anchorObj.onClick = Poulli_onClick;
	anchorObj.onOver = Poulli_onOver;	
	anchorObj.onOut = Poulli_onOut;	
	// inharited EVENT
	anchorObj.onclick = function(){return this.onClick();};
	anchorObj.onmouseover = function(){return this.onOver();};
	anchorObj.onmouseout = function(){return this.onOut();};
}

// NAME : Poulli_initCaption
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : set the new methodes of leaf(an anchor) object
// PARAMETERS : 
//		anchorObj : the anchor object that will be updated
// CALL :
//		<poulli object>.initCaption(<anchor obj>)
function Poulli_initCaption(anchorObj) {
	this.addIcon(anchorObj);
	anchorObj.displayStatus = '';	// leafs have no displayStatus

	if (anchorObj.parentNode.parentNode.parentNode.tagName != 'LI') {
		anchorObj.father = null;
	}
	else {
		anchorObj.father = anchorObj.parentNode.parentNode.parentNode.getElementsByTagName('a')[0]; // a direct access to the father
	}
	
	anchorObj.navigation = this;
	
	/// The TITLE is set
	if (!anchorObj.title && anchorObj.lastChild && this.autoTitle) {	
		var entryTitle = new String(anchorObj.lastChild.nodeValue);
		// in IE the <br> is interprated
		entryTitle = entryTitle.replace(/<br>/ig," ");
		anchorObj.title = entryTitle;	
	}
	anchorObj.getAnchor = Poulli_getAnchor;
	anchorObj.onOver = Poulli_onOver;	
	anchorObj.onOut = Poulli_onOut;	
	// inharited EVENT
	anchorObj.onmouseover = function(){return this.onOver();};
	anchorObj.onmouseout = function(){return this.onOut();};
}


// NAME : Poulli_setTitle
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : customize link belonging to an UL object
// PARAMETERS : 
// CALL :
//		<poulli object>.customize()
function Poulli_customize() {
	var nodeUL; // nested ul of the <navigationObj>
	var entryLI = this.navigationSource.getElementsByTagName('li'); // an li object
	var entry; // an anchor object belonging to an entryLI object
	
	// set className of the first UL to 'root'
//	this.navigationSource.getElementsByTagName('ul')[0].className = "root";

	for (var i=0;i<entryLI.length;i++) {
		// LI containing an UL are nodes
		nodeUL = entryLI[i].getElementsByTagName('ul');

		// the entry is a node cuz there is a nested UL
		if (nodeUL.length!=0) {
			nodeUL[0].id = 'node_' + this.name + '_' + i;
			entry = entryLI[i].firstChild;
			if (entry.tagName == 'A') {
				entry.id = this.name + '_' + i;
				// a new attribute is added to the anchor
				entry.myType = "node";
				if (!entry.target)
					entry.target = "_self";
				// new methodes are added to the anchor
				this.initNode(entry);
			}
			else {
				var newA = document.createElement("a");
				newA.setAttribute("href","#");
				newA.setAttribute("target","_self");
				newA.setAttribute("id",this.name + '_' + i);
				// a new attribute is added to the anchor
				newA.myType = "node";
				// new methodes are added to the anchor
				if (entry.tagName != undefined) {
					newA.innerHTML = entry.innerHTML;
					if (entry.title)
						newA.title = entry.title;
					if (entry.className)
						newA.className = entry.className;
				}			
				else {
					newA.innerHTML = entry.nodeValue;
				}
				entryLI[i].replaceChild(newA,entryLI[i].firstChild);				
				this.initNode(newA);
			}
		}
		else { // the entry is a leaf
			entry = entryLI[i].firstChild;
			if (entry.tagName == 'A') {
				entry.myType = "leaf";
				if (!entry.target)
					entry.target = "_self";
				entry.id = this.name + '_' + i;
				// new methodes are added to the entry object
				this.initLeaf(entry);
			}
			else {
				if (entry.className != 'separator') {
					var newSPAN = document.createElement("span");
					newSPAN.myType = "caption";
					if (entry.title)
						newSPAN.title = entry.title;
					if (entry.className)
						newSPAN.className = entry.className;
					newSPAN.id = this.name + '_' + i;
					if (entry.innerHTML != undefined)
						newSPAN.innerHTML = entry.innerHTML;
						else
						newSPAN.innerHTML = entry.nodeValue;
					entryLI[i].replaceChild(newSPAN,entryLI[i].firstChild);
					// new methodes are added to the SPAN object
					this.initCaption(newSPAN);
				}
			}
		}
	}
	this.navigationEntries = this.navigationSource.getElementsByTagName('a'); // list of all entry of the navigation, each entry is an A HTML element
	this.collapseAll();
	// the current page is activated in the navigation
	if (this.autoSelectEntry) {
		var activeLeaf = this.getLeafByURL();
		if (activeLeaf!=null) {
			activeLeaf.selectEntry();
			// it can not be a node without url or a "caption" !
			if (activeLeaf.myType == "node") 
				activeLeaf.expand();
			activeLeaf.expandParents();
		}
}
	

}

// NAME : Poulli_onOver
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object, called on a onMouseOver event
// PARAMETERS : 
// CALL :
//		<customized anchor object>.onOver()
function Poulli_onOver () {
	if (this.navigation.mouseover) {
		window.clearTimeout(this.navigation.timer);
		this.navigation.unpopupAll(this);
		if (this.displayStatus == 'close')
			this.popup();
	}
	window.status=this.title;
	return true;
}

// NAME : Poulli_onOut
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object, called on a onMouseOut event
// PARAMETERS : 
// CALL :
//		<customized anchor object>.onOut()
function Poulli_onOut () {
	var currObj = this;
	if (this.navigation.mouseover) {
		this.navigation.timer = window.setTimeout(function(){currObj.navigation.unpopupAll();}, this.navigation.timeout);
	}
			
	window.status='';
	return true;
}

// NAME : Poulli_onClick
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object, called on a onclick event
// PARAMETERS : 
// CALL :
//		<customized anchor object>.onClick()
function Poulli_onClick () {
	/* a node ic clicked */
	if (this.myType == 'node') {
		// there is a real url on this link
		if (this.href.match(/[^#]$/)) {
			this.selectEntry();
			if (!this.navigation.mouseover) 
				this.expandCollapse();
			return true;
		}
		else {
			if (!this.navigation.mouseover) 
				this.expandCollapse();
			return false;
		}
	}
	/* a leaf is clicked */
	else {
		this.selectEntry();
//		this.switchIcon();
		return true;
	}
}

// NAME : Poulli_switchIcon
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object. Switch the icon inside the anchor
// PARAMETERS : 
// CALL :
//		<customized anchor object>.switchIcon()
function Poulli_switchIcon() {
	// The Entry icon is switched	
	if (this.icon) {
		if (this.navigation.selectedEntry) {
			if (this.navigation.nodeIconActive && this.navigation.selectedEntry.id == this.id && this.myType == 'node') {
				this.icon.src = this.icon.src.replace(/(_(c|o)\.([^\.]*))$/,'_a.$3');
				return;
			}
		}
		// if the object is a closed node
		if (this.displayStatus == 'close')
			this.icon.src = this.icon.src.replace(/(_(a|o)\.([^\.]*))$/,'_c.$3');
		else 
			/// if the object is an opened node or a leaf currently unselected
			if (this.icon.src.match(/_(a|c)\.[^\.]*$/)) 
				this.icon.src = this.icon.src.replace(/(_(a|c)\.([^\.]*))$/,'_o.$3');
			else 
				// if the object is a leaf currently selected
				this.icon.src = this.icon.src.replace(/_o\.([^\.]*)$/,'_c.$1');	

	}
}

// NAME : Poulli_selectEntry
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object. Change the layout of the anchor when it's clicked
// PARAMETERS : 
// CALL :
//		<customized anchor object>.selectEntry()
function Poulli_selectEntry() {
	if (this.navigation.selectedEntry != null) {
		if (this.navigation.selectedEntry.id != this.id) {
			// the new selected entry must be set before the icon of the old one is changed, cuz of folder active status of a node
			var unselectOld = this.navigation.selectedEntry;
			this.navigation.selectedEntry = this;
			unselectOld.className = unselectOld.className.replace(/\s?selected$/,'');
			unselectOld.switchIcon();
			this.className += ' selected';
			this.switchIcon();			
			// Parents have to be unhighlighted
			if (this.navigation.trackParents) {
				unselectOld.unhighlightParents();
				this.highlightParents();
			}
		}
	}
	else {
		// 	only used the first time an entry is clicked
		this.navigation.selectedEntry = this;
		this.className += ' selected';
		this.switchIcon();
		// Parents have to be highlighted
		if (this.navigation.trackParents)
			this.highlightParents();
	}
}

// NAME : Poulli_closeChildren
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object. Collapse the children of the anchor
// PARAMETERS : 
// CALL :
//		<customized anchor object>.closeChildren()
function Poulli_closeChildren () {
	for (i=0;i<this.childrenEntries.length;i++) 
		if (this.childrenEntries[i].displayStatus == 'open')
			this.childrenEntries[i].collapse();
}	

// NAME : Poulli_closeBrother
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object. Collapse the brother (node having the same father) of the anchor
// PARAMETERS : 
// CALL :
//		<customized anchor object>.closeBrother()
/*
function Poulli_closeBrother () {
	if (this.navigation.mouseover) {
		for (i=0;i<this.brothers.length;i++) 
			if ((this.brothers[i].displayStatus == 'popup') && (this.brothers[i].id != this.id)) {
				this.brothers[i].collapse();
			}
			this.brothers[i].closeChildren();	
	}
	else {
		for (i=0;i<this.brothers.length;i++) 
			if ((this.brothers[i].displayStatus == 'open') && (this.brothers[i].id != this.id)) {
					this.brothers[i].collapse();
				if (this.navigation.subClose)
					this.brothers[i].closeChildren();	
			}
	}
}
*/
// NAME : Poulli_expandCollapse
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object. Expand or collapse the UL associated to the anchor if this one is a node BUT don't modify the icon
// PARAMETERS : 
// CALL :
//		<customized anchor object>.expandCollapse()
function Poulli_expandCollapse () {
	if (this.displayStatus == 'open') {
		this.collapse();
		
		// children have to be closed too
		if (this.navigation.subClose)
			this.closeChildren();	
	}
	else {
		// the other folder have to be closed excepting the parents of the current one
		if (this.navigation.globalClose) {
			this.navigation.collapseAll(this);
			this.navigation.expandedNodes.push(this);
		}
		this.expand();
	}
}

// NAME : Poulli_expand
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object. Expand the UL associated to the anchor if this one is a node
// PARAMETERS : 
// CALL :
//		<customized anchor object>.expand()
function Poulli_expand () {
	this.displayStatus='open';
//	if (this.title == this.navigation.nodeOpenTitle) this.title = this.navigation.nodeCloseTitle;
	this.switchIcon();
	this.subLevel.style.display = '';
	this.className += " expand";
}

// NAME : Poulli_expandParents
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : expand all the parents of an entry
// PARAMETERS : 
// CALL :
//		<customized anchor object>.expandParents()
function Poulli_expandParents () {
	var anEntry = this;
	while (anEntry.father != null) {
		if (anEntry.father.displayStatus == 'close')
			anEntry.father.expand();
		anEntry = anEntry.father;
	}
}

// NAME : Poulli_popup
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object. Popup the UL associated to the anchor if this one is a node
// PARAMETERS : 
// CALL :
//		<customized anchor object>.popup()
function Poulli_popup () {
//	 var DL_bIE = document.all ? true : false; // initialize var to identify IE
	//hideSelectObject(this.id);
	this.displayStatus='popup';
	var objX = 0;
	var objY = 0;
	
	if (this.level == 0) {	
		// mode popup
		if (this.navigation.layout == "popup") {
			objX = getLeft(this)-this.offsetLeft+parseInt(this.offsetWidth)+this.navigation.gapX;
			objY = getTop(this)-1+this.navigation.gapY;
		}
		// mode horizontal
		else {
//			if (DL_bIE) {
				objX = getLeft(this)+this.navigation.gapX;
				objY = getTop(this)+parseInt(this.offsetHeight)+this.navigation.gapY;		
//			}		
//			else {
//			objX = DL_GetElementLeft(this)+this.navigation.gapX;
//			objY = DL_GetElementTop(this)+parseInt(this.offsetHeight)+this.navigation.gapY;
//			}

		}
	}
	else {
		if (this.father.displayStatus != 'popup') {
			objX = getLeft(this)-this.offsetLeft+parseInt(this.offsetWidth)+this.navigation.gapX;
			objY = getTop(this)+this.navigation.gapY;
		}
		else {
			objX = parseInt(this.parentNode.parentNode.offsetWidth)+this.navigation.gapX;
			objY = parseInt(this.parentNode.offsetTop)+this.navigation.gapY;
		}
	}
	
//	if (this.parentNode.parentNode.style.left) {
//		objX = parseInt(this.parentNode.parentNode.offsetWidth)-1+this.navigation.gapX;
//	}
//	if (this.parentNode.parentNode.style.top)
//	if (this.level >0)
//		objY = parseInt(this.parentNode.offsetTop)+this.navigation.gapY-1;
//		validPosition(this.subLevel,objX,objY);
	this.subLevel.className += ' popup';
	this.subLevel.style.left = objX + 'px';
	this.subLevel.style.top = objY+ 'px';
	this.navigation.popupOpened.push(this);
	
	// I really hate to do that but I haven't found any other solution
	// The first seperator in a popup ul should not be displayed
	// I can not use firstChild.firstChild because of Mozilla and also in case there is something between the ul and its first LI
	var sepTemp = this.subLevel.getElementsByTagName('li')[0].firstChild;
	if (sepTemp.className == "separator")
		sepTemp.style.display="none";
	try {
		this.subLevel.style.display = '';
	} catch(e){}
}

// NAME : Poulli_collapse
// METHODE OF THE OBJECT : anchor
// DESCRIPTION : new method of an anchor object. Collapse the UL associated to the anchor if this one is a node
// PARAMETERS : 
// CALL :
//		<customized anchor object>.collapse()
function Poulli_collapse () {
	this.subLevel.style.display = 'none';
//	if (this.title == this.navigation.nodeCloseTitle)
//		this.title = this.navigation.nodeOpenTitle;
	
	if (this.subLevel.className)
		this.subLevel.className = this.subLevel.className.replace(/\s?popup$/,'');
	if (this.className)
		this.className = this.className.replace(/\s?expand$/,'');

	this.displayStatus='close';
	this.switchIcon();
}

// NAME : Poulli_getBreadcrumb
// METHODE OF THE OBJECT : anchor or span
// DESCRIPTION : return the breadcrumb of the leaf, all links to the parent pages with long descriptions
// PARAMETER : if the current anchor should not be returned you have to set the onlyParent to true. This parameter is not mandatory
// CALL :
//		<customized anchor object>.getBreadcrumb()
function Poulli_getBreadcrumb(onlyParent){
	var currentEntry = this;
	// it will be easier with outerHTML, but it's not working with Mozilla and then you wil kept extended methodes and classes
	
	if (onlyParent && currentEntry.father != null)
		currentEntry = currentEntry.father;
	var HTMLBreadcrumb = currentEntry.getAnchor();
			
	while (currentEntry.father != null) {
		HTMLBreadcrumb = currentEntry.father.getAnchor() + this.navigation.breadcrumbSeparator + HTMLBreadcrumb;
		currentEntry = currentEntry.father;
	}
	
	HTMLBreadcrumb = HTMLBreadcrumb.replace(/<br>/gi,' ');
	HTMLBreadcrumb = HTMLBreadcrumb.replace(/<img[^>]*>/gi,'');
	return HTMLBreadcrumb;
}

// NAME : Poulli_getAnchor
// METHODE OF THE OBJECT : anchor or span
// DESCRIPTION : return the anchor html code of the leaf but without any icone
// CALL :
//		<customized anchor object>.getAnchor()
function Poulli_getAnchor(){
	if (this.href != null && this.href.match(/[^#]$/) || this.myType == 'leaf') {
		return '<a href="' + this.href + '" target="' + this.target + '" title="' + this.title + '">' + this.innerHTML + '</a>';
	}
	else {
		return this.innerHTML;
	}
}

// NAME : Poulli_highlightParents
// METHODE OF THE OBJECT : anchor or span
// DESCRIPTION : highlight the parents of the node/leaf. Nodes are not expanded.
// PARAMETERS : 
// CALL :
//		<customized anchor object>.highlightParents()
function Poulli_highlightParents () {
	var father = this.father;
	while (father != null) {
		father.className += ' breadcrumb';
		father = father.father;
	}
}

// NAME : Poulli_unhighlightParents
// METHODE OF THE OBJECT : anchor or span
// DESCRIPTION : highlight the parents of the node/leaf. Nodes are not expanded.
// PARAMETERS : 
// CALL :
//		<customized anchor object>.unhighlightParents()
function Poulli_unhighlightParents () {
	var father = this.father;
	while (father != null) {
		father.className = father.className.replace(/\s?breadcrumb$/,'');
		father = father.father;
	}
}


/* POULLI METHODES */

// NAME : Poulli_collapseAll
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : hide all UL tag excepting the first one
// PARAMETERS : 
// CALL :
//		<poulli object>.collapseAll()
function Poulli_collapseAll (currentEntry) {
	if (currentEntry) {
		for (var j=this.expandedNodes.length-1;j>-1;j--) {
			if (this.expandedNodes[j].id == currentEntry.id) 
					break;	
			if (currentEntry.father != null)
				if (this.expandedNodes[j].id == currentEntry.father.id) 
					break;					
			this.expandedNodes[j].collapse();
			this.expandedNodes.pop();
		}
	}
	else {
		for (var j=0;j<this.navigationEntries.length;j++)
			if (this.navigationEntries[j].displayStatus == 'open')
				this.navigationEntries[j].collapse();
	}
}

// NAME : Poulli_unpopupAll
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : hide all UL tag excepting the first one
// PARAMETERS : 
// CALL :
//		<poulli object>.unpopupAll()
function Poulli_unpopupAll (currentEntry) {
		if (currentEntry) {
			for (var j=this.popupOpened.length-1;j>-1;j--) {
				if (this.popupOpened[j].id == currentEntry.id) 
					return;
				if (this.popupOpened[j].level < currentEntry.level)
					return;
				this.popupOpened[j].collapse();
				this.popupOpened.pop();
			}
		}
		else {
			for (var j=this.popupOpened.length-1;j>-1;j--) {
					this.popupOpened[j].collapse();
					this.popupOpened.pop();
			}
			// hidden select form object are restored
			//showSelectObject();
		}
}

// NAME : Poulli_expandAll
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : display all UL tag excepting the first one
// PARAMETERS : 
// CALL :
//		<poulli object>.expandAll()
function Poulli_expandAll () {
	for (var j=0;j<this.navigationEntries.length;j++) 
		if (this.navigationEntries[j].displayStatus == 'close') 
			this.navigationEntries[j].expand();
}

// NAME : Poulli_expandNode
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : expand a node and all its parents
// PARAMETERS : 
//		anchorID : anchor ID associated to the node, it's the entry number .
// CALL :
//		<poulli object>.expand()
function Poulli_expandNode (anchorID) {
	// the node is expanded
	var anEntry = this.navigationEntries[anchorID];
	if (anEntry.displayStatus == 'close')
		anEntry.expand();
	// now we have to take care of its parents
	while (anEntry.father != null) {
		if (anEntry.father.displayStatus == 'close')
			anEntry.father.expand();
		anEntry = anEntry.father;
	}
}

// NAME : Poulli_selectNavigationEntry
// METHODE OF THE OBJECT : Poulli
// DESCRIPTION : select an entry and expand its parents
// PARAMETERS : 
//		anchorID : anchor ID associated the node, it's the entry number .
// CALL :
//		<poulli object>.selectEntry()
function Poulli_selectNavigationEntry (anchorID) {
	// a node is selected
	if (this.navigationEntries[anchorID].myType == 'node') {
		// there is a real url on this link, the node can be selected
		if (this.navigationEntries[anchorID].href.match(/[^#]$/))
			this.navigationEntries[anchorID].selectEntry();
	}
	// a leaf is selected
	else {
		this.navigationEntries[anchorID].selectEntry();
//		this.navigationEntries[anchorID].switchIcon();
	}
	// now we take care of the parents
	this.expand(anchorID);		
}

// NAME : Poulli-getLeafByURL
// METHODE OF THE OBJECT : poulli object
// DESCRIPTION : return the leaf associated to the current URL of the page
// PARAMETERS : 
//		URL : the searched URL
// CALL :
//		<poulli object>.getLeafByURL("URL")
// NOTE : The function will return the FIRST leaf (or node) having the URL string parameter in its URL.
//	Be sure to not have different leaf with the same peace of URL.
function Poulli_getLeafByURL(URL){
	if (!URL)
		var cleanedURL = this.documentURL;
	else
		var cleanedURL = URL;
	cleanedURL = cleanedURL.replace('?no-redirect',''); // Because of Interwoven
	// if # is in last position, it should be removed
	cleanedURL = cleanedURL.replace(/#$/,'');
	// Everything before the root folder of the URL need to be removed
	// Interwoven is a special case
	cleanedURL = cleanedURL.replace(/^(.*\/WORKAREA\/)/,'')
	// root stard after the first / in the URL
	//cleanedURL = cleanedURL.replace(/^[^\/]*(\/.*)$/,'$1')
	cleanedURL = cleanedURL.replace(/^([^\/]*)/,'')
	for(var j=0;j<this.navigationEntries.length;j++){
		// anchor with an url set to # must be ignored
		if (!this.navigationEntries[j].href.match(/#$/)) {
			// anchor ended by / should match the default index.shtml
			if (this.navigationEntries[j].href.match(/\/$/)) 
				navigationURL = this.navigationEntries[j].href+'index.html';
			else
				navigationURL = this.navigationEntries[j].href;
			if (navigationURL.indexOf(cleanedURL) != -1) {
	//		if ((this.navigationEntries[j].href.indexOf(cleanedURL) != -1) && (this.navigationEntries[j].href.match(/[^#]$/))) {
				return (this.navigationEntries[j]);
			}
		}
	}
	// The page has not been found in the navigation but maybe the default page of the current folder exist in the navigation.
	// Let's try to found it

	// So we removed the current page name and replace it by the default one. Of course if the current page is already index.html we do nothing.
	if (!cleanedURL.match(/index.html$/)) {
		cleanedURL = cleanedURL.replace(/[^\/]*$/,'index.html');	
		for(var j=0;j<this.navigationEntries.length;j++){
			// anchor with an url set to # must be ignored
			if (this.navigationEntries[j].href.match(/#$/)) {
				// anchor ended by / should match the default index.html
				if (this.navigationEntries[j].href.match(/\/$/)) 
					navigationURL = this.navigationEntries[j].href+'index.html';
				else
					navigationURL = this.navigationEntries[j].href;
				if (navigationURL.indexOf(cleanedURL) != -1) {
					return (this.navigationEntries[j]);
				}
			}
		}
	}
	
	return null;
}


// NAME : Poulli_switchIcon
// METHODE OF THE OBJECT : 
// DESCRIPTION : constructor of the object Poulli
// PARAMETERS : 
// CALL :
//		var <navigationobject> = new Poulli('<navigationobject name>');
function Poulli(layerID){
	// properties
	this.documentURL = self.document.location.href; // default value of the current URL, it as parameter so you can modify it if you used POULLI with frames.
	this.globalClose  = true;       // All folders are closed when a folder is opened ?
	this.subClose     = true;       // Subfolder will be closed when the father is closed ?
	this.autoSelectEntry = true;	// If set to True, the URL of the Current page will be detected and the corresponding entry in the tree will be selected.
	this.autoTitle = false;			// If set to true entries without title will get a default one base on the entry text.
	this.trackParents = true;		// If set to true the parent sof the selected entry are highlighted with the CSS class a.breadcrumb.
	this.layout = 'horizontal';	// can be tree, horizontal, tabs or popup
	this.name = layerID;
	this.selectedEntry = null;		// the current selected anchor(entry in the navigation)
	this.navigationSource = document.getElementById(layerID); // the layer containing the navigation. it's id is the name of the navigation object create with the method 'new Poulli'
	this.navigationEntries = new Array(); // list of all entry of the navigation, each entry is an A HTML element	

	this.modeAuto = true; // if set to true, icon are added automatically and links to handle sub levels too
//	this.nodeOpenTitle = "Mouse click to expand"; // ALT/TITLE property value of a collapsed node
//	this.nodeCloseTitle = "Mouse click to collapse"; // ALT/TITLE property value of a expanded node
	this.nodeIconOpenSrc = ""; // icon of an opened node
	this.nodeIconW = 10;
	this.nodeIconH = 10;
	this.leafIconSrc = ""; // icon of a leaf
	this.leafIconW = 10;
	this.leafIconH = 10;
	this.gapX = 0;
	this.gapY = 1;
	this.breadcrumbSeparator = "&nbsp;&gt; ";
	this.timer = null;	//timer used when mouseover is set to true
	this.popupOpened = new Array(); // list of popuped nodes
	this.expandedNodes = new Array(); // list of expanded nodes, only used in globalClose mode
	this.timeout = 500;	// timout used to wait until a node is closed when the mouse is mover out of it
	this.positionIcon = 'right'; // to move the icon on right you have to update the css and to set this parameter to right to disable the automated indentation of the text
								// if you want the icon on left you have to update the css and to set this paramter to left;
	this.mouseover = true;	// if set to true when moving your mouse over a node it's expanded
	this.nodeIconActive = true; // by default node's icon have only two status 'open' and 'close' by setting this parameter to true the status 'active' is handled. Means a node can have three different icones.
								// nodes are not supposed to have real link, they are not supposed to be selected this why the default status of the nodeIconActive is set to false.
								
	// METHODES

	this.getLeafByURL = Poulli_getLeafByURL; // Return the leaf associated to the URL
	this.unpopupAll = Poulli_unpopupAll;		// Collapse all popuped nodes
	this.collapseAll = Poulli_collapseAll;		// Collapse all nodes
	this.expandAll = Poulli_expandAll;			// Expand all nodes
	this.customize = Poulli_customize; // Upgrade the existing UL/LI to produce the navigation
	this.addIcon = Poulli_addIcon;		// add an icon to an anchor object
	
	// why three constructors ? To save memory and to not implement unused methodes or parameters to the objects
	this.initNode = Poulli_initNode;	// set the new methodes of an anchor object
	this.initLeaf = Poulli_initLeaf;	// set the new methodes of an anchor object
	this.initCaption = Poulli_initCaption;	// set the new methodes of an anchor object
	
	this.expand = Poulli_expandNode;	// expand a node and all its parent. You must give the node number in parameter
	this.selectEntry = Poulli_selectNavigationEntry // will select the entry given in parameter and will expand its parents
return this;
}

function validPosition(obj,X,Y){
	var limitW = 0;
	var limitH = 0;
	var scrollerSize = 21;
	if (document.all) {
		limitW = (document.body.clientWidth+document.body.scrollLeft) - obj.offsetWidth;
		limitH = (document.body.clientHeight+document.body.scrollTop) - obj.offsetHeight;
	} else if (document.getElementById) {
		limitW = (window.innerWidth+window.pageXOffset) - scrollerSize - obj.offsetWidth;
		limitH = (window.innerHeight+window.pageYOffset) - scrollerSize - obj.offsetHeight;
	}
	if (Y > limitH) obj.style.top = limitH;
	else obj.style.top = Y;
	if (X > limitW) obj.style.left = limitW;
	else obj.style.left = X;
}

function getTop(obj) {
	if (document.getElementById) { 
		for (var ly=0; obj!=null; ly+=obj.offsetTop, obj=obj.offsetParent);
		return ly;
 	} else { return obj.top; }
}

function getLeft(obj) {
	if (document.getElementById) { 
		for (var lx=0; obj!=null; lx+=obj.offsetLeft, obj=obj.offsetParent);
		return lx-document.body.firstChild.offsetLeft;
//		return lx;
//	return 0;
	} else { return obj.left;}
}