实现了CheckBox连动效果的treeview

原创 2007年09月25日 16:26:00
<!----------------------------------------------------------------------
//  Copyright (c) 2000-2003 Microsoft Corporation.  All Rights Reserved.
//
---------------------------------------------------------------------->

<public:component tagname=treeview literalcontent=true>
    
<public:attach event=oncontentready onevent="oncontentready()" />
    
<public:attach event=ondocumentready onevent="ondocumentready()" />
    
<public:attach event="onscroll" onevent="onScroll()" />
    
<public:event name="onexpand" id="_tvevtExpand" />
    
<public:event name="oncollapse" id="_tvevtCollapse" />
    
<public:event name="onselectedindexchange" id="_tvevtSelect" />
    
<public:event name="oncheck" id="_tvevtCheck" />
    
<public:event name="onfirequeuedevents" id="_tvevtFireQueuedEvents" />
    
<public:event name="onnodebound" id="_tvevtNodeBound" />
    
<public:event name="onnodetypesbound" id="_tvevtNodeTypesBound" />
    
<public:event name="onhover" id="_tvevtHover" />
    
<public:event name="onunhover" id="_tvevtUnhover" />
    
<public:property name="clickedNodeIndex" GET="getClickedNodeIndex" />
    
<public:property name="defaultStyle" id="_tvpropDefaultStyle" GET="getDefaultStyle" PUT="setDefaultStyle" />
    
<public:property name="hoverStyle" id="_tvpropHoverStyle" GET="getHoverStyle" PUT="setHoverStyle" />
    
<public:property name="selectedStyle" id="_tvpropSelectedStyle" GET="getSelectedStyle" PUT="setSelectedStyle" />
    
<public:property name="childType" id="_tvpropChildType" GET="getChildType" PUT="setChildType" />
    
<public:property name="imageUrl" id="_tvpropImageUrl" GET="getImageUrl" PUT="setImageUrl" />
    
<public:property name="expandedImageUrl" id="_tvpropExpandedImageUrl" GET="getExpandedImageUrl" PUT="setExpandedImageUrl" />
    
<public:property name="selectedImageUrl" id="_tvpropSelectedImageUrl" GET="getSelectedImageUrl" PUT="setSelectedImageUrl" />
    
<public:property name="target" id="_tvpropTarget" GET="getTarget" PUT="setTarget" />
    
<public:property name="treeNodeSrc" id="_tvpropTreeNodeSrc" GET="getTreeNodeSrc" PUT="setTreeNodeSrc" />
    
<public:property name="treeNodeXsltSrc" id="_tvpropTreeNodeXsltSrc" GET="getTreeNodeXsltSrc" PUT="setTreeNodeXsltSrc" />
    
<public:property name="selectExpands" id="_tvpropSelectExpands" GET="getSelectExpands" PUT="setSelectExpands" />
    
<public:property name="expandLevel" id="_tvpropExpandLevel" GET="getExpandLevel" PUT="setExpandLevel" />
    
<public:property name="autoSelect" id="_tvpropAutoSelect" GET="getAutoSelect" PUT="setAutoSelect" />
    
<public:property name="treeNodeTypeSrc" id="_tvpropTreeNodeTypeSrc" GET="getTreeNodeTypeSrc" PUT="setTreeNodeTypeSrc" />
    
<public:property name="showLines" id="_tvpropShowLines" GET="getShowLines" PUT="setShowLines" />
    
<public:property name="showPlus" id="_tvpropShowPlus" GET="getShowPlus" PUT="setShowPlus" />
    
<public:property name="showToolTip" id="_tvpropShowToolTip" GET="getShowToolTip" PUT="setShowToolTip" />
    
<public:property name="indent" id="_tvpropIndent" GET="getIndent" PUT="setIndent" />
    
<public:property name="selectedNodeIndex" id="_tvpropSelectedNodeIndex" GET="getSelectedNodeIndex" PUT="setSelectedNodeIndex" />
    
<public:property name="systemImagesPath" id="_tvpropSystemImagesPath" GET="getSystemImagesPath" PUT="setSystemImagesPath" />
    
<public:method name="queueEvent" />
    
<public:method name="getTreeNode" />
    
<public:method name="addAt" />
    
<public:method name="createTreeNode" />
    
<public:method name="getTreeNodeType" />
    
<public:method name="createTreeNodeType" />
    
<public:method name="addTreeNodeType" />
    
<public:method name="add" />
    
<public:method name="databind" />
    
<public:method name="databindTypes" />
    
<public:method name="getChildren" />
    
</public:component>

<script language=javascript>

var contentNode;
var treeviewNode;
var g_typesNode;
var g_styles;
var g_event;
var g_timer = -1;
var g_nodeClicked = null;
var g_strQueuedEvents = "";
var g_bInteractive = false;
var g_numStop = 0;
var g_selectedNodeBeforeDelay = "";
var g_bFocus = false;
var g_bCreated = false;
var g_typeIsland = null;
var g_bNodesReady = false;
var g_bTypesReady = false;
var g_bMouseDown = false;
var g_pendingBinds = new Array(0);
var g_pendingSyncBinds = new Array(0);
var g_bindTimer = -1;
var g_bLock = false;
var g_bInTypesBoundEvent = false;
var L_strMSXMLError_Text = "Error creating MSXML object.  Please make sure the MSXML library is installed on your computer.";
var L_strRetrievingNodes_Text = "Retrieving nodes...";
var L_strXMLError_Text = "Error loading XML file %s";
var L_strInvalidXML_Text = "Invalid XML in %s";
var L_strXSLTError_Text = " or unsupported XSLT in %s";
var L_fontSize_Text = "10pt";
var L_fontName_Text = "Times";
var L_strToolTip_Text = "Use +/- to expand/collapse";

// properties
var prop_defaultStyle = null;
var prop_hoverStyle = null;
var prop_selectedStyle = null;
var prop_childType = null;
var prop_imageUrl = null;
var prop_expandedImageUrl = null;
var prop_selectedImageUrl = null;
var prop_target = null;
var prop_treeNodeSrc = null;
var prop_treeNodeXsltSrc = null;
var prop_selectExpands = null;
var prop_expandLevel = -1;
var prop_autoSelect = false;
var prop_treeNodeTypeSrc = null;
var prop_showLines = true;
var prop_showPlus = true;
var prop_showToolTip = true;
var prop_indent = 19;
var prop_selectedNodeIndex = null;
var prop_systemImagesPath = null;

//
//
 QueueEvent()
//
//
 Queue an event for later posting to the server, when the
//
 _tvevtFireQueuedEvents event fires.
//
function queueEvent(strEvent, strParams)
{
    
if (g_strQueuedEvents.length > 0)
        g_strQueuedEvents 
+= ";";
    g_strQueuedEvents 
+= (strEvent + "," + strParams);
    setHiddenHelperValue();
}

function getQueuedEvents()
{
    
return g_strQueuedEvents;
}

