/*
*   Menu Builder, an HTML widget generator.
*
* Author:        T. Gochenour
* Date created:  6/2000
* Copyright (c) Peregrine Systems 2000 
* All rights reserved.  Use of this software in whole
* or in part without prior written permission of Peregrine
* Systems is strictly prohibited.
*/

var isNav4, isIE4;
if (parseInt(navigator.appVersion.charAt(0)) >= 4) {
  isNav4 = (navigator.appName == "Netscape") ? true : false;
  isIE4 = (navigator.appName.indexOf("Microsoft") != -1) ? true : false;
}

var m_menu = [];              // Global hashtable of menu object indexed by ID
var m_contentWindow = null;   // Global pointer to secondary window for links


/////// GLOBAL FUNCTIONS /////////
//////////////////////////////////

/**
 *  click - Handle the click of an item
 */
function handleClick(menuID,id,clickedOnText)
{
  var item = m_menu[menuID].getDescendent(id);
  if( item != null )
    item.handleClick(clickedOnText);
  if( m_menu )
	  setTimeout("m_menu["+menuID+"].build()",100);
}

/**
 *  Fetch menu instance from global hastable indexed by ID
 */
function getMenu(menuID)
{
  return m_menu[menuID];
}

function hover(menuID,id,bMouseOver)
{
  var item = m_menu[menuID].getDescendent(id);

  if( item != null )
  {
    item.doHover(bMouseOver);
    if( bMouseOver )
      window.status=item.statusMsg;
    else
      window.status="";
  }
  else
    window.status="";
  return true;
}

/**
 *   Find a span and set it's classname.  NOTE: This is
 *  hardcoded to use getit_header, which keeps this
 *  code from being used elsewhere.
 */
function setCSSClass(strValueID,strCSSClass)
{
  if( ! isIE4 ) {
    return;
  }

  var span = top.getit_header.document.all(strValueID);
  if( span != null )
    span.className = strCSSClass;
}




/////////// ITEM CLASS //////////
/////////////////////////////////
/**
 *  Item Class - Defines the display characteristics of an item
 *
 *  value      - Display string
 *  statusMsg  - Help message for status bar
 *  link       - URL link 
 *  target     - Layer to receive response from URL link
 *  context    - Defines context when this list will be seen
 *  condition  - Defines condition by which this list will be seen
 *  id         - Override default ID generator with 'unique' ID
 *  isSelected - Initialize menu with this item selected.
 */
