/**
 * HierarchyTreeNode
 */
function HierarchyTreeNode(id, parent, text, iconClass)
{
  this.id = id;
  this.parent = parent;
  this.childNodes = new Array();
  this.collapsed = false;
  this.text = text;
  this.iconClass = null;
  if (iconClass)
    this.iconClass = iconClass;
  this.elementHovered = null;
  
  this.bStateMutex = false;
  this.bShowIcon = true;
  this.bReadOnly = false;
  this.bDisabled = false;
  
  if (parent != null)
    this.parent.childNodes.push( this );
}
HierarchyTreeNode.prototype.setStateTextOnly = function()
{
  this.bStateMutex = true;
  this.bShowIcon = false;
}
HierarchyTreeNode.prototype.setStateDisabled = function(bValue)
{
  this.bDisabled = bValue;
}
HierarchyTreeNode.prototype.getDisabled = function()
{
  return this.bDisabled;
}
HierarchyTreeNode.prototype.setStateReadOnly = function(bValue)
{
  this.bReadOnly = bValue;
}
HierarchyTreeNode.prototype.getId = function()
{
  return this.id;
}
HierarchyTreeNode.prototype.getChildNodes = function()
{
  return this.childNodes;
}
HierarchyTreeNode.prototype.getParent = function()
{
  return this.parent;
}
HierarchyTreeNode.prototype.getCollapsed = function()
{
  return this.collapsed;
}
HierarchyTreeNode.prototype.setCollapsed = function( s )
{
  this.collapsed = s;
}
HierarchyTreeNode.prototype.getText = function()
{
  return this.text;
}
HierarchyTreeNode.prototype.setText = function( t )
{
  this.text = t;
}
HierarchyTreeNode.prototype.getIconClass = function()
{
  return this.iconClass;
}
HierarchyTreeNode.prototype.setIconClass = function( iconClass )
{
  this.iconClass = iconClass;
}
HierarchyTreeNode.prototype.getHierarchyText = function()
{
    var hSeparator = ' / ';
    var hText = this.getText();
    var p = this.getParent();
    
    while(!IsNullOrUndefined(p))
    {
        hText = p.getText() + hSeparator + hText;
        
        p = p.getParent();        
    }
    
    return hText;
}
/**
 * HierarchyTree
 */
function HierarchyTree(id, rootNodeList, nodeMap)
{
  this.id = id;

  this.readOnlyHomeId = null;
  
  this.selectedItemIdList = new Object();
  
  this.idAll = 'All';
  this.idNone = 'None';
  this.idNoChange = 'NoChange';

  this.textAll  = '< All >';
  this.textNone = '< None >';
  this.textNoChange = '< No Change >';
  
  this.enableCheckBox = false;
  this.enableCheckBoxTriState = false;
  
  this.onClickCheckBox = new REvent();

  this.rootNodeList = IsNullOrUndefined(rootNodeList)?new Array():rootNodeList;
  this.nodeMap = IsNullOrUndefined(rootNodeList)?new Object():rootNodeList;
  this.nodeImageMap = new Object();

  this.onClickItem = new REvent();
  this.onExpand    = new REvent();
  this.onCollapse  = new REvent();
  this.onMouseOver = new REvent();
  this.onMouseOut  = new REvent();

  this.onSelectItem = new REvent();
  
  RegisterControl.statics.getInstance().add(this);
}

HierarchyTree.prototype.setReadOnlyHomeId = function(id)
{
  this.readOnlyHomeId = id;
}

HierarchyTree.statics = new Object();

HierarchyTree.prototype.getId = function()
{
  return this.id;
}

HierarchyTree.prototype.getCheckBoxId = function(nodeId)
{
    return this.getId() + "CheckBox" + nodeId;
}

HierarchyTree.prototype.setEnableCheckBox = function( bEnable )
{
  this.enableCheckBox = bEnable;
  
  if(bEnable == true)
  {
    this.onClickItem.addEventListener(new REventListener(HierarchyTree.prototype.onClickItemCheckBoxListener, this));
  }
}

