/*	lib:			js-dfc-tree		description:	implements a UI tree widget	methods:		DFCTree					addChild					createConfiguration					create					select					expand					collapseAll					setDOMParent					getDOMParent				DFCTreeNode					addChild					select					enable					getLabel					getData					events:		onSelect		requires:		js-dfc					created:		Oct. 7, 2002		contributed:	Wolfgang Schramm*/// --------------------------- DFCTreeNodeConfig -----------------------------DFCTreeNodeConfig = function() {	// displayed items	this.showExpanded			= true;	this.showTwisty			= false;	this.showIcon				= false;	this.showTwistyFirst		= true;	// behaviour	this.selectOnDown			= true;	this.selectOnEnterKey		= false;	this.expandOnDown			= false;	this.expandOnDblClick		= false;	this.collapseOnDown			= false;	this.collapseOnDblClick		= false;	this.useCSSDown			= false;	// true: only one sibling will be open at a time if there is another open, this will be collapsed	this.autoCollapseSiblings	= false;		// access with tab key	this.keyAccess				= false;		// dynamic loading	this.loadOnDemand			= false;		// true: showExpanded must be false		// positioning / offsets	this.widthTwisty			= '16px';	this.widthIcon				= '18px';	this.childOffsetX			= '20px';	// css	this.cssNodeContainerOtherChilds		= '';	this.cssNodeContainerLastChild		= '';	this.cssChildContainer				= '';		this.cssHover						= '';			this.cssTwisty						= '';	this.cssTwistyDown					= '';	this.cssTwistyContainerOtherChilds		= '';	this.cssTwistyContainerOtherChildsOver	= '';	this.cssTwistyContainerOtherChildsDown	= '';	this.cssTwistyContainerLastChild		= '';	this.cssTwistyContainerLastChildOver	= '';	this.cssTwistyContainerLastChildDown	= '';		this.cssIcon						= '';	this.cssIconDown					= '';		this.cssIconContainer				= '';	this.cssIconContainerOver			= '';	this.cssIconContainerDown			= '';	this.cssIconContainerSelected			= '';		this.cssLabel						= '';	this.cssLabelDown					= '';	this.cssLabelOver					= '';	this.cssLabelSelected				= '';	this.cssLabelDisabled				= '';	this.cssLabelExpanded				= '';		this.cssLabelContainer				= '';	this.cssLabelContainerDown			= '';	this.cssLabelContainerOver			= '';	this.cssLabelContainerSelected		= '';	this.cssLabelContainerSelectedCollapsed	= '';	this.cssLabelContainerDisabled		= '';	this.cssLabelContainerDisabledOver		= '';	this.cssLabelContainerExpanded		= '';	this.cssLabelContainerExpandedOver		= '';		// default icons	this.twistyOpen		= 'treeSysTwistyOpen.gif?OpenImageResource';	this.twistyClosed		= 'treeSysTwistyClosed.gif?OpenImageResource';		this.iconClosed		= 'treeFolderClosed.gif?OpenImageResource';	this.iconOpen			= 'treeFolderOpen.gif?OpenImageResource';	};// ---------------------------------- DFCTree -----------------------------------------DFCTree = function(hWin) {	// hWin		window where the tree is displayed		DFCEvent.call(this);			// DOM anchestor	this._hWin			= hWin;	this._domParent		= hWin.document.body;	// DOM parent element for the whole tree		this._iNodeId			= -1;				// node counter	this._aAllNodes		= new Array();	this._aNodesByCustId	= new Array();	this._hSelectedNode		= null;				// currently selected node		// create default node configuration	this._hConfig			= new DFCConfig(DFCTreeNodeConfig);		// create root node (invisible node)	this._hRootNode		= new DFCTreeNode('/');	this._hRootNode._hTree	= this;	this._hRootNode._iLevel	= 0;					// nesting level	this._hRootNode._hConfig	= this._hConfig.get();	this._hRootNode._isExpanded = true;	this._registerNode(this._hRootNode);		this._domNodeContProto	= null;		// DOM node prototype	// define and register event which can be raised by this widget	this._sEvent_onSelect	= 'onSelect';		this._registerEvent(this._sEvent_onSelect);};DFCTree.prototype = new DFCEvent();DFCTree.aLoading = new Array();DFCTree.prototype.setDOMParent = function(domParent) {	// set DOM parent element for the whole tree	this._domParent	= domParent;};DFCTree.prototype.getDOMParent = function() {	// return DOM parent element	return this._domParent;};DFCTree.prototype.addChild = function(sLabel, opt_jsData, opt_sConfig, opt_sSourceUrl, opt_isEnabled, opt_sId) {	// create child node with root as parent	// return:	created child		return this._hRootNode.addChild(sLabel, opt_jsData, opt_sConfig, opt_sSourceUrl, opt_isEnabled, opt_sId);};DFCTree.prototype.create = function() {	// display in memory tree in the browser	// create DOM for all expanded nodes	var domTree = this._hRootNode._getNodeDOM();		if (domTree) {		dfc.preventTextSelection(domTree);		this._domParent.appendChild(domTree);	}};DFCTree.prototype.select = function(sId, opt_isFireEvent) {		// select a tree node by using the custom id		// sId:			custom id	// opt_isFireEvent	true: the onSelect event is fired		var hNode = this._aNodesByCustId[sId];		if (hNode == null) {		alert('DFCTree.select: node with id "' + sId + '" is not defined');		return;	}		hNode.select();		if (opt_isFireEvent) {		this._raiseEvent(this._sEvent_onSelect, hNode);	}};DFCTree.prototype.expand = function(sId, isExpand) {		// expand/collapse a tree node by using the custom id		// sId:			custom id	// isExpanded		true: expand		false: collapse		var hNode = this._aNodesByCustId[sId];		if (hNode == null) {		alert('DFCTree.expand: node with id "' + sId + '" is not defined');		return;	}	if (isExpand && hNode._isExpanded) {		// node is already expanded		return;	}	if (!isExpand && !hNode._isExpanded){		// node is already collapsed		return;	}		hNode._expandNode(isExpand, true);};DFCTree.prototype.collapseAll = function() {	// collapse all nodes	var aAllNodes = this._aAllNodes;		// loop: all nodes	for (var iNode = 0; iNode < aAllNodes.length; iNode++) {			var hNode	= aAllNodes[iNode];		if (hNode != this._hRootNode && hNode._isExpanded) {			// collapse all expanded nodes			hNode._isExpanded				= false;				hNode._domChildCont.style.display	= 'none';			var hCfg = hNode._hConfig;			if (hCfg.showTwisty)	{ hNode._domTwisty.src	= hCfg.twistyClosed; }			if (hCfg.showIcon)		{ hNode._domIcon.src	= hCfg.iconClosed; }			if (hNode._domLabel)	{				hNode._domLabelCont.className	= hCfg.cssLabelContainer;				hNode._domLabel.className	= hCfg.cssLabel;			}				}	}}/* loading css dynamically works, but Mozilla lacks an onload eventDFCTree.prototype.setCSSLink = function(sUrl) {	// set link to external css style sheet		var domLink	= this._hWin.document.createElement("link"); 	domLink.rel	= 'stylesheet';	domLink.type	= 'text/css';	domLink.href	= sUrl;	dfc.addEventListener(domLink, 'load', this._onloadCSSLink);		this._hWin.document.documentElement.childNodes[0].appendChild(domLink);	}DFCTree.prototype._onloadCSSLink = function() {	alert('isloaded')}*/DFCTree.prototype.createConfiguration = function(hCfg, opt_sKey, opt_sConfigInherit) {	// create a new tree node configuration	// hCfg			DFCTreeNodeConfig structure	// opt_sKey			key for this configuration, null if this is the default	// opt_sConfigInherit	key where the configuration is inheriting from	var cssDefault;		cssDefault = hCfg.cssLabelContainer;	hCfg.cssLabelContainerDown			= hCfg.cssLabelContainerDown				|| cssDefault;	hCfg.cssLabelContainerOver			= hCfg.cssLabelContainerOver				|| cssDefault;	hCfg.cssLabelContainerSelected		= hCfg.cssLabelContainerSelected			|| cssDefault;	hCfg.cssLabelContainerSelectedCollapsed	= hCfg.cssLabelContainerSelectedCollapsed	|| hCfg.cssLabelContainerSelected;	hCfg.cssLabelContainerDisabled		= hCfg.cssLabelContainerDisabled			|| cssDefault;	hCfg.cssLabelContainerDisabledOver		= hCfg.cssLabelContainerDisabledOver		|| hCfg.cssLabelContainerDisabled;	hCfg.cssLabelContainerExpanded		= hCfg.cssLabelContainerExpanded			|| cssDefault;	hCfg.cssLabelContainerExpandedOver		= hCfg.cssLabelContainerExpandedOver		|| hCfg.cssLabelContainerExpanded;				cssDefault = hCfg.cssLabel;	hCfg.cssLabelDown					= hCfg.cssLabelDown						|| cssDefault;	hCfg.cssLabelOver					= hCfg.cssLabelOver						|| cssDefault;	hCfg.cssLabelSelected				= hCfg.cssLabelSelected					|| cssDefault;	hCfg.cssLabelDisabled				= hCfg.cssLabelDisabled					|| cssDefault;	hCfg.cssLabelExpanded				= hCfg.cssLabelExpanded					|| cssDefault;		this._hConfig.create(hCfg, opt_sKey, opt_sConfigInherit);};DFCTree.prototype._registerNode = function(hNode, opt_sId) {	// register a new tree node in the tree	var sNodeId = (++this._iNodeId).toString();	hNode._sNodeId = sNodeId;	this._aAllNodes[sNodeId] = hNode;		if (opt_sId) {		this._aNodesByCustId['' + opt_sId] = hNode;	}};DFCTree.prototype._getLoadingDOM = function(hNode) {	// create DOM node which is displayed when nodes are loaded dynamically	// this node is not yet appended to the document			var domLoading;	var domDoc	= this._hWin.document;		domLoading = domDoc.createElement('div');		//domLoading.className = hCfg.cssLabel;					domLoading.appendChild(domDoc.createTextNode('Loading...'));	return domLoading;};DFCTree.prototype._onloadSubtree = function(hLoadCtx) {	// callback when a subtree was loaded	// hLoadCtx	loading context, this was returned from dfc.load		var hTN = hLoadCtx.EventTreeNode;		// add sub nodes to the tree	subTreeData(hTN);		// replace the node 'loading...' with the loaded node(s)	// create children DOM tree	var domChildren = hTN._getChildrenDOM();	if (domChildren) {		hTN._domNodeCont.replaceChild(domChildren, hTN._domNodeCont.childNodes[1]);		hTN._domChildCont = hTN._domNodeCont.childNodes[1];	}		// reset loading	hTN._isLoaded	= true;	hTN._isLoading	= false;};// ---------------------------------------------------------------------//                              DFCTreeNode// ---------------------------------------------------------------------DFCTreeNode = function(sLabel, opt_jsData, opt_isEnabled) {	this._sLabel		= sLabel;	this._jsData		= opt_jsData || '';	this._isExpanded	= null;	this._isEnabled	= (typeof opt_isEnabled == 'undefined' || opt_isEnabled == null) ? true : opt_isEnabled;		this._hTree		= null;	this._hParent		= null;	this._aChilds		= null;	this._isLastChild	= false;	this._iLevel		= null;	this._sNodeId		= null;	// dynamically loaded node(s)	this._isLoaded		= false;	this._isLoading	= false;	this._sSourceUrl	= '';				// url where the node gets the js data		this._domHover		= null;	this._domFocus		= null;		this._domNodeCont	= null;				// DOM node	this._domChildCont	= null;				// container with DOM childs	this._domTwisty	= null;	this._domTwistyCont	= null;				// TD which contains the twisty	this._domIcon		= null;	this._domIconCont	= null;				// TD which contains the icon	this._domLabel		= null;	this._domLabelCont	= null;				// node label container		this._hConfig		= null;};DFCTreeNode.prototype.addChild = function(sLabel,opt_jsData, opt_sConfig, opt_sSourceUrl, opt_isEnabled, opt_sId) {	// add child to current node		// return:	created child		var hNode = new DFCTreeNode(sLabel, opt_jsData, opt_isEnabled);	hNode._hTree		= this._hTree;	hNode._hParent		= this;	hNode._iLevel		= this._iLevel + 1;		hNode._hConfig		= this._hTree._hConfig.get(opt_sConfig);	hNode._isExpanded	= hNode._hConfig.showExpanded;	hNode._sSourceUrl	= opt_sSourceUrl;	hNode._sId		= opt_sId;		// register new child at current node	if (this._aChilds == null) {		this._aChilds = new Array();	}	this._aChilds[this._aChilds.length] = hNode;		// register new child in tree	this._hTree._registerNode(hNode, opt_sId);		return hNode;};DFCTreeNode.prototype.select = function() {	// select a tree node		if (this._hParent._isExpanded == false) {		alert('DFCTreeNode: parent is not expanded (this is not yet supported)');	}		this._deselectLastNode();		this._selectNode();	};DFCTreeNode.prototype.enable = function(isEnabled) {	// enable/disable a tree node		this._isEnabled	= isEnabled;		this._domLabelCont.className	= this._isEnabled ? 									this._hConfig.cssLabelContainer : 									this._hConfig.cssLabelContainerDisabled;										this._domLabel.className		= this._isEnabled ? 									this._hConfig.cssLabel : 									this._hConfig.cssLabelDisabled;};DFCTreeNode.prototype.getLabel = function() {	// return the nodes label	return this._sLabel;};DFCTreeNode.prototype.getData = function() {	// return custom data	return this._jsData;};// ---------------------------------- private methods -------------------------------------DFCTreeNode.prototype._getNodeDOM = function() {	// !! recursive !!		// returns the DOM for a treenode including expanded subnodes		var hTree		= this._hTree;	var hCfg		= this._hConfig;	var domDoc	= hTree._hWin.document;	var domNodeContProto, domNodeCont, domNode, domHover, domLabelCont, domLabel;	var domImg, domT, domTB, domTR, domTD, domInp;			// create prototype if not yet done so	if (hTree._domNodeContProto == null) {				domNodeContProto = domDoc.createElement('div');			domNode = domDoc.createElement('div');							domNode.style.position	= 'relative';					// ------------------ EVENT --------------------------						domHover = domDoc.createElement('div');									var hStyle = domHover.style;					hStyle.position	= 'absolute';					hStyle.top		= '0px';					hStyle.width		= '99%';					hStyle.overflow	= 'hidden';											// IE needs content in the layer to fire the mouse events					domHover.innerHTML = '<table border=0 width=100% height=100% cellpadding=0 cellspacing=0><tr><td>&nbsp;</td></tr></table>';						domNode.appendChild(domHover);					// ------------------- TABLE ------------------------								domT	= domDoc.createElement('table');									domT.setAttribute('border', '0', 0);					domT.setAttribute('cellpadding', '0', 0);					domT.setAttribute('cellspacing', '0', 0);									domTB = domDoc.createElement('tbody');													domTR = domDoc.createElement('tr');							domTB.appendChild(domTR);									domT.appendChild(domTB);									domNode.appendChild(domT);								// --------------------------------------------------									domNodeContProto.appendChild(domNode);				hTree._domNodeContProto = domNodeContProto;	}			// create tree node	if (hTree._hRootNode == this) {			// root is a dummy node				domNodeCont	= domDoc.createElement('div');		} else {			// not a root node				domNodeCont	= hTree._domNodeContProto.cloneNode(true);				// ---------------------------- HOVER / TABLE ---------------------------		domHover				= domNodeCont.firstChild.childNodes[0];				domHover.style.left		= '-' + ((this._iLevel-1) * parseInt(hCfg.childOffsetX)).toString() + 'px';		domHover.style.zIndex	= 0;		domHover.className		= hCfg.cssHover;		this._domHover			= domHover;				domT					= domNodeCont.firstChild.childNodes[1];		domT.style.zIndex		= 2;		domT.style.position		= 'relative';		domTR				= domT.firstChild.firstChild;		// add event handler to the event layer and table		if (hTree._hRootNode != this) {						dfc.addEventListener(domHover, 'mouseover',	this._onEvent);			dfc.addEventListener(domHover, 'mouseout',	this._onEvent);			dfc.addEventListener(domHover, 'mousedown',	this._onEvent);			dfc.addEventListener(domHover, 'mouseup',	this._onEvent);			dfc.addEventListener(domHover, 'dblclick',	this._onEvent);					// table			dfc.addEventListener(domT, 'mouseover',		this._onEvent);			dfc.addEventListener(domT, 'mouseout',		this._onEvent);			dfc.addEventListener(domT, 'mousedown',		this._onEvent);			dfc.addEventListener(domT, 'mouseup',		this._onEvent);			dfc.addEventListener(domT, 'dblclick',		this._onEvent);					// put tree context into the DOM			domHover.EventTreeNode	= this;			domT.EventTreeNode		= this;				}					// ---------------------------- TWISTY ---------------------------------		if (hCfg.showTwisty) {			domTD = domDoc.createElement('td');			domTD.style.width = hCfg.widthTwisty;						if (this._aChilds || hCfg.loadOnDemand) {						domImg = domDoc.createElement('img');					domImg.setAttribute('src', this._isExpanded ? hCfg.twistyOpen : hCfg.twistyClosed, 0);				domImg.setAttribute('border', '0', 0);				// workaround for bug in IE which is stretching the image :-(				if (dfc.isIE) {					domImg.style.width = '100%';					domImg.style.height = '100%';				}				domTD.appendChild(domImg);						domTD.style.width = hCfg.widthTwisty;				this._domTwisty = domImg;							} else {				// instead of the icon we put space in the cell				domTD.style.width = hCfg.widthTwisty;			}						this._domTwistyCont	= domTD;					}		// ---------------------------- ICON ---------------------------------		if (hCfg.showIcon) {			domTD = domDoc.createElement('td');			domTD.style.width = hCfg.widthIcon;							domImg = domDoc.createElement('img');						domImg.setAttribute('src', this._isExpanded && this._aChilds ? hCfg.iconOpen : hCfg.iconClosed, 0);					domImg.setAttribute('border', '0', 0);										// workaround for bug in IE which is stretching the image :-(					if (dfc.isIE) {						domImg.style.width = '100%';					}									domTD.appendChild(domImg);			this._domIcon 		= domImg;			this._domIconCont	= domTD;		}		// add icon/twisty according to the sequence		var dom1, dom2;		dom1 = hCfg.showTwistyFirst ? this._domTwistyCont : this._domIconCont;		dom2 = hCfg.showTwistyFirst ? this._domIconCont : this._domTwistyCont;				if (dom1) { domTR.appendChild(dom1); }		if (dom2) { domTR.appendChild(dom2); }				// ---------------------------- LABEL ---------------------------------				domTD = domDoc.createElement('td');					domLabelCont = domDoc.createElement('div');	 			domLabelCont.className = this._isEnabled ?									hCfg.cssLabelContainer : 									hCfg.cssLabelContainerDisabled;				domLabel = domDoc.createElement('div');					domLabel.className = this._isEnabled ?									hCfg.cssLabel :									hCfg.cssLabelDisabled;					if (hCfg.keyAccess) {											this._domFocus = dfc.createAccessableText(domLabel, this._sLabel);						domLabel.EventTreeNode = this;						dfc.addEventListener(domLabel, 'keydown', this._onEvent);											} else {						domLabel.appendChild(domDoc.createTextNode(this._sLabel));										}									domLabelCont.appendChild(domLabel);				this._domLabel	= domLabel;			domTD.appendChild(domLabelCont);			this._domLabelCont = domLabelCont;				domTR.appendChild(domTD);	}	// process childs		var domChildren = this._getChildrenDOM();		if (domChildren) {		this._domChildCont = domNodeCont.appendChild(domChildren);	}		return domNodeCont;};DFCTreeNode.prototype._getChildrenDOM = function() {	// !! recursive !!	// create DOM for all children of current node		var hTree		= this._hTree;	var hCfg	= this._hConfig;	var domDoc	= hTree._hWin.document;		// setup child container	var domChildCont	= domDoc.createElement('div');		domChildCont.className = hCfg.cssChildContainer;		var hStyle = domChildCont.style;	hStyle.position = 'relative';								if (hTree._hRootNode != this) {		hStyle.left = hCfg.childOffsetX;	}		if (hCfg.loadOnDemand && this._aChilds == null && this._isExpanded) {		// childs of this node are not yet loaded						domChildCont.appendChild(hTree._getLoadingDOM());			} else if (this._aChilds && this._isExpanded) {				// this node has childs which are available				var aChilds		= this._aChilds;				// set flag which indicates the last child		aChilds[aChilds.length - 1]._isLastChild = true;				// loop: all childs of current node		for (var iChild = 0; iChild < aChilds.length; iChild++) {				var hChild		= aChilds[iChild];			var hCfgChild	= hChild._hConfig;				// get DOM for current child			var domChild	= hChild._getNodeDOM();						if (domChild) {							hChild._domNodeCont = domChildCont.appendChild(domChild);							// set formatting								if (hChild._isLastChild) {					// last child										hChild._domNodeCont.className = hCfgChild.cssNodeContainerLastChild;					if (hChild._domTwistyCont) {						hChild._domTwistyCont.className = hCfgChild.cssTwistyContainerLastChild;					}						} else {									// other childs					hChild._domNodeCont.className = hCfgChild.cssNodeContainerOtherChilds;										if (hChild._domTwistyCont) {						hChild._domTwistyCont.className = hCfgChild.cssTwistyContainerOtherChilds;					}				}								if (hChild._domIconCont) {					hChild._domIconCont.className		= hCfgChild.cssIconContainer;				}			}		}			} else {		// _isExpanded could be set to true from the configuration, so we reset it		this._isExpanded = false;		return null;	}		return domChildCont;			};// ---------------------------------------- EVENT's ---------------------------------------------DFCTreeNode.prototype._onEvent = function(hEvent) {	// handle all events	hEvent = hEvent || dfc.event(this, hEvent);	// shortcuts	var hTN		= this.EventTreeNode || hEvent.srcElement.EventTreeNode;	var hTree		= hTN._hTree;	var hCfg	= hTN._hConfig;		// check which part was hit with the mouse	var hSrc 			= hEvent.srcElement;	var isTwisty		= (hSrc == hTN._domTwisty	|| hSrc == hTN._domTwistyCont);	switch (hEvent.type) {		case 'click':	case 'dblclick':	case 'mousedown':	case 'keydown':			if (hTN._isLoading || !hTN._isEnabled) { break; }				// keyboard events are translated into the corresponding mouse events		var isKeyExpand	= false;		var isKeySelect	= false;			if (hEvent.type == 'keydown') {			switch (hEvent.keyCode.toString()) {			case '13':		// enter = expand/collapse				isKeyExpand	= true;								if (hCfg.selectOnEnterKey) { isKeySelect = true; }								break;							case '32':		// space = select				isKeySelect	= true;								break;			}						if (!(isKeyExpand || isKeySelect)) { break; }		}			// expand/collapse subtree					if (	(	(hEvent.type == 'mousedown') && 				(isTwisty || hCfg.expandOnDown || hCfg.collapseOnDown)) || 			(	(hEvent.type == 'dblclick' && !isTwisty) &&				(hCfg.expandOnDblClick || hCfg.collapseOnDblClick)) ||				(isKeyExpand)) {			var isExpand = !(hTN._isExpanded && hTN._domChildCont);						hTN._expandNode(isExpand, isTwisty);						// set 'down' style			if (hCfg.useCSSDown) {				if (hTN._domTwisty) {							hTN._domTwisty.className		= hCfg.cssTwistyDown;							if (hCfg.cssTwistyContainerOtherChildsDown != '') {						if (hTN._isLastChild) {							hTN._domTwistyCont.className = hCfg.cssTwistyContainerLastChildDown;						} else {							hTN._domTwistyCont.className = hCfg.cssTwistyContainerOtherChildsDown;						}					}				}						if (hEvent.type != 'keydown') {					if (hTN._domIcon) {						hTN._domIconCont.className	= hCfg.cssIconContainerDown;								hTN._domIcon.className		= hCfg.cssIconDown;					}							if (hTN != hTree._hSelectedNode) {						if (hTN._domLabel) {							hTN._domLabelCont.className 	= hCfg.cssLabelContainerDown;							hTN._domLabel.className 		= hCfg.cssLabelDown;						}					}				}			}		}		// select node		if (	hTN._isLoading ||			isTwisty || 			hTN			== hTree._hSelectedNode || 			hEvent.type	== 'dblclick' ||			hEvent.type	== 'keydown' && !isKeySelect) {			// do nothing		} else {					// select node			if (hCfg.selectOnDown || hCfg.selectOnEnterKey) {				hTN._deselectLastNode();				// set new selected node				hTree._hSelectedNode = hTN;				hTree._raiseEvent(hTree._sEvent_onSelect, hTN);				if (hEvent.type != 'keydown') {					if (hCfg.useCSSDown) {						if (hTN._domIcon) {							hTN._domIconCont.className	= hCfg.cssIconContainerDown;									hTN._domIcon.className		= hCfg.cssIconDown;						}						if (hTN._domLabel) {							hTN._domLabelCont.className 	= hCfg.cssLabelContainerDown;							hTN._domLabel.className 		= hCfg.cssLabelDown;						}					} else {						if (hTN._domIcon) {							hTN._domIconCont.className	= hCfg.cssIconContainerSelected;						}										if (hTN._domLabel) {							hTN._domLabelCont.className	= hTN._isExpanded ? 														hCfg.cssLabelContainerSelected : 														hCfg.cssLabelContainerSelectedCollapsed;							hTN._domLabel.className 		= hCfg.cssLabelSelected;						}					}				}			}		}				// set focus		if (hTN._domFocus) {			hTN._domFocus.focus();		}									break;			case 'mouseup':				if (hTN._isLoading || !hTN._isEnabled) { break; }				if (hTN._domTwisty) {			hTN._domTwisty.className		= hCfg.cssTwisty;			if (hCfg.cssTwistyContainerOtherChildsOver != '') {				if (hTN._isLastChild) {					hTN._domTwistyCont.className = hCfg.cssTwistyContainerLastChildOver;				} else {					hTN._domTwistyCont.className = hCfg.cssTwistyContainerOtherChildsOver;				}			}		}						if (hTN == hTree._hSelectedNode) {						if (hTN._domIcon) {				hTN._domIconCont.className	= hCfg.cssIconContainerSelected;			}				if (hTN._domLabel) {				hTN._domLabelCont.className	= hTN._isExpanded ? 											hCfg.cssLabelContainerSelected : 											hCfg.cssLabelContainerSelectedCollapsed;				hTN._domLabel.className 		= hCfg.cssLabelSelected;			}		} else {			if (hTN._domIcon) {				hTN._domIconCont.className	= hCfg.cssIconContainerOver;				hTN._domIcon.className		= hCfg.cssIcon;			}			if (hTN._domLabel) {				hTN._domLabelCont.className	= hCfg.cssLabelContainerOver;				hTN._domLabel.className 		= hCfg.cssLabel;			}		}			break;	case 'mouseover':		if (hTN._isEnabled) {					// enabled node						if (hTN._domTwisty) {					hTN._domTwisty.className		= hCfg.cssTwisty;					if (hCfg.cssTwistyContainerOtherChildsOver != '') {					if (hTN._isLastChild) {						hTN._domTwistyCont.className = hCfg.cssTwistyContainerLastChildOver;					} else {						hTN._domTwistyCont.className = hCfg.cssTwistyContainerOtherChildsOver;					}				}			}								if (hTree._hSelectedNode != hTN) {				if (hTN._domIcon) {					hTN._domIconCont.className	= hCfg.cssIconContainerOver;				}				if (hTN._domLabel)	{					hTN._domLabelCont.className	= hTN._isExpanded ? 												hCfg.cssLabelContainerExpandedOver : 												hCfg.cssLabelContainerOver;					hTN._domLabel.className		= hCfg.cssLabelOver;				}							}		} else {					// disabled node						if (hTN._domLabel) {				hTN._domLabelCont.className	= hCfg.cssLabelContainerDisabledOver;			}		}		break;	case 'mouseout':		if (hTN._isEnabled) {					// enabled node						if (hTN._domTwisty) {							hTN._domTwisty.className		= hCfg.cssTwisty;								if (hCfg.cssTwistyContainerOtherChilds != '') {					if (hTN._isLastChild) {						hTN._domTwistyCont.className = hCfg.cssTwistyContainerLastChild;					} else {						hTN._domTwistyCont.className = hCfg.cssTwistyContainerOtherChilds;					}				}			}						if (hTN == hTree._hSelectedNode) {				if (hTN._domIcon) {					hTN._domIconCont.className		= hCfg.cssIconContainerSelected;				}								// select new node				if (hTN._domLabel) {					hTN._domLabelCont.className		= hTN._isExpanded ? 													hCfg.cssLabelContainerSelected : 													hCfg.cssLabelContainerSelectedCollapsed;					hTN._domLabel.className 			= hCfg.cssLabelSelected;				}							} else {							if (hTN._domIcon)	{ 					hTN._domIconCont.className		= hCfg.cssIconContainer;					hTN._domIcon.className			= hCfg.cssIcon;				}							if (hTN._domLabel)	{ 					if (hTN._isExpanded) {						hTN._domLabelCont.className	= hCfg.cssLabelContainerExpanded;						hTN._domLabel.className		= hCfg.cssLabelExpanded;					} else {						hTN._domLabelCont.className	= hCfg.cssLabelContainer;						hTN._domLabel.className		= hCfg.cssLabel;					}				}			}		} else {					// disabled node						if (hTN._domLabel)	{				hTN._domLabelCont.className	= hCfg.cssLabelContainerDisabled;			}		}		break;			default:				break;	}		dfc.stopPropagation(hEvent);};DFCTreeNode.prototype._deselectLastNode = function() {	var hTree		= this._hTree;	// deselect last selected node	if (hTree._hSelectedNode) {		var hSN 		= hTree._hSelectedNode;		var hSNConfig	= hSN._hConfig;				if (hSN._domIcon) {			hSN._domIconCont.className	= hSNConfig.cssIconContainer;		}				if (hSN._domLabel) {			hSN._domLabelCont.className	= hSNConfig.cssLabelContainer;			hSN._domLabel.className		= hSNConfig.cssLabel;		}		if (hSN._domLabel)	{ 			if (hSN._isExpanded) {				hSN._domLabelCont.className	= hSNConfig.cssLabelContainerExpanded;				hSN._domLabel.className		= hSNConfig.cssLabelExpanded;			} else {				hSN._domLabelCont.className	= hSNConfig.cssLabelContainer;				hSN._domLabel.className		= hSNConfig.cssLabel;			}		}	}};DFCTreeNode.prototype._selectNode = function() {	var hTree	= this._hTree;	var hCfg	= this._hConfig;	if (this._domIcon) {		this._domIconCont.className		= hCfg.cssIconContainerSelected;	}		// select new node	if (this._domLabel) {		this._domLabelCont.className		= hCfg.cssLabelContainerSelected;		this._domLabel.className 		= hCfg.cssLabelSelected;	}	// set new selected node	hTree._hSelectedNode = this;};DFCTreeNode.prototype._expandNode = function(isExpand, isTwisty) {	var hTree	= this._hTree;	var hCfg	= this._hConfig;	if (!isExpand) {			// collapse				if (isTwisty || hCfg.collapseOnDown || hCfg.collapseOnDblClick) {					this._isExpanded = false;				this._domChildCont.style.display	= 'none';			// show collapsed twisty/icon			if (hCfg.showTwisty)	{ this._domTwisty.src	= hCfg.twistyClosed; }			if (hCfg.showIcon)		{ this._domIcon.src		= hCfg.iconClosed; }		}			} else {			// expand		if (this._aChilds || hCfg.loadOnDemand) {						// expanded status must be set before children are created			this._isExpanded = true;			// create children DOM tree			if (this._domChildCont == null) {				var domChildren = this._getChildrenDOM();				if (domChildren) {					this._domChildCont = this._domNodeCont.appendChild(domChildren);				}			}						this._domChildCont.style.display	= 'block';						// show expanded twisty/icon			if (hCfg.showTwisty)	{ this._domTwisty.src	= hCfg.twistyOpen; }			if (hCfg.showIcon)		{ this._domIcon.src		= hCfg.iconOpen; }			// load subtree if expanded node is not yet loaded			if (hCfg.loadOnDemand && !this._isLoaded) {				this._isLoading = true;				var hLoadCtx = dfc.load(this._sSourceUrl, hTree._onloadSubtree, hTree, true);				hLoadCtx.EventTreeNode = this;			}		}		this._autoCollapse();	}};DFCTreeNode.prototype._autoCollapse = function() {	var hCfg = this._hConfig;		// check if siblings should be collapse	if (hCfg.autoCollapseSiblings) {			var aSiblings = this._hParent._aChilds;				for (var iChild = 0; iChild < aSiblings.length; iChild++) {			var hTN = aSiblings[iChild];						if (hTN != this && hTN._isExpanded) {				// sibling is not current node but expanded, collapse it				hTN._isExpanded = false;					hTN._domChildCont.style.display	= 'none';				var hChildCfg = hTN._hConfig;				if (hChildCfg.showTwisty)	{ hTN._domTwisty.src	= hChildCfg.twistyClosed; }				if (hChildCfg.showIcon)		{ hTN._domIcon.src		= hChildCfg.iconClosed; }				if (hTN._domLabel)	{					hTN._domLabelCont.className	= hCfg.cssLabelContainer;					hTN._domLabel.className		= hCfg.cssLabel;				}			}		}	}};