// (c) Copyright 2001, TIBCO Software Inc.  All rights reserved.
// LEGAL NOTICE:  This source code is provided to specific authorized end
// users pursuant to a separate license agreement.  You MAY NOT use this
// source code if you do not have a separate license from TIBCO Software
// Inc.  Except as expressly set forth in such license agreement, this
// source code, or any portion thereof, may not be used, modified,
// reproduced, transmitted, or distributed in any form or by any means,
// electronic or mechanical, without written permission from  TIBCO
// Software Inc.
//---------------------------------------------------------------------------
// THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT
// THE PROGRAM IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
// PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
// PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD ANY PART OF THE PROGRAM
// PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT TIBCO) ASSUME THE COST OF ANY
// NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY
// CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF THE PROGRAM IS
// AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
//---------------------------------------------------------------------------


// APMenus.js


//_____________________
//
//       APMenu
//_____________________

function APMenu(name) {
  if (! window.APMenus) {
    window.APMenus = new Array();
  }

  // Members
  this.mName = name;
  this.mIndex = window.APMenus.length;
  window.APMenus[this.mIndex] = this;
  this.mActivated = false;
  this.mTimeOutLength = 200;
  this.mX = 0;
  this.mY = 0;
  this.mZ = 0;
  this.mLayer = '';
  this.mItemParent= '';
  this.mItemHilited = '';
  this.mOnLeave = '';
  this.mMouseOnBase = false;
  this.mClassName = 'tibMenu';
  this.mClassNameStub = 'tibMenuStub';
  this.mClassNameItemSelectedHi = 'tibMenuSelectedHi';
  this.mClassNameItemSelectedLo = 'tibMenuSelectedLo';
  this.mClassNameItemDeSelectedHi = 'tibMenuDeSelectedHi';
  this.mClassNameItemDeSelectedLo = 'tibMenuDeSelectedLo';
  this.mClassNameSeparator = 'tibMenuSeparator';
  this.mItems = new Array();

  // Methods
  this.addItem = APMenu_addItem;
  this.addItemByValues = APMenu_addItemByValues;
  this.addSubMenu = APMenu_addSubMenu;
  this.addSeparatorLine = APMenu_addSeparatorLine;
  this.hide = APMenu_hide;
  this.hideIfOut = APMenu_hideIfOut;
  this.show = APMenu_show;
  this.showAt = APMenu_showAt;
  this.showInFrontOf = APMenu_showInFrontOf;
  this.showRightOf = APMenu_showRightOf;
  this.showUnder = APMenu_showUnder;
  this.onMouseOver = APMenu_onMouseOver;
  this.onMouseOut = APMenu_onMouseOut;
  this.activate = APMenu_activate;
  this.isOut = APMenu_isOut;
  this.isIn = APMenu_isIn;
  this.isShown = APMenu_isShown;
  this.moveTo = APMenu_moveTo;
  this.moveBy = APMenu_moveBy;
  this.writeStub = APMenu_writeStub;
  this.findMenuByName = APMenu_findMenuByName;
  this.findMenuByItemText = APMenu_findMenuByItemText;
  window.APMenus_getObjectCoords = APMenu_getObjectCoords;

//__________
// getCoords: Returns an object whose x, y, z, width, height properties
//            are the coordinates and size of the argument element.
//
function APMenu_getObjectCoords(anElement) {
  var coords = new Object();
  coords.x = anElement.offsetLeft;
  coords.y = anElement.offsetTop;
  coords.z = (anElement.style ? anElement.style.zIndex : anElement.zIndex);
  coords.width = anElement.offsetWidth;
  coords.height = anElement.offsetHeight;
  parentCoords = anElement.offsetParent;
  while (parentCoords) {
    coords.x += parentCoords.offsetLeft;
    coords.y += parentCoords.offsetTop;
    parentCoords = parentCoords.offsetParent;
  }
  return coords;
}


//________
// moveTo: Moves the menu layer to the coordinates
//         given as argument.
//
function APMenu_moveTo(x, y, z) {
  this.mX = x;
  this.mY = y;
  this.mZ = z;
  this.activate();
  var layerStyle = this.mLayer.style;
  if (layerStyle) {
    layerStyle.left   = this.mX;
    layerStyle.top    = this.mY;
    layerStyle.zIndex = this.mZ;
  } else {
    this.mLayer.left   = this.mX;
    this.mLayer.top    = this.mY;
    this.mLayer.zIndex = this.mZ;
  }
}


//________
// moveBy: Moves the menu layer by the increments
//         given as argument.
//
function APMenu_moveBy(x, y, z) {
  this.mX += x;
  this.mY += y;
  this.mZ += z;
  this.activate();
  var layerStyle = this.mLayer.style;
  if (layerStyle) {
    layerStyle.left   = this.mX;
    layerStyle.top    = this.mY;
    layerStyle.zIndex = this.mZ;
  } else {
    this.mLayer.left   = this.mX;
    this.mLayer.top    = this.mY;
    this.mLayer.zIndex = this.mZ;
  }
}


//_________
// addItem: Adds an APMenuItem to this menu.
//          Returns the menu item.
//
function APMenu_addItem(item) {
  this.mItems[this.mItems.length] = item;
  item.mMenu = this;
  if (item.isSelected()) {
    this.mSelectedText = item.mText;
  }
  return item;
}


//_________________
// addItemByValues: Creates an APMenuItem from the arguments
//                  and adds it to this menu.
//                  Returns the menu item.
//
function APMenu_addItemByValues(text, link, selected) {
  return this.addItem(new APMenuItem(text, link, selected));
}


//____________
// addSubMenu: Adds a submenu to this menu.
//             Returns the corresponding menu item.
//
function APMenu_addSubMenu(text, submenu) {
  var item = new APMenuItem(text, '', false);
  item.setSubMenu(submenu);
  this.addItem(item);
  return item;
}


//____________
// addSeparatorLine: Adds a separator line in  this menu.
//
function APMenu_addSeparatorLine() {
  return this.addItemByValues(
    '<hr size="1" class="'+this.mClassNameSeparator+'">',
    '', false);
}


//_______
// isOut: Returns true iif no menu item is hilited.
//
function APMenu_isOut() {
  return !this.isIn();
}


//______
// isIn: Returns true iif at least one menu item is hilited
//
function APMenu_isIn() {
  return (this.mMouseOnBase || this.mItemHilited);
}


//__________
// activate: Generate the DHTML elements and event handlers
//           corresponding to the definition of this menu.
//
function APMenu_activate() {
  if (!this.mActivated) {
    APMenu_makeLayer(this);
    this.mActivated = true;
  }
}


//____________
// onMouseOut: Triggers cleanup, called when it seems
//             that the mouse is out of the menu.
//
function APMenu_onMouseOut() {
  this.mMouseOnBase = false;
  if (! this.mItemParent) {
    setTimeout('APMenu_hideIfOutByIndex('+this.mIndex+')', this.mTimeOutLength);
  }
}


//_____________
// onMouseOver: Show the menu under the stub.
//              Called when the mouse is over the menu stub.
//
function APMenu_onMouseOver(stubElement) {
  this.mMouseOnBase = true;
  var parentItem = this.mItemParent;
  if (parentItem) {
     parentItem.mMenu.mMouseOnBase = true;
     parentItem.hilite();
  }
  stubElement ? this.showUnder(stubElement) : this.show();
}


//______
// Hide: Hides the menu.
//
function APMenu_hide() {
  this.activate();
  if (this.mLayer.style) this.mLayer.style.visibility = 'hidden';
  else this.mLayer.visibility = 'hide';
  if (this.mItemHilited) {
    this.mItemHilited.deHilite('');
  }
  if (this.mOnLeave) {
    eval (this.mOnLeave);
    this.mOnLeave = '';
  }
}


//______
// show: Shows the menu.
//
function APMenu_show() {
  this.activate();
  if (this.mLayer.style) this.mLayer.style.visibility = 'visible';
  else this.mLayer.visibility = 'show';
}


//_________
// isShown: True iif the menu is visible.
//
function APMenu_isShown() {
  if (this.mLayer.style) {
    return (this.mLayer.style.visibility == 'visible');
  } else {
    return (this.mLayer.visibility == 'show');
  }
}


//________
// showAt: Shows the menu at the given corrdinates.
//
function APMenu_showAt(x, y, z) {
  this.moveTo(x, y, z);
  this.show();
}


//_______________
// showInFrontOf: Shows the menu at the same location as
//                the given element, but with a bigger zIndex.
//
function APMenu_showInFrontOf(anElement) {
  if (anElement) {
      var coords = window.APMenus_getObjectCoords(anElement);
      this.showAt(coords.x, coords.y, 1+coords.z);
  }
}


//___________
// showUnder: Shows the menu just under the given element,
//            with a bigger zIndex.
//
function APMenu_showUnder(anElement) {
  if (anElement) {
      var coords = window.APMenus_getObjectCoords(anElement);
      this.showAt(coords.x, coords.y+coords.height, 1+coords.z);
  }
}


//____________
// showRightOf: Shows the menu just at the right of the given element,
//            with a bigger zIndex.
//
function APMenu_showRightOf(anElement) {
  if (anElement) {
      var coords = window.APMenus_getObjectCoords(anElement);
      this.showAt(coords.x+coords.width, coords.y, 1+coords.z);
  }
}


//___________
// writeStub: Write in the document the element on which the menu
//            is attached. The visible part of this element is the argument.
// 
function APMenu_writeStub(text, onEnter_code) {
  this.activate();
  onEnter_code = (onEnter_code ? onEnter_code.replace(/"/, '\\"') : '');
  document.write('<div style="border:0;margin:0;padding:0;white-space:nowrap"'
    +' id="APMenu_stub_'+this.mIndex+'"'
    +' onmouseover="window.APMenus['+this.mIndex+'].onMouseOver(this);'
    + onEnter_code+'"'
    +' onmouseout="window.APMenus['+this.mIndex+'].onMouseOut();">'
    +'<span class="'+this.mClassNameStub+'">'+text+'</span></div>');
}


//____________________
// findMenuByItemText: Returns an existing menu that has an item
//                     whose text is equal to the argument.
// 
function APMenu_findMenuByItemText(itemText) {
  if (!window.APMenus) return;
  var i, j;
  for (var i=window.APMenus.length-1; i>=0; i--) {
    var menu = window.APMenus[i];
    for (var j=menu.mItems.length-1; j>=0; j--) {
      if (menu.mItems[j].mText == itemText) return menu;
    }
  }
}


//________________
// findMenuByName: Returns an existing menu
//                 whose name is equal to the argument.
// 
function APMenu_findMenuByName(menuName) {
  if (!window.APMenus) return;
  var i;
  for (var i=window.APMenus.length-1; i>=0; i--) {
    var menu = window.APMenus[i];
    if (menu.mName == menuName) return menu;
  }
}


// PRIVATE
// makeLayer: Creates the DHTML elements for the given menu.
// 
function APMenu_makeLayer(menu) {
  document.write('<div id="APMenu_div_'+menu.mIndex+'"'
    +' style="visibility:hidden;position:absolute;z-index:'+menu.mZ
    +';left:'+menu.mX+'px;top:'+menu.mY+'px;"'
    +' onMouseOver="this.APMenu.onMouseOver();"'
    +' onMouseOut="this.APMenu.onMouseOut();"'
    +' class="'+menu.mClassName+'">'
    +'<table cellspacing="0" cellpadding="0" border="0">');
  for (i=0; i<menu.mItems.length; i++) {
    var item = menu.mItems[i];
    document.write('<tr><td'
      +' class="'
      +(item.isSelected() ? menu.mClassNameItemSelectedLo
        : menu.mClassNameItemDeSelectedLo )+'"'
      +' onMouseOver="window.APMenus['+menu.mIndex+'].mItems['+i
        +'].hilite(this);"'
      +' onMouseOut="window.APMenus['+menu.mIndex+'].mItems['+i
        +'].deHilite(this);"'
      +' onClick="window.APMenus['+menu.mIndex+'].mItems['+i
        +'].onClick(this);"'
      +'>'+item.mText+'</td></tr>');
  }
  document.write('</table></div>');
  menu.mLayer = findObject('APMenu_div_'+menu.mIndex);
  menu.mLayer.APMenu = menu;

//__________
// findObject: Finds a DHTML object by name in a document.
//
function findObject(name, doc) {
  var i, object, position = name.indexOf("?");
  if (!doc) {
    doc = document;
  }
  if ( (position > 0) && parent.frames.length) {
    doc = parent.frames[name.substring(position+1)].document;
    name = name.substring(0,position);
  }
  if (doc.all) {
    return doc.all(name);
  }
  if (doc.getElementById) {
    return doc.getElementById(name);
  }
  object = doc[name];
  for (i=0; (!object && i<doc.forms.length); i++) {
    object = doc.forms[i][name];
  }
  for (i=0; (!object && doc.layers && (i<doc.layers.length));i++) {
    object=findObject(name,doc.layers[i].document);
  }
  return object;
}


} // End of APMenu_makeLayer

// PRIVATE
// hideIfOut: Closes the menu if no menu item is highlighted.
//
function APMenu_hideIfOut() {
  if (this.isOut()) this.hide();
}


} //Enf of APMenu


// PRIVATE
// hideIfOutByIndex: Closes the menu whose index is given as argument
//                   if no menu item is highlighted in this menu.
//
function APMenu_hideIfOutByIndex(index) {
  var menu = window.APMenus[index];
  if (menu) {
    menu.hideIfOut();
  }
}



//_____________________
//
//     APMenuItem
//_____________________

function APMenuItem(text, link, selected,  onclick) {

  // Members
  this.mText = text;
  this.mLink = link;
  this.mSelected = (selected ? true : false);
  this.mHilited = false;
  this.mSubMenu = false;
  this.mIsSeparator = false;

  // Methods
  this.select = APMenuItem_select;
  this.deSelect = APMenuItem_deSelect;
  this.isSelected = APMenuItem_isSelected;
  this.hilite = APMenuItem_hilite;
  this.deHilite = APMenuItem_deHilite;
  this.isHilited = APMenuItem_isHilited;
  this.setSubMenu = APMenuItem_setSubMenu;
  this.onClick = APMenuItem_onClick;


//________
// setSubMenu: Binds a submenu to this menu item
//
function APMenuItem_setSubMenu(menu) {
  this.mSubMenu = menu;
}


//________
// removeSubMenu: Unbinds any submenu bound to this item
//
function APMenuItem_removeSubMenu() {
  this.mSubMenu = '';
}


//________
// hilite: Highlights this menu item
//
function APMenuItem_hilite(object) {
  if (object) this.mElement = object;
  if (this.mSubMenu) {
    this.mSubMenu.mItemParent= this;
    this.mSubMenu.mMouseOnBase = true;
    this.mSubMenu.showRightOf(this.mElement);
  }
  var menu = this.mMenu;
  if (menu) {
    if (menu.mItemHilited && (menu.mItemHilited != this)) {
      menu.mItemHilited.deHilite();
    }
    menu.mItemHilited = this;
  }
  this.mHilited = true;
  this.mElement.className = this.mSelected
    ? this.mMenu.mClassNameItemSelectedHi
    : this.mMenu.mClassNameItemDeSelectedHi;
}


//__________
// deHilite: Dims this menu item
//
function APMenuItem_deHilite(object) {
  if (object) this.mElement = object;
  var sub = this.mSubMenu;
  if (sub) {
      sub.mMouseOnBase = false;
      sub.hide();
  }
  if (this.mMenu && (this.mMenu.mItemHilited == this)) {
    this.mMenu.mItemHilited = '';
  }
  this.mHilited = false;
  this.mElement.className = this.mSelected
    ? this.mMenu.mClassNameItemSelectedLo
    : this.mMenu.mClassNameItemDeSelectedLo;
}


//____________
// isHilited: Returns true iif this menu item is Highlighted
//
function APMenuItem_isHilited() {
  return this.mHilited;
}

//________
// select: Selects this menu item
//
function APMenuItem_select(object) {
  if (object) this.mElement = object;
  this.mSelected = true;
  this.mElement.className = this.mHilited
    ? this.mMenu.mClassNameItemSelectedHi
    : this.mMenu.mClassNameItemSelectedLo;
  if (this.mMenu) {
    this.mMenu.mSelectedText = this.mText;
  }
}


//_________
// onClick: Called when the user clicks on the menu.
//
function APMenuItem_onClick(object) {
  if (object) this.mElement = object;
  if (this.mLink) {
    window.top.location.href = this.mLink;
  }
}


//__________
// deselect: Deselects this menu item
//
function APMenuItem_deSelect(object) {
  if (object) this.mElement = object;
  this.mSelected = false;
  this.mElement.className = this.mHilited
    ? this.mMenu.mClassNameItemDeselectedHi
    : this.mMenu.mClassNameItemDeselectedLo;
}


} // End of APMenuItem


//____________
// isSelected: Returns true iif this menu item is selected
//
function APMenuItem_isSelected() {
  return this.mSelected;
}





//_____________________
// The End,
// NP.