function Item(value,statusMsg,link,target,context,condition,id,isSelected)
{
  if( value )
  {
    this.id = id || Item.prototype.itemCounter++;  
  }

  this.value =                  value || "";            // Value to display in table cell
  this.statusMsg =              statusMsg || "";        // Help message for status bar
  this.link =                   link || "";             // URL Link to access when item is selected
  this.target =                 target || "self";       // Target frame or window
  this.context =                context || "";          // Only show item when menu context found within this string
  this.condition =              condition || "";        // Only show item when menu condition found within this string
  this.menu =                   null;                   // item belongs to this menu
  this.parent =                 null;                   // Is defined if children are added.
  this.depth =                  -1;                     // Number of parents
  this.initSelected =           isSelected || false;    // Is item initialized as selected ?
}
// Class variables for Item
Item.prototype.class1 =         "Item";
Item.prototype.class2 =         "selectedItem";
Item.prototype.img1 =           m_noselectedIcon;          
Item.prototype.img2 =           m_selectedIcon;
Item.prototype.itemCounter =    0;                      // Generates unique identifier
Item.prototype.tokenMap =       [];                     // Hashmap cache of tokens (key) and their replacement strings (value) 
Item.prototype.goOnEverySelect = true;                  // Does a click on an item alway invoke the URL link?
// Class functions for Item
Item.prototype.build =          _item_build;            // Build HTML section to represent this item
Item.prototype.getCSSClass =    _item_getCSSClass;      // Get the CSS class
Item.prototype.getDepth =       _item_getDepth;         // How deep is the menu, how wide is the table
Item.prototype.getIcon =        _item_getIcon;          // Get this items icon, depending on if it's selected (item) or expanded (folder) 
Item.prototype.getMenu =        _item_getMenu;          // Get this item's root level ancestor.
Item.prototype.getParent =      _item_getParent;        // Get this item's immediate parent
Item.prototype.getToken =       _item_getToken;         // (key) returns value
Item.prototype.getValue =       _item_getValue;         // Returns the value, replacing any tokens contained within.
Item.prototype.getWidth =       _item_getWidth;         // How many rows (self+children) needed for display
Item.prototype.go =             _item_gotoLink;         // Activate URL link
Item.prototype.handleClick =    _item_click;            // User clicked on item
Item.prototype.doHover =        _item_hover;            // Change classname when mouse hovers over item
Item.prototype.isDescendantOf = _item_isDescendantOf;   // (item) Is this item a child of given item
Item.prototype.isInContext =    _item_isInContext;      // Should this item be displayed
Item.prototype.isSelection =    _item_isSelection;      // Is this item currently selected
Item.prototype.replaceTokens =  _item_replaceTokens;    // Search for and replace all key values surrounded by $$() with tokens
Item.prototype.setSelection =   _item_setSelection;     // (item) Set as currently selected item (when collapse is false)
Item.prototype.setDepth =       _item_setDepth;         // Position in menu hierarchy
Item.prototype.setToken =       _item_setToken;         // Define a token and it's replacement string
Item.prototype.log =            _item_log;









//////////// LIST CLASS ////////////
////////////////////////////////////
/**
 *  Class List tracks one collection of elements.
 *               Extends Item class
 *
 *  value      - Display string
 *  statusMsg  - Help message for status bar
 *  link       - URL link 
 *  target     - Layer to receive response from URL link
 *  context    - Defines context when this list will be seen
 *  condition  - Defines condition by which this list will be seen
 *  isExpanded - Is list expanded?
 *  id         - Override default ID generator with 'unique' ID
 */
function List(value,statusMsg,link,target,context,condition,id,isExpanded) 
{
  this.base =                   Item;
  this.base(value,statusMsg,link,target,context,condition,id);
  this.items =                  [];                     // Collection array, one or more items or sublists.
  this.currentSelection =       null;                   // Selected item in list
  this.lastSelection =          null;                   // Reset to last selection when menu.restore is true
  this.expanded =               false;                  // Is this list displayed as expanded

  if( isExpanded )
    this.setExpanded();
}
List.prototype =                new Item;
// Class variables for List
List.prototype.class1 =         "List";
List.prototype.class2 =         "expandedList";
List.prototype.img1 =           m_collapsedIcon;        // overrides Item class
List.prototype.img2 =           m_expandedIcon;         // overrides Item class
List.prototype.treatIconAsText = true;                  // Is a click on the icon treated the same as a click on the text?
// Class functions for List
List.prototype.add =            _list_add;
List.prototype.build =          _list_build;            // Overrides Item class
List.prototype.get =            _list_get;
List.prototype.getSelection =   _list_getSelection;     // Get currently selected item (when collapse is false)
List.prototype.getWidth =       _list_getWidth;         // Overrides Item class
List.prototype.handleClick =    _list_click;            // Overrides Item class
List.prototype.hasChildInContext = _list_hasChildInContext; // Display if at least one child is shown in context or condition
List.prototype.hasVisibleChild = _list_hasVisibleChild; // Test to see if a child item needs to be included in build
List.prototype.isExpanded =     _list_isExpanded;
List.prototype.isVisibleChild = _list_isVisibleChild;   // Is item to be included in build?
List.prototype.setDepth =       _list_setDepth;         // Overrides Item class
List.prototype.setExpanded =    _list_setExpanded;
List.prototype.setSelection =   _list_setSelection;     // Set currently selected item (when collapse is false)