HierarchyTree.prototype.getCheckState = function(checkBox)
{
    var state = null;
    if(!this.enableCheckBoxTriState)
    {
        state = checkBox.checked;
    }
    else 
    {
        var className = checkBox["className"];
        if(className == 'checkDis') 
        {
            state = 'checkDisabled';
        }
        else if(className == 'checkOn') 
        {
            state = true;
        }
        else if(className == 'checkOff') 
        {
            state = false;
        }
    }
    return state;
}

HierarchyTree.prototype.onClickItemCheckBoxListener = function(nodeId,nodeText)
{
    var checkBoxId = this.getCheckBoxId(nodeId);
    var checkBox = $(checkBoxId);
    var state = null;
    if(!this.enableCheckBoxTriState)
    {
        checkBox.checked = !checkBox.checked;
        state = checkBox.checked;
    }
    else 
    {
        var className = checkBox["className"];
        if(className == 'checkDis') 
        {
            state = 'checkDisabled';
            checkBox["className"] = 'checkOn';
        }
        else if(className == 'checkOn') 
        {
            state = true;
            checkBox["className"] = 'checkOff';
        }
        else if(className == 'checkOff') 
        {
            state = false;
            checkBox["className"] = 'checkDis';
        }
    }
    var parent = checkBox.parentNode;
    this.onClickCheckBox.trigger( state, parent.nodeId );//, checkBox.nodeVal );
}

HierarchyTree.prototype.deselectAll = function(ignoreId)
{
    for(var nodeId in this.nodeMap)
    {
        if(nodeId != ignoreId)
        {
            var node = this.nodeMap[nodeId];
            var state = IsNullOrUndefined(this.selectedItemIdList[nodeId])?false:this.selectedItemIdList[nodeId];
            
            if(state) 
            {   
                if(this.enableCheckBox)
                {
                    var checkBoxId = this.getCheckBoxId(nodeId);
                    var checkBox = $(checkBoxId);
    
                    // uncheck checkbox
                    checkBox.checked = false;
               
                    this.onClickCheckBox.trigger( !state, nodeId );
                }
                this.onSelectItem.trigger( !state, nodeId );
            }
        }
    }
}

HierarchyTree.prototype.deselectStateMutexNodes = function(ignoreId)
{
    for(var i = 0; i < this.rootNodeList.length; i++)
    {
        var node = this.rootNodeList[i];
        var nodeId = node.id;
        if(!node.bStateMutex)
        {
            // assumes the only the rootNodeList nodes can be mutex
            break;
        }
        else 
        {
            // deselect nodes
            var state = IsNullOrUndefined(this.selectedItemIdList[nodeId])?false:this.selectedItemIdList[nodeId];
            if(state) 
            {   
                if(this.enableCheckBox)
                {
                    var checkBoxId = this.getCheckBoxId(nodeId);
                    var checkBox = $(checkBoxId);
    
                    // uncheck checkbox
                    checkBox.checked = false;
               
                    this.onClickCheckBox.trigger( !state, nodeId );//, checkBox.nodeVal );
                }
                this.onSelectItem.trigger( !state, nodeId );
            }
        }
    }
}
// event on checkbox dom node
HierarchyTree.statics._clickCheckBox = function( event )
{
    var instance = $I(this.instanceId);
    var state = null;
    var parent = null;
    if(!instance.enableCheckBoxTriState)
    {
        var checkBox = $(this.checkBoxId);
        state = checkBox.checked;
        
        parent = checkBox.parentNode;
    }
    else 
    {
        var checkBox = $(instance.getCheckBoxId(this.nodeId));
        parent = checkBox.parentNode;
    
        var className = checkBox["className"];
        if(className == 'checkDis') 
        {
            state = true;
            checkBox["className"] = 'checkOn';
        }
        else if(className == 'checkOn') 
        {
            state = false;
            checkBox["className"] = 'checkOff';
        }
        else if(className == 'checkOff') 
        {
            state = 'checkDisabled';
            checkBox["className"] = 'checkDis';
        }
    }
    
    if(state && instance.getNode(parent.nodeId).bStateMutex)
    {
        instance.deselectAll(parent.nodeId);
    }
    
    instance.onClickCheckBox.trigger( state, parent.nodeId );//, checkBox.nodeVal );
    
    instance.onSelectItem.trigger( state, parent.nodeId );
}

HierarchyTree.prototype.addCheckBoxToDomNode = function( domNode, nodeId, funcOnClickCheckBox, bReadOnly )
{   
    if(!this.enableCheckBoxTriState && bReadOnly != true)
    {
        // required to get around IE bug.
        // IE does not render checked state
        var checkBoxId = this.getCheckBoxId(nodeId);
        var checkBoxString = new Array();
        checkBoxString[checkBoxString.length] = "<input type='checkbox'";
        checkBoxString[checkBoxString.length] = " id='"+checkBoxId+"'";
        checkBoxString[checkBoxString.length] = " instanceId='"+this.getId()+"'";
        checkBoxString[checkBoxString.length] = " nodeId='"+nodeId+"'";
        // set prechecked items
        if(this.selectedItemIdList[nodeId] == true)
        {
            checkBoxString[checkBoxString.length] = " checked='"+true+"'";
        }
        checkBoxString[checkBoxString.length] = " ></input>";
        
        domNode.innerHTML = checkBoxString.join('');    
        domNode.onclick = funcOnClickCheckBox;    //checkBoxString[checkBoxString.length] = " onclick="+funcOnClickCheckBox;
        domNode.checkBoxId = checkBoxId;
        domNode.instanceId = this.getId();
        domNode.nodeId = nodeId;
    }
    else 
    {
        var checkBoxId = this.getCheckBoxId(nodeId);
        var checkBox = $C('div');
        checkBox.id = checkBoxId;
        checkBox.instanceId = this.getId();
        checkBox.nodeId = nodeId;
        if(this.selectedItemIdList[nodeId] == true)
        {
            checkBox['className'] = 'checkOn';
        }
        else if(this.selectedItemIdList[nodeId] == false)
        {
            checkBox['className'] = 'checkOff';
        }
        else 
        {
            checkBox['className'] = 'checkDis';
        }
        if(bReadOnly != true)
            checkBox.onclick = funcOnClickCheckBox;
        
        //checkBox.style.width = "16px";
        //checkBox.style.height = "16px";

        domNode.appendChild(checkBox);
        domNode.nodeId = nodeId;
    }
}

HierarchyTree.prototype.treeRecurse = function( tbody, parent, prefixList, parentCollapsed, bAddParent )
{
  var nodeList;
  if (IsNullOrUndefined(parent.parent) && bAddParent)
  {
    // root node
    nodeList = new Array();
    nodeList.push( parent );
  }
  else
    nodeList = parent.getChildNodes();

  for (var i = 0, iCnt = nodeList.length; i < iCnt; i++)
  {
    var node = nodeList[ i ];
    var nodeId = node.getId();

    var tr = $C( "tr" );
    tr.id = RegisterControl.statics.encodeId( this, nodeId, "nodeRow" );
    tr.nodeId = nodeId;

    tbody.appendChild( tr );

    var td = $C( "td" );
    tr.appendChild( td );

    var innerTable = $C( "table" );
    td.appendChild( innerTable );

    var innerTbody = $C( "tbody" );
    innerTable.appendChild( innerTbody );

    var innerTr = $C( "tr" );
    innerTbody.appendChild( innerTr );
    
    /*** checkbox as first td ***/
    if(this.enableCheckBox)
    {
        if(this.readOnlyHomeId == nodeId || // home dept
            (node.bReadOnly && this.selectedItemIdList[nodeId] != true) ) // readonly and not selected
        {
            // readonly node
            var tdBlank = $C( "td" );
            tdBlank.style.width = '20px';
            tdBlank.id = this.getCheckBoxId(nodeId);
            
            innerTr.appendChild(tdBlank);
        }
        else 
        {
            var tdCheckBox = $C( "td" );
            tdCheckBox.instanceId = this.getId();
            tdCheckBox.style.width = '20px';
            
            var bReadOnly = (node.bReadOnly && this.selectedItemIdList[nodeId] == true); // readonly and selected
            this.addCheckBoxToDomNode(tdCheckBox, nodeId, HierarchyTree.statics._clickCheckBox, bReadOnly);
            
            innerTr.appendChild(tdCheckBox);
        }
    }
    
    if(this.readOnlyHomeId == nodeId)
    {
        // readonly node
        tr["className"] = "treeNodeReadOnly";
    }
    else if(!this.enableCheckBoxTriState && this.selectedItemIdList[nodeId] == true) 
    {
        if(!this.enableCheckBox)
        {
            // initially set selected style
            tr["className"] = "treeNodeSelect";
        }
    }    

    
    var img = 'E';
    var icon = "ICON";
    var prefixImg = 'E';

    if ( parent && !bAddParent ) // non-root node
    {
      if ( i == (iCnt-1) )
        img = 'NE';
      else
      {
        img = 'NSE';
        prefixImg = 'NS';
      }
    }

    var collapsed = node.getCollapsed() || parentCollapsed;
    if (parentCollapsed && !bAddParent)
      tr.style.display = "none";

    for (var j = 0; j < prefixList.length; j++)
      innerTr.appendChild( prefixList[ j ].cloneNode( true ) );

    if ( node.childNodes.length > 0 )
    {
      // child nodes
      this.nodeImageMap[ nodeId ] = img;

      var suffix;
      if ( node.getCollapsed() )
        suffix = "p";
      else
        suffix = "m";
        
      img += suffix;
      icon += suffix;

      innerTr.appendChild( this.getCellAndImage( img, nodeId ) );
      innerTr.appendChild( this.getCellAndIcon( icon, nodeId ) );

      this.renderNode( innerTr, node );

      prefixList.push( this.getCellAndImage( prefixImg ) );
      this.treeRecurse( tbody, node, prefixList, collapsed );
      prefixList.length--;
    }
    else
    {
      // end leaf node
      innerTr.appendChild( this.getCellAndImage( img, nodeId ) );
      innerTr.appendChild( this.getCellAndIcon( icon, nodeId ) );
      this.renderNode( innerTr, node );
    }
  }
}

// nodeId only use supplied if collapsable
HierarchyTree.prototype.getCellAndImage = function( imageIndex, nodeId )
{
  var td = $C( "td" );

  td["className"] = "HierarchyTree"+imageIndex;
  if ( nodeId )
  {
    td.id = RegisterControl.statics.encodeId(this, nodeId, "nodeExp");
    td.instanceId = this.getId();
      
    td.nodeId = nodeId;
      
    td.onclick = HierarchyTree.statics._toggleCollapse;
  }
  return td;
}

HierarchyTree.prototype.getCellAndIcon = function( imageIndex, nodeId )
{
  if(this.readOnlyHomeId == nodeId) imageIndex = 'Home';

  var node = this.getNode(nodeId);
  var td = $C( "td" );

  if ( imageIndex && node.bShowIcon)
  {
    td.id = RegisterControl.statics.encodeId(this, nodeId, "nodeIcon");
    td["className"] = "HierarchyTree"+imageIndex;
    if(node.getIconClass())
      td["className"] += " " + node.getIconClass();
  }

  return td;
}

HierarchyTree.prototype.getNode = function(id)
{
  return this.nodeMap[id];
}

HierarchyTree.prototype.addTextNodeToTop = function( id, text, iconClass )
{
  // ensure adding only once
  if(IsNullOrUndefined(this.nodeMap[id]))
  {
      var node = new HierarchyTreeNode(id, null, text, iconClass );
      node.setStateTextOnly();
      this.nodeMap[id] = node;
    
      this.rootNodeList.splice(0,0,node);
  }
}

HierarchyTree.prototype.addNode = function( id, parentId, text, iconClass, bReadOnly, bDisabled )
{
  var parent = null;
  if (parentId && this.nodeMap[ parentId ])
    parent = this.nodeMap[ parentId ];
  
  var node = new HierarchyTreeNode(id, parent, text, iconClass );
    
  if(bReadOnly) {
    node.setStateReadOnly(bReadOnly);
  }
  
  if(bDisabled) {
    node.setStateDisabled(bDisabled);
  }
  
  this.nodeMap[id] = node;

  if (!parentId || !this.nodeMap[ parentId ])
    this.rootNodeList[this.rootNodeList.length] = node;
}

HierarchyTree.prototype.appendNode = function( id, text, iconClass )
{
  var node = new HierarchyTreeNode(id, null, text, iconClass );
  this.nodeMap[id] = node;

  this.rootNodeList[this.rootNodeList.length] = node;

  var tbody = $( RegisterControl.statics.encodeId( this, "tree" ) );
  
  this.treeRecurse( tbody, node, new Array(), node.getCollapsed(), true);
  
  return node;
}

HierarchyTree.prototype.removeNode = function( node )
{
  if (node)
  {
    // remove the children
    var childNodes = node.getChildNodes();
    for (var i=0, iCnt=childNodes.length; i<iCnt; i++)
    {
      var childNode = childNodes[i];
      this.removeNode(childNode);
    }

    // remove the node from the root node list if it is there
    for (var j=0; j<this.rootNodeList.length; j++)
    {
      if (this.rootNodeList[j].getId() == node.getId())

      {
        this.rootNodeList.splice(j, 1);
        break;
      }
    }

    // remove the node form the map
    delete this.nodeMap[node.getId()];

    // remove the html for the node
    var row = document.getElementById(RegisterControl.statics.encodeId( this, node.getId(), "nodeRow" ));
    if (row)
      row.parentNode.removeChild(row);
  }
}

HierarchyTree.prototype.setCollapsed = function( id, collapsed )
{
  var node = this.nodeMap[ id ];
  
  if (node.getChildNodes().length == 0)
    return;
  
  node.setCollapsed( collapsed );
  this.setChildrenHidden( node, collapsed );

  var suffix;
  if ( collapsed )
    suffix = "p";
  else
    suffix = "m";

  var td = $( RegisterControl.statics.encodeId( this, id, "nodeExp" ) );
  td["className"] = "HierarchyTree" + this.nodeImageMap[ id ] + suffix;

  var tdIcon = $( RegisterControl.statics.encodeId( this, id, "nodeIcon" ) );
  if (tdIcon)
    tdIcon["className"] = "HierarchyTree" + "ICON" + suffix;

  if (collapsed)
    this.onCollapse.trigger(node);
  else
    this.onExpand.trigger(node);
}

HierarchyTree.prototype.setChildrenHidden = function ( parent, collapsed )
{
  var nodeList = parent.getChildNodes();
  for ( var i = 0; i < nodeList.length; i++ )
  {
    var node = nodeList[i];
    var display = "";
    if ( collapsed )
      display = "none";

    $( RegisterControl.statics.encodeId( this, node.getId(), "nodeRow" ) ).style.display = display;
    
    this.setChildrenHidden( node, collapsed || node.getCollapsed() );
  }
}

HierarchyTree.prototype.attach = function( e )
{
  var table = $C( "table" );
  table["className"] = "hierarchyTreeTable";
  var tbody = $C( "tbody" );
  tbody.id = RegisterControl.statics.encodeId( this, "tree" );
  table.appendChild( tbody );
  e.appendChild( table );
}

HierarchyTree.prototype.addTableCheckBoxAndTextToDomNode = function(domNode, nodeId, nodeText, funcOnClickCheckBox, funcOnClickItem)
{
    var table = $C('table');  
    domNode.appendChild(table);
    
    var tableTbody = $C('tbody');
    table.appendChild(tableTbody);
    
    var tableTr = $C('tr');
    tableTbody.appendChild(tableTr);
    
    if(this.enableCheckBox)
    {
        var tdCheckBox = $C( "td" );
        this.addCheckBoxToDomNode(tdCheckBox, nodeId, funcOnClickCheckBox);
        tableTr.appendChild(tdCheckBox);
    }
    var tableTd = $C('td');
    tableTd.id = RegisterControl.statics.encodeId( this, nodeId, "node" );
    tableTd.instanceId = this.getId();
    tableTd.checkBoxId = this.getCheckBoxId(nodeId);
    tableTd.nodeId = nodeId;
            
    tableTd["className"]  = 'treeNode';
    tableTd.innerHTML     = nodeText;
    tableTd.onmouseover   = HierarchyTree.statics._mouseOver;
    tableTd.onmouseout    = HierarchyTree.statics._mouseOut;
    tableTd.onclick       = funcOnClickItem;

    tableTr.appendChild(tableTd);
}

HierarchyTree.prototype.refresh = function()
{
  var tbody = $( RegisterControl.statics.encodeId( this, "tree" ) );
  
  // clear tbody
  while (tbody.firstChild) 
  {
    //The list is LIVE so it will re-index each call
    tbody.removeChild(tbody.firstChild);
  };

  for(var i=0; i<this.rootNodeList.length; i++)
  {
    // add all root nodes with children
    this.treeRecurse( tbody, this.rootNodeList[i], new Array(), this.rootNodeList[i].getCollapsed(), true);
  }
}

HierarchyTree.prototype.isNodeVisible = function( nodeId )
{
  for ( var node = this.nodeMap[nodeId]; node != null; node = node.getParent() )
    if (node.getCollapsed())
      return false;

  return true;
}

HierarchyTree.statics._clickItem = function()
{
	//Click handler for selecting entries in the tree.
  var instance = $I(this.instanceId);
  var node = instance.getNode(this.nodeId);

  instance.onClickItem.trigger(node.getId(), node.getText());

  var bSelected = instance.selectedItemIdList[node.getId()];
  if(IsNullOrUndefined(bSelected)) bSelected = true; // when undefined, the initial state is assumed 'checkDisabled' or false
  else 
  {
      if(!this.enableCheckBoxTriState)
      {
        bSelected = !bSelected;
      }
      else 
      {
        // tristate
        if(bSelected == true) 
            bSelected = false;
        else if(bSelected == false)
            bSelected = 'checkDisabled';
        else bSelected = true;
      }
  }
  instance.onSelectItem.trigger(bSelected, node.getId());
}

// virtual method
HierarchyTree.prototype.renderNode = function( tr, node )
{
    var td = $C( "td" );
    var nodeText = node.getText()
    if( node.bDisabled )
    {
        nodeText += " (Disabled)";
    }
    td.appendChild( document.createTextNode( nodeText ) );
    td.style.whiteSpace = "nowrap";

    if(node.bReadOnly || node.bDisabled) 
      td.stateDisabled = true;
    else 
      td.stateDisabled = false;
    
    td.id = this.getNodeDomElementId(node);
    td.instanceId = this.getId();
    td.nodeId = node.getId();

    td.onmouseout    = HierarchyTree.statics._mouseOut;
    if(!node.bReadOnly) 
    {
        td.onclick       = HierarchyTree.statics._clickItem;
        td.onmouseover   = HierarchyTree.statics._mouseOver;
    }
    
    this.setMouseOutStyle(td);

    tr.appendChild( td );
}

/**
 * _toggleCollapse
 */
HierarchyTree.statics._toggleCollapse = function() 
{ 
  var instance = $I(this.instanceId);
  var node = instance.getNode(this.nodeId);
  
  // collapse
  instance.setCollapsed( node.getId(), !node.getCollapsed() );
}
HierarchyTree.prototype.toggleCheckBox = function(id)
{
    var checkBox = $(id);
    checkBox.checked = !checkBox.checked;
}

HierarchyTree.prototype.getNodeDomElementId = function(node)
{
  return RegisterControl.statics.encodeId( this, node.getId(), "node" );
}

HierarchyTree.prototype.getNodeDomElement = function(node)
{
  return $(this.getNodeDomElementId(node));
}

/**
 * Mouse Events
 */
HierarchyTree.statics._mouseOver = function()
{
	//Handles general mouse over w/ or w/o a drop object
  var instance = $I(this.instanceId);
  var domElement = $(this.id);
  instance.setMouseOverStyle(domElement);

  var node = instance.getNode(this.nodeId);
  instance.onMouseOver.trigger(node)
}
HierarchyTree.statics._mouseOut = function()
{
  var instance = $I(this.instanceId);
  var domElement = $(this.id);
  instance.setMouseOutStyle(domElement);

  var node = instance.getNode(this.nodeId);
  instance.onMouseOut.trigger(node)
}
HierarchyTree.prototype.setMouseOverStyle = function(domElement)
{
  if(this.elementHovered != null) 
  {
    this.setMouseOutStyle(this.elementHovered);
  }
  this.elementHovered=domElement;
  domElement.className = "treeNodeOver";
}
HierarchyTree.prototype.setMouseOutStyle = function(domElement)
{
  // this.elementHovered (do not set to null)
  domElement.className = "treeNode";
  
  if(domElement.stateDisabled == true)
    domElement.className += " disabled"; 
}

// call after nodemap is set and before refresh()
HierarchyTree.prototype.addNoneOptionToNodeMap = function()
{
  this.addTextNodeToTop(this.idNone, this.textNone);
}
// call after nodemap is set and before refresh()
HierarchyTree.prototype.addAllOptionToNodeMap = function()
{
  this.addTextNodeToTop(this.idAll, this.textAll);
}
// call after nodemap is set and before refresh()
HierarchyTree.prototype.addNoChangeOptionToNodeMap = function()
{
  this.addTextNodeToTop(this.idNoChange, this.textNoChange);
}
HierarchyTree.prototype.setOptionAllText = function( text )
{
    this.textAll = text;
}
HierarchyTree.prototype.setOptionNoneText = function( text )
{
    this.textNone = text;
}
HierarchyTree.prototype.setOptionNoChangeText = function( text )
{
    this.textNoChange = text;
}



/**
 * HierarchyTreeScrollable
 */
subclass(HierarchyTreeScrollable, HierarchyTree);
function HierarchyTreeScrollable(id, rootNodeList, nodeMap)
{
  HierarchyTree.call(this, id);
  
  this.width = '200px';
  this.height = '300px';
  
  this.rootNodeList = rootNodeList;
  this.nodeMap = nodeMap;
  
  this.onSelectItem.addEventListener( new REventListener(HierarchyTreeScrollable.prototype.changeListener, this) );
}
HierarchyTreeScrollable.prototype.setSize = function(width, height)
{
    this.width = width;
    this.height = height;
}
HierarchyTreeScrollable.prototype.attach = function( e )
{
    var div = $C("div");
    div['className']='hierarchyTreeScrollable'; // container for scrollable window
    div.style.width = this.width;
    div.style.height = this.height;
    
    HierarchyTree.prototype.attach.call(this, div);
    e.appendChild(div);
}
HierarchyTreeScrollable.prototype.changeListener = function(bSelected, id)
{
    if(this.readOnlyHomeId == id) return;
    this.selectedItemIdList[id] = bSelected;
    var node = this.getNode(id);
    
    if(bSelected == true && node.bStateMutex) this.deselectAll(id);
    
    // highlight
    var element = $(RegisterControl.statics.encodeId( this, id, "nodeRow" ));
    if(bSelected == true && !this.enableCheckBoxTriState)
    {
        // deselect top elements
        if(!node.bStateMutex)
            this.deselectStateMutexNodes(id);
        
        if(!this.enableCheckBox)
        {
            // initially set selected style
            element["className"] = "treeNodeSelect";
        }
    }
    else 
    {
        element["className"] = "";
    }
}
HierarchyTreeScrollable.prototype.getSelectedItemArray = function()
{
    var selectedItemArray = new Array();
    for(var item in this.selectedItemIdList)
    {
        if(this.selectedItemIdList[item] == true)
            selectedItemArray[selectedItemArray.length] = item;
    }
    
    return selectedItemArray;
}
HierarchyTreeScrollable.prototype.getDeselectedItemArray = function()
{
    var selectedItemArray = new Array();
    for(var item in this.selectedItemIdList)
    {
        if(this.selectedItemIdList[item] == false)
            selectedItemArray[selectedItemArray.length] = item;
    }
    
    return selectedItemArray;
}
HierarchyTreeScrollable.prototype.setSelectedItemArray = function(selectedItemArray)
{
    for(var i=0; i<selectedItemArray.length; i++)
    {
        this.selectedItemIdList[ selectedItemArray[i] ] = true;
    }
}
HierarchyTreeScrollable.prototype.setDeselectedItemArray = function(deselectedItemArray)
{
    for(var i=0; i<deselectedItemArray.length; i++)
    {
        this.selectedItemIdList[ deselectedItemArray[i] ] = false;
    }
}