function fireQueuedEvents()
{
    
if (g_strQueuedEvents != "")
    {
        
if (getAttribute("onfirequeuedevents"!= null)
        {
            
if (g_timer != -1)
            {
                
// force pending autoSelect to trigger
                window.clearTimeout(g_timer);
                autoSelect();
            }
            
else
            {
                g_bInteractive 
= false;
                g_numStop 
= 0;
                _tvevtFireQueuedEvents.fire();
            }
        }
    }
}

//
//
 SetAnchorClass()
//
//
 Set the cssText property in addition to the className, since just setting className
//
 doesn't do the trick.  
//
//
 node: Anchor to which we're applying a new class
//
 name: the class to apply
//
       DefaultStyle: Apply DefaultStyle
//
       HoverStyle: Apply DefaultStyle, then HoverStyle
//
       SelectedStyle: Apply DefaultStyle, then SelectedStyle
//

function SetAnchorClass(node, name)
{
    
var strStyle = "";
    
var lname = name.toLowerCase();
    
    
// Everything is based on DefaultStyle
    strStyle += cascadeStyle(getParentTreeNode(node), "defaultstyle");

    
if (lname != "defaultstyle")
    {
        
var str = cascadeStyle(getParentTreeNode(node), lname);
        
if (str != null)
        {
            strStyle 
+= ";" + str;
        }        
    }
    node.style.cssText 
= strStyle;
    
if (lname == "hoverstyle" && g_bFocus == false)
        blurFilter(node);
                
    node.className 
= lname;
}

//
//
 getParentTreeNode()
//
//
 Walk up the display tree (NOT the TREENODE tree) until we find an element with
//
 a treenode expando.
//
function getParentTreeNode(node)
{
    
var el = node;
    
while (el != null && el.getAttribute("treenode"== null)
        el 
= el.parentElement;
    
return el.getAttribute("treenode");
}

//
//
 HoverNode()
//
//
 Apply hover effect to given text node
//
//
 textnode: textnode (id: _tntext) to apply hover to, or treenode
//
function HoverNode(textnode)
{
    
var node;
    
    
if (textnode.tagName.toLowerCase() == "treenode")
        node 
= textnode.subtree.all.item("_tntext"0);
    
else
        node 
= textnode;

    
var nodeIndex = getNodeIndex(getParentTreeNode(node));

    
if (node.className == "defaultstyle")
    {
        SetAnchorClass(node, 
"hoverstyle");
        HoverNodeIndex 
= nodeIndex;
    }
    
else if (node.className != "hoverstyle")
        HoverNodeIndex 
= "";
    e 
= element.document.createEventObject();
    e.treeNodeIndex 
= nodeIndex;
    _tvevtHover.fire(e);
    setHiddenHelperValue();
}

//
//
 UnhoverNode()
//
//
 Remove hover effect from given text node
//
//
 textnode: textnode (id: _tntext) to remove hover from, or treenode
//
function UnhoverNode(textnode)
{
    
if (textnode != null)
    {
        
var node;
        
if (textnode.tagName.toLowerCase() == "treenode")
            node 
= textnode.subtree.all.item("_tntext"0);
        
else
            node 
= textnode;
            
        
if (node.className == "hoverstyle")
        {
            SetAnchorClass(node, 
"defaultstyle");
        }
        e 
= element.document.createEventObject(event);
        
if (HoverNodeIndex == "")
            e.treeNodeIndex 
= getNodeIndex(getParentTreeNode(node))
        
else
            e.treeNodeIndex 
= HoverNodeIndex;
        _tvevtUnhover.fire(e);
        HoverNodeIndex 
= "";
        setHiddenHelperValue();
    }
}
    
// mOver()
//
//
 onmouseover handler for the anchor of a treenode
//
function mOver()
{
    
if (g_bInteractive == true)
    {
        
var oItem = this.all.item("_tntext"0);
        
if (HoverNodeIndex.length > 0)
            UnhoverNode(getNodeFromIndex(HoverNodeIndex));
        HoverNode(oItem);
    }
}

//
//
 mOut()
//
//
 onmouseout handler for the anchor of a treenode
//
function mOut()
{
    
if (g_bInteractive == true)
    {
        
var node = this.parentElement.treenode;
        
var nodeIndex = getNodeIndex(node)
        
if (nodeIndex == HoverNodeIndex)
        {
            UnhoverNode(node);
            window.status 
= window.defaultStatus;
        }
        
else if (nodeIndex == selectedNodeIndex)
        {
            e 
= element.document.createEventObject(event);
            e.treeNodeIndex 
= nodeIndex;
            _tvevtUnhover.fire(e);
        }        
    }
}

//
//
 onkeydown
//
function onkeydown()
{
    
if (!g_bInteractive)
        
return;
    
    
if (event.altKey == true)
        
return;
            
    
var oldNode;
    
var hoverNode = null;
    
if (HoverNodeIndex.length > 0)
    {
        oldNode 
= getNodeFromIndex(HoverNodeIndex);
        hoverNode 
= oldNode;
    }
    
else
        oldNode 
= getNodeFromIndex(selectedNodeIndex);
    
switch (event.keyCode)
    {
        
case 187:   // keyboard +/=
            if (event.shiftKey != true)
                
break;
            
// else fall through
        case 107:   // keypad +
            if (oldNode.getAttribute("expanded"!= true)
            {
                doNodePlusMinusClick(oldNode);
                fireQueuedEvents();
            }
            event.returnValue 
= false;    
            
break;
        
case 189:   // keyboard -/_
            if (event.shiftKey == true)
                
break;
            
// else fall through
        case 109:   // keypad -
            if (oldNode.getAttribute("expanded"== true)
            {
                doNodePlusMinusClick(oldNode);
                fireQueuedEvents();
            }
            event.returnValue 
= false;
            
break;   
        
case 39:    // right arrow
            event.returnValue = false;
            
if (oldNode.children.tags("treenode").length == 0)
            {
                
var exp = getNodeAttribute(oldNode, "expandable");
                
if (exp == null && oldNode.getAttribute("TreeNodeSrc"!= null)
                    exp 
= "checkOnce";
                
if (oldNode.getAttribute("expanded"== true || !(exp == "always" || (exp == "checkOnce" && oldNode.getAttribute("checkedExpandable"!= true)))
                    
break;
            }
            
if (oldNode.getAttribute("expanded"!= true)
            {
                doNodePlusMinusClick(oldNode);
                updateStatus(oldNode);
                fireQueuedEvents();
                
break;
            }
            
// fall through
        case 40:    // down arrow
            var node = getNextVisibleNode(oldNode);
            
if (node != null)
            {
                
if (element.getAttribute("autoselect"== true)
                {
                    selectNode(node, 
true);
                    updateStatus(node);
                    UnhoverNode(hoverNode);
                }
                
else
                {                    
                    UnhoverNode(oldNode);
                    HoverNode(node);
                    changeFocus(node, oldNode);                    
                    updateStatus(node);
                }
                scrollTree(node);
            }
            event.returnValue 
= false;
            
break;
        
case 37:    // left arrow
            if (oldNode.getAttribute("expanded"== true)
            {
                doNodePlusMinusClick(oldNode);
                fireQueuedEvents();
            }
            
else
            {
                
// jump the hover up to the parent node
                var node = oldNode.parentElement;
                
while (node.tagName.substr(0,4).toLowerCase() != "tree")
                    node 
= node.parentElement;
                
if (node.tagName.toLowerCase() == "treenode")
                {
                    
if (element.getAttribute("autoselect"== true)
                    {
                        selectNode(node, 
true);
                        updateStatus(node);
                        UnhoverNode(hoverNode);
                    }
                    
else
                    {
                        UnhoverNode(oldNode);
                        HoverNode(node);
                        changeFocus(node, oldNode);
                        updateStatus(node);
                    }
                    scrollTree(node);
                }
            }
            event.returnValue 
= false;
            
break;
        
case 38:    // up arrow
            var node = getPreviousVisibleNode(oldNode);
            
if (node != null)
            {
                
if (element.getAttribute("autoselect"== true)
                {
                    selectNode(node, 
true);
                    updateStatus(node);
                    UnhoverNode(hoverNode);
                }
                
else
                {
                    UnhoverNode(oldNode);
                    HoverNode(node);
                    changeFocus(node, oldNode);
                    updateStatus(node);
                }
                scrollTree(node);
            }
            event.returnValue 
= false;
            
break;
        
case 32:    // spacebar
            var cb = oldNode.subtree.all.item("_cb"0);
            
if (cb != null)
            {
                cb.setAttribute(
"checked"!cb.getAttribute("checked"), 0);
                doCheckboxClick(oldNode);
                fireQueuedEvents();
            }
            event.returnValue 
= false;
            
break;
        
case 13:    // enter key
            doNodeClick(oldNode)
            
if (!navigateNode(oldNode))
            {
                
if (element.getAttribute("selectExpands"== true)
                    doNodePlusMinusClick(oldNode);
                fireQueuedEvents();
            }
            event.returnValue 
= false;
            
break;
    }
}

//
//
 changeFocus()
//
function changeFocus(node, oldNode)
{
    
var accessnode = node.subtree.all.item("_tnaccess"0);
    accessnode.tabindex 
= 1;
    accessnode.focus();
    accessnode 
= oldNode.subtree.all.item("_tnaccess"0);
    accessnode.tabindex 
= -1;
}

//
//
 updateStatus()
//
function updateStatus(node)
{
    
var href = node.getAttribute("navigateurl");
    
if (href != null)
        window.status 
= href;
    
else
        window.status 
= window.defaultStatus;
}

//
//
 onstop
//
function onstop()
{
    g_numStop
++;
    
if (g_numStop >= 2)
    {
        g_bInteractive 
= true;
    }

    
for (var i = 0; i < g_pendingBinds.length; i++)
    {
        
if (g_pendingBinds[i] != null && g_pendingBinds[i].el != null)
            g_pendingBinds[i].el._bound 
= null;
    }
}

//
//
 onfocus
//
function onfocus()
{
    
if (!g_bFocus)
    {
        dofocus();
    }
}

//
//
 dofocus
//
function dofocus()
{
    
var node = null;
    g_bFocus 
= true;  // sometimes we just call dofocus() without going through onfocus()
    try
    {
        node 
= getNodeFromIndex(selectedNodeIndex);
    }
    
catch (e)
    {
    }
    
if (node != null)
    {
        
var oItem = node.subtree.all.item("_tnaccess"0);
        
if (oItem != null)
        {
            
if (g_bInteractive)
            {
                focusFilter(oItem);
                oItem.tabIndex 
= 1;
                
if (!g_bMouseDown) // don't scroll the window when selecting a new node
                {
                    
try
                    {
                        
var prevScrollTop = element.scrollTop;
                        
var prevScrollLeft = element.scrollLeft;

                        oItem.focus();

                        element.scrollTop 
= prevScrollTop;
                        element.scrollLeft 
= prevScrollLeft;
                    }
                    
catch (e)
                    {
                    }
                }
            }
        }
    }

    node 
= null;
    
try
    {
        node 
= getNodeFromIndex(HoverNodeIndex);
    }
    
catch (e)
    {
    }

    
if (node != null && g_bInteractive)
    {
        
var oItem = node.subtree.all.item("_tnaccess"0);
        
if (oItem != null)
            focusFilter(oItem);
    }
}

//
//
 focusFilter
//
function focusFilter(oItem)
{
    
if (oItem.id == "_tnaccess")
        oItem 
= oItem.all.item("_tntext"0); 
    
if (oItem.filters.length > 0)
    {
        
var oFilter = oItem.filters.item("DXImageTransform.Microsoft.Alpha");
        
if (oFilter)
        {
            oFilter.opacity 
*= 2;
        }
    }
}

//
//
 onblur
//
function onblur()
{
    
var node = null;
    g_bFocus 
= false;
    
try
    {
        node 
= getNodeFromIndex(selectedNodeIndex);
    }
    
catch (e)
    {
    }

    
if (node != null)
    {
        
var oItem = node.subtree.all.item("_tnaccess"0);
        
if (oItem != null)
        {
            blurFilter(oItem);
            oItem.tabIndex 
= -1;
        }
    }

    node 
= null;
    
try
    {
        node 
= getNodeFromIndex(HoverNodeIndex);
    }
    
catch (e)
    {
    }
    
if (node != null)
    {
        
var oItem = node.subtree.all.item("_tnaccess"0);
        
if (oItem != null)
        {
            blurFilter(oItem);
            oItem.tabIndex 
= -1;
        }
    }    
    setHiddenHelperValue();
}

//
//
 blurFilter
//
//
 decreases alpha filter opacity on given node by 50%, adding one if needed
//
function blurFilter(oItem)
{
    
if (oItem.id == "_tnaccess")
        oItem 
= oItem.all.item("_tntext"0); 
    
if (oItem.filters.length > 0)
    {
        
var oFilter = oItem.filters.item("DXImageTransform.Microsoft.Alpha");
        
if (oFilter)
        {
            oFilter.opacity 
/= 2;
            
return;
        }
    }
    oItem.style.filter 
+= "progid:DXImageTransform.Microsoft.Alpha(opacity=50,style=0)";
}

//
//
 oncontentready
//
//
 oncontentready handler for the TREEVIEW element.  Initializes the tree.
//
function oncontentready()
{
    
if (element.document.parentWindow.name.indexOf("__hifSmartNav"== 0)
        
return// don't run script in SmartNav's IFrame
 
    g_styles 
= new Object();
    
var strFont = "font: " + L_fontSize_Text + " " + L_fontName_Text + "";
    g_styles[
"parent"= strFont + "text-decoration: none; color: black; overflow:hidden;";
    g_styles[
"child"= strFont + "overflow:hidden;";
    g_styles[
"defaultstyle"= strFont + "display:inline-block; color: black; text-decoration:none; cursor: hand; overflow:hidden;";
    g_styles[
"hoverstyle"= "color: highlighttext; background-color:highlight; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50,style=0);";
    g_styles[
"selectedstyle"= "color: highlighttext; background-color:highlight;";
    g_styles[
"icon"= "cursor:hand;";
    
    
if (element.style.overflowX == "");
        element.style.overflowX 
= "auto";
    
    
//
    // Set treeview attributes to boolean
    //
    verifyBooleanAttribute(element, "showPlus");
    
if (element.getAttribute("showPlus"== false && element.getAttribute("selectExpands"== null)
        element.setAttribute(
"selectExpands"true0);
    verifyBooleanAttribute(element, 
"selectExpands");
    verifyBooleanAttribute(element, 
"autoSelect");
    verifyBooleanAttribute(element, 
"showLines");
    verifyBooleanAttribute(element, 
"showToolTip");
    
    
var systemImagesPath = element.getAttribute("SystemImagesPath");
    
if (systemImagesPath == null)
        element.setAttribute(
"SystemImagesPath""treeimages/"0);
    
else if (systemImagesPath.charAt(systemImagesPath.length - 1!= '/')
        element.setAttribute(
"SystemImagesPath", systemImagesPath + '/'0);
    
if (isRtl())
    {
        element.setAttribute(
"SystemImagesPath", element.getAttribute("SystemImagesPath"+ "rtl/"0);
    }
    
    
// Create div for parsing content
    contentNode = element.document.createElement("treeview");
    contentNode.innerHTML 
= element.innerHTML;
    
    element.tabIndex
=0;
    element.attachEvent(
"onkeydown", onkeydown);
    element.attachEvent(
"onfocus", onfocus);
    element.attachEvent(
"onblur", onblur);
    f_AddStopEvent();
    element.hideFocus 
= true;

    
if (element.getAttribute("selectedNodeIndex"== null)
        prop_selectedNodeIndex 
= "";

    
if (element.getAttribute("HoverNodeIndex"== null)
        element.setAttribute(
"HoverNodeIndex"""0);
           
    
// Create nodeTypes collection on the element
    if (element.getAttribute("TreeNodeTypeSrc"== null)
    {
        element.nodeTypes 
= contentNode.children.tags("TREENODETYPE");
        verifyTypeValues();
        g_bTypesReady 
= true;
    }
    
else
        databindTypes();

    
if (treeNodeSrc != null)
    {
        
if (element.nodeTypes != null)
        {
            contentNode.innerHTML 
= getNodeTypeHtml();
            element.nodeTypes 
= contentNode.children.tags("TREENODETYPE");
        }
        
else
            contentNode.innerHTML 
= "";
        databindNode(element);
    }
    
else
    {
        g_bNodesReady 
= true;
        tryToBuildTreeFromRoot();
    }
}

//
//
 ondocumentready()
//
function ondocumentready()
{
    
if (element.document.parentWindow.name.indexOf("__hifSmartNav"== 0)
        
return// don't run script in SmartNav's IFrame

    f_CleanupEvents();

    g_strQueuedEvents 
= "";

    
if (HoverNodeIndex.length > 0)
        HoverNode(getNodeFromIndex(HoverNodeIndex));

    g_bInteractive 
= true;

    
if (element.getAttribute("Focused"!= null)
        dofocus();
    
else
        onblur();

    
var newScrollTop = element.getAttribute("__scrollTop");
    
var newScrollLeft = element.getAttribute("__scrollLeft");
    
if (newScrollTop != null)
        element.scrollTop 
= newScrollTop;
    
if (newScrollLeft != null)
        element.scrollLeft 
= newScrollLeft;

    
var parent = element.offsetParent;
    
if (parent != null)
    {
        
var newParentTop = element.getAttribute("__parentTop");
        
var newParentLeft = element.getAttribute("__parentLeft");
        
if (newParentTop != null)
            parent.scrollTop 
= newParentTop;
        
if (newParentLeft != null)
            parent.scrollLeft 
= newParentLeft;
    }
    
    
// verify selectedNodeIndex
    if (getNodeFromIndex(selectedNodeIndex) == null)
    {
        
if (getNodeFromIndex("0"!= null)
            selectedNodeIndex 
= "0";
        
else
            selectedNodeIndex 
= "";
    }    
}

//
//
 changeIcon(node, imageUrl)
//
//
 Change the icon to the given Url.  If the Url isn't found, don't change anything.  The exception
//
 is if we try to set the icon to an unspecified ExpandedImageUrl, we instead show the ImageUrl.
//

function changeIcon(node, imageUrl)
{
    
var icon1;
    
var imageUrlLC = imageUrl.toLowerCase();
    
var textnode = node.subtree.all("_tntext"0);
    
var accessnode = node.subtree.all("_tnaccess"0);
    
var spacer = accessnode.previousSibling;
    
if (spacer != null)
    {   
        icon1 
= spacer.previousSibling;
        
if (icon1 != null && icon1.id != "_nodeicon")   
            icon1 
= null
    }
    
else
        icon1 
= null;
    
var newSrc = getNodeAttribute(node, imageUrlLC);
    
    
if (newSrc != null && icon1 == null)
    {
        
// node's ImageUrl attribute was not defined, so there is no icon.  Make one.
        icon1 = node.document.createElement("<IMG align='absmiddle' border='0' class='icon' id='_nodeicon' >");
        icon1.src 
= newSrc;
        accessnode.parentElement.insertBefore(icon1, accessnode);
        
// don't forget the spacer
        spacer = node.document.createElement("<SPAN>");
        spacer.style.width 
= 5;
        accessnode.parentElement.insertBefore(spacer, accessnode);        
    }
    
else if (newSrc != null)
    {
        icon1.src 
= newSrc;
        icon1.style.display 
= "inline";
    }
    
else if (imageUrlLC == "imageurl")
    {
        
if (icon1 != null)
        {
            
// If the node's ImageUrl isn't defined, we don't want to leave a selected or expanded icon showing.  Hide it.
            icon1.style.display = "none";
        }
    }
    
else if (imageUrlLC == "selectedimageurl" && node.getAttribute("expanded"== true)
        changeIcon(node, 
"expandedimageurl");
    
else 
        changeIcon(node, 
"imageurl");
    
if (icon1 != null)
    {
        icon1.style.cursor 
= textnode.style.cursor;
        spacer.style.cursor 
= textnode.style.cursor;
    }
}   

//
//
 selectNode(node)
//
//
 Make node the selected node, unselecting the previously selected node.
//
//
 node: node to select
//
 delay: TRUE to delay event firing (used on keyboard nav with autoselect=true)
//
function selectNode(node, delay)
{
    
var nodeIndex;
    
var selectedNode = null;
    
var strImage;
    
var oItem;
    
var oOldItem = null;

    
if (node && node.subtree == null)
        node 
= getNodeFromIndex("0"); // can't select a node that hasn't been built; select root instead      
        
    nodeIndex 
= getNodeIndex(node);
    
if (selectedNodeIndex != nodeIndex)
    {
        
if (selectedNodeIndex != "" && selectedNodeIndex != null)
        {
            
// unselect previous item
            selectedNode = getNodeFromIndex(selectedNodeIndex);
            
if (selectedNode != null && selectedNode.subtree != null)
            {
                oOldItem 
= selectedNode.subtree.all.item("_tntext"0);
                SetAnchorClass(oOldItem, 
"defaultstyle");
                oOldItem.parentElement.tabIndex 
= -1;
                
// restore old icon
                if (selectedNode.getAttribute("expanded"== true)
                    strImage 
= "ExpandedImageUrl";
                
else
                    strImage 
= "ImageUrl";
                changeIcon(selectedNode, strImage);
            }
        }

        
if (node)
        {
            oItem 
= node.subtree.all.item("_tntext"0);
            applySelection(node, oItem);
        }
                
        
if (selectedNodeIndex.length > 0)
        {
            
// Fire event
            g_event = createEventObject();
            g_event.newTreeNodeIndex 
= nodeIndex;
            g_event.oldTreeNodeIndex 
= selectedNodeIndex;
            prop_selectedNodeIndex 
= nodeIndex;
            
if (delay != true)
                _tvevtSelect.fire(g_event);
            
else
            {
                
if (g_timer != -1)
                    window.clearTimeout(g_timer);
                g_timer 
= window.setTimeout(autoSelect, 500"JScript");
                
if (g_selectedNodeBeforeDelay == "")
                    g_selectedNodeBeforeDelay 
= g_event.oldTreeNodeIndex;
            }
        }
        
else
            prop_selectedNodeIndex 
= nodeIndex;

        
// Because we use a timeout to set focus, between a nodeclick and changing the selected node
        // a user's event, which could have an alert, can occur.  An alert blurs the tree, which
        // leaves the old selected node with a 50% filter.  So if we're blurred when we unselect the
        // old node, call focusFilter to it to correct the problem.  
        if (!g_bFocus && g_bInteractive)
        {
            
if (oOldItem != null)
                focusFilter(oOldItem);
        }     
    }
    setHiddenHelperValue();  
// here instead of inside the main IF to preserve focus change
}

function autoSelect()
{
    g_timer 
= -1;
    
if (selectedNodeIndex != g_selectedNodeBeforeDelay)
    {
        navigateNode(getNodeFromIndex(g_event.newTreeNodeIndex));
        _tvevtSelect.fire(g_event);
        fireQueuedEvents();
    }
    g_selectedNodeBeforeDelay 
= "";
}

//
//
 applySelection()
//
function applySelection(node, oItem)
{
    SetAnchorClass(oItem, 
"SelectedStyle");
    
    
// set new icon
    changeIcon(node, "SelectedImageUrl");

    scrollTree(node);
    
    
if (selectedNodeIndex.length > 0)
    {
        
if (g_bFocus)
            changeFocus(node, getNodeFromIndex(selectedNodeIndex));
    }
    
    
//  We need to blur node if we re-selected it while blurred (which can happen when using client OM)
    if (!g_bFocus && g_bInteractive)
    {
        blurFilter(oItem);
    }
}

//
//
 reselectNode()
//
function reselectNode(el)
{
    
if (selectedNodeIndex == getNodeIndex(el))
        applySelection(el, el.subtree.all.item(
"_tntext"0));
}

//
//
 tryToBuildTreeFromRoot()
//
function tryToBuildTreeFromRoot()
{
    
if (g_bNodesReady == true && g_bTypesReady == true)
    {
        
var bRebuilding = g_bCreated;
        
        buildTreeFromRoot();

        
if (selectedNodeIndex.length == 0)
        {
            prop_selectedNodeIndex 
= "0";
        }
        
var node = getNodeFromIndex(selectedNodeIndex);
        prop_selectedNodeIndex 
= "";
        selectNode(node);
    }
}

//
//
 buildTreeFromRoot()
//
function buildTreeFromRoot()
{
    
// Create TREEVIEW surrogate div, to encapsulate all other DIVs.
    treeviewNode = element.document.createElement("HTML");
    
var bodyNode = element.document.createElement("BODY");
    bodyNode.dir 
= element.getAttribute("dir");
    bodyNode.style.direction 
= element.currentStyle.direction;        
    
    
var head = element.document.createElement("HEAD");
    
var base = element.document.createElement("BASE");
    
var path = null;
    
if (window.location.pathname != null)
    {
        
var lastslash = window.location.pathname.lastIndexOf("/");
        
if (lastslash != -1)
            path 
= window.location.pathname.substr(0, lastslash + 1);
        
else
            path 
= window.location.pathname;
    }
    
var protocol = window.location.protocol.toLowerCase();
    base.href 
= window.location.protocol + (protocol != "mailto:" && protocol != "news:" ? "//" : ""+ window.location.host + path;
    head.appendChild(base);
    treeviewNode.appendChild(head);
    
    
var kids = contentNode.children.tags("treenode");
    
if (kids[0!= undefined)
    {
        
for (var i = 0; i < kids.length; i++)
        {
            kids[i].sibIndex 
= i;
            
var subtree = buildTree(kids[i], 0);
            bodyNode.appendChild(subtree);
        }
    }
    treeviewNode.appendChild(bodyNode);
    
    
// Create viewlink.
    treeviewNode.style.display = "block";
    treeviewNode.subtree 
= bodyNode;
    defaults.viewLink 
= treeviewNode.document;
    setHiddenHelperValue();

    g_bCreated 
= true;
}       

//
//
 buildTree()
//
//
 Recursively traverses the
//
 parsed TREEVIEW tree and creates the document tree of nested
//
 DIVs for the viewlink.
//
//
 root: Root node of the subtree to build
//
 level: level of the tree
//
//
 returns: created subtree
//
function buildTree(root, level)
{  
    
var display = true;
    
if (root.subtree != null && root.subtree.style.display == "none")
        display 
= false;
        
    root.detachEvent(
"onclick", DefaultNodeOnClick);
    root.attachEvent(
"onclick", DefaultNodeOnClick);
    
    
// clear all cached values for this node
    root.inheritedType = undefined;
    root.nodetypeIndex 
= undefined;

    
// process expandLevel
    var exp = makeBoolean(root.getAttribute("expanded"));
    
if (exp == null)
    {
        
if (level < element.getAttribute("ExpandLevel"))
        {
            root.setAttribute(
"expanded"true0);
            exp 
= true;
        }
        
else
            exp 
= false;
    }
    
    
//
    // convert string values to boolean
    //
    if (!verifyBooleanAttribute(root, "expanded"))
        root.setAttribute(
"expanded"false0);
    
if (!verifyBooleanAttribute(root, "checked"))
        root.setAttribute(
"checked"false);
    verifyBooleanAttribute(root, 
"checkBox");
    verifyBooleanAttribute(root, 
"checkedExpandable");
             
    
if (root.getAttribute("type"!= null)
        root.setAttribute(
"type", root.getAttribute("type").toLowerCase(), 0);
    
if (root.getAttribute("childType"!= null)
        root.setAttribute(
"childType", root.getAttribute("childType").toLowerCase(), 0);
        
    
// Create this node first
    var collChildren = root.children.tags("treenode");
    
var iChildren = collChildren.length;
    
var expandable = getNodeAttribute(root, "expandable");
    
if (expandable == null && root.getAttribute("TreeNodeSrc"!= null)
        expandable 
= "checkOnce";
    
if (root.getAttribute("_bound"!= "binding")
    {
        
var subtree = generateItem(root, iChildren > 0 || (expandable == "always" || (expandable == "checkOnce" && root.getAttribute("checkedExpandable"!= true)) ? "parent" : "child");
        
if (display == false)
            subtree.style.display 
= "none";
            
        
if (exp == true && root.getAttribute("TreeNodeSrc"!= null && root.getAttribute("_bound"!= "complete")
        {
            
// Databind.  When databinding is finished, this subtree will be built automatically
            root.setAttribute("expanded"true0);
            saveSubtree(root, subtree);
            databindNode(root);
        }
        
else
        {
            
// Create children
            if (root.getAttribute("expanded"== true)
            {
                
for (var i = 0; i < iChildren; i++)
                {
                    collChildren[i].sibIndex 
= i;
                    
var sub2 = buildTree(collChildren[i], level + 1);
                    
if (sub2 != undefined)
                        subtree.appendChild(sub2);
                }
            }
            
else
            {
                
for (var i = 0; i < iChildren; i++)
                {
                    
if (collChildren[i].getAttribute("subtree"!= null)
                        collChildren[i].subtree 
= null;
                }
            }
            saveSubtree(root, subtree);
        }
    }
    
    
return root.subtree;
}

//
//
 saveSubtree(el, subtree)
//
function saveSubtree(el, subtree)
{
    
if (el.getAttribute("subtree"== null)
        el.subtree 
= subtree;
    
else {
        el.subtree.replaceNode(subtree);
        el.subtree 
= subtree;
    }
}
     
//
//
 calcJunction(el)
//
//
 Determine if this node is at an L, T, or top root (R) junction.
//
function calcJunction(el)
{
    
var elParent = el.parentElement;
    
var collChildren = elParent.children.tags("treenode");
    
    
if (elParent.tagName == "treeview"  && collChildren[0== el)
    {
        
if (collChildren.length > 1)
            
return ('F');
        
else
            
return ('R');
    }
    
else
    {
        
if (collChildren[collChildren.length - 1== el)
        {
            
return ('L');
        }
        
else
        {
            
return ('T');
        }
    }
}

//
//
 generateItem(el, nodeclass)
//
//
 Creates the DOM object tree for a TREEVIEW item.
//
//
 el: TREENODE element for which the tree is generated
//
 nodeclass: "parent" or "child" (leaf)
//
function generateItem(el, nodeClass)
{
    
var image;
    
var plusminusNode;
    
var elAnchor;
    
    
var expImgUrl = getNodeAttribute(el, "ExpandedImageUrl");
    
var imgUrl = getNodeAttribute(el, "ImageUrl");
    
var node = el.document.createElement("DIV");
    
var cJunction;
    
var junctionNode;
    
var str;
    
    node.className 
= nodeClass;
    node.treenode 
= el;
    node.noWrap 
= true
    node.style.display 
= "block";
    
    
if (nodeClass == "child" && el.getAttribute("expanded"== true)
        el.setAttribute(
"expanded"false0);
        
    
// Determine L, T, or root junction
    cJunction = calcJunction(el);
    junctionNode 
= generateJunctionNode(el, cJunction, nodeClass);          
    node.appendChild(junctionNode);
    
    addLinesAndWhitespace(node, el, junctionNode);  
    
    
// Add checkbox
    if (getNodeAttribute(el, "checkBox"== true)
    {
        
var cb = createCheckBox(el);
        node.appendChild(cb);
    }
             
    
// Add anchor tag
    elAnchor = el.document.createElement("<A>");
    elAnchor.onclick 
= nodePlusMinusClick;
    junctionNode.applyElement(elAnchor, 
"outside");
        
    
// Add second anchor for image/text
    elAnchor = el.document.createElement("<A tabindex=-1>");
    str 
= getNodeAttribute(el, "NavigateUrl");
    
if (str != null && str != "")
    {
        elAnchor.href 
= str;
    }
    str 
= getNodeAttribute(el, "Target");
    
if (str != null)
        elAnchor.target 
= str;
        
    
// For accessibility, generate another anchor to enclose the text node
    var accessAnchor = elAnchor.cloneNode();
    accessAnchor.id 
= "_tnaccess";
    
    elAnchor.onclick 
= nodeClick;
    elAnchor.oncontextmenu 
= contextmenu;
    elAnchor.onmousedown 
= mousedown;
    elAnchor.onmouseup 
= mouseup;
    node.insertBefore(elAnchor);
        
    imageSrc 
= (nodeClass == "parent" && el.getAttribute("expanded"== true && expImgUrl != null ? expImgUrl : imgUrl);

    
var spacer = null;
    
if (imageSrc != null && imageSrc != undefined)
    {
        image 
= el.document.createElement("<IMG align='absmiddle' border='0' class='icon' id='_nodeicon'>");
        image.src 
= imageSrc;
        image.style.cssText 
= g_styles["icon"];
        elAnchor.appendChild(image);
        spacer 
= el.document.createElement("<SPAN>");
        spacer.style.width 
= 5;
        elAnchor.appendChild(spacer);
    }
    
    
var textNode = generateTextNode(el);
    
if (spacer != null)
    {
        spacer.style.cursor 
= textNode.style.cursor;
        image.style.cursor 
= textNode.style.cursor;
    }
    
    
if (nodeClass == "parent" && element.getAttribute("showToolTip"!= false)
        accessAnchor.title 
= textNode.innerText + " : " + L_strToolTip_Text;
    
    accessAnchor.appendChild(textNode);
    elAnchor.appendChild(accessAnchor);
    
    elAnchor.onmouseenter 
= mOver;
    elAnchor.onmouseleave 
= mOut;
        
    
return node;
}

//
//
 createCheckBox
//
function createCheckBox(el)
{
    
var form = el.document.createElement("<FORM style='display:inline' name='_fcb'>");
    
var bChecked = el.getAttribute("checked");
    
var cb = el.document.createElement("<INPUT style='display:inline' tabindex=-1 type=checkbox name='_cb'" + (bChecked ? " checked " : " "+ "/>");
    cb.onclick 
= checkboxClick;
    form.appendChild(cb);
    
    
return form;
}

//
//
 generateJunctionNode()
//
function generateJunctionNode(el, cJunction, nodeClass)
{
    
var imageSrc;
    
var junctionNode;
    
var systemImagesPath = element.getAttribute("systemImagesPath");
    
    
if (element.getAttribute("showLines"!= false)
    {
        imageSrc 
= systemImagesPath;
        
switch (cJunction)
        {
            
case 'L':
                imageSrc 
+= "L";
                
break;
            
case 'T':
                imageSrc 
+= "T";
                
break;
            
case 'R':
                imageSrc 
+= "R";
                
break;
            
case 'F':
                imageSrc 
+= "F";
                
break;
            
default:
                
return null;
                
break;
        }
        
if (nodeClass == "parent" && element.getAttribute("showPlus"!= false )
        {
            
if (el.getAttribute("expanded"== true)
                imageSrc 
+= "minus.gif";
            
else
                imageSrc 
+="plus.gif";
        }
        
else
            imageSrc 
+= ".gif";
    }
    
else
    {
        
if (nodeClass == "parent" && element.getAttribute("showPlus"!= false)
        {
            
if (el.getAttribute("expanded"== true)
                imageSrc 
= systemImagesPath + "minus.gif";
            
else
                imageSrc 
= systemImagesPath + "plus.gif";
        }
        
else
        {
            imageSrc 
= systemImagesPath + "white.gif";
        }
    }
    
if (element.getAttribute("showLines"== false && element.getAttribute("showPlus"== false)
        junctionNode 
= element.document.createElement("<SPAN name='junction'>");
    
else
    {
        junctionNode 
= element.document.createElement("<IMG align='absmiddle' border='0' class='icon' name='junction'>");
        junctionNode.src 
= imageSrc;
    }    
    
return junctionNode;
}

//
//
 addLinesAndWhitespace()
//
function addLinesAndWhitespace(node, el, junctionNode)
{
    
//
    // Walk up tree to draw lines/whitespace
    //
    var elWalk = el.parentElement;
    
var elInsertBefore = junctionNode;
    
var systemImagesPath = element.getAttribute("systemImagesPath");

    
if (element.getAttribute("showLines"!= false)
    {
        
while (elWalk && elWalk.tagName.toLowerCase() == "treenode")
        {
            
var nextSib = elWalk.nextSibling;
            
while (nextSib != null && nextSib.nodeType == 3)
                nextSib 
= nextSib.nextSibling;
                
            
var imageSrc;
            
var image;
            
            
if (nextSib != null && nextSib.tagName.toLowerCase() == "treenode")
                imageSrc 
= systemImagesPath + "I.gif";
            
else
                imageSrc 
= systemImagesPath + "white.gif";
            image 
= el.document.createElement("<IMG align='absmiddle' border='0'>");
            image.src 
= imageSrc;
            elInsertBefore 
= node.insertBefore(image, elInsertBefore);
            elWalk 
= elWalk.parentElement;
        }
    }    
    
else
    {
        
var strIndex = getNodeIndex(el);
        
if (strIndex.indexOf("."!= -1)
        {
            
if (element.getAttribute("Indent"!= null)
            {
                
if (isRtl())
                    node.style.marginRight 
= element.getAttribute("Indent");
                
else                           
                    node.style.marginLeft 
= element.getAttribute("Indent");
            }
        }
    }
}

//
//
 generateTextNode()
//
//
 el: treenode for which to generate text node
//
function generateTextNode(el)
{
    
var textNode = el.document.createElement("<SPAN id=_tntext tabIndex=-1 style='display:inline; height=100%'>");
    
    
if (el.getAttribute("Text"!= null)
    {
        textNode.innerHTML 
= el.getAttribute("Text");
    }
    
else
    {
        
// Remove any TREENODEs from the inner content, keeping everything else.
        var iChild = 0;
        
while (iChild < el.childNodes.length)
        {
            
if (el.childNodes[iChild].nodeType == 3 || el.childNodes[iChild].tagName.toLowerCase() != "treenode")
            {
                
// just copy the content
                var oClone = el.childNodes[iChild].cloneNode(true);
                textNode.appendChild(oClone);
            }
            iChild
++;
        }
    }
    textNode.className 
= "defaultstyle";
    
var defStyle = cascadeStyle(el, "defaultstyle");
    textNode.style.cssText 
= defStyle;

    
return textNode;
}

//
//
 updateTree(el)
//
//
 Show or hide the children of element el based on el's Expanded
//
 attribute.
//
  
function updateTree(el)
{
    
if (el.getAttribute("expanded"== true)
    {
        
// If we previously expanded this
        // node, just show its children without rebuilding them.
        var i = 0;
        
var coll = el.children.tags("treenode");
        
var bRebuild = true;
        
if (el.getAttribute("_buildChildren"!= true && (coll.length > 0 && coll(0).getAttribute("subtree"!= null))
        {   
            bRebuild 
= false
            
for (var i = 0; i < coll.length; i++)
            {
                
if (coll(i).subtree == null)
                {
                    
// a node has been added since we last expanded.  Rebuild everything.
                    bRebuild = true;
                    
break;
                }
                coll(i).subtree.style.display 
= "block";
            }
        }
        
if (bRebuild)
        {
            
// build and show children
            el.removeAttribute("_buildChildren");
            buildTree(el, getNodeLevel(el));
            reselectNode(el);
            
if (HoverNodeIndex == getNodeIndex(el))
                HoverNode(el);
        }
    }
    
    
else
    {
        
// hide children
        var collChildren = el.children.tags("treenode");
        
for (var i = 0; i < collChildren.length; i++)
        {
            collChildren(i).subtree.style.display 
= "none";
        }
               
        
// If the selected or hovered node was one of the collapsed node's descendants,
        // the collapsed node must become selected/hovered instead
        var index = getNodeIndex(el);
        
if (selectedNodeIndex.length > index.length && selectedNodeIndex.substr(0,index.length) == index)
        {
            selectNode(el);
        }
        
else if (selectedNodeIndex == index)
            changeIcon(el, 
"SelectedImageUrl");
            
        
if (HoverNodeIndex.length >= index.length && HoverNodeIndex.substr(0, index.length) == index)
        {
            
if (selectedNodeIndex != index)
            {
                
if (HoverNodeIndex != index)
                {
                    UnhoverNode(getNodeFromIndex(HoverNodeIndex));
                    HoverNode(el);
                }
            }
            
else
                UnhoverNode(getNodeFromIndex(HoverNodeIndex));
        }
    }
    setHiddenHelperValue();
}        
    
//
//
 cascadeStyle(el, att)
//
//
 Cascade style from built-in to the tree to the type to the node.
//
function cascadeStyle(el, att)
{
    
// built-in
    var str = g_styles[att];

    
// tree
    var strStyle = element.getAttribute(att);
    
if (strStyle != null)
        str 
= str + ";" + strStyle;
    
    
// type
    strStyle = getNodeTypeAttribute(el, att);
    
if (strStyle != null)
        str 
= str + ";" + strStyle;
    
    
// node
    strStyle = el.getAttribute(att);
    
if (strStyle != null)
        str 
= str + ";" + strStyle;
    
    
return str;
}

//
//
 getNodeTypeAttribute    
//
//
 Returns the given attribute from the given element's node type.
//
function getNodeTypeAttribute(el, att)
{
    
var _nodetype = getNodeTypeObject(el);
    
if (_nodetype != null)
        
return _nodetype.getAttribute(att);
    
return null;
}

//
//
 getNodeAttribute
//
//
 Returns the given attribute from the node, the node's type, or the treeview
//
function getNodeAttribute(el, att)
{
    
var strReturn;
    
    
// try the node
    strReturn = el.getAttribute(att);
    
if (strReturn != null)
        
return strReturn;
        
    
// try the node's type
    strReturn = getNodeTypeAttribute(el, att);
    
if (strReturn != null)
        
return strReturn;
        
    
// try the tree
    return element.getAttribute(att);
}

//
//
 navigateNode()
//
//
 If the given node has a NavigateUrl, navigate to it.  Return TRUE if we're navigating our own page; FALSE otherwise.
//
function navigateNode(el)
{
    
var url = getNodeAttribute(el, "NavigateUrl");
    
if (url != null && url != "")
    {
        
var target = getNodeAttribute(el, "Target");
        
if (target == null || target == "_self")
        {
            window.open(url, 
"_self");
            
return true;
        }
        
else
            window.open(url, target);
    }
    
return false;
}

//
//
 checkboxClick()
//
//
 event handler for mouse click on an item's checkbox
//
function checkboxClick()
{
    
if (g_bInteractive == false)
        
return;

    
var el = this.parentElement.parentElement.treenode;
    event.cancelBubble 
= true;
    
    doCheckboxClick(el);
    fireQueuedEvents();
}

//
//
 doCheckboxClick()
//
 function doCheckboxClick(el){
            
var checked = private_getAttribute(el,"checked")
            el.checked 
= !checked;
            
var evt = createEventObject();
            evt.treeNodeIndex 
= getNodeIndex(el);
            g_nodeClicked 
= el;
            _tvevtCheck.fire(evt);
            setNodeState(el,el.checked);
// maybe need el only,but I think it's safly
        }
        
function  setNodeState(el,state){
            _setChildNode(el,state);
            _setParentNode(el,state);
        }
         
function  _setChildNode(el,state){
            
var childNodes = el.children;
            
if(childNodes.length > 0){// if has childs 
                for(var i = 0 ;i<=childNodes.length-1;i++){
                    private_setAttribute(childNodes[i],
"Checked",state);
                    _saveCheckState(childNodes[i]);
                    _setChildNode(childNodes[i],state);
                }
            }
        }
        
function  _setParentNode(el,state){
            
var parentNode = el.parentElement;
            
if(parentNode){
                
if(!_checkSiblingdNode(el)){
                    private_setAttribute(parentNode,
"Checked",state);
                    _saveCheckState(parentNode);
                    _setParentNode(parentNode,state);
                }
            }
        }
        
function _checkSiblingdNode(el){
            
var parentNode = el.parentElement;// you can use getParentTreeNode function in this htc,but I like this usage.
            for(var i = 0;i<=parentNode.children.length-1;i++){
                
if(el != parentNode.children[i]){
                    
if(private_getAttribute(parentNode.children[i],"Checked")){
                        
return true;
                    }
                }
            }
            
return false;
        }
            
            
function _saveCheckState(el){
            
if(getNodeIndex(el))
                queueEvent(
'oncheck', getNodeIndex(el));
        }
//
//
 nodeClick()
//
//
 event handler for mouse click on an item in the tree
//
function nodeClick()
{
    
if (g_bInteractive == false)
        
return;

    
var el = this.parentElement.treenode;
    
if (doNodeClick(el) == true)
    {
        
if (element.getAttribute("selectExpands"== true)
            doNodePlusMinusClick(el);
        fireQueuedEvents();
    }
}

//
//
 contextmenu()
//
//
 event handler for right-clicking a tree node
//
function contextmenu()
{
    event.cancelBubble 
= true;
    e 
= element.document.createEventObject(event);
    e.treeNodeIndex 
= getNodeIndex(this.parentElement.treenode);
    event.returnValue 
= element.fireEvent("oncontextmenu", e);
}

//
//
 mousedown()
//
function mousedown()
{
    
if (event.button & 1)
    {
        g_bMouseDown 
= true;
    }
}

//
//
 mouseup()
//
function mouseup()
{
    g_bMouseDown 
= false;
}

//
//
 nodePlusMinusClick()
//
//
 event handler for mouse click on the plus/minus icon of a treenode
//
function nodePlusMinusClick()
{
    
if (g_bInteractive == false)
        
return;

    
var el = this.parentElement.treenode;
    
if (doNodePlusMinusClick(el) == true)
        fireQueuedEvents();
}

//
//
 doNodeClick()
//
//
 Does the work associated with a node click.  Separated out from nodeClick() so that
//
 we can call it directly without having to identify the anchor element of a node.
//
//
 returns: true to continue processing
//
          false to stop (because we're navigating our own page)
//
function doNodeClick(el)
{
    
if (g_bInteractive == false)
        
return;
        
    g_nodeClicked 
= el;

    
// The element, which is in a content node outside of the document, is outside the event hierarchy.
    // Fire the event ourselves, rather than relying on bubbling.
    event.cancelBubble = true;
    el.fireEvent(
"onclick");        // Execute our onclick handler
    element.fireEvent("onclick", event);  // Execute the tree's onclick handler

    
if (getNodeAttribute(el, "NavigateUrl"!= null)
    {
        
var target = getNodeAttribute(el, "Target");
        
if (target == null || target.toLowerCase() == "_self")
            
return false;
    }

    selectNode(el);
    
return true;
}

//
//
 doNodePlusMinusClick()
//
//
 Does the work associated with a node click.  Separated out from nodePlusMinusClick() so that
//
 we can call it directly without having to identify the anchor element of a node.
//
//
 return: true if something interesting happened (expanded, collapsed), false otherwise
//
function doNodePlusMinusClick(el)
{
    
if (g_bInteractive == false)
        
return false;
        
    
// The element, which is in a content node outside of the document, is outside the event hierarchy.
    // Fire the event ourselves, rather than relying on bubbling.
    event.cancelBubble = true;

    g_nodeClicked 
= el;

    
if (el.getAttribute("expanded"== false && el.getAttribute("_bound"== null && el.getAttribute("TreeNodeSrc"!= null)
    {
        el._isExpanding 
= true;
        private_databind(el);
        
return true;
    }
    
else
        
return finishNodePlusMinusClick(el);
}

function finishNodePlusMinusClick(el)
{        
    
// See if we're a leaf (no children) or a branch (children)
    var exp = getNodeAttribute(el, "expandable");
    
if (exp == null && el.getAttribute("TreeNodeSrc"!= null)
        exp 
= "checkOnce";

    
if (el.children.tags("treenode").length > 0 || exp == "always" || (exp == "checkOnce" && el.getAttribute("checkedExpandable"!= true))
    {
        
//
        // We're a branch.  Update ourselves.
        //
        var expanded = !el.getAttribute("expanded");
        el.setAttribute(
"expanded", expanded, 0);
        
        
if (exp == "checkOnce")
            el.checkedExpandable 
= true;
            
        
var evt = createEventObject();
        evt.treeNodeIndex 
= getNodeIndex(el);

        
var eventToFire = changeJunctionImage(el);
        
        
// update our children
        updateTree(el);
        doVisualRefresh();
        
        
// show status node if we're posting back for databinding
        if (expanded == true && el.children.tags("treenode").length == 0 && element.getAttribute("onfirequeuedevents"!= null)
            addStatusNode(el, L_strRetrievingNodes_Text);
        
        eventToFire.fire(evt);

        
return true;
    }
    
return false;
}

//
//
 changeJunctionImage()
//
//
 Changes the +/- junction image to match current Expanded state.
//
//
 el: treenode element containing junction image to change
//
function changeJunctionImage(el)
{
    
// find the icons we need to change
    var icon1 = el.subtree.all("junction",0);
    
    
if (el.getAttribute("expanded"== true)
    {
        
// Expanding the node
        if (icon1 != null)
            icon1.src 
= icon1.src.replace(/plus/"minus");
        
if (selectedNodeIndex != getNodeIndex(el) || getNodeAttribute(el, "selectedimageurl"== null)
            changeIcon(el, 
"ExpandedImageUrl");
        
return _tvevtExpand;
    }
    
else
    {
        
// Collapsing the node
        if (icon1 != null)
            icon1.src 
= icon1.src.replace(/minus/"plus");
        
if (selectedNodeIndex != getNodeIndex(el))
            changeIcon(el, 
"ImageUrl");
        
return _tvevtCollapse;
    }
}

//
//
 DefaultNodeOnClick()
//
//
 A default onclick handler for treenode elements to cancel the event bubble.
//
 This is needed for the server control, otherwise the event will bubble up the
//
 tree until it hits a node with an onclick handler.  In the case of a server
//
 control, odds are good that the onclick handler will cause a server postback,
//
 thereby preventing the tree from getting its onclick.  So we need to cancel
//
 the bubble, allowing the onclick event we fire on the tree to get through.
//
function DefaultNodeOnClick()
{
    event.cancelBubble 
= true;
}

function getClickedNodeIndex()
{
    
if (g_nodeClicked != null)
        
return getNodeIndex(g_nodeClicked);
    
else
        
return null;
}

function getNodeLevel(node)
{
    
var level = 0;
    
while (node.parentElement.tagName.toLowerCase() == "treenode")
    {
        node 
= node.parentElement;
        level
++;
    }
    
return level;
}
    
//
//
 getNodeIndex()
//
//
 Walks up the tree, generating an index string of the form a.b.c[...].z (ex: 1.0.5.12) where
//
 each number represents a 0-based index into a set of children.  Each set of these values
//
 creates a unique index to a node.  In the following tree:
//
         A
//
       / | 
//
      B  C  D
//
     /    / 
//
    E   F G   H
//
 node F is 0.0.1, node G is 0.2.0, and H is 0.2.1.
//
function getNodeIndex(node)
{
    
var strIndex = "";
    
if (node != null)
    {
        
if (node.getAttribute("sibIndex"== null)
        {
            
if (node.parentElement == null)
            {
                
// There is no parent, this node is in the ether
                return null;
            }

            
// generate a sibling index
            var col = node.parentElement.children.tags("treenode");
            
var i = 0;
            
while (col[i] != node)
                i
++;
            node.sibIndex 
= i;
        }
        strIndex 
= node.sibIndex.toString();
        
while (node.parentElement && node.parentElement.tagName.toLowerCase() == "treenode")
        {
            node 
= node.parentElement;
            
if (node.getAttribute("sibIndex"== null)
                
return null;
            strIndex 
= node.sibIndex + "." + strIndex;
        }
    }
    
return strIndex;
}

//
//
 getNodeFromIndex()
//
//
 The flipside of getNodeIndex, this function returns a node given a dot-delimited index
//
function getNodeFromIndex(strIndex)
{
    
if (strIndex != null && strIndex != undefined && strIndex.length != 0)
    {
        
// convert index string into array of strings
        var a = strIndex.split(".");
        
var i = 0;
        
var node = contentNode;
        
while (i < a.length)
        {
            
var coll = node.children.tags("treenode");
            
if (coll == null || coll.length < (a[i] - 0+ 1)
            {
                
return null;
            }                
            node 
= coll.item(a[i++- 0);
        }
        
return node;
    }
    
else
    {
        
return null;
    }
}
 

//
//
 getNextVisibleNode()
//
function getNextVisibleNode(node)
{
    
var next = node;
    
if (node.getAttribute("expanded"== true)
    {
        
// get first child treenode
        next = node.children[0];
        
while (next != null && next != undefined && next.nodeName.toLowerCase() != "treenode")
            next 
= next.nextSibling;
        
if (next)
            
return next;
    }
    
    
// get first sibling treenode
    next = node.nextSibling;
    
while (next != null && next != undefined && next.nodeName.toLowerCase() != "treenode")
        next 
= next.nextSibling;
    
if (next != null
        
return next;
     
    
// get first sibling of first ancestor that has one     
    next = node.parentElement;
    
while ((next.nextSibling == null || next.nextSibling == undefined) && next.nodeName.toLowerCase() == "treenode")
    {
        next 
= next.parentElement;
    }
    
if (next.nextSibling != null && next.nextSibling != undefined && next.nextSibling.nodeName.toLowerCase() == "treenode")
        
return next.nextSibling;
    
else
        
return null;
}
        
//
//
 getPreviousVisibleNode()
//
function getPreviousVisibleNode(node)
{
    
var prev = node;
    
    
// check for a previous sibling
    prev = node.previousSibling;
    
while (prev != null && prev != undefined && prev.nodeName.toLowerCase() != "treenode")
        prev 
= prev.previousSibling;
    
if (prev)
    {
        
// Found a previous sibling.  If that sibling is expanded, we need to drop down to its last child
        if (prev.getAttribute("expanded"== true)
        {
            
// get last child
            var lastChild = prev;
            
while (lastChild != node && lastChild != null)
            {
                prev 
= lastChild;
                lastChild 
= getNextVisibleNode(prev);
            }
        }
        
return prev;
    }
    
    
// get parent
    if (node.parentElement.nodeName.toLowerCase() == "treenode")
        
return node.parentElement;
    
else
        
return null;
}        

//
//
 setHiddenHelperValue()
//
function setHiddenHelperValue()
{
    
var id = element.HelperID;
    
if (id == null)
        
return;

    
var helper = window.document.all(id);
    
if (helper == null)
        
return;

    
var parentTop = -1;
    
var parentLeft = -1;
    
var parent = element.offsetParent;
    
if (parent != null)
    {
        parentTop 
= parent.scrollTop;
        parentLeft 
= parent.scrollLeft;
    }

    helper.value 
= (g_bFocus ? "1" : "0"+ "|" + HoverNodeIndex + "|" + element.scrollTop + "|" + element.scrollLeft + "|" + parentTop + "|" + parentLeft + "|" + g_strQueuedEvents;
}

//
//
 scrollTree()
//
function scrollTree(tnode)
{
    
var node = tnode.subtree.all.item("_tntext"0);

    
var top = node.offsetTop - element.scrollTop;
    
if (top < 0)
    {
        element.scrollTop 
+= top;
    }
    
else
    {
        
var bottom = top + node.offsetHeight;
        
var elemHeight = element.clientHeight;
        
if (bottom > elemHeight)
        {
            element.scrollTop 
+= bottom - elemHeight;
        }
    }

    
var rc = node.getBoundingClientRect();
    
var elRc = element.getBoundingClientRect();

    
// scroll window if we're focused  
    if (g_bFocus)
    {
        
if (elRc.top + rc.top < element.document.body.clientTop) 
            node.scrollIntoView(
true);
        
else if (elRc.top + rc.bottom > element.document.body.clientHeight)
            node.scrollIntoView(
false);
    }

}

//
//
 getInheritedType()
//
//
 Returns the node's inheritedType, if defined, or finds it and returns it if undefined.
//
 A node's inheritedType is the first of:
//
      * parent's childType
//
      * parent's type's childType
//
      * parent's inheritedType's childType
//
      * parent's inheritedType
//
function getInheritedType(el)
{
    
if (el.inheritedType === undefined || g_bInTypesBoundEvent)
    {
        
var parentNode = el.parentElement;
/*
        while (parentNode.tagName.toLowerCase() != "treenode" && parentNode.tagName.toLowerCase() != "treeview")
            parentNode = parentNode.parentElement;
*/        
        
// parent's childType
        el.inheritedType = parentNode.getAttribute("childType");
        
var tagname = parentNode.tagName.toLowerCase();
        
        
if (el.inheritedType == null && tagname != "treeview")
        {
            
// parent's type's or inheritedType's childType
            var _parenttype = getNodeTypeObject(parentNode);
            
if (_parenttype != null)
            {
                el.inheritedType 
= _parenttype.getAttribute("childType");
            }
                       
            
// parent's inheritedType
            if (el.inheritedType == null && tagname == "treenode")
            {
                el.inheritedType 
= getInheritedType(parentNode);
            }
        }

        
// grab from the treeview
        if (el.inheritedType == null)
            el.inheritedType 
= element.getAttribute("childType");
    }
    
return el.inheritedType;
}
 
//
//
 getNodeTypeObject()
//
//
 Returns the node type object for the given node, if defined.  If undefined, searches
//
 for and stores the node type object, then returns it.  Returns null if no type is defined
//
 for this node.
//
//
 This function assumes that a node's type or inheritedType attribute holds the name of its type
//
function getNodeTypeObject(el)
{
    
if (el.nodetypeIndex == undefined || g_bInTypesBoundEvent)
    {
        
var theType = el.getAttribute("type");
        
if (theType == null)
            theType 
= getInheritedType(el);
        
if (theType == null)
            
return null;
        
        theType 
= theType.toLowerCase();
        
var i = 0;
        
var len = element.nodeTypes.length;
        
while (i < len)
        {
            
if (element.nodeTypes[i].getAttribute("type"== theType)
            {
                el.nodetypeIndex 
= i;
                
break;
            }
            i
++;
        }
    }
    
return element.nodeTypes[el.nodetypeIndex];
}

//
//
 replaceJunctionNode()
//
//
 Replace the junction node of the given node by generating a new one
//
 
//
 node: treenode on which to perform replacement
//
function replaceJunctionNode(node)
{
    
if (node.subtree == null)
        
return;
    
var oldNode = node.subtree.all("junction"0);
    
if (oldNode == null)
        
return;
        
    
var cJunction = calcJunction(node);
    
var exp = node.getAttribute("Expandable");
    
if (exp == null && node.getAttribute("TreeNodeSrc"!= null)
        exp 
= "checkOnce";
    
var bChildNodes = node.children.tags("treenode").length > 0;
    
var junctionNode = generateJunctionNode(node, cJunction, bChildNodes || (exp == "always" || (exp == "checkOnce" && node.getAttribute("checkedExpandable"!= true)) ? "parent" : "child");          
    
var accessNode = node.subtree.all("_tnaccess"0);
    
if (!bChildNodes)
        accessNode.title 
= ""
    
else
    {
        
var textNode = node.subtree.all("_tntext"0);
        accessNode.title 
= textNode.innerText + " : " + L_strToolTip_Text;
    }
    oldNode.replaceNode(junctionNode);
}

//
//
 addStatusNode()
//
function addStatusNode(el, str)
{
    
if (el.subtree != null && el.subtree.all.item("_fetch"0!= null)
        
return;
        
    
// Show "fetching" message
    var fetchNode =  el.document.createElement("<DIV id=_fetch>");
    
var imageNode = el.document.createElement("<IMG align='absmiddle' border='0'>");
    imageNode.src 
= element.getAttribute("systemimagespath"+ "white.gif";
    fetchNode.appendChild(imageNode);    
    
var junctionNode = generateJunctionNode(null'L'"child");
    fetchNode.appendChild(junctionNode);
    addLinesAndWhitespace(fetchNode, el 
== element ? contentNode : el, junctionNode);  
    
var textNode = el.document.createElement("<SPAN id=_tntext tabIndex=-1 style='display:inline; height=100%'>");
    textNode.innerText 
= str;
    textNode.className 
= "defaultstyle";
    
var defStyle;
    
if (el == element)
        defStyle 
= g_styles["defaultstyle"+ ";" + element.getAttribute("defaultstyle");
    
else
        defStyle 
= cascadeStyle(el, "defaultstyle");
    textNode.style.cssText 
= defStyle;
    fetchNode.appendChild(textNode);
    
if (el == element)
    {
        
if (!g_bCreated)
        {
            
// Create viewlink.
            fetchNode.style.display = "block";
            defaults.viewLink 
= fetchNode.document;
        }
        
else
        {
            treeviewNode.appendChild(fetchNode);
        }
    }
    
else
    {
        
if (el.subtree != null)
            el.subtree.appendChild(fetchNode);
    }
    doVisualRefresh();
}

//
//
 databindNode()
//
//
 Databind to the given node's TreeNodeSrc & TreeNodeXsltSrc.  This creates
//
 the node's children based on this binding, but does not affect the node
//
 itself.
//
//
 el: node for which we're databinding
//
function databindNode(el)
{
    
var src = el.getAttribute("TreeNodeSrc");
    
if (src == null)
        
return;

    addStatusNode(el, L_strRetrievingNodes_Text);
    el._bound 
= "binding";  

    
var XsltSrc = el.getAttribute("TreeNodeXsltSrc");
    
var databindInfo = new Object();
    databindInfo.el 
= el;
    databindInfo.transform 
= null;
    databindInfo.island 
= null;
    databindInfo.src 
= src;
    
    
if (el == contentNode)
        g_bNodesReady 
= false;

    
if (XsltSrc != null)
    {
        databindInfo.transform 
= element.document.all(XsltSrc);
        
if (databindInfo.transform == null)
        {
            
// create our own data island for the transform

            
try
            {
                databindInfo.transform 
= new ActiveXObject("Msxml2.DOMDocument");
            }
            
catch (e)
            {
                databindError(databindInfo, L_strMSXMLError_Text);
                
return;
            }
            databindInfo.transform.async 
= false;
            
if (!databindInfo.transform.loadXML(XsltSrc))
                databindInfo.transform.load(XsltSrc);
        }
        
else
            databindInfo.transform 
= databindInfo.transform.XMLDocument;
    }
    
    databindInfo.island 
= element.document.all(src);

    
if (databindInfo.island == null)
    {
        
// create our own data island
        try
        {
            databindInfo.island 
= new ActiveXObject("Msxml2.DOMDocument");
        }
        
catch (e)
        {
            databindError(databindInfo, L_strMSXMLError_Text);
            
return;
        }
        databindInfo.island.async 
= false;
        g_pendingSyncBinds 
= g_pendingSyncBinds.concat(databindInfo);
        
if (g_bindTimer == -1)
            g_bindTimer 
= window.setTimeout(syncBind, 10"JScript");
    }
    
else
        finishDatabindingNode(databindInfo, 
true);
}

function syncBind()
{
    
// loop through pending synchronous databinds
    while (g_pendingSyncBinds.length > 0)
    {
        
var databindInfo = g_pendingSyncBinds[0];
        
// remove from array
        g_pendingSyncBinds.splice(01);
        
if (!databindInfo.island.loadXML(databindInfo.src))
        {
            databindInfo.island.async 
= true;
            
// add to our array of pending databinds
            g_pendingBinds = g_pendingBinds.concat(databindInfo);
            databindInfo.island.onreadystatechange 
= finishDatabindingNodeHandler;
            databindInfo.island.load(databindInfo.src);
        }
        
else
            finishDatabindingNode(databindInfo, 
true);
    }
    g_bindTimer 
= -1;
}
    
function finishDatabindingNodeHandler()
{
    
// loop through pending databinds, resolving those which are complete
    for (var i = 0; i < g_pendingBinds.length; i++)
    {
        
if (g_pendingBinds[i].island.readyState == 1)
            g_pendingBinds[i].b 
= true;
        
if (g_pendingBinds[i].island.readyState == 4 && g_pendingBinds[i].b == true)
        {
            
var bindInfo = g_pendingBinds[i];
            g_pendingBinds.splice(i, 
1);
            finishDatabindingNode(bindInfo, 
false);
            i
--;
        }
    }
}

function finishDatabindingNode(databindInfo, bReady)
{
    
if (bReady != true && databindInfo.island == null)
        
return;

    
if (databindInfo.island.xml == "" || (databindInfo.transform != null && databindInfo.transform.xml == ""))
    {
        
var regexp = /%s/;
        
var str = "<B>" + L_strXMLError_Text + "</B>";
        str 
= str.replace(regexp, databindInfo.el.getAttribute('TreeNodeSrc'));
        databindError(databindInfo, str);
        
return;
    }
   
    
// Databind to this data island
    if (databindInfo.transform != null)
    {
        
var html = databindInfo.island.transformNode(databindInfo.transform);
        
try
        {
            databindInfo.island 
=  new ActiveXObject("Msxml2.DOMDocument");
        }
        
catch (e)
        {
            databindError(databindInfo, L_strMSXMLError_Text);
            
return;
        }
        databindInfo.island.loadXML(html);
    }

    
// Make sure the root is a TREENODES tag
    var container = databindInfo.island.selectSingleNode("TREENODES");
    
if (container == null)
    {
        
var strXslt = databindInfo.el.getAttribute("TreeNodeXsltSrc");
        
var strError = "<B>" + L_strInvalidXML_Text;
        
var regexp = /%s/;
        strError 
= strError.replace(regexp, databindInfo.el.getAttribute('TreeNodeSrc'));
        
if (strXslt != null)
        {
            strError 
+= L_strXSLTError_Text + "</B>";
            strError 
= strError.replace(regexp, databindInfo.el.getAttribute('TreeNodeXsltSrc')); 
        }
        
else
            strError 
+= "</B>";
        databindError(databindInfo, strError);
        
return;
    }
    
    
var child = container.firstChild;
    
var html = "";
    
while (child != null)
    {
        
if (child.nodeName.toLowerCase() == "treenode")
            html 
+= child.xml;
        child 
= child.nextSibling;
    }
    databindInfo.el._bound 
= "complete";
    
    
// All nodes must have namespace inserted
    html = html.replace(/(</?)(treenode)/gi, "$1" + element.scopeName + ":$2");
    
    
if (databindInfo.el == element)
    {
        contentNode.innerHTML 
= html;
        g_bNodesReady 
= true;
        tryToBuildTreeFromRoot(); 
    }
    
else
    {
        databindInfo.el.innerHTML 
+= html;
        
if (databindInfo.el.subtree != null)
        {
            buildTree(databindInfo.el, getNodeLevel(databindInfo.el));
            
if (databindInfo.el._isExpanding == true)
            {
                databindInfo.el.removeAttribute(
"_isExpanding");
                finishNodePlusMinusClick(databindInfo.el);
            }
            
else
            {
                reselectNode(databindInfo.el);
            }
        }
    }

    doVisualRefresh();
    
    
var evt = element.document.createEventObject();
    
if (databindInfo.el == element)
        evt.treeNodeIndex 
= null;
    
else
        evt.treeNodeIndex 
= getNodeIndex(databindInfo.el);
    evt.reason 
= 0;
    _tvevtNodeBound.fire(evt);
}

//
//
 databindError()
//
//
 Report an error during databinding
//
function databindError(databindInfo, strError)
{
    
var fetch;
    
var event = createEventObject();
    
if (databindInfo.el == element)
        event.treeNodeIndex 
= null;
    
else
        event.treeNodeIndex 
= getNodeIndex(databindInfo.el);
    event.reason 
= 2;
    _tvevtNodeBound.fire(event);
    
    
if (databindInfo.el == element)
        fetch 
= defaults.viewLink.all.item("_fetch"0);
    
else
        fetch 
= databindInfo.el.subtree.all.item("_fetch"0);
    
if (fetch != null)
    {
        
var tntext = fetch.all.item("_tntext"0);
        tntext.innerHTML 
= strError;
    }
}

//
//
 databindTypes()
//
//
 Bind the tree for TreeNodeTypes
//
function databindTypes()
{
    
var src = element.getAttribute("TreeNodeTypeSrc");

    
if (src == null)
        
return;
 
    g_bTypesReady 
= false;
    
    g_typeIsland 
= element.document.all(src);
    
if (g_typeIsland == null)
    {
        
// create our own data island
        try
        {
            g_typeIsland 
= new ActiveXObject("Msxml2.DOMDocument");
        }
        
catch (e)
        {
            databindError(databindInfo, L_strMSXMLError_Text);
            
return;
        }
        g_typeIsland.async 
= false;
        
if (!g_typeIsland.loadXML(src))
        {
            g_typeIsland.async 
= true;
            g_typeIsland.onreadystatechange 
= finishDatabindingTypes;
            g_typeIsland.load(src);
        }
        
else
            finishDatabindingTypes();
    }
}

function finishDatabindingTypes()
{
    
if (g_typeIsland.readyState != 4)
        
return;

    
if (g_typeIsland.xml == "")
    {
        databindTypesError();
        
return;
    }
            
    
// Make sure the root is a TREENODETYPES tag
    var container = g_typeIsland.selectSingleNode("TREENODETYPES");
    
if (container == null)
    {
        databindTypesError();
        
return;
    }
    
    
var child = container.firstChild;
    
var html = "";
    
while (child != null)
    {
        
if (child.nodeName.toLowerCase() == "treenodetype")
            html 
+= child.xml;
        child 
= child.nextSibling;
    }

    
// All nodetypes must have namespace inserted
    html = html.replace(/(</?)(treenodetype)/gi, "$1" + element.scopeName + ":$2");
    
    g_typesNode 
= element.document.createElement("DIV");
    g_typesNode.innerHTML 
= html;

    element.nodeTypes 
= g_typesNode.children.tags("TREENODETYPE");
    verifyTypeValues();
    g_bTypesReady 
= true;
    
var evt = element.document.createEventObject();
    evt.reason 
= 0;
    g_bInTypesBoundEvent 
= true;
    _tvevtNodeTypesBound.fire(evt);
    g_bInTypesBoundEvent 
= false;
    tryToBuildTreeFromRoot();
}

//
//
 databindTypesError()
//
function databindTypesError()
{
    
var event = createEventObject();
    event.reason 
= 2;
    g_bInTypesBoundEvent 
= true;
    _tvevtNodeTypesBound.fire(event);
    g_bInTypesBoundEvent 
= false;
    g_typesNode 
= element.document.createElement("DIV");
    element.nodeTypes 
= g_typesNode.children.tags("TREENODETYPE");
    g_bTypesReady
=true;
}

//
//
 verifyExpandableValue()
//
//
 Verifies that the value is one of the acceptable Expandable values
//
//
 value: value to verify
//
function verifyExpandableValue(value)
{
    
var lval = value.toLowerCase();
    
switch (lval)
    {
        
case "auto":
        
case "checkonce":
        
case "always":
            
return true;
        
default:
            
return false;
            
break;
    }
}

//
//
 verifyBooleanAttribute()
//
//
 Verifies that the attribute's value is boolean, or a text equivalent.  If the latter,
//
 the attribute is converted to the corresponding boolean.  If the value is not a boolean
//
 equivalent or null, the attribute is set to false.
//
//
 node: node on which to verify attribute
//
 att: attribute to verify
//
//
 returns: true if the value was a boolean or equivalent
//
          false otherwise
//
function verifyBooleanAttribute(node, att)
{
    
var value = node.getAttribute(att);
    
if (value == null)
        
return false;

    
var boolval = makeBoolean(value);
       
    
if (value == boolval)
        
return true;

    node.setAttribute(att, boolval 
== null ? false : boolval, 0);
    
return (boolval != null);
}

function makeBoolean(value)
{
    
if (value == true || value == false)
        
return value;
    
    
if (value == null)
        
return null;
        
    
var lval = value.toLowerCase();
    
switch (lval)
    {
        
case "true":
            
return true;
        
case "false":
            
return false;
        
default:
            
return null;
    }
}

//
//
 verifyTypeValues()
//
//
 converts the value of each TreeNodeType's Type attribute to lower case, and
//
 string booleans to true booleans
//
function verifyTypeValues()
{
    
var len = element.nodeTypes.length;
    
for (var i = 0; i < len; i++)
    {
        
var str = element.nodeTypes[i].getAttribute("type");
        
if (str != null)
            element.nodeTypes[i].setAttribute(
"type", str.toLowerCase(), 0);
        verifyBooleanAttribute(element.nodeTypes[i], 
"expanded");
        verifyBooleanAttribute(element.nodeTypes[i], 
"checkBox");
    }
}

//
//
 getNodeTypeHtml()
//
//
 Get the HTML source for the nodeTypes collection
//
function getNodeTypeHtml()
{
    
var html = "";
    
for (var i = 0; i < element.nodeTypes.length; i++)
    {
        html 
+= element.nodeTypes[i].outerHTML;
    }
    
return html;
}

//---------------------------------------------------
//
//
 Public OM
//
//
---------------------------------------------------

//
//
 TreeView properties
//

function getDefaultStyle()
{
    
return prop_defaultStyle;
}

function setDefaultStyle(value)
{
    
if (prop_defaultStyle == value)
        
return;
        
    
if (typeof value == "string")
    {
        prop_defaultStyle 
= value;

        
if (g_bCreated)
        {
            modifyNodesByType(contentNode, 
null"defaultstyle")
            _tvpropDefaultStyle.fireChange();
        }
    }
}

function getHoverStyle()
{
    
return prop_hoverStyle;
}

function setHoverStyle(value)
{
    
if (prop_hoverStyle == value)
        
return;
        
    
if (typeof value == "string")
    {
        prop_hoverStyle 
= value;

        
if (g_bCreated)
        {
            modifyNodesByType(contentNode, 
null"hoverstyle")
            _tvpropHoverStyle.fireChange();
        }
    }
}

function getSelectedStyle()
{
    
return prop_selectedStyle;
}

function setSelectedStyle(value)
{
    
if (prop_selectedStyle == value)
        
return;
        
    
if (typeof value == "string")
    {
        prop_selectedStyle 
= value;

        
if (g_bCreated)
        {
            modifyNodesByType(contentNode, 
null"selectedstyle")
            _tvpropSelectedStyle.fireChange();
        }
    }
}

function getChildType()
{
    
return prop_childType;
}

function setChildType(value)
{
    
if (prop_childType != value)
    {
        prop_childType 
= value;
        
if (g_bCreated)
        {
            
var col = contentNode.children.tags("treenode");
            
for (var i = 0; i < col.length; i++)
                buildTree(col[i], 
0);  
            
            _tvpropChildType.fireChange();
        }
    }
}    
        
function getImageUrl()
{
    
return prop_imageUrl;
}

function setImageUrl(value)
{
    
if (prop_imageUrl != value)
    {
        prop_imageUrl 
= value;
        
if (g_bCreated)
        {
            modifyNodesInheritingFromRoot(contentNode, 
"imageurl", value);
            _tvpropImageUrl.fireChange();
        }
    }
}
   
function getSelectedImageUrl()
{
    
return prop_selectedImageUrl;
}

function setSelectedImageUrl(value)
{
    
if (prop_selectedImageUrl != value)
    {
        prop_selectedImageUrl 
= value;
        
if (g_bCreated)
        {
            modifyNodesInheritingFromRoot(contentNode, 
"selectedimageurl", value);
            _tvpropSelectedImageUrl.fireChange();
        }
    }
}
   
function getExpandedImageUrl()
{
    
return prop_expandedImageUrl;
}

function setExpandedImageUrl(value)
{
    
if (prop_expandedImageUrl != value)
    {
        prop_expandedImageUrl 
= value;
        
if (g_bCreated)
        {
            modifyNodesInheritingFromRoot(contentNode, 
"expandedimageurl", value);
            _tvpropExpandedImageUrl.fireChange();
        }
    }
}
   
function getTarget()
{
    
return prop_target;
}

function setTarget(value)
{
    
if (prop_target != value)
    {
        prop_target 
= value;
        
if (g_bCreated)
        {
            modifyNodesInheritingFromRoot(contentNode, 
"target", value);
            _tvpropTarget.fireChange();
        }
    }
}

function getTreeNodeSrc()
{
    
return prop_treeNodeSrc;
}

function setTreeNodeSrc(value)
{
    
if (prop_treeNodeSrc != value)
    {
        prop_treeNodeSrc 
= value;
        _tvpropTreeNodeSrc.fireChange();
    }
}

function getTreeNodeXsltSrc()
{
    
return prop_treeNodeXsltSrc;
}

function setTreeNodeXsltSrc(value)
{
    
if (prop_treeNodeXsltSrc != value)
    {
        prop_treeNodeXsltSrc 
= value;
        _tvpropTreeNodeXsltSrc.fireChange();
    }
}

function getSelectExpands()
{
    
return prop_selectExpands;
}

function setSelectExpands(value)
{
    
var boolval = makeBoolean(value)
    
if (boolval != null && boolval != prop_selectExpands)
    {
        prop_selectExpands 
= value;
        
if (g_bCreated)
            _tvpropSelectExpands.fireChange();
    }
}

function getExpandLevel()
{
    
return prop_expandLevel;
}

function setExpandLevel(value)
{
    
if (prop_expandLevel != value)
    {
        prop_expandLevel 
= value - 0;
        
if (g_bCreated)
        {
            expandNodes(contentNode, value);
            _tvpropExpandLevel.fireChange();
        }
    }
}

function getAutoSelect()
{
    
return prop_autoSelect;
}

function setAutoSelect(value)
{
    
var boolval = makeBoolean(value)
    
if (boolval != null && boolval != prop_autoSelect)
    {
        prop_autoSelect 
= value;
        
if (g_bCreated)
            _tvpropAutoSelect.fireChange();
    }
}

function getTreeNodeTypeSrc()
{
    
return prop_treeNodeTypeSrc;
}

function setTreeNodeTypeSrc(value)
{
    
if (prop_treeNodeTypeSrc != value)
    {
        prop_treeNodeTypeSrc 
= value;
        
if (g_bCreated)
        {
            _tvpropTreeNodeTypeSrc.fireChange();
        }
    }
}

function getShowLines()
{
    
return prop_showLines;
}

function setShowLines(value)
{
    
var boolval = makeBoolean(value);
    
if (prop_showLines != boolval && boolval != null)
    {
        prop_showLines 
= boolval;
        
if (g_bCreated)
        {
            buildTreeFromRoot();
            _tvpropShowLines.fireChange();
        }
    }
}

function getShowPlus()
{
    
return prop_showPlus;
}

function setShowPlus(value)
{
    
var boolval = makeBoolean(value);
    
if (prop_showPlus != boolval && boolval != null)
    {
        prop_showPlus 
= boolval;
        
if (g_bCreated)
        {
            modifyNodesByType(contentNode, 
null"_showplus");
            _tvpropShowPlus.fireChange();
        }
    }
}

function getShowToolTip()
{
    
return prop_showToolTip;
}

function setShowToolTip(value)
{
    
var boolval = makeBoolean(value);
    
if (prop_showToolTip != boolval && boolval != null)
    {
        prop_showToolTip 
= boolval;
        
if (g_bCreated)
        {
            _tvpropShowToolTip.fireChange();
        }
    }
}

function getIndent()
{
    
return prop_indent;
}

function setIndent(value)
{
    
if (prop_indent != value)
    {
        
if (typeof value == "string")
        {
            
var i = parseInt(value);
            
if (i == NaN)
                
return;
            
else
                prop_indent 
= i;       
        }
        
else if (typeof value == "number")
            prop_indent 
= value;
        
else
            
return;
        
if (g_bCreated)
        {
            
if (getShowLines() != true)
                modifyNodesByType(contentNode, 
null"_indent");
            _tvpropShowLines.fireChange();
        }
    }
}

function getSelectedNodeIndex()
{
    
return prop_selectedNodeIndex;
}

function setSelectedNodeIndex(value)
{
    
if (prop_selectedNodeIndex != value && typeof value == "string")
    {
        
// validate format of string
        if (value.length == 0)
            
return;
        
        
if (value.search(/[^0-9.]/!= -1)    // a character other than a digit or .
            return;

        
if (value[0== '.')     // mustn't begin with a .
            return;

        
if (value.indexOf(".."!= -1)   // mustn't have two consecutive periods
            return;
            
        
if (g_bCreated)
        {
            
// does a node exist at this index?
            var node = getNodeFromIndex(value);
            
if (node != null && node.subtree != null)
            {
                selectNode(node);
                _tvpropSelectedNodeIndex.fireChange();
            }
            
else
            {
                
// Set index to 0, if possible
                if (value != "0")
                    selectedNodeIndex 
= "0";
                
else
                    prop_selectedNodeIndex 
= "";
            }
        }
        
else
            prop_selectedNodeIndex 
= value;
    }
}

function getSystemImagesPath()
{
    
return prop_systemImagesPath;
}

function setSystemImagesPath(value)
{
    
if (prop_systemImagesPath != value && typeof value == "string")
    {
        prop_systemImagesPath 
= value;
        
if (g_bCreated)
        {
            buildTreeFromRoot();
            _tvpropSystemImagesPath.fireChange();
        }
    }
}

//
//
 expandNodes()
//
//
 Recursively expand all nodes from root down through the given
//
 number of levels
//
//
 root: starting node
//
 level: number of levels to expand
//
function expandNodes(root, level)
{
    
if (root != contentNode)
    {
        
var exp = root.getAttribute("expanded");
        
if (exp != true)
        {
            doNodePlusMinusClick(root);
        }
    }
    
if (level > 0)
    {
        
var col = root.children.tags("treenode");
        
for (var i = 0; i < col.length; i++)
        {
            expandNodes(col[i], level 
- 1);
        }
    }
}

//
//
 databind()
//
//
 Force the tree to rebind
//
function databind()
{
    
if (g_typesNode == null)
        g_typesNode 
= element.document.createElement("DIV");

    g_typesNode.innerHTML 
= getNodeTypeHtml();                        
    element.nodeTypes 
= g_typesNode.children.tags("TREENODETYPE");
    treeviewNode.subtree.removeNode(
true);
    contentNode.innerText 
= "";
    databindNode(element);
}

//
//
 getTreeNodeType()
//
//
 Retrieves a public object representing the treenodetype at the requested index or
//
  with the requested name
//
//
 key: string name or integer index of type to get
//
function getTreeNodeType(key)
{
    
var tnt = null;
    
var len = element.nodeTypes.length;
    
    
if (typeof key == "number")
    {
        
if (key >= 0 && key < len)
            tnt 
= element.nodeTypes[key];
    }
    
else
    {
        
for (var i = 0; i < len; i++)
        {
            
var temp = element.nodeTypes[i];
            
if (temp.getAttribute("Type"== key)
            {
                tnt 
= temp;
                
break;
            }
        }
    }
    
    
if (tnt != null)
        
return private_getTreeNodeType(tnt);
    
else
        
return null;
}

//
//
 createTreeNodeType()
//
//
 Create a new treenodetype in the ether
//
function createTreeNodeType()
{
    
var realtnt = element.document.createElement("treenodetype");
    
return private_getTreeNodeType(realtnt);
}

//
//
 private_getTreeNodeType()
//
//
 Returns a public object representing the given treenodetype
//
//
 tnt: treenodetype for which to generate a public object
//
function private_getTreeNodeType(tnt)
{
    
var obj = new Object();
    
    obj.addTo 
= function(tree)
    {
        
if (tree.nodeTypes == null || tree.nodeTypes.length == 0)
        {
            g_typesNode 
= element.document.createElement("DIV");
            g_typesNode.appendChild(tnt); 
            tree.nodeTypes 
= g_typesNode.children.tags("TREENODETYPE");
        }
        
else
        {
            g_typesNode.appendChild(tnt);
            tree.nodeTypes 
= g_typesNode.children.tags("TREENODETYPE");
        }            
        modifyNodesByType(contentNode, tnt.getAttribute(
"type"), "type");
    }
    obj.remove 
= function(bRedraw) { private_removeTreeNodeType(tnt, bRedraw); };
    obj.getAttribute 
= function(name) { return private_getNodeTypeAttribute(tnt, name); };
    obj.setAttribute 
= function(name, value) { private_setNodeTypeAttribute(tnt, name, value); };
    
    
return obj;
}

//
//
 addTreeNodeType()
//
//
 Add the given treenodetype to the end of the tree's nodetypes collection
//
//
 tnt: treenodetype to add
//
function addTreeNodeType(tnt)
{
    tnt.addTo(element);
}

//
//
 private_removeTreeNodeType()
//
//
 Remove the treenodetype from the tree.  Note that redrawing nodes of this type
//
 requires a full tree traversal, which can be very slow.
//
//
 tnt: type to remove
//
 bRedraw: Redraw nodes of this type?
//
function private_removeTreeNodeType(tnt, bRedraw)
{
    
var name = tnt.getAttribute("Type");
    
    tnt.removeNode(
false);
    
    
if (bRedraw != false)
    {
        
// Because indices may have shifted, we'll need to rebuild the tree.
        modifyNodesByType(contentNode, null"type");
    }
    
else
    {
        
// uncache the nodetypeIndex of all nodes
        modifyNodesByType(contentNode, null"_nodetypeIndex");
    }
}

//
//
 modifyNodesByType()
//
//
 Rebuild all nodes of the given type
//
//
 node: current node
//
 type: name of type; if null, rebuild all nodes
//
 att: attribute of node being modified (in lower case)
//
function modifyNodesByType(node, type, att)
{
    
if (node != contentNode)
    {
        
if (node.subtree == null// if the node hasn't been built yet, don't go any further
            return;
        
        
if (type == null || getNodeAttribute(node, "Type"== type)
        {
            modifyNode(node, att, 
null, type);
            
if (att == "type" || att == "childtype")
                
return// these atts already handle the node's children
        }
    }
    
var col = node.children.tags("treenode");
    
for (var i = 0; i < col.length; i++)
    {
        modifyNodesByType(col[i], type, att);
    }
}

//
//
 modifyNodesInheritingFromRoot()
//
//
 Searches the tree from the given node downward for all nodes which
//
 inherited the given attribute from the root, rebuilding the appropriate
//
 aspect of such nodes.  This function is called when an inheritable attribute
//
 is changed on the TreeView itself.
//
//
 root: starting node of search
//
 att: attribute to check
//
 value: new value of attribute
//
function modifyNodesInheritingFromRoot(root, att, value)
{
    
if (root != contentNode)
    {
        
if (root.subtree == null)
            
return;
            
        
if (inheritsFromRoot(root, att))
        {
            modifyNode(root, att, value, 
null);
            
if (att == "type" || att == "childtype")
                
return// these atts already handle the node's children
        }
    }
    
var col = root.children.tags("treenode");
    
for (var i = 0; i < col.length; i++)
    {
        modifyNodesInheritingFromRoot(col[i], att, value);
    }
}

//
//
 inheritsFromRoot()
//
//
 Determines if the given node inherits its att value from the TreeView
//
//
 node: node to check
//
 att: att to check
//
function inheritsFromRoot(node, att)
{
    
// try the node
    if (node.getAttribute(att) != null)
        
return false;
        
    
// try the node's type
    if (getNodeTypeAttribute(node, att) != null)
        
return false;
        
    
return true;
}          

//
//
 private_getNodeTypeAttribute()
//
//
 Gets the given attribute from the given node
//
//
 tnt: treenodetype from which to retrieve attribute
//
 name: name of attribute to retrieve
//
function private_getNodeTypeAttribute(tnt, name)
{
    
return tnt.getAttribute(name.toLowerCase());
}

//
//
 private_setNodeTypeAttribute()
//
//
 Sets the given attribute on the given node
//
//
 tnt: treenodetype on which to set attribute
//
 name: name of attribute to set
//
 value: value of attribute to set
//
function private_setNodeTypeAttribute(tnt, name, value)
{
    
var lname = name.toLowerCase();
    
if (lname == "outerhtml")
        
return;
        
    
var old = tnt.getAttribute(name, value);
    
    tnt.setAttribute(name, value, 
0);
    
if (tnt.parentElement == null)
        
return;
        
    
// Update display tree if display-related change was made
    switch (lname)
    {
        
case "text":            
        
case "innertext":
            
break;
        
        
case "expandable":
            
if (verifyExpandableValue(value) == true)
                modifyNodesByType(contentNode, tnt.getAttribute(
"type"), lname);
            
else
                tnt.setAttribute(name, old, 
0);
            
break;

        
default:
            modifyNodesByType(contentNode, tnt.getAttribute(
"type"), lname);
            
break;
    }

            
//
//
 createTreeNode()
//
//
 Creates a new treenode in the ether
//
function createTreeNode()
{
    
var realNode = element.document.createElement("treenode");
    
return private_getTreeNode(realNode);
}

//
//
 getTreeNode()
//
//
 Retrieves a public object representing the node at the requested index
//
//
 index: dot-separated index string of node to retrieve
//
function getTreeNode(index)
{
    
var node = getNodeFromIndex(index);
    
if (node == null)
        
return null;
    
    
return private_getTreeNode(node);
}

//
//
 private_getTreeNode()
//
//
 Retrieves a public object representing the given node
//
//
 node: treenode to munge into public object
//
function private_getTreeNode(node)
{
    
var obj = new Object();
    
    obj.addAt 
= function(index, newnode)
    {
        
if (newnode._real != null)
            private_addAt(node, index, newnode._real);
        
else
        {
            
var temp = private_getTreeNode(node);
            temp._real 
= node;
            newnode.addTo(index, temp);
        }
    };
    obj.addTo 
= function(index, parent)
    {
        
if (parent._real != null)
            private_addAt(parent._real, index, node);
        
else
        {
            
var temp = private_getTreeNode(node);
            temp._real 
= node;
            parent.addAt(index, temp);
        }
    };
    obj.add 
= function(newnode) { obj.addAt(node.children.tags("treenode").length, newnode); }; 
    obj.remove 
= function() { private_remove(node); };
    obj.databind 
= function() { private_databind(node); };
    obj.getAttribute 
= function(name) { return private_getAttribute(node, name); };
    obj.setAttribute 
= function(name, value) { private_setAttribute(node, name, value); };
    obj._real 
= null;
    obj.findAttribute 
= function(name) { return getNodeAttribute(node, name); };
    obj.getNodeIndex 
= function()
    {
        
var index = getNodeIndex(node);
        
if (index == "")
            
return null;
        
return index;
    };
    obj.getParent 
= function()
    {
        
if (node.parentElement == null || node.parentElement.tagName.toLowerCase() != "treenode")
            
return null;
        
else
            
return private_getTreeNode(node.parentElement);
    }; 
    obj.getChildren 
= function() { return private_getChildren(node); };
    
    
return obj;
}

//
//
 addAt()
//
//
 Add a root node at the given index.  TreeView method.
//
//
 index: integer index at which to add the node
//
 node: node to add
//
function addAt(index, node)
{
    node.addTo(index, private_getTreeNode(contentNode));
}

//
//
 add()
//
//
 Add a root node to the end of the tree.  TreeView method.
//
//
 node: node to add
//
function add(node)
{
    node.addTo(contentNode.children.tags(
"treenode").length, private_getTreeNode(contentNode));
}

//
//
 private_addAt()
//
//
 Implements addition of a node to the tree
//
//
 parent: node to add a child to
//
 index: integer index at which to add a child node
//
 child: node to add
//
function private_addAt(parent, index, child)
{
    
if (child.parentElement != null)
        
return;
        
    
var col = parent.children.tags("treenode");
    
var iCount = col.length;
    
    
if (index < 0 || index > iCount)
        
return;
  
    
var selectedNode = getNodeFromIndex(selectedNodeIndex);
    
    
//
    // add node to tree
    //
    if (index == iCount)
        parent.appendChild(child);
    
else
    {
        col[index].insertAdjacentElement(
"beforeBegin", child);
    }

    
//
    // adjust sibling indices
    //
    child.sibIndex = index;
    
for (var i = index; i <= iCount; i++)
        col[i].sibIndex 
= i;

    
//
    // adjust selected index if necessary
    //
    if (selectedNode != null && index < selectedNode.sibIndex)
        prop_selectedNodeIndex 
= getNodeIndex(selectedNode);
        
    
//
    // update display tree if the node is now part of a treeview and its parent or previous sibling is expanded
    //
    var p = parent;
    
while (p != null && p.tagName.toLowerCase() == "treenode")
        p 
= p.parentElement;
    
if (p != null && p.tagName.toLowerCase() != "treeview")
        
return;
    
if (parent.getAttribute("expanded"== true || parent == contentNode)
    {
        
// build added node's display tree
        var disptree = buildTree(child, getNodeLevel(child));
        
if (index == iCount)
        {
            
if (parent.subtree == null)
            {
                
if (parent == contentNode)
                    tryToBuildTreeFromRoot();
                
else
                    parent.subtree 
= disptree;
            }
            
else
            {
                
if (parent == contentNode)
                    treeviewNode.subtree.appendChild(disptree);
                
else
                    parent.subtree.appendChild(disptree);
            }
        }
        
else
            col[index 
+ 1].subtree.insertAdjacentElement("beforeBegin", disptree);
            
        
if (element.getAttribute("showlines"!= false && index > 0 && col[index - 1].getAttribute("expanded"== true)
        {
            
// rebuild previous sibling's display tree, to show correct lines.
            buildTree(col[index - 1], getNodeLevel(col[index - 1]));
            
// if that tree contains the selected node, redisplay the selection
            if (selectedNodeIndex.indexOf(getNodeIndex(col[index - 1])) == 0)
                reselectNode(getNodeFromIndex(selectedNodeIndex));
        }
    }
    
    
//
    // Update the junctions of the nodes immediately above and below this node, if needed
    //
    if (iCount == 0)                                // parent's first child
    {
        
if (parent != contentNode)
            replaceJunctionNode(parent);
    }
    
else if (index == iCount)                       // new last sibling
        replaceJunctionNode(col[index - 1]);
    
else if (index == 0)
        replaceJunctionNode(col[
1]);                // new first sibling
    
    
if (selectedNode != null)
        prop_selectedNodeIndex 
= getNodeIndex(selectedNode);
    
else
        selectNode(child);
}

//
//
 private_remove()
//
//
 Remove the given node from the tree
//
//
 node: node to remove
//
function private_remove(node)
{
    
if (node.parentElement == null)
        
return null;
    
    
var parent = node.parentElement;
    
var col = parent.children.tags("treenode");
    
var iCount = col.length;
    
var sibindex = node.sibIndex;
    
var selectedNode = getNodeFromIndex(selectedNodeIndex);
    
var nodeIndex = getNodeIndex(node);
    
    node.subtree.removeNode(
true);
    node.subtree 
= null;
    node.removeNode(
true);
    node.removeAttribute(
"sibIndex");
    
if (node.getAttribute("expanded"== false)
        node._buildChildren 
= true// set expando so we'll rebuild the node's children if the node is added again and then expanded
     
    
//
    // adjust junctions and whitespace/lines
    //        
    if (iCount == 1)
        replaceJunctionNode(parent);
    
else if (sibindex != 0 && sibindex == iCount - 1)
        buildTree(col[sibindex 
- 1], getNodeLevel(col[sibindex - 1])); // rebuild previous sibling and its subtree
    else if (sibindex == 0 && parent.tagName.toLowerCase() != "treenode")
        replaceJunctionNode(col[
0]); // new first root
    
    
//
    // adjust sibling indices
    //
    for (var i = sibindex; i < col.length; i++)
        col[i].sibIndex 
= i;       

    
//
    // adjust selectedNodeIndex
    //
    if (node == selectedNode ||
     (selectedNodeIndex.length 
> nodeIndex.length && selectedNodeIndex.substr(0, nodeIndex.length + 1== nodeIndex + "."))
    {
        
// deleted the selected node or an ancestor of the selected node.
        var temp = prop_selectedNodeIndex;
        prop_selectedNodeIndex 
= "";
        
if (iCount - 1 > sibindex)
            selectNode(col[sibindex]);          
// the node now at the same index as the deleted node
        else if (iCount > 1 && sibindex > 0)
            selectNode(col[sibindex 
- 1]);      // the first sibling prior to the deleted node
        else if (nodeIndex != "0")
            selectNode(parent);                 
// the parent of the deleted node
        else
        {
            prop_selectedNodeIndex 
= temp;
            selectNode(
null);
        }
    }
    
else
    {
        
// adjust the selected node index to reflect new tree structure
        prop_selectedNodeIndex = "";
        selectNode(selectedNode);
    }
    
return node;
}

//
//
 private_databind()
//
//
 node: node to bind
//
function private_databind(node)
{
    
// If the selection is within the subtree under the node being databound,
    // then select the node.
    var dataNodeIndex = getNodeIndex(node);
    
if ((dataNodeIndex != selectedNodeIndex) && (selectedNodeIndex.indexOf(dataNodeIndex) == 0))
        selectNode(node);
    
    
// delete all treenode content
    col = node.children.tags("treenode");
    
for (var i = col.length - 1; i >= 0; i--)
    {
        
if (col[i].subtree != null)
            col[i].subtree.removeNode(
true);
        col[i].removeNode(
true);
    }
    node._bound 
= null;
    databindNode(node);
}

//
//
 private_getAttribute()
//
//
 Gets the given attribute from the given node
//
//
 node: node from which to retrieve attribute
//
 name: name of attribute to retrieve
//
function private_getAttribute(node, name)
{
    
var lcName = name.toLowerCase();
    
var ret = node.getAttribute(lcName);
    
if (ret == null && lcName == "text")
    {
        
var textnode = node.subtree.all.item("_tntext"0);
        ret 
= textnode.innerText;
    }
    
return ret;
}

//
//
 private_setAttribute()
//
//
 Sets the given attribute on the given node
//
//
 node: node on which to set attribute
//
 name: name of attribute to set
//
 value: value of attribute to set
//
function private_setAttribute(node, name, value)
{
    
var lname = name.toLowerCase();
    
if (lname == "outerhtml")
        
return;
        
    
var old = node.getAttribute(name, value);
    
    node.setAttribute(name, value, 
0);
    
if (node.parentElement == null)
        
return;
        
    
if (node.subtree == null)
        
return;

    modifyNode(node, lname, value, old);        
}

//
//
 getChildren()
//
//
 public entry point for private_getChildren()
//
function getChildren()
{
    
return private_getChildren(contentNode);
}

//
//
 private_getChildren()
//
//
 Returns an array of public treenode objects representing the top-level children of the given root
//
//
 root: DOM object parent from which to get children
//
function private_getChildren(root)
{
    
var col = root.children.tags("treenode");
    
var objArray = new Array(col.length);
    
for (var iNode = 0; iNode < col.length; iNode++)
    {
        objArray[iNode] 
= private_getTreeNode(col[iNode]);
    }
    
return objArray;
}

//
//
 modifyNode()
//
//
 Rebuild display node as required by change to given attribute
//
//
 node: node to modify
//
 lname: name of changed attribute, in lower case
//
 value: new value of attribute
//
 old: old value of attribute
//
function modifyNode(node, lname, value, old)
{
    
// Update display tree if display-related change was made
    switch (lname)
    {
        
case "defaultstyle":
        
case "hoverstyle":
        
case "selectedstyle":
        
case "style":
            
var oItem = node.subtree.all.item("_tntext"0);
            
var stylename = oItem.className;
            
if (stylename == "")
                stylename 
= "defaultstyle";
            SetAnchorClass(oItem, stylename); 
// reapply current style
            if (!g_bFocus && (stylename == "selectedstyle"))
            {
                blurFilter(oItem);
            }
            
break;
            
        
case "text":
        
case "innertext":
        
case "innerhtml":
            
var tntext = node.subtree.all.item("_tntext"0);          
            
var newText = generateTextNode(node);
            tntext.replaceNode(newText);
            
var accessAnchor = node.subtree.all.item("_tnaccess"0);
            
if (accessAnchor.getAttribute("title"!= "")
                accessAnchor.title 
= newText.innerText + " : " + L_strToolTip_Text;
            
            reselectNode(node);                
            
break;

        
case "imageurl":
            
if (selectedNodeIndex == getNodeIndex(node))
            {
                
if (getNodeAttribute(node, "selectedImageUrl"== null)
                    changeIcon(node, lname);
            }
            
else if (node.getAttribute("Expanded"== true)
                changeIcon(node, 
"expandedimageurl");  // let changeIcon function figure things out
            else
                changeIcon(node, lname);
            
break;
        
case "selectedimageurl":          
            
if (selectedNodeIndex == getNodeIndex(node))
                changeIcon(node, lname);
            
break;
        
case "expandedimageurl":
            
if (node.getAttribute("Expanded"== true && (selectedNodeIndex != getNodeIndex(node) || getNodeAttribute(node, "selectedImageUrl"== null))
                changeIcon(node, lname);
            
break;
            
        
case "type":
            
// the new type could contain a new childType, so rebuild the whole subtree
            buildTree(node, getNodeLevel(node));
            
var temp = getNodeFromIndex(selectedNodeIndex);
            prop_selectedNodeIndex 
= "";
            selectNode(temp);
            
break;
            
        
case "childtype":
            
var col = node.children.tags("treenode");
            
for (i = 0; i < col.length; i++)
            {
                buildTree(col[i], getNodeLevel(col[i]));
                
var temp = getNodeFromIndex(selectedNodeIndex);
                prop_selectedNodeIndex 
= "";
                selectNode(temp);
            }
            
break;
            
        
case "target":
            
var accessnode = node.subtree.all("_tnaccess"0);
            accessnode.target 
= getNodeAttribute(node, lname);
            accessnode.parentElement.target 
= accessnode.target;
            
break;
        
case "navigateurl":
            
var accessnode = node.subtree.all("_tnaccess"0);
            
var url = getNodeAttribute(node, lname);
            
if (url == "" || url == null)
            {
                accessnode.removeAttribute(
"href");
                accessnode.parentElement.removeAttribute(
"href");
                
if (url == "")
                    node.removeAttribute(
"navigateUrl");
            }
            
else
            {
                accessnode.href 
= getNodeAttribute(node, lname);
                accessnode.parentElement.href 
= accessnode.href;
            }
            
break;
            
        
case "expandable":
            
if (verifyExpandableValue(value) == true)
                replaceJunctionNode(node);
            
else
                node.setAttribute(lname, old, 
0);
            
break;
            
        
case "expanded":
            
if (verifyBooleanAttribute(node, lname) == false)
                node.setAttribute(lname, old, 
0);
            
else if (node.getAttribute(lname) != old)
            {
                node.setAttribute(
"expanded"!node.getAttribute("expanded"), 0);
                doNodePlusMinusClick(node);
            }
            
break;
            
        
case "checked":
            
if (verifyBooleanAttribute(node, lname) == false)
                node.setAttribute(lname, old, 
0);
            
else if (getNodeAttribute(node, "checkBox"== true && node.getAttribute(lname) != old)
            {
                
var cb = node.subtree.all.item("_cb"0);
                cb.setAttribute(
"checked", node.getAttribute(lname), 0);
            }
            
break;                
                
        
case "checkbox":
            
if (verifyBooleanAttribute(node, lname) == false && node.getAttribute(lname) != null)
                node.setAttribute(lname, old, 
0);
            
else if (getNodeAttribute(node, "checkbox"== true)
            {
                
if (old != true)
                {
                    
var jn = node.subtree.all("junction"0);
                    
if (jn)
                    {
                        
var cb = createCheckBox(node);
                        jn.parentElement.insertAdjacentElement(
"afterEnd", cb);
                    }
                }
            }
            
else
            {
                
var cb = node.subtree.all("_fcb"0);
                
if (cb)
                    cb.removeNode(
true);
            }
            
break;
        
        
case "treenodesrc":
        
case "treenodexsltsrc":
            
if (value != null)
            {
                node.setAttribute(
"checkedExpandable"false0);
                node._bound 
= null;
            }
            
break;
        
        
case "_showplus":   // not a real attribute-- back door for TreeView
            replaceJunctionNode(node);
            
break;                      
            
        
case "_indent":     // not a real attribute-- back door for TreeView
            var strIndex = getNodeIndex(node);
            
if (strIndex.indexOf("."!= -1)
            {
                
if (isRtl())
                    node.subtree.style.marginRight 
= prop_indent;
                
else
                    node.subtree.style.marginLeft 
= prop_indent;
            }
            
break;
            
        
case "_nodetypeIndex"// not a real attribute-- back door for TreeView
            node.nodetypeIndex = undefined;
            node.inheritedType 
= undefined;
            
break;
            
    }
}
            
//
//
 Cleans up the OnStop events left over from previous postbacks
//
function f_CleanupEvents()
{
    
var eventArray = window.__treeviewAttachedEvents;

    
if ((eventArray != null&& (eventArray[0]))
    {
        
var newArray = new Array(false);

        
// First array element is the dirty bit
        for (var i = 1; i < eventArray.length; i++)
        {
            
if (element.document.all[eventArray[i][0]] == null)
            {
                element.document.detachEvent(
"onstop", eventArray[i][1]);
            }
            
else
            {
                newArray 
= newArray.concat(new Array(eventArray[i]));
            }
        }

        window.__treeviewAttachedEvents 
= newArray;
    }
}

//
//
 Adds an OnStop event
//
function f_AddStopEvent()
{
    
var eventArray = window.__treeviewAttachedEvents;
    
if (eventArray == null)
    {
        eventArray 
= new Array(false);
    }

    element.document.attachEvent(
"onstop", onstop);
    eventArray[
0= true;
    entry 
= new Array(element.uniqueID, onstop);
    window.__treeviewAttachedEvents 
= eventArray.concat(new Array(entry));
}

//
//
 Responds to onscroll
//
function onScroll()
{
    setHiddenHelperValue();
}

//
//
 isRtl()
//
//
 true if we're rendering right to left; false otherwise
//
function isRtl()
{
    
if (element.currentStyle.direction.toLowerCase() == "rtl" || element.dir.toLowerCase() == "rtl")
        
return true;
    
else
        
return false;
}

//
//
 Visually refreshes the TreeView (workaround for IE 5.5 refresh bug)
//
function doVisualRefresh()
{
    
var display = element.style.display;
    element.style.display 
= "none";
    element.style.display 
= display;
}

</script>
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

双tableview连动效果实现

双tableview连动。

城市的连动效果

  • 2013-04-24 20:40
  • 983B
  • 下载

TreeView的CheckBox实现

  • 2008-07-25 11:03
  • 56KB
  • 下载

实现标题栏与viewPager的连动

实现标题栏与viewPager的连动

如何进行js动态生成option?如何实现二级连动?

何为二级连动?首先要明白什么是二级连动!顾名思义,就是一个动,另外一个也跟着一起动看下面的例子:这里有一个“市级”的选择列表框,还有一个“县级”的选择列表框,如果“市级”的选择列表框中的值发现变化,那...

JS+XML实现省市县三级连动

JS实现类 var provincesNode, citysNode; window.onload = function() {     // 获取xml doc 对象     var xmlDoc...

js 实现年月日连动

  • 2013-05-02 14:59
  • 880B
  • 下载

Asp.net TreeView异步加载数据,并结合checkbox实现多选删除

JS:         void PopulateNode(Object sender, TreeNodeEventArgs e)    &#...

Android spinner三级连动菜单实现核心代码

“` package com.l000phone.day05_spinnerexercise3;import java.util.LinkedHashSet; import java.util.L...

C# 中TreeView 控件实现点击CheckBoX自动打钩的事件

自己想要做一个TreeView,点击节点的CheckBox能让其子节点及父节点做出相应的事件。也不知道是不是自己的搜索方式不对,只能找到个近似的框架,通过自己修改以达到自己的要求。现将自己的需求及代码...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)