//////////// MENU CLASS ////////////
////////////////////////////////////
/**
 *  Menu Class - Initialize a menu on a client-side HTML page.
 *               Extends List class
 *
 *  layer      - Define the <DIV id="<layer>"> destination for the list.
 *  collapse   - Collapse all but last folder selected
 *  restore    - Restore last selection in folder
 *  indent     - Does the menu ident subitems ?
 *  id         - Override default ID generator with 'unique' ID
 */
function Menu(layer,collapse,restore,indent,id)
{
  this.base =                 List;
  this.base("MENU",null,null,null,null,null,id);
  m_menu[this.id] = this;

  // Instance variables
  this.layer =                layer || "self";
  this.collapse =             collapse || false;        // Collapse previous selection when true
  this.restore =              restore || false;         // Remember last selection in list and restore when re-activated
  this.indent =               (indent==null?true:indent); // Does the menu indent subitems ?
  this.currentContextStr =    "";                       // Current context filter
  this.currentConditionStr =  "";                       // Current condition filter 
  this.currentList =          null;                     // Currently expanded list when in collapse mode
  this.descendents =          [];                       // Hashmap of all items in menu indexed by ID
  this.border =               "0";
  this.doLinks =              true;                     // Turn off to stop URL links from being accessed
}
Menu.prototype=               new List;
Menu.prototype.class1 =         "Menu";
// Class functions for Menu
Menu.prototype.addDescendent = _menu_addDescendent;     // Register all descendents in lookup hashtable
Menu.prototype.build =         _menu_build;             // Overrides Item class
Menu.prototype.getCurrentList = _menu_getCurrentList;   // Get the current expanded list when in autocollapse mode
Menu.prototype.getDescendent = _menu_getDescendent;     // (ID) Lookup item based on ID
Menu.prototype.getMenu =       _menu_getMenu;           // Overrides Item class
Menu.prototype.getTotalDepth = _menu_getTotalDepth;     // Longest path from root to leaf node
Menu.prototype.isInContext =   _menu_isInContext;       // (item) Is item in current context
Menu.prototype.setBorder =     _menu_setBorder;         // (boolean) Set/Clear border display
Menu.prototype.setContext =    _menu_setContext;        // (context,condition) Define the context and condition
Menu.prototype.setCurrentList = _menu_setCurrentList;   // Set the current expanded list when in autocollapse mode
Menu.prototype.setExpanded =   _menu_setExpanded;       // Overrides List class
Menu.prototype.setLinks =      _menu_setLinks;          // (boolean) Turn off link navigation when not connected to Web








/////// MISC OBJECT METHODS ////////
////////////////////////////////////
/**
 *   Get expand/select or collapsed/blank icon
 *   if list/item is current.
 */
function _item_getIcon()
{
	if( this.isSelection && this.isSelection() ||
      this.isExpanded && this.isExpanded() )
		return this.img2;
	return this.img1;
}

/**
 *  Get the CSS class for this item
 */
function _item_getCSSClass()
{
	if( this.isSelection && this.isSelection() ||
      this.isExpanded && this.isExpanded() )
		return this.class2;
	return this.class1;
}

/**
 *  Return the value for this item, replacing any $$() keys with
 *  corresponding token value.
 */
function _item_getValue()
{
  return this.replaceTokens(this.value);
}

/**
 *  Change style and icon when mouse over item
 */
function _item_hover(bMouseOver)
{
  if( bMouseOver )
  {
    if( this.class3 && this.class3 != "" )
    {
      setCSSClass("link"+this.id,this.class3);
    }
  }
  else
  {
    if( this.class3 && this.class3 != "" )
    {
      setCSSClass("link"+this.id,this.getCSSClass());
    }
  }
}


/**
 *
 */
function _item_log(func,str,category)
{
  if( !category )
    category = "general";

  if( str )
    log(category,"<td nowrap>"+this.getValue()+"</td><td nowrap>"+func+"</td><td width=100%>"+str+"</td>" );
  else
    log(category,"<td nowrap>"+this.getValue()+"</td><td>&nbsp;</td><td width=100%>"+func+"</td>" );

}
/** 
 *  Add an item (or sublist) to this list
 *  Call listItem.addItem(new List());
 *  The list can be empty, which will then
 *  be treated as 
 */
function _list_add(item)
{
  if( this != item )
  {
    this.items[this.items.length] = item;
    item.parent = this;
  }
  if( this.getMenu() )
    this.getMenu().addDescendent(item);
  if( item.initSelected )
    this.setSelection(item);
  if( item.getSelection && item.getSelection() != null )
    this.setSelection(item.getSelection);
}

/**
 *  Get the nth item from the list
 */
function _list_get(offset)
{
  if(  this.items[offset] )
    return this.items[offset];
  return null;
}

/**
 *  Return true if the child at the given offset should be displayed. 
 *  Either the list is expanded, or the item is selected, or the item
 *  is a list that contains the selection, or the item is a list that
 *  is currently expanded, or the item is a list that contains the
 *  currently expanded list, or the item is a sibling to the currently
 *  expanded list.
 */
function _list_isVisibleChild(itemsOffset)
{
  var item = this.get(itemsOffset);
  if( ! item.isInContext() )
    return false;
  return( this.isExpanded()
       || this.getSelection() != null 
          && ( this.getSelection() == item
               || this.getSelection().isDescendantOf(item) > 0 
             ) 
       || this.getMenu().getCurrentList() != null 
          && ( this.getMenu().getCurrentList() == item 
               || this.getMenu().getCurrentList().isDescendantOf(item) 
               || this.getMenu().getCurrentList().getParent() == item.getParent()
             ) 
        );
}

/**
 *  Returns true if the list has at least one child that should be
 *  displayed.  Either the list is expanded, or the list contains
 *  the current selection, or the list contains the current expanded
 *  list.
 */
function _list_hasVisibleChild()
{
  return( this.isExpanded() 
          && this.hasChildInContext()
       || this.getSelection() != null 
          && this.getSelection().isInContext()
       || this.getMenu().collapse 
          && this.getMenu().getCurrentList() != null 
          && this.getMenu().getCurrentList().isInContext() 
          && this.getMenu().getCurrentList().isDescendantOf(this)
        );
}


/**
 * Return true if at least one child is visible by reason of context or condition
 */
function _list_hasChildInContext()
{
 	for( var i=0; i < this.items.length; ++i )
  {
    if( this.items[i].isInContext() )
      return true;
  }
  return false;
}

/**
 * Add item to menu hashtable of all children
 */
function _menu_addDescendent(item)
{
  this.descendents[item.id] = item;
}

/**
 *  getItem - Retrieve an item or list from the global hashmap
 */
function _menu_getDescendent(id)
{
  if( this.descendents[id] )
    return this.descendents[id];
  return null;
}


function _menu_setBorder(isSet)
{
  if( isSet )
    this.border="1";
  else
    this.border="0";
}

/**
 *  Enable or disable links (used when debugging offline).
 */
function _menu_setLinks(isSet)
{
  this.doLinks=(isSet?true:false);
}



////////// BUILD ROUTINES ////////
//////////////////////////////////
/**
 *  Returns the HTML for a single item
 */
function _item_build()
{
  this.log("ITEM BUILD","-","build");

  if( !this.isInContext() )
    return "";
  var span = 1;
  if( this.getMenu().indent )
    span = this.getMenu().getTotalDepth()-this.getDepth() + 1;
	var retString = "   <td class='"+this.getCSSClass()+"' valign=top>";
     if( this.link != "" )
       retString += "<A href='javascript:handleClick(\""+this.getMenu().id+"\",\"" + this.id + "\",false)' onmouseover='return hover(\""+this.getMenu().id+"\",\"" + this.id + "\",true);' onmouseout='return hover(\""+this.getMenu().id+"\",\"" + this.id + "\",false);'>";
     retString += this.getIcon()+(this.link!=""?"</a>":"")+"</td>\n";
     retString += "   <td class='"+this.getCSSClass()+"' valign=top width=100% colspan="+span+">" + (m_showHeight?span+"&nbsp;":"");

     if( this.link != "" )
     {
       retString += "<A id='link"+this.id+"' class='"+this.getCSSClass()+"' href='javascript:handleClick(\""+this.getMenu().id+"\",\"" + this.id + "\",true)'";
       retString += " onmouseover='return hover(\""+this.getMenu().id+"\",\"" + this.id + "\",true);'";
       retString += " onmouseout='return hover(\""+this.getMenu().id+"\",\"" + this.id + "\",false);'>";
     }
	   retString += this.getValue()+(this.link!=""?"</a>":"")+"</td>\n";

	return retString;
}

/**
 *
 */
function _list_build()
{
  this.log("LIST BUILD","-","build");

  if( !this.isInContext() )
    return "";
  var span = 1;
  if( this.getMenu().indent )
    span = this.getMenu().getTotalDepth()-this.getDepth() + 1;
	var retString = "   <td  class='"+this.getCSSClass()+"' valign=top><A href='javascript:handleClick(\""+this.getMenu().id+"\",\"" + this.id + "\",false)' onmouseover='return hover(\""+this.getMenu().id+"\",\"" + this.id + "\",true);' onmouseout='return hover(\""+this.getMenu().id+"\",\"" + this.id + "\",false);'>";
     retString += this.getIcon()+"</a></td>\n";
     retString += "   <td  class='"+this.getCSSClass()+"' valign=top width=100% colspan="+span+">" + (m_showHeight?span+"&nbsp;":"");
     retString += "<A id='link"+this.id+"' class='"+this.getCSSClass()+"' href='javascript:handleClick(\""+this.getMenu().id+"\",\"" + this.id + "\",true)'";
     retString += " onmouseover='return hover(\""+this.getMenu().id+"\",\"" + this.id + "\",true);'";
     retString += " onmouseout='return hover(\""+this.getMenu().id+"\",\"" + this.id + "\",false);'>";
     retString += this.getValue()+"</a></td>\n";


  if( this.hasVisibleChild() )
  {
    retString += "</tr><tr>\n";
    if( this.getMenu().indent )
      retString += "<td valign=top rowspan="+this.getWidth()+">"+(m_showWidth?this.getWidth():m_blankIcon)+"</td>\n";
    var cnt = 0;
		for( var i=0; i < this.items.length; ++i )
    {
      if( this.isVisibleChild(i) )
      {
        if( cnt > 0 )
          retString += "<tr>\n";
        retString += this.items[i].build();
        retString += "</tr>";
        cnt++;
      }
    }
  }
	return retString;
}

/**
 *
 */
function _menu_build()
{
	var retString = "<table class='"+this.getCSSClass()+"' width='100%' BORDER="+this.border+" CELLPADDING=3 CELLSPACING=0>\n<tr>\n";
  for( var i=0; i < this.items.length; ++i )
  {
    retString += this.items[i].build();
    if( i+1 < this.items.length )
      retString += "</tr><tr>\n";
  }

  retString += "</tr></table>\n";
  
  log("HTML",encode(retString));

  var layers = this.layer.split(".");
  var layer = top;
  var i;
  for( i=0; i < layers.length; ++i )
  {
    if( isIE4 )
      layer = layer.document.frames[layers[i]];
    if( isNav4 )
    {
      if( layer.frames.length > 0 )
        layer = layer.frames[layers[i]];
      else
        layer = layer.document.layers[layers[i]];
    }
  }
  if(isIE4) 
    layer.innerHTML = retString;
  if(isNav4)
  {
    layer.document.open();
    layer.document.writeln(retString);
    layer.document.close();
  }

  showLog();
}








///////////// MENU ///////////////
//////////////////////////////////
/**
 *  Returns reference to menu.
 */
function _item_getMenu()
{
  if( this.menu == null )
  {
    if( this.parent != null )
    {
      this.menu = this.parent.getMenu();
      return this.menu;
    }
  }
  return this.menu;
}

function _menu_getMenu()
{
  return this;
}








///////////// PARENTAGE //////////
//////////////////////////////////
/**
 *
 */
function _item_getParent()
{
  return this.parent;
}


/**
 *  Walk up the parent change to find a match to item
 *  Return number of levels removed (parent=1, grandparent=2,...)
 */
function _item_isDescendantOf(item,level)
{
  if( ! level )
    level = 1;
  if( ! item.items )
  {
    return 0;
  }

  if( this.parent != null )
  {
    if( this.parent == item )
      return level;
    return this.parent.isDescendantOf(item,level+1);
  }
  return 0;
}








////////// HANDLE CLICK //////////
//////////////////////////////////
/**
 *   Take action when the item is selected
 *   There's no difference between clicking on text or icon
 */
function _item_click(clickedOnText) 
{
  if( this.getMenu().collapse )
  {
    this.getMenu().setExpanded(false);
    this.getParent().setExpanded(true);
  }

  if( this.goOnEverySelect || ! this.isSelection() )
  {
    this.setSelection();
    this.go();
  }
}

/**
 *   Take action when the item is selected
 *   Expand only when not clickOnText
 */
function _list_click(clickOnText) 
{
  var expand = !this.expanded;

  if( this.getMenu().collapse )
  {
    this.getMenu().setCurrentList(this);
    if( expand )
      this.getMenu().setExpanded(false);
    else
      return;
  }

  this.setExpanded(expand);

  if( clickOnText || this.treatIconAsText )
  {
    if( this.currentSelection != null )
      this.currentSelection.go();
    else 
    {
      if( this.getMenu().getSelection() != null )
        this.getMenu().getSelection().getParent().setSelection(null);
      this.go();
    }
  }
}

/**
 *   Activate the link
 */
function _item_gotoLink()
{
  if( (!this.getMenu() || this.getMenu().doLinks) && this.link != null && this.link != "" )
  {
    if( this.target != null && top.frames[this.target] != null )
      top.frames[this.target].location.href=this.link;
    else
    {
      if( m_contentWindow == null || m_contentWindow.closed)
      {
        m_contentWindow = window.open("","","");
        m_contentWindow.moveBy(500,0);
      }
      m_contentWindow.location.href = this.link;
    }
  }
}









/////////// SELECTION ////////////
//////////////////////////////////
/**
 *
 */
function _item_setSelection()
{
  this.log("ITEM SET SELECTION","Setting item:  '"+this.value+"'","selection");
    
  if( this.getMenu().collapse && this.getMenu().getCurrentList() != this.getParent() )
  {
    this.getMenu().setCurrentList(this.getParent());
    this.getMenu().setExpanded(false);
  }

  this.getParent().setSelection(this);
  this.getParent().lastSelection = this;
  this.getParent().setExpanded(true);
}

/**
 *  Remember the last item selected
 */
function _list_setSelection(item)
{

  if( item != null )
    this.log("LIST SET SELECTION","Setting item:  '"+item.value+"'","selection");
  else
    this.log("LIST SET SELECTION","setting null","selection");

  if( item == this.currentSelection )
    return;

  if( this.parent != null )
  {
    this.getParent().setSelection(item);
  }

  if( item != null && this.currentSelection != null )
  {
    this.log("LIST SET SELECTION","Clearing Old Selection: '"+this.currentSelection.value+"'","selection" );
    this.currentSelection.getParent().setSelection(null);
  }

  if( item != null )
    this.log("LIST SET SELECTION","Setting new selection: '"+item.value+"'","selection");
  else
    this.log("LIST SET SELECTION","Setting new selection to null","selection");
    
  this.currentSelection = item;
}

/**
 *  Is this the current item
 */
function _item_isSelection()
{
  if( this.getParent() 
      && this == this.getParent().getSelection() )
      return true;

  return false;
}

/**
 * Returns the last item selected
 */
function _list_getSelection()
{
  return this.currentSelection;
}









////// LIST EXPANSION  //////
/////////////////////////////
/**
 *  Is this the current item
 */
function _list_isExpanded()
{
  return this.expanded;
}

/**
 *
 */
function _list_setExpanded(val)
{
  this.log("LIST EXPAND",""+val,"expand");

  this.expanded = val;

  if( !val )
  {
		for( var i=0; i < this.items.length; ++i )
    {
      if( this.items[i].setExpanded )
        this.items[i].setExpanded(false);
    }
  }
  else
  {
    this.log("LIST EXPAND RESTORE",this.getMenu().restore+":"+(this.lastSelection?this.lastSelection.value:"null"),"expand");
    if( this.getMenu().restore && this.lastSelection != null && this.lastSelection != this.currentSelection )
      this.lastSelection.setSelection();
    if( ! this.getMenu().collapse && this.getParent() != null && this.getParent() != this.getMenu() )
      this.getParent().setExpanded(true);
  }
}

/**
 *
 */
function _menu_setExpanded(val)
{
  this.log("MENU SET EXPANDED",""+val,"expand");
  for( var i=0; i < this.items.length; ++i )
  {
    if( this.items[i].setExpanded )
      this.items[i].setExpanded(val);
  }
}

/**
 *  Get the only expanded list when in collapse mode
 */
function _menu_getCurrentList()
{
  return this.currentList;
}

/**
 *  Set the only expanded list when in collapse mode
 */
function _menu_setCurrentList(list)
{
  this.log("SET CURRENT LIST",list.value,"expand");
  this.currentList = list;
}








/////// CONTEXT SWITCHING ////////
//////////////////////////////////
/**
 *  Build the HTML for a single item
 */
function _item_isInContext()
{
  if( this.value.length == 0 )
    return false;
  if( this.getMenu() != null )
    return this.getMenu().isInContext(this);
  return true;
}

/**
 *  Define the menu's context and condition masks
 */
function _menu_setContext(strContext,strConditionField)
{
  this.currentContextStr = strContext;
  this.currentConditionStr = strConditionField;
}

/**
 *  Are the given strings found in the menu's context or condition mask
 */
function _menu_isInContext(item)
{
  return( ( item.context.length== 0 
            || item.context.indexOf(this.currentContextStr) != -1 
          ) 
          && ( item.condition.length == 0 
               || ( this.currentConditionStr.length > 0   
                    && item.condition.indexOf(this.currentConditionStr) != -1 
                  )
             )
        );
}








///// REPLACEMENT STRINGS ////////
//////////////////////////////////
/**
 *  Defines a key and token
 */
function _item_setToken(key,token)
{
  this.log( "SET TOKEN","Key:"+key+" token:"+token, "token" );
  this.tokenMap[key] = token;
}

/**
 *   Returns token associated with given key
 */
function _item_getToken(key)
{
  var ret = this.tokenMap[key];
  if( ret )
    return ret;
  return null;
}

/**
 *   Replace all occurrances of $(key) or $$(key) in string
 *   with the value of the token associated with the key.
 */
function _item_replaceTokens(value)
{
  var bNotDone = true;
  var startNdx = value.indexOf("$(");
  var endNdx, key, token, offset;
  while( startNdx >= 0 )
  {
    offset = 2;
    if( startNdx > 0 && value.charAt(startNdx-1) == '$' )
    {
      --startNdx;
      offset = 3;
    }
    endNdx = value.indexOf(")",startNdx);
    if( endNdx > startNdx )
    {
      key = value.substring(startNdx+offset,endNdx);
      token = this.getToken(key);
      if( token == null )
        token = "["+key+"]";
      value = value.substring(0,startNdx) + token + value.substring(endNdx+1,value.length);
      startNdx = value.indexOf("$(");
    }
    else
      startNdx = -1;
  }
  return value;
}




/////  DEPTH OF ITEM IN TREE /////
//////////////////////////////////
/**
 *   Get the level depth of this item in the menu hierarcy
 */
function _item_getDepth()
{
  if( this.depth == -1 )
    this.getMenu().getTotalDepth();
  return this.depth;
}

/**
 *  Set the level in the menu hierarchy.
 */
function _item_setDepth(level)
{
  this.depth = level;
  if( this.getMenu().depth < level )
    this.getMenu().depth = level;
}

/**
 *  Set the level in the menu hierarchy.
 */
function _list_setDepth(level)
{
  this.depth = level;
  if( this.getMenu().depth < level )
    this.getMenu().depth = level;

  if( this.items )
  {
    for( var i=0; i < this.items.length; ++i )
    {
      this.items[i].setDepth(level+1);
    }
  }
}

/**
 *  Returns the longest path from root to leaf node
 */
function _menu_getTotalDepth()
{
  if( this.depth == -1 )
  {
    var i;
    for( i= 0; i < this.items.length; ++i )
    {
      this.items[i].setDepth(0);
    }
  }
  return this.depth;
}





///////  WIDTH OF SUBTREE ////////
//////////////////////////////////
/**
 *   Get the number of expanded children under this list
 */
function _item_getWidth()
{
  return 0;
}


/**
 *  Set the level in the menu hierarchy.
 */
function _list_getWidth()
{
  var width = 0;
  for( var i=0; i < this.items.length; ++i )
  {
    if( this.isVisibleChild(i) )
      width += 1+ this.items[i].getWidth();
  }

  return width;
}









//////// DEBUG LOGGING////////////
//////////////////////////////////
var m_log = "";
var m_logWindow = null;
var m_doAlerts = false;
var m_categories = ["build","HTML","selection","expand","width","height"];
var m_showLog = new Array();
m_showLog["general","general"];
var m_showWidth = false;
var m_showHeight = false;
/**
 *
 */
function setLogging(category,isOn)
{
  if( isOn )
  {
    m_showLog[category] = category;
  }
  else
    m_showLog[category] = null;
  if( category == "width" )
      m_showWidth = isOn;
  if( category == "height" )
      m_showHeight = isOn;
}

function log(str)
{
  log("general",str);
}

function log(category,str)
{
  if( isLog(category) )
  {
    if( m_log == "" )
      m_log = "<table border=1 cellspacing=0 width=100%><tr>\n"
    if( str.indexOf("<td") >= 0 || str.indexOf("<TD") >= 0 )
      m_log += str + "</tr>\n";
    else
      m_log += "<td colspan=3>"+str+"</td></tr>\n";
    if( m_doAlerts )
      alert( m_log );
  }
}

function isLog(category)
{
  if( m_showLog[category] )
    return (m_showLog[category] != null);
  return false;
}

function showLog()
{
  if( m_log != "" )
  {
    m_log += "</table>";
    if( m_logWindow == null || m_logWindow.closed )
    {
      m_logWindow = window.open("","","");
      m_logWindow.moveBy(500,0);
    }
    m_logWindow.document.write(m_log);
    m_logWindow.document.close();
    m_log = "";
  }
}
function closeLog()
{
  if( m_logWindow != null )
    m_logWindow.close();
  m_logWindow = null;
}
/**
 *  Change all '<' and '>' to &lt; and &gt;
 */
function encode(str)
{
  str = str.replace(/ /g,"&nbsp;");
  str = str.replace(/</g,"&lt;");
  str = str.replace(/>/g,"&gt;");
  var lines = str.split('\n');
  str = "";
  for( var i=0; i < lines.length; ++i )
    str += lines[i]+"<br>\n";
  return str;
}

