[DOM Menu] : Menu : GUI Components JAVASCRIPT DHTML TUTORIALS


JAVASCRIPT DHTML TUTORIALS » GUI Components » Menu »

 

[DOM Menu]




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
            "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
  <head>
    <title>[DOM Menu:: Example :: Flash Hiding</title>
    <style>
body {
    margin: 0;
    padding: 10px;
}
a:link, a:visited, a:active {
    font-family: Verdana, sans-serif; 
    font-size: 12px;
    text-decoration: underline;
    color: #000066;
    font-weight: bold;
}
a:hover {
    text-decoration: none;
}
div.p {
    font-family: Verdana, sans-serif; 
    font-size: 12px;
    margin: 0;
    padding: 10px;
}
div.small {
    font-family: Verdana, sans-serif; 
    font-size: 10px;
}
div.title {
    color: #000066;
    padding-left: 1px;
    font-family: monospace;
    letter-spacing: 2px;
    font-size: 12px;
    line-height: 9px;
    height: 9px;
    margin-bottom: 1px;
}
div.main {
    border: 1px solid #000066;
}
/* Default Style (Opera inspired) */
div.domMenu_menuBar {
    border: solid #7E7E7E;  
    border-width: 1px 0 0 1px;
}
div.domMenu_menuElement {
    font-family: Arial, sans-serif; 
    font-size: 12px;
    border: solid #7E7E7E;  
    border-width: 0 1px 1px 0;
    background: url(gradient.pngrepeat-x; 
    color: #0F0F0F;
    text-align: center;
    height: 28px;
    line-height: 28px;
    vertical-align: middle;
}
div.domMenu_menuElementHover {
    background: url(gradient_hover.pngrepeat-x;
}
div.domMenu_subMenuBar {
    border: solid #7E7E7E 1px;
    background-color: #FFFFFF;
    padding-bottom: 1px;
    opacity: .9;
    filter: alpha(opacity=90);
}
div.domMenu_subMenuElement {
    font-family: Arial, sans-serif; 
    font-size: 12px;
    border: solid #CCCCCC 1px;
    margin: 1px 1px 0 1px;
    color: #0F0F0F;
    padding: 2px 7px;
}
div.domMenu_subMenuElementHover {
    background-color: #EFEFEF;
}
/* Keramik Style */
div.keramik_menuBar {
    padding: 2px 4px 0 4px;
}
div.keramik_subMenuBar {
    background: url(keramik_gradient_h.gifrepeat-y;
    border: 1px solid;
    border-color: #FFFFFF #535352 #535352 #FFFFFF;
}
div.keramik_menuElement, div.keramik_subMenuElement {
    border: 0;
    color: #535352;
    font-family: serif; 
    font-size: 12px;
    line-height: 14px;
    text-align: left;
    padding: 3px 5px;
}
div.keramik_subMenuElement {
    padding: 3px 3px 3px 13px;
}
div.keramik_menuElementHover {
    padding: 2px 4px;
    border: 1px solid;
    border-color: #535352 #FFFFFF #FFFFFF #535352;
    background-color: #FFFFFF;
}
div.keramik_subMenuElementHover {
    padding: 2px 2px 2px 12px;
    border: 1px solid;
    border-color: #82A0C2;
    background: url(keramik_bubble.gifrepeat-x;
}
div.domMenu_subMenuElementHeading {
    font-weight: bold;
}
/* BrainJar Style */
div.BJ_menuBar, div.BJ_menuElement,
div.BJ_subMenuBar, div.BJ_subMenuElement {
    font-family: 'MS Sans Serif', Arial, sans-serif;
    font-size: 10px;
    color: #000000;
    text-align: left;
}
div.BJ_menuBar,
div.BJ_subMenuBar {
    background-color: #c09070;
    border: 2px solid;
    border-color: #e0b090 #906040 #906040 #e0b090;
}
div.BJ_menuBar {
    padding: 1px 4px;
}
div.BJ_menuElement {
    border: 1px solid #c09070;
    padding: 2px 6px 2px 6px;
    font-weight: bold;
}
div.BJ_subMenuElement {
    padding: 2px 6px 2px 6px;
    margin: 0 1px 1px 0;
}
div.BJ_subMenuElementHover {
    background-color: #906040;
    color: #FFFFFF;
}
div.BJ_subMenuElementHeading {
    font-weight: bold;
}
div.BJ_menuElementHover {
    border-color: #e0b090 #906040 #906040 #e0b090;
}
div.BJ_menuElementActive {
    background-color: #906040;
    color: #FFFFFF;
    border-color: #906040 #e0b090 #e0b090 #906040;
}
div.hr {
    border-top: 1px solid #906040;
    border-bottom: 1px solid #e0b090;
}
/* NBLSA styles */
.domMenuNBLSA_subMenuElement {
  background-color: #000000;
  font-family: Verdana;
  color: #EBCC72;
  font-weight: bold;
  font-size: 10px;
  text-align: left;
  vertical-align: top;
  padding: 6px 10px;
  white-space: nowrap;
}
.domMenuNBLSA_subMenuElementHover {
  background-color: #EBCC72;
  color: #000000;
}

    </style>
    <script language="javascript">
/** $Id: domLib.js 1891 2005-05-25 05:01:19Z dallen $ */
// {{{ docs <-- this is a VIM (text editor) text fold

/**
 * Title: DOM Library Core
 * Version: 0.65
 *
 * Summary:
 * A set of commonly used functions that make it easier to create javascript
 * applications that rely on the DOM.
 *
 * Updated: 2005/05/17
 *
 * Maintainer: Dan Allen <dan.allen@mojavelinux.com>
 * Maintainer: Jason Rust <jrust@rustyparts.com>
 *
 * License: LGPL
 */

// }}}
// {{{ global constants (DO NOT EDIT)

/**
 * Global constants (DO NOT EDIT)
 */

// -- Browser Detection --
var domLib_userAgent = navigator.userAgent.toLowerCase();
var domLib_isMac = navigator.appVersion.indexOf('Mac') != -1;
var domLib_isWin = domLib_userAgent.indexOf('windows') != -1;
var domLib_isOpera = domLib_userAgent.indexOf('opera') != -1;
var domLib_isOpera7up = domLib_userAgent.match(/opera.(7|8)/i);
var domLib_isSafari = domLib_userAgent.indexOf('safari') != -1;
var domLib_isKonq = domLib_userAgent.indexOf('konqueror') != -1;
// Both konqueror and safari use the khtml rendering engine
var domLib_isKHTML = (domLib_isKonq || domLib_isSafari || domLib_userAgent.indexOf('khtml') != -1);
var domLib_isIE = (!domLib_isKHTML && !domLib_isOpera && (domLib_userAgent.indexOf('msie 5') != -|| domLib_userAgent.indexOf('msie 6') != -1));
var domLib_isIE5up = domLib_isIE;
var domLib_isIE50 = (domLib_isIE && domLib_userAgent.indexOf('msie 5.0') != -1);
var domLib_isIE55 = (domLib_isIE && domLib_userAgent.indexOf('msie 5.5') != -1);
var domLib_isIE5 = (domLib_isIE50 || domLib_isIE55);
// safari and konq may use string "khtml, like gecko", so check for destinctive /
var domLib_isGecko = domLib_userAgent.indexOf('gecko/'!= -1;
var domLib_isMacIE = (domLib_isIE && domLib_isMac);
var domLib_isIE55up = domLib_isIE5up && !domLib_isIE50 && !domLib_isMacIE;
var domLib_isIE6up = domLib_isIE55up && !domLib_isIE55;

// -- Browser Abilities --
var domLib_standardsMode = (document.compatMode && document.compatMode == 'CSS1Compat');
var domLib_useLibrary = (domLib_isOpera7up || domLib_isKHTML || domLib_isIE5up || domLib_isGecko || domLib_isMacIE || document.defaultView);
var domLib_hasBrokenTimeout = (domLib_isMacIE || (domLib_isKonq && domLib_userAgent.match(/konqueror/3.([2-9])/== null));
var domLib_canFade = (domLib_isGecko || domLib_isIE || domLib_isSafari || domLib_isOpera);
var domLib_canDrawOverSelect = (domLib_isMac || domLib_isOpera || domLib_isGecko);
var domLib_canDrawOverFlash = (domLib_isMac || domLib_isWin);

// -- Event Variables --
var domLib_eventTarget = domLib_isIE ? 'srcElement' : 'currentTarget';
var domLib_eventButton = domLib_isIE ? 'button' : 'which';
var domLib_eventTo = domLib_isIE ? 'toElement' : 'relatedTarget';
var domLib_stylePointer = domLib_isIE ? 'hand' : 'pointer';
// NOTE: a bug exists in Opera that prevents maxWidth from being set to 'none', so we make it huge
var domLib_styleNoMaxWidth = domLib_isOpera ? '10000px' : 'none';
var domLib_hidePosition = '-1000px';
var domLib_scrollbarWidth = 14;
var domLib_autoId = 1;
var domLib_zIndex = 100;

// -- Detection --
var domLib_collisionElements;
var domLib_collisionsCached = false;

var domLib_timeoutStateId = 0;
var domLib_timeoutStates = new Hash();

// }}}
// {{{ DOM enhancements

if (!document.ELEMENT_NODE)
{
  document.ELEMENT_NODE = 1;
  document.ATTRIBUTE_NODE = 2;
  document.TEXT_NODE = 3;
  document.DOCUMENT_NODE = 9;
  document.DOCUMENT_FRAGMENT_NODE = 11;
}

Object.prototype.clone = function()
{
  var copy = {};
  for (var i in this)
  {
    var value = this[i];
    try
    {
      if (value != null && typeof(value== 'object' && value != window && !value.nodeType)
      {
        // for IE5 which doesn't inherit prototype
        value.clone = Object.clone;
        copy[i= value.clone();
      }
      else
      {
        copy[i= value;
      }
    }
    catch(e)
    {
      copy[i= value;
    }
  }

  return copy;
}

// }}}
// {{{ class Hash()

function Hash()
{
  this.length = 0;
  this.numericLength = 0
  this.elementData = [];
  for (var i = 0; i < arguments.length; i += 2)
  {
    if (typeof(arguments[i + 1]) != 'undefined')
    {
      this.elementData[arguments[i]] = arguments[i + 1];
      this.length++;
      if (arguments[i== parseInt(arguments[i])) 
      {
        this.numericLength++;
      }
    }
  }
}

// using prototype as opposed to inner functions saves on memory 
Hash.prototype.get = function(in_key)
{
  return this.elementData[in_key];
}

Hash.prototype.set = function(in_key, in_value)
{
  if (typeof(in_value!= 'undefined')
  {
    if (typeof(this.elementData[in_key]) == 'undefined')
    {
      this.length++;
      if (in_key == parseInt(in_key)) 
      {
        this.numericLength++;
      }
    }

    return this.elementData[in_key= in_value;
  }

  return false;
}

Hash.prototype.remove = function(in_key)
{
  var tmp_value;
  if (typeof(this.elementData[in_key]) != 'undefined')
  {
    this.length--;
    if (in_key == parseInt(in_key)) 
    {
      this.numericLength--;
    }

    tmp_value = this.elementData[in_key];
    delete this.elementData[in_key];
  }

  return tmp_value;
}

Hash.prototype.size = function()
{
  return this.length;
}

Hash.prototype.has = function(in_key)
{
  return typeof(this.elementData[in_key]) != 'undefined';
}

Hash.prototype.find = function(in_obj)
{
  for (var tmp_key in this.elementData
  {
    if (this.elementData[tmp_key== in_obj
    {
      return tmp_key;
    }
  }
}

Hash.prototype.merge = function(in_hash)
{
  for (var tmp_key in in_hash.elementData
  {
    if (typeof(this.elementData[tmp_key]) == 'undefined') 
    {
      this.length++;
      if (tmp_key == parseInt(tmp_key)) 
      {
        this.numericLength++;
      }
    }

    this.elementData[tmp_key= in_hash.elementData[tmp_key];
  }
}

Hash.prototype.compare = function(in_hash)
{
  if (this.length != in_hash.length
  {
    return false;
  }

  for (var tmp_key in this.elementData
  {
    if (this.elementData[tmp_key!= in_hash.elementData[tmp_key]) 
    {
      return false;
    }
  }
  
  return true;
}

// }}}
// {{{ domLib_isDescendantOf()

function domLib_isDescendantOf(in_object, in_ancestor)
{
  if (in_object == in_ancestor)
  {
    return true;
  }

  while (in_object != document.documentElement)
  {
    try
    {
      if ((tmp_object = in_object.offsetParent&& tmp_object == in_ancestor)
      {
        return true;
      }
      else if ((tmp_object = in_object.parentNode== in_ancestor)
      {
        return true;
      }
      else
      {
        in_object = tmp_object;
      }
    }
    // in case we get some wierd error, just assume we haven't gone out yet
    catch(e)
    {
      return true;
    }
  }

  return false;
}

// }}}
// {{{ domLib_detectCollisions()

/**
 * For any given target element, determine if elements on the page
 * are colliding with it that do not obey the rules of z-index.
 */
function domLib_detectCollisions(in_object, in_recover, in_useCache)
{
  // the reason for the cache is that if the root menu is built before
  // the page is done loading, then it might not find all the elements.
  // so really the only time you don't use cache is when building the
  // menu as part of the page load
  if (!domLib_collisionsCached)
  {
    var tags = [];

    if (!domLib_canDrawOverFlash)
    {
      tags[tags.length'object';
    }

    if (!domLib_canDrawOverSelect)
    {
      tags[tags.length'select';
    }

    domLib_collisionElements = domLib_getElementsByTagNames(tags);
    domLib_collisionsCached = in_useCache;
  }

  // if we don't have a tip, then unhide selects
  if (in_recover)
  {
    for (var cnt = 0; cnt < domLib_collisionElements.length; cnt++)
    {
      var thisElement = domLib_collisionElements[cnt];

      if (!thisElement.hideList)
      {
        thisElement.hideList = new Hash();
      }

      thisElement.hideList.remove(in_object.id);
      if (!thisElement.hideList.length)
      {
        domLib_collisionElements[cnt].style.visibility = 'visible';
        if (domLib_isKonq)
        {
          domLib_collisionElements[cnt].style.display = '';
        }
      }
    }

    return;
  }
  else if (domLib_collisionElements.length == 0)
  {
    return;
  }

  // okay, we have a tip, so hunt and destroy
  var objectOffsets = domLib_getOffsets(in_object);

  for (var cnt = 0; cnt < domLib_collisionElements.length; cnt++)
  {
    var thisElement = domLib_collisionElements[cnt];

    // if collision element is in active element, move on
    // WARNING: is this too costly?
    if (domLib_isDescendantOf(thisElement, in_object))
    {
      continue;
    }

    // konqueror only has trouble with multirow selects
    if (domLib_isKonq &&
      thisElement.tagName == 'SELECT' &&
      (thisElement.size <= && !thisElement.multiple))
    {
      continue;
    }

    if (!thisElement.hideList)
    {
      thisElement.hideList = new Hash();
    }

    var selectOffsets = domLib_getOffsets(thisElement)
    var center2centerDistance = Math.sqrt(Math.pow(selectOffsets.get('leftCenter') - objectOffsets.get('leftCenter'), 2+ Math.pow(selectOffsets.get('topCenter') - objectOffsets.get('topCenter'), 2));
    var radiusSum = selectOffsets.get('radius') + objectOffsets.get('radius');
    // the encompassing circles are overlapping, get in for a closer look
    if (center2centerDistance < radiusSum)
    {
      // tip is left of select
      if ((objectOffsets.get('leftCenter') <= selectOffsets.get('leftCenter') && objectOffsets.get('right') < selectOffsets.get('left')) ||
      // tip is right of select
        (objectOffsets.get('leftCenter') > selectOffsets.get('leftCenter') && objectOffsets.get('left') > selectOffsets.get('right')) ||
      // tip is above select
        (objectOffsets.get('topCenter') <= selectOffsets.get('topCenter') && objectOffsets.get('bottom') < selectOffsets.get('top')) ||
      // tip is below select
        (objectOffsets.get('topCenter') > selectOffsets.get('topCenter') && objectOffsets.get('top') > selectOffsets.get('bottom')))
      {
        thisElement.hideList.remove(in_object.id);
        if (!thisElement.hideList.length)
        {
          thisElement.style.visibility = 'visible';
          if (domLib_isKonq)
          {
            thisElement.style.display = '';
          }
        }
      }
      else
      {
        thisElement.hideList.set(in_object.id, true);
        thisElement.style.visibility = 'hidden';
        if (domLib_isKonq)
        {
          thisElement.style.display = 'none';
        }
      }
    }
  }
}

// }}}
// {{{ domLib_getOffsets()

function domLib_getOffsets(in_object)
{
  var originalObject = in_object;
  var originalWidth = in_object.offsetWidth;
  var originalHeight = in_object.offsetHeight;
  var offsetLeft = 0;
  var offsetTop = 0;

  while (in_object)
  {
    offsetLeft += in_object.offsetLeft;
    offsetTop += in_object.offsetTop;
    in_object = in_object.offsetParent;
  }

  // MacIE misreports the offsets (even with margin: 0 in body{}), still not perfect
  if (domLib_isMacIE) {
    offsetLeft += 10;
    offsetTop += 10;
  }

  return new Hash(
    'left',    offsetLeft,
    'top',    offsetTop,
    'right',  offsetLeft + originalWidth,
    'bottom',  offsetTop + originalHeight,
    'leftCenter',  offsetLeft + originalWidth/2,
    'topCenter',  offsetTop + originalHeight/2,
    'radius',  Math.max(originalWidth, originalHeight
  );
}

// }}}
// {{{ domLib_setTimeout()

function domLib_setTimeout(in_function, in_timeout, in_args)
{
  if (typeof(in_args== 'undefined')
  {
    in_args = [];
  }

  if (in_timeout == -1)
  {
    // timeout event is disabled
    return;
  }
  else if (in_timeout == 0)
  {
    in_function(in_args);
    return 0;
  }

  // must make a copy of the arguments so that we release the reference
  if (typeof(in_args.clone!= 'function')
  {
    in_args.clone = Object.clone;
  }

  var args = in_args.clone();

  if (!domLib_hasBrokenTimeout)
  {
    return setTimeout(function() { in_function(args)}, in_timeout);
  }
  else
  {
    var id = domLib_timeoutStateId++;
    var data = new Hash();
    data.set('function', in_function);
    data.set('args', args);
    domLib_timeoutStates.set(id, data);

    data.set('timeoutId', setTimeout('domLib_timeoutStates.get(' + id + ').get('function')(domLib_timeoutStates.get(' + id + ').get('args')); domLib_timeoutStates.remove(' + id + ');', in_timeout));
    return id;
  }
}

// }}}
// {{{ domLib_clearTimeout()

function domLib_clearTimeout(in_id)
{
  if (!domLib_hasBrokenTimeout)
  {
    clearTimeout(in_id);
  }
  else
  {
    if (domLib_timeoutStates.has(in_id))
    {
      clearTimeout(domLib_timeoutStates.get(in_id).get('timeoutId'))
      domLib_timeoutStates.remove(in_id);
    }
  }
}

// }}}
// {{{ domLib_getEventPosition()

function domLib_getEventPosition(in_eventObj)
{
  var eventPosition = new Hash('x'0'y'0'scrollX', 0'scrollY', 0);

  // IE varies depending on standard compliance mode
  if (domLib_isIE)
  {
    var doc = (domLib_standardsMode ? document.documentElement : document.body);
    // NOTE: events may fire before the body has been loaded
    if (doc)
    {
      eventPosition.set('x', in_eventObj.clientX + doc.scrollLeft);
      eventPosition.set('y', in_eventObj.clientY + doc.scrollTop);
      eventPosition.set('scrollX', doc.scrollLeft);
      eventPosition.set('scrollY', doc.scrollTop);
    }
  }
  else
  {
    eventPosition.set('x', in_eventObj.pageX);
    eventPosition.set('y', in_eventObj.pageY);
    eventPosition.set('scrollX', in_eventObj.pageX - in_eventObj.clientX);
    eventPosition.set('scrollY', in_eventObj.pageY - in_eventObj.clientY);
  }

  return eventPosition;
}

// }}}
// {{{ domLib_cancelBubble()

function domLib_cancelBubble(in_event)
{
  var eventObj = in_event ? in_event : window.event;
  eventObj.cancelBubble = true;
}

// }}}
// {{{ domLib_getIFrameReference()

function domLib_getIFrameReference(in_frame)
{
  if (domLib_isGecko || domLib_isIE)
  {
    return in_frame.frameElement;
  }
  else
  {
    // we could either do it this way or require an id on the frame
    // equivalent to the name
    var name = in_frame.name;
    if (!name || !in_frame.parent)
    {
      return;
    }

    var candidates = in_frame.parent.document.getElementsByTagName('iframe');
    for (var i = 0; i < candidates.length; i++)
    {
      if (candidates[i].name == name)
      {
        return candidates[i];
      }
    }
  }
}

// }}}
// {{{ domLib_getElementsByClass()

function domLib_getElementsByClass(in_class)
{
  var elements = domLib_isIE5 ? document.all : document.getElementsByTagName('*');  
  var matches = [];  
  var cnt = 0;
  for (var i = 0; i < elements.length; i++)
  {
    if ((" " + elements[i].className + " ").indexOf(" " + in_class + " "!= -1)
    {
      matches[cnt++= elements[i];
    }
  }

  return matches;
}

// }}}
// {{{

function domLib_getElementsByTagNames(in_list)
{
  var elements = [];
  for (var i = 0; i < in_list.length; i++)
  {
    var matches = document.getElementsByTagName(in_list[i]);
    for (var j = 0; j < matches.length; j++)
    {
      elements[elements.length= matches[j];  
    }
  }

  return elements;
}

// }}}
// {{{ makeTrue()

function makeTrue()
{
  return true;
}

// }}}
// {{{ makeFalse()

function makeFalse()
{
  return false;
}

// }}}

    </script>
    <script language="javascript">
/** $Id: domMenu.js 1884 2005-05-24 05:08:38Z dallen $ */
// {{{ docs <-- this is a VIM (text editor) text fold

/**
 * DOM Menu 0.3.4
 *
 * Summary: Allows developers to add dynamic drop down menus on webpages.  The
 *          menu can either be horizontal or vertical, and can open in either
 *          direction.  It has both edge detection and <select> tag detection
 *          (for browsers that cannot hide these form elements).  The styles
 *          for the menu items are controlled almost entirely through CSS and
 *          the menus are created and destroyed using the DOM.  Menu configuration
 *          is done using a custom Hash() class and is very portable from a PHP
 *          type array structure.
 *
 * Dependency: domLib.js version 0.67
 *
 * Maintainer (lead): Dan Allen <dan@mojavelinux.com>
 * Maintainer: Jason Rust <jrust@rustyparts.com>
 *
 * License: LGPL - however, if you use this library, please post to my forum where you
 *          use it so that I get a chance to see my baby in action.  If you are doing
 *          this for commercial work perhaps you could send me a few Starbucks Coffee
 *          gift dollars to encourage future developement (NOT REQUIRED).  E-mail me
 *          for and address.
 *
 * Homepage: http://www.mojavelinux.com/forum/viewtopic.php
 *
 * Freshmeat Project: http://freshmeat.net/projects/dommenu/?topic_id=92
 *
 * Updated: $Id: domMenu.js 1884 2005-05-24 05:08:38Z dallen $
 *
 * Supported Browsers: Mozilla (Gecko), IE 5.0+, IE on Mac, Safari, Konqueror, Opera 7+
 *
 * Usage: 
 *
 * Menu Options: Each option is followed by the value for that option. The options avaiable are:
 *            'contents'
 *            'rolloverContents',
 *            'uri' (may be javascript)
 *            'statusText'
 *            'target'
 *            [0-9] an index to create a submenu item
 *
 * API:
 *
 * menuElementObject {
 *     ** properties **
 *     data
 *       contents
 *       uri
 *       target
 *       statusText
 *       parentElement
 *       subMenu
 *       childElements
 *       level
 *       index (index within this level)
 *     id
 *     className
 *     style
 *     cellSpacing (Konq only)
 *     
 *     ** events **
 *     mouseover/click -> domMenu_openEvent
 *     mouseout        -> domMenu_closeEvent
 *     click           -> domMenu_resolveLink
 * }
 *
 * If there is a non-negative click open delay, then any uri of the element will be ignored
 *
 * The alternate contents for a hover element are treated by creating to <span> wrapper elements
 * and then alternating the display of them.  This avoids the need for innerHTML, which can
 * do nasty things to the browsers.  If <span> turns out to be a bad choice for tags, then a
 * non-HTML element can be used instead.
 *
 * Dev Notes:
 * - added cellSpacing = 0 for domLib_isMacIE (two places)
 * - seems that Safari and Firefox share an offset problem of menu under parent (pmp example)
 * - must use createTextNode() to add the "n" that is required for Mac to
 *   render the appendChild element (two places); this might be the solution for
 *   the sub menus as well
 * - Safari seems to have a problem with offsetTop if a descendent of body has a margin; solution
 *   is to use padding on the body
 */

// }}}
// {{{ settings (editable)

var domMenu_data = new Hash();
var domMenu_settings = new Hash();

domMenu_settings.set('global', new Hash(
    'menuBarClass', 'domMenu_menuBar',
    'menuElementClass', 'domMenu_menuElement',
    'menuElementHoverClass', 'domMenu_menuElementHover',
    'menuElementActiveClass', 'domMenu_menuElementHover',
    'subMenuBarClass', 'domMenu_subMenuBar',
    'subMenuElementClass', 'domMenu_subMenuElement',
    'subMenuElementHoverClass', 'domMenu_subMenuElementHover',
    'subMenuElementActiveClass', 'domMenu_subMenuElementHover',
    'subMenuElementHeadingClass', 'domMenu_subMenuElementHeading',
    'menuBarWidth', '100%',
    'subMenuMinWidth', 'inherit',
    'distributeSpace', true,
    'axis', 'horizontal',
    'verticalExpand', 'south',
    'horizontalExpand', 'east',
    'expandMenuArrowUrl', 'arrow.gif',
    'subMenuWidthCorrection', 0,
    'verticalSubMenuOffsetY', 0,
    'verticalSubMenuOffsetX', 0,
    'horizontalSubMenuOffsetX', 0,
    'horizontalSubMenuOffsetY', 0,
    'screenPadding', 0,
    'openMouseoverMenuDelay', 300,
    'openMousedownMenuDelay', -1,
    'closeMouseoutMenuDelay', 800,
    'closeClickMenuDelay', -1,
    'openMouseoverSubMenuDelay', 300,
    'openClickSubMenuDelay', -1,
    'closeMouseoutSubMenuDelay', 300,
    'closeClickSubMenuDelay', -1,
    'baseZIndex', 100,
    'baseUri', ''
));

// }}}
// {{{ global variables

/**
 * The data for the menu is stored here, loaded from an external file
 * @hash domMenu_data
 */
var domMenu_data;

var domMenu_selectElements;
var domMenu_scrollbarWidth = 14;
var domMenu_eventTo = domLib_isIE ? 'toElement' : 'relatedTarget';
var domMenu_eventFrom = domLib_isIE ? 'fromElement' : 'relatedTarget';

var domMenu_activeElement = new Hash();

/**
 * Array of hashes listing the timouts currently running for opening/closing menus
 * @array domMenu_timeouts
 */
var domMenu_timeouts = new Array();
domMenu_timeouts['open'] new Hash();
domMenu_timeouts['close'] new Hash();

/**
 * Style to use for a link pointer, which is different between Gecko and IE
 * @var domMenu_pointerStyle
 */
var domMenu_pointerStyle = domLib_isIE ? 'hand' : 'pointer';

// }}}
// {{{ domMenu_activate()

function domMenu_activate(in_containerId, in_disableWarning)
{
    var container;
    var data;

    // make sure we can use the menu system
    if (!domLib_useLibrary)
    {
        if (!in_disableWarning)
        {
                alert('domMenu: Browser not supported.  Menu will be disabled.');
        }

        return;
    }

    // make sure that this is a valid menu, 
    // and that the menu actually has data
    if (!(container = document.getElementById(in_containerId)) || 
        !(data = domMenu_data.get(in_containerId)) ||
        data.numericLength == 0) {
        if (!in_disableWarning) {
                alert('domMenu: Menu failed to load.');
        }

        return;
    }

    if (window.attachEvent) {
        window.attachEvent('onunload', domMenu_fixCircleRefs);
    }

    // start with the global settings and merge in the local changes
    if (!domMenu_settings.has(in_containerId)) {
        domMenu_settings.set(in_containerId, new Hash());
    }

    var settings = domMenu_settings.get(in_containerId);
    for (var i in domMenu_settings.get('global').elementData) {
        if (!settings.has(i)) {
            settings.set(i, domMenu_settings.get('global').get(i));
        }
    }

    // populate the zero level element
    container.data = new Hash(
        'parentElement', false,
        'numChildren', data.numericLength,
        'childElements', new Hash(),
        'level', 0,
        'index', 1
    );
    
    // if we choose to distribute either height or width, determine ratio of each cell
    var distributeRatio = Math.round(100/container.data.get('numChildren')) '%';
    
    // the first menu is the rootMenu, which is a child of the zero level element
    var rootMenu = document.createElement('div');
    rootMenu.id = in_containerId + '-0';
    rootMenu.className = settings.get('menuBarClass');
    container.data.set('subMenu', rootMenu);

    var rootMenuTable = rootMenu.appendChild(document.createElement('table'));
    if (domLib_isKonq || domLib_isMacIE) {
        rootMenuTable.cellSpacing = 0;
    }

    rootMenuTable.style.border = 0;
    rootMenuTable.style.borderCollapse = 'collapse';
    rootMenuTable.style.width = settings.get('menuBarWidth');
    var rootMenuTableBody = rootMenuTable.appendChild(document.createElement('tbody'));

    var numSiblings = container.data.get('numChildren');
    for (var index = 1; index <= numSiblings; index++) {
        // create a row the first time if horizontal or each time if vertical
        if (index == || settings.get('axis') == 'vertical') {
            var rootMenuTableRow = rootMenuTableBody.appendChild(document.createElement('tr'));
        }

        // create an instance of the root level menu element
        var rootMenuTableCell = rootMenuTableRow.appendChild(document.createElement('td'));
        rootMenuTableCell.style.padding = 0;
        rootMenuTableCell.id = in_containerId + '-' + index;
        // add element to list of parent children
        container.data.get('childElements').set(rootMenuTableCell.id, rootMenuTableCell);

        // assign the settings to the root level element
        // NOTE: this is a problem if two menus are using the same data
        rootMenuTableCell.data = data.get(index);
        rootMenuTableCell.data.merge(new Hash(
            'basename', in_containerId,
            'parentElement', container,
            'numChildren', rootMenuTableCell.data.numericLength,
            'childElements', new Hash(),
            'offsets', new Hash(),
            'level', container.data.get('level') 1,
            'index', index
        ));

        // assign the styles
        rootMenuTableCell.style.cursor = 'default';
        if (settings.get('axis') == 'horizontal') {
            if (settings.get('distributeSpace')) {
                rootMenuTableCell.style.width = distributeRatio;
            }
        }

        // Needed for when the text wraps
        rootMenuTableCell.style.verticalAlign = 'top';

        var rootElement = rootMenuTableCell.appendChild(document.createElement('div'));
        rootElement.className = settings.get('menuElementClass');
        // fill in the menu element contents
        var spanElement = rootElement.appendChild(document.createElement('span'));
        // can't use createTextNode() because there might be img tags in the contents
        spanElement.innerHTML = rootMenuTableCell.data.get('contents').replace(/////, settings.get('baseUri'));
        // add hover contents if needed
        if (rootMenuTableCell.data.has('contentsHover')) {
            spanElement = rootElement.appendChild(document.createElement('span'));
            spanElement.style.display = 'none';
            spanElement.innerHTML = rootMenuTableCell.data.get('contentsHover').replace(/////, settings.get('baseUri'));
        }

        // MacIE has to have a newline at the end or else it barfs
        // additionally, it MUST be added using createTextNode() or IE will crash!
        if (domLib_isMacIE) {
            rootMenuTableCell.appendChild(document.createTextNode("n"));
        }

        // attach the events
        rootMenuTableCell.onmouseover = domMenu_runMouseoverOpenEvent;
        rootMenuTableCell.onmouseout = domMenu_runCloseEvent;

        if (settings.get('openMousedownMenuDelay') >= && rootMenuTableCell.data.get('numChildren')) {
            rootMenuTableCell.onmousedown = domMenu_runMousedownOpenEvent;
            // cancel mouseup so that it doesn't propogate to global mouseup event
            rootMenuTableCell.onmouseup = domLib_cancelBubble;
            if (domLib_isIE) {
                rootMenuTableCell.ondblclick = domMenu_runMousedownOpenEvent;
            }
        }
        else if (rootMenuTableCell.data.get('uri')) {
            rootMenuTableCell.style.cursor = domMenu_pointerStyle;
            rootMenuTableCell.onclick = domMenu_runResolveLink;
        }

        // prevent highlighting of text
        if (domLib_isIE) {
            rootMenuTableCell.onselectstart = makeFalse; 
        }

        rootMenuTableCell.oncontextmenu = makeFalse; 
    }
    
    // add the menu rootMenu to the zero level element
    rootMenu = container.appendChild(rootMenu);

    // even though most cases the top level menu does not go away, it could
    // if this menu system is used by another process
    domLib_detectCollisions(rootMenu, false, false);
}

// }}}
// {{{ domMenu_activateSubMenu()

function domMenu_activateSubMenu(in_parentElement)
{
    // NOTE: submenus not supported in MacIE because of problems using
    // appendChild on document.body
    if (domLib_isMacIE) {
        return;
    }

    // see if submenu already exists
    if (in_parentElement.data.has('subMenu')) {
        domMenu_toggleSubMenu(in_parentElement, 'visible');
        return;
    }

    var settings = domMenu_settings.get(in_parentElement.data.get('basename'));

    // build the submenu
    var menu = document.createElement('div');
    menu.id = in_parentElement.id + '-0';
    menu.className = settings.get('subMenuBarClass');
    menu.style.zIndex = settings.get('baseZIndex');
    menu.style.position = 'absolute';
    // position the menu in the upper left corner hidden so that we can work on it
    menu.style.visibility = 'hidden';
    menu.style.top = 0;
    menu.style.left = 0;

    in_parentElement.data.set('subMenu', menu);

    var menuTable = menu.appendChild(document.createElement('table'));
    // ** opera wants to make absolute tables width 100% **
    if (domLib_isOpera) {
        menuTable.style.width = '1px';
        menuTable.style.whiteSpace = 'nowrap';
    }

    if (domLib_isKonq || domLib_isMacIE) {
        menuTable.cellSpacing = 0;
    }

    menuTable.style.border = 0;
    menuTable.style.borderCollapse = 'collapse';
    var menuTableBody = menuTable.appendChild(document.createElement('tbody'));

    var numSiblings = in_parentElement.data.get('numChildren');
    for (var index = 1; index <= numSiblings; index++) {
        var dataIndex = in_parentElement.data.get('level') == && settings.get('verticalExpand') == 'north' && settings.get('axis') == 'horizontal' ? numSiblings + - index : index;
        var menuTableCell = menuTableBody.appendChild(document.createElement('tr')).appendChild(document.createElement('td'));
        menuTableCell.style.padding = 0;
        menuTableCell.id = in_parentElement.id + '-' + dataIndex;

        // add element to list of parent children
        in_parentElement.data.get('childElements').set(menuTableCell.id, menuTableCell);

        // assign the settings to nth level element
        menuTableCell.data = in_parentElement.data.get(dataIndex);
        menuTableCell.data.merge(new Hash(
            'basename', in_parentElement.data.get('basename'),
            'parentElement', in_parentElement,
            'numChildren', menuTableCell.data.numericLength,
            'childElements', new Hash(),
            'offsets', new Hash(),
            'level', in_parentElement.data.get('level') 1,
            'index', index
        ));
        
        // assign the styles
        menuTableCell.style.cursor = 'default';
        
        var element = menuTableCell.appendChild(document.createElement('div'))
        var outerElement = element;
        outerElement.className = settings.get('subMenuElementClass'); 

        if (menuTableCell.data.get('numChildren')) {
            element = outerElement.appendChild(document.createElement('div'));
            // FIXME: this should depend on which way we are opening the menu!
            element.style.backgroundImage = 'url(' + settings.get('expandMenuArrowUrl') ')';
            element.style.backgroundRepeat = 'no-repeat';
            element.style.backgroundPosition = 'right center';
            // add appropriate padding to fit the arrow
            element.style.paddingRight = '12px';
        }

        // fill in the menu item contents
        if (domLib_isMacIE) {
            // we don't support images in sub-menu elements in MacIE because in order for
            // the menu to work consistently the data has to be added with createTextNode()
            element.appendChild(document.createTextNode(menuTableCell.data.get('contents')));
            // MacIE has to have a newline and it has to be added with createTextNode!
            menuTableCell.appendChild(document.createTextNode("n"));
        }
        else {
            element.innerHTML = menuTableCell.data.get('contents');
        }

        // attach the events
        menuTableCell.onmouseover = domMenu_runMouseoverSubOpenEvent;
        menuTableCell.onmouseout = domMenu_runCloseEvent;

        if (settings.get('openClickSubMenuDelay') >= && menuTableCell.data.get('numChildren')) {
            menuTableCell.onmousedown = domMenu_runClickSubOpenEvent;
            menuTableCell.onmouseup = domLib_cancelBubble;
            if (domLib_isIE) {
                menuTableCell.ondblclick = domMenu_runClickSubOpenEvent;
            }
        }
        else if (menuTableCell.data.get('uri')) {
            menuTableCell.style.cursor = domMenu_pointerStyle;
            menuTableCell.onclick = domMenu_runResolveLink;
        }
        else if (!menuTableCell.data.get('numChildren')) {
            outerElement.className += ' ' + settings.get('subMenuElementHeadingClass');
        }

        // prevent highlighting of text
        if (domLib_isIE) {
            menuTableCell.onselectstart = makeFalse;
        }

        menuTableCell.oncontextmenu = makeFalse;
    }

    menu = document.body.appendChild(menu);
    domMenu_toggleSubMenu(in_parentElement, 'visible');
}

// }}}
// {{{ domMenu_changeActivePath()

/**
 * Close the old active path up to the new active element
 * and return the value of the new active element (or the same if unchanged)
 * NOTE: If the new active element is not set (false), the top level is assumed
 *
 @return mixed new active element or false if not set
 */
function domMenu_changeActivePath(in_newActiveElement, in_oldActiveElement, in_closeDelay)
{
    // protect against crap
    if (!in_oldActiveElement && !in_newActiveElement) {
        return false;
    }

    // cancel open timeouts since we know we are opening something different now
    for (var i in domMenu_timeouts['open'].elementData) {
        domLib_clearTimeout(domMenu_timeouts['open'].get(i));
    }

    // grab some info about this menu system...will this ever be null?
    var basename = in_oldActiveElement ? in_oldActiveElement.data.get('basename') : in_newActiveElement.data.get('basename');
    var settings = domMenu_settings.get(basename);

    // build the old active path and unhighlight previously selected element, if appropriate
    var oldActivePath = new Hash();
    if (in_oldActiveElement) {
        var tmp_newActiveLevel = in_newActiveElement ? in_newActiveElement.data.get('level') : -1;
        var tmp_oldActivePathElement = in_oldActiveElement;
        do {
            // NOTE: using set() causes IE to lag and leaves behind highlighted artifacts!
            oldActivePath.elementData[tmp_oldActivePathElement.id= tmp_oldActivePathElement; 
            // unhighlight if sibling of new element, even if it has open submenus
            if (tmp_newActiveLevel >= && tmp_oldActivePathElement.data.get('level') == tmp_newActiveLevel) {
                domMenu_toggleHighlight(tmp_oldActivePathElement, false);
            }
        while ((tmp_oldActivePathElement = tmp_oldActivePathElement.data.get('parentElement')) && tmp_oldActivePathElement.id != basename);

        // unhighlight element immediately if no submenu (or submenu is closed)
        if (!in_oldActiveElement.data.get('subMenu') || in_oldActiveElement.data.get('subMenu').style.visibility == 'hidden') {
            domMenu_toggleHighlight(in_oldActiveElement, false);
        }
    }

    // build the new path and...(explain me!)
    var newActivePath = new Hash();
    var intersectPoint;
    if (in_newActiveElement) {
        var actualActiveElement = in_newActiveElement;
        window.status = in_newActiveElement.data.get('statusText') ' ';

        // in the event we have no old active element, just highlight new one and return
        // without setting the new active element (handled later)
        if (!in_oldActiveElement) {
            domLib_clearTimeout(domMenu_timeouts['close'].get(in_newActiveElement.id));
            domMenu_toggleHighlight(in_newActiveElement, true);
            return false;
        }
        // if the new element is in the path of the old element, then pretend event is
        // on the old active element
        else if (oldActivePath.has(in_newActiveElement.id)) {
            in_newActiveElement = in_oldActiveElement;
        }

        var tmp_newActivePathElement = in_newActiveElement;
        do {
            // if we have met up with the old active path, then record merge point
            if (!intersectPoint && oldActivePath.has(tmp_newActivePathElement.id)) {
                intersectPoint = tmp_newActivePathElement;
            }

            newActivePath.set(tmp_newActivePathElement.id, tmp_newActivePathElement)
            domLib_clearTimeout(domMenu_timeouts['close'].get(tmp_newActivePathElement.id));
            // FIXME: this is ugly!
            if (tmp_newActivePathElement != in_oldActiveElement || actualActiveElement == in_oldActiveElement) {
                domMenu_toggleHighlight(tmp_newActivePathElement, true);
            }
        while ((tmp_newActivePathElement = tmp_newActivePathElement.data.get('parentElement')) && tmp_newActivePathElement.id != basename);

        // if we move to the child of the old active element
        if (in_newActiveElement.data.get('parentElement') == in_oldActiveElement) {
            return in_newActiveElement;
        }
        // if the new active element is in the old active path
        else if (in_newActiveElement == in_oldActiveElement) {
            return in_newActiveElement;
        }

        // find the sibling element
        var intersectSibling;
        if (intersectPoint && oldActivePath.length > 0) {
            for (var i in oldActivePath.elementData) {
                if (oldActivePath.get(i).data.get('parentElement') == intersectPoint) {
                    intersectSibling = oldActivePath.get(i);
                    break;
                }
            }
        }

        var isRootLevel = in_newActiveElement.data.get('level') == true false;
        var closeDelay = isRootLevel ? settings.get('closeMouseoutMenuDelay') : settings.get('closeMouseoutSubMenuDelay');
    }
    else {
        var isRootLevel = false;
        var closeDelay = settings.get('closeMouseoutMenuDelay');
        window.status = window.defaultStatus;
    }

    // override the close delay with that passed in
    if (typeof(in_closeDelay!= 'undefined') {
        closeDelay = in_closeDelay;
    }

    // if there is an intersect sibling, then we need to work from there up to 
    // preserve the active path
    if (intersectSibling) {
        // only if this is not the root level to we allow the scheduled close
        // events to persist...otherwise we close immediately
        if (!isRootLevel) {
            // toggle the sibling highlight (only one sibling highlighted at a time)
            domMenu_toggleHighlight(intersectSibling, false);
        }
        // we are moving to another top level menu
        // FIXME: clean this up
        else {
            // add lingering menus outside of old active path to active path
            for (var i in domMenu_timeouts['close'].elementData) {
                if (!oldActivePath.has(i)) {
                    var tmp_element = document.getElementById(i);
                    if (tmp_element.data.get('basename') == basename) {
                        oldActivePath.set(i, tmp_element);
                    }
                }
            }
        }
    }

    // schedule the old active path to be closed
    for (var i in oldActivePath.elementData) {
        if (newActivePath.has(i)) {
            continue;
        }

        // make sure we don't double schedule here
        domLib_clearTimeout(domMenu_timeouts['close'].get(i));

        if (isRootLevel) {
            domMenu_toggleHighlight(oldActivePath.get(i)false)
            domMenu_toggleSubMenu(oldActivePath.get(i)'hidden');
        }
        else {
            domMenu_timeouts['close'].set(i, domLib_setTimeout(domMenu_runCloseMenu, closeDelay, [oldActivePath.get(i), basename]));
        }
    }
    
    return in_newActiveElement;
}

// }}}
// {{{ domMenu_deactivate()

function domMenu_deactivate(in_basename, in_delay)
{
    if (!in_delay) {
        in_delay = 0;
    }

    domMenu_changeActivePath(false, domMenu_activeElement.get(in_basename), in_delay);
}

// }}}
// {{{ domMenu_openEvent()

/**
 * Handle the mouse event to open a menu
 *
 * When an event is received to open the menu, this function is
 * called, handles reinitialization of the menu state and sets
 * a timeout interval for opening the submenu (if one exists)
 */
function domMenu_openEvent(in_this, in_event, in_delayType)
{
    if (domLib_isGecko) {
        window.getSelection().removeAllRanges();
    }

    // setup the cross-browser event object and target
    var eventObj = domLib_isIE ? event : in_event;
    var currentTarget = domLib_isIE ? in_this : eventObj.currentTarget;
    var basename = currentTarget.data.get('basename');
    var settings = domMenu_settings.get(basename);

    // if we are moving amoungst DOM children of the same element, just ignore event
    if (eventObj.type != 'mousedown' && domMenu_getElement(eventObj[domMenu_eventFrom], basename== currentTarget) {
        return;
    }

    // if we click on an open menu, close it
    if (eventObj.type == 'mousedown' && domMenu_activeElement.get(basename)) {
        domMenu_changeActivePath(false, domMenu_activeElement.get(basename), currentTarget.data.get('level') == ? settings.get('closeClickMenuDelay') : settings.get('closeClickSubMenuDelay'));
        return;
    }

    // if this element has children, popup the child menu
    if (currentTarget.data.get('numChildren')) {
        // the top level menus have no delay when moving between them
        // so activate submenu immediately
        if (currentTarget.data.get('level') == && domMenu_activeElement.get(basename)) {
            // ** I place changeActivePath() call here so the hiding of selects does not flicker **
            // THOUGHT: instead I could tell changeActivePath to clear select ownership but not
            // toggle visibility....hmmm....
            domMenu_activateSubMenu(currentTarget);
            // clear the active path and initialize the new one
            domMenu_activeElement.set(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.get(basename)));
        }
        else {
            // clear the active path and initialize the new one
            domMenu_activeElement.set(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.get(basename)));
            domMenu_timeouts['open'].set(currentTarget.id, domLib_setTimeout(domMenu_runOpenMenu, settings.get(in_delayType)[currentTarget, basename]));
        }
    }
    else {
        // clear the active path and initialize the new one
        domMenu_activeElement.set(basename, domMenu_changeActivePath(currentTarget, domMenu_activeElement.get(basename)));
    }
}

// }}}
// {{{ domMenu_closeEvent()

/**
 * Handle the mouse event to close a menu
 *
 * When an mouseout event is received to close the menu, this function is
 * called, sets a timeout interval for closing the menu.
 */
function domMenu_closeEvent(in_this, in_event)
{
    // setup the cross-browser event object and target
    var eventObj = domLib_isIE ? event : in_event;
    var currentTarget = domLib_isIE ? in_this : eventObj.currentTarget;
    var basename = currentTarget.data.get('basename');
    var relatedTarget = domMenu_getElement(eventObj[domMenu_eventTo], basename);

    // if the related target is not a menu element then we left the menu system
    // at this point (or cannot discern where we are in the menu)
    if (domMenu_activeElement.get(basename)) {
        if (!relatedTarget) {
            domMenu_changeActivePath(false, domMenu_activeElement.get(basename));
        }
    }
    // we are highlighting the top level, but menu is not yet 'active'
    else {
        if (currentTarget != relatedTarget) {
            domLib_clearTimeout(domMenu_timeouts['open'].get(currentTarget.id));
            domMenu_toggleHighlight(currentTarget, false);
        }
    }
}    

// }}}
// {{{ domMenu_getElement()

function domMenu_getElement(in_object, in_basename)
{
    while (in_object) {
        try {
            if (in_object.id && in_object.id.search(new RegExp('^' + in_basename + '([[0-9]\])*\[[1-9]\]$')) == 0) {
                return in_object;
            }
            else {
                in_object = in_object.parentNode;
            }
        }
        catch(e) {
            return false;
        }
    }
    
    return false;
}

// }}}
// {{{ domMenu_correctEdgeBleed()

function domMenu_correctEdgeBleed(in_width, in_height, in_x, in_y, in_padding, in_axis)
{
    if (domLib_isIE && !domLib_isIE5 && !domLib_isMacIE) {
        var pageHeight = document.documentElement.clientHeight;
    }
    else if (!domLib_isKonq) {
        var pageHeight = document.body.clientHeight;
    }
    else {
        var pageHeight = window.innerHeight;
    }

    var pageYOffset = domLib_isIE ? document.body.scrollTop : window.pageYOffset;
    var pageXOffset = domLib_isIE ? document.body.scrollLeft : window.pageXOffset;
    
    if (in_axis == 'horizontal') {
        var bleedRight = (in_x - pageXOffset+ in_width - (document.body.clientWidth - in_padding);
        var bleedLeft = (in_x - pageXOffset- in_padding;
        // we are bleeding off the right, move menu to stay on page
        if (bleedRight > 0) {
            in_x -= bleedRight;
        }

        // we are bleeding to the left, move menu over to stay on page
        // we don't want an 'else if' here, because if it doesn't fit we will bleed off the right
        if (bleedLeft < 0) {
            in_x += bleedLeft;
        }
    }
    else {
        var bleedTop = (in_y - pageYOffset- in_padding;
        var bleedBottom = (in_y - pageYOffset+ in_height - (pageHeight - in_padding);
        // if we are bleeding off the bottom, move menu to stay on page
        if (bleedBottom > 0) {
            in_y -= bleedBottom;
        }

        // if we are bleeding off the top, move menu down
        // we don't want an 'else if' here, because if we just can't fit it, bleed off the bottom
        if (bleedTop < 0) {
            in_y += bleedTop;
        }
    }
    
    return new Array(in_x, in_y);
}

// }}}
// {{{ domMenu_toggleSubMenu()

function domMenu_toggleSubMenu(in_parentElement, in_style)
{
    var subMenu = in_parentElement.data.get('subMenu');
    if (subMenu && subMenu.style.visibility != in_style) {
        var settings = domMenu_settings.get(in_parentElement.data.get('basename'));
        var prefix = in_parentElement.data.get('level') == 'menu' : 'subMenu';
        var className = settings.get(prefix + 'ElementClass');
        // :BUG: this is a problem if submenus click to open, then it won't
        // have the right class when you click to close
        if (in_style == 'visible') {
            className += ' ' + settings.get(prefix + 'Element' + (in_style == 'visible' ? 'Active' : 'Hover') 'Class');
        }

        in_parentElement.firstChild.className = className;
        
        // position our submenu
        if (in_style == 'visible') {
            var tmp_offsets = domLib_getOffsets(in_parentElement);
            if (in_parentElement.data.get('level') == 1) {
                tmp_offsets.set('top', tmp_offsets.get('top') + settings.get('verticalSubMenuOffsetY'));
                tmp_offsets.set('bottom', tmp_offsets.get('bottom') + settings.get('verticalSubMenuOffsetY'));
                tmp_offsets.set('left', tmp_offsets.get('left') + settings.get('verticalSubMenuOffsetX'));
                tmp_offsets.set('right', tmp_offsets.get('right') + settings.get('verticalSubMenuOffsetX'));
            }

            // reposition if there was a change in the parent position/size
            if (!in_parentElement.data.get('offsets').compare(tmp_offsets)) {
                in_parentElement.data.set('offsets', tmp_offsets);

                if (settings.get('axis') == 'horizontal' && in_parentElement.data.get('level') == 1) {
                    var xCoor = tmp_offsets.get('left');
                    if (settings.get('verticalExpand') == 'north') {
                        var yCoor = tmp_offsets.get('top') - subMenu.offsetHeight - settings.get('verticalSubMenuOffsetY');
                    }
                    else {
                        var yCoor = tmp_offsets.get('bottom');
                    }
                }
                else {
                    var xCoor = tmp_offsets.get('right') + settings.get('horizontalSubMenuOffsetX');
                    var yCoor = tmp_offsets.get('top') + settings.get('horizontalSubMenuOffsetY');
                    if (domLib_isOpera || domLib_isSafari) {
                        var marginLeft = parseInt(document.defaultView.getComputedStyle(document.body, '').getPropertyValue('margin-left'));
                        var marginTop = parseInt(document.defaultView.getComputedStyle(document.body, '').getPropertyValue('margin-top'));
                        xCoor -= marginLeft;
                        yCoor -= marginTop;
                    }
                }

                var minWidth = settings.get('subMenuMinWidth');
                var renderedWidth = subMenu.offsetWidth;
                if (minWidth == 'inherit') {
                    minWidth = in_parentElement.offsetWidth + settings.get('subMenuWidthCorrection');
                }
                else if (minWidth == 'auto') {
                    minWidth = renderedWidth;
                }

                if (domLib_isKonq) {
                    // change with width of the first cell
                    subMenu.firstChild.firstChild.firstChild.firstChild.style.width = Math.max(minWidth, renderedWidth'px';
                }
                else {
                    // change the width of the table
                    subMenu.firstChild.style.width = Math.max(minWidth, renderedWidth'px';
                }
                
                var coordinates = domMenu_correctEdgeBleed(subMenu.offsetWidth, subMenu.offsetHeight, xCoor, yCoor, settings.get('screenPadding'), settings.get('axis'));
                subMenu.style.left = coordinates[0'px';
                subMenu.style.top = coordinates[1'px';

                // ** if we inherit, it is necessary to check the parent element width again **
                if (settings.get('axis') == 'horizontal' && settings.get('subMenuMinWidth') == 'inherit') {
                    subMenu.firstChild.style.width = Math.max(in_parentElement.offsetWidth + settings.get('subMenuWidthCorrection'), renderedWidth'px';
                }
            }
        }

        // force konqueror to change the styles
        if (domLib_isKonq) {
            in_parentElement.firstChild.style.display = 'none';
            in_parentElement.firstChild.style.display = '';
        }

        subMenu.style.visibility = in_style;
        domLib_detectCollisions(subMenu, (in_style == 'hidden'), true);
    }
}

// }}}
// {{{ domMenu_toggleHighlight()

function domMenu_toggleHighlight(in_element, in_status)
{
    // if this is a heading, don't change the style
    if (!in_element.data.get('numChildren') && !in_element.data.get('uri')) {
        return;
    }

    var settings = domMenu_settings.get(in_element.data.get('basename'));
    var prefix = in_element.data.get('level') == 'menu' : 'subMenu';
    var className = settings.get(prefix + 'ElementClass');
    var highlightElement = in_element.firstChild;

    var pseudoClass;
    if (in_status) {
        if (in_element.data.has('subMenu') && in_element.data.get('subMenu').style.visibility == 'visible') {
            pseudoClass = 'Active';
        }
        else if (in_element.data.get('numChildren') || in_element.data.get('uri')) {
            pseudoClass = 'Hover';
        }
    }

    if (pseudoClass) {
        className += ' ' + settings.get(prefix + 'Element' + pseudoClass + 'Class');
        // if we are changing to hover, change the alt contents (only change if needs it)
        if (highlightElement.childNodes.length == 2) {
            //alert(highlightElement.lastChild);
        }
        if (highlightElement.childNodes.length == && highlightElement.lastChild.style.display == 'none') {
            highlightElement.firstChild.style.display = 'none';
            highlightElement.lastChild.style.display = '';
        }
    }
    else {
        // if we are changing to non-hover, change the alt contents (only change if needs it)
        if (highlightElement.childNodes.length == && highlightElement.firstChild.style.display == 'none') {
            highlightElement.lastChild.style.display = 'none';
            highlightElement.firstChild.style.display = '';
        }
    }

    highlightElement.className = className;

    // force konqueror to change the styles
    if (domLib_isKonq) {
        highlightElement.style.display = 'none';
        highlightElement.style.display = '';
    }
}

// }}}
// {{{ domMenu_resolveLink()

function domMenu_resolveLink(in_this, in_event)
{
    var eventObj = domLib_isIE ? event : in_event;
    var currentTarget = domLib_isIE ? in_this : eventObj.currentTarget;
    var basename = currentTarget.data.get('basename');

    // close the menu system immediately when we resolve the uri
    domMenu_changeActivePath(false, domMenu_activeElement.get(basename)0);

    var uri = currentTarget.data.get('uri');
    if (uri) {
        window.status = 'Resolving Link...';
        uri = uri.replace(/////, domMenu_settings.get(basename).get('baseUri'));

        // open in current window
        if (!currentTarget.data.get('target') || currentTarget.data.get('target') == '_self') {
            window.location = uri;
        }
        // open in new window
        else {
            window.open(uri, currentTarget.data.get('target'));
        }
    }
}

// }}}
// {{{ domMenu_fixCircleRefs()

// We try and get rid of all circular references by using the domMenu_runXXX()
// methods, but some are still left, so we run this function for IE
// @see http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=bcslfd%24ahl%241%248300dec7%40news.demon.co.uk
function domMenu_fixCircleRefs()
{
    var clearElementProps = ['data', 'onmouseover', 'onmouseout', 'onmousedown', 
        'onmouseup', 'ondblclick', 'onclick', 'onselectstart', 'oncontextmenu'];
    var el;
    for (var d = document.all.length; d--;) {
        el = document.all[d];
        for (var c = clearElementProps.length; c--;) {
            el[clearElementProps[c]] null;
        }
    }
}

// }}}
// {{{ domMenu_runXXX()

// All of these domMenu_runXXX() methods are used by the event handling sections to
// avoid the circular memory leaks caused by inner functions
function domMenu_runMouseoverOpenEvent(in_event) { domMenu_openEvent(this, in_event, 'openMouseoverMenuDelay'); }
function domMenu_runMousedownOpenEvent(in_event) { domMenu_openEvent(this, in_event, 'openMousedownMenuDelay'); }
function domMenu_runMouseoverSubOpenEvent(in_event) { domMenu_openEvent(this, in_event, 'openMouseoverSubMenuDelay'); }
function domMenu_runClickSubOpenEvent(in_event) { domMenu_openEvent(this, in_event, 'openClickSubMenuDelay'); }
function domMenu_runCloseEvent(in_event) { domMenu_closeEvent(this, in_event)}
function domMenu_runResolveLink(in_event) { domMenu_resolveLink(this, in_event)};
function domMenu_runCloseMenu(argv
{
    domMenu_toggleHighlight(argv[0]false)
    domMenu_toggleSubMenu(argv[0]'hidden');
    // if this is the top level, then the menu is being deactivated
    if (argv[0].data.get('level') == 1) {
        domMenu_activeElement.set(argv[1]false);
    }
}
function domMenu_runOpenMenu(argv)
{
    if (!domMenu_activeElement.get(argv[1])) { 
        domMenu_activeElement.set(argv[1], argv[0])
    

    domMenu_activateSubMenu(argv[0]);
}

// }}}

    </script>
    <script language="javascript">
// {{{ domMenu_main: data

domMenu_data.set('domMenu_main', new Hash(
    1new Hash(
        'contents', 'Home',
        'contentsHover', 'Home',
        'uri', 'http://mojavelinux.com',
        'target', '_self',
        'statusText', 'Mojavelinux.com homepages',
        1new Hash(
            'contents', 'News',
            'uri', 'http://mojavelinux.com',
            'target', '_blank',
            'statusText', 'Latest mojavelinux.com news'
        ),
        2new Hash(
            'contents', 'Cooker',
            'uri', 'http://www.navioo.com',
            'statusText', 'Released open source programs',
            1new Hash(
                'contents', 'Demos',
                'uri', 'http://www.navioo.com',
                'statusText', 'Program demos'
            ),
            2new Hash(
                'contents', 'Beta',
                'uri', 'http://www.navioo.com',
                'statusText', 'Program betas'
            )
        ),
        3new Hash(
            'contents', 'Pictures',
            'uri', 'http://www.navioo.com',
            'statusText', 'Pictureview picture catalog'
        ),
        4new Hash(
            'contents', 'Tutorials',
            'uri', 'http://www.navioo.com',
            'statusText', 'Various tutorials I have put together'
        ),
        5new Hash(
            'contents', 'Stats',
            'uri', 'http://www.navioo.com',
            'statusText', 'website statistics')),
    2new Hash(
        'contents', 'Forums',
        'contentsHover', 'Forums',
        'uri', '',
        'statusText', 'Mojave forums',
        1new Hash(
            'contents', 'Cooker',
            'uri', 'http://www.navioo.com',
            'statusText', 'Released programs'
        ),
        2new Hash(
            'contents', 'phpBB Mods',
            'uri', 'http://www.navioo.com',
            'statusText', 'phpBB Forum Modifications'
        ),
        3new Hash(
            'contents', 'MyCalendar Mod',
            'uri', 'http://www.navioo.com',
            'statusText', 'MyCalendar add-on for phpBB')),
    3new Hash(
        'contents', 'Demos',
        'contentsHover', 'Demos',
        'uri', '',
        'statusText', 'Demo Sites',
        1new Hash(
            'contents', 'DOM Menu',
            'uri', 'http://www.navioo.com',
            'statusText', 'Dynamic hierarchial menu using the DOM'
        ),
        2new Hash(
            'contents', 'DOM Tooltip',
            'uri', 'http://www.navioo.com',
            'statusText', 'Dynamic tooltips using the DOM'
        ),
        3new Hash(
            'contents', 'Popup Calendar',
            'uri', 'http://www.navioo.com',
            'statusText', 'Date selector popup calendar')),
    4new Hash(
        'contents', 'Tutorials',
        'contentsHover', 'Tutorials',
        'uri', '',
        'statusText', 'Various tutorials',
        1new Hash(
            'contents', 'Hash Tables',
            'uri', 'http://www.navioo.com',
            'statusText', 'Creating hash tables in javascript'
        ),
        2new Hash(
            'contents', 'Understanding Events',
            'uri', 'http://www.navioo.com',
            'statusText', 'Understanding Events in javascript'
        ),
        3new Hash(
            'contents', 'Using setTimeout',
            'uri', 'http://www.navioo.com',
            'statusText', 'Using the setTimeout method in javascript'
        ),
        4new Hash(
            'contents', 'Tips & Tricks',
            'uri', 'http://www.navioo.com',
            'statusText', 'Random tips and tricks')),
    5new Hash(
        'contents', 'Pictures',
        'contentsHover', 'Pictures',
        'uri', 'http://www.navioo.com',
        'statusText', 'Picture sites',
        1new Hash(
            'contents', 'Pictureview',
            'uri', 'http://www.navioo.com',
            'statusText', 'Mojavelinux.com picture catalog'
        ),
        2new Hash(
            'contents', 'Chintoons',
            'uri', 'http://www.navioo.com',
            'statusText', 'Chinchilla cartoons')),
    6new Hash(
        'contents', 'Stats',
        'contentsHover', 'Stats',
        'uri', 'http://www.navioo.com',
        'statusText', 'Mojavelinux.com site statistics',
        1new Hash(
            'contents', 'Overall Site Statistics for mojavelinux.com',
            'uri', 'http://www.navioo.com',
            'statusText', 'Overall statistics for mojavelinux.com'))
));

// }}}
// {{{ domMenu_main: settings

domMenu_settings.set('domMenu_main', new Hash(
    'subMenuWidthCorrection', -1,
    'verticalSubMenuOffsetX', -1,
    'verticalSubMenuOffsetY', -1,
    'horizontalSubMenuOffsetX', 1,
    'openMouseoverMenuDelay', 300,
    'closeMouseoutMenuDelay', 500,
    'expandMenuArrowUrl', 'arrow.gif'
));

// }}}
// {{{ domMenu_keramik: data

domMenu_data.set('domMenu_keramik', new Hash(
    1new Hash(
        'contents', 'Home',
        'uri', '',
        'statusText', 'Home',
        1new Hash(
            'contents', 'Main Page',
            'uri', 'http://www.navioo.com',
            'statusText', 'Mojave Page'
        ),
        2new Hash(
            'contents', 'Contact mojavelinux.com',
            'uri', '',
            'statusText', 'Contact mojavelinux.com',
            1new Hash(
                'contents', 'Dan',
                'uri', 'http://www.navioo.com',
                'statusText', 'Dan'
            ),
            2new Hash(
                'contents', 'Sarah',
                'uri', 'http://www.navioo.com',
                'statusText', 'Sarah'
            )
        ),
        3new Hash(
            'contents', 'Terms of Use',
            'uri', 'http://www.navioo.com',
            'statusText', 'Terms of Use'
        ),
        4new Hash(
            'contents', 'Search this site',
            'uri', 'http://www.navioo.com',
            'statusText', 'Search this site'
        ),
        5new Hash(
            'contents', 'Customize',
            'uri', '',
            'statusText', 'Customize',
            1new Hash(
                'contents', 'Style Schemas',
                'uri', '',
                'statusText', 'Style Schemas'
            ),
            2new Hash(
                'contents', 'Blue',
                'uri', 'http://navioo.com',
                'statusText', 'Blue'
            ),
            3new Hash(
                'contents', 'Green',
                'uri', 'http://navioo.com',
                'statusText', 'Green',
                1new Hash(
                    'contents', 'Green',
                    'uri', 'http://navioo.com',
                    'statusText', 'Green'
                )
            )
        )
    ),
    2new Hash(
        'contents', 'CSS',
        'uri', '',
        'statusText', 'CSS',
        1new Hash(
            'contents', 'Tutorials',
            'uri', '',
            'statusText', 'Tutorial Links'
        ),
        2new Hash(
            'contents', 'Using Stylesheets',
            'uri', 'http://www.navioo.com',
            'statusText', ''
        ),
        3new Hash(
            'contents', 'CSS Positioning',
            'uri', 'http://www.navioo.com',
            'statusText', 'Learning how to position elements with CSS'
        )
    ),
    3new Hash(
        'contents', 'JavaScript',
        'uri', '',
        'statusText', 'JavaScript Section',
        1new Hash(
            'contents', 'Tutorials',
            'uri', '',
            'statusText', 'JavaScript Tutorials'
        ),
        2new Hash(
            'contents', 'Custom Hash() Class',
            'uri', 'http://www.navioo.com',
            'statusText', 'Making your own associative arrays in javascript'
        )
    ),
    4new Hash(
        'contents', 'DHTML',
        'uri', '',
        'statusText', 'Dynamic HTML',
        1new Hash(
            'contents', 'Tutorials',
            'uri', '',
            'statusText', 'Dynamic HTML Tutorials'
        ),
        2new Hash(
            'contents', 'DOM Tooltip',
            'uri', 'http://www.navioo.com',
            'statusText', 'Making custom tooltips using the DOM'
        )
    ),
    5new Hash(
        'contents', 'PHP',
        'uri', '',
        'statusText', 'PHP Section',
        1new Hash(
            'contents', 'Tutorials',
            'uri', '',
            'statusText', 'PHP Tutorials'
        ),
        2new Hash(
            'contents', 'Handling actions',
            'uri', 'http://www.navioo.com',
            'statusText', 'Form actions in PHP'
        )
    )
));

// }}}
// {{{ domMenu_keramik: settings

domMenu_settings.set('domMenu_keramik', new Hash(
    'menuBarWidth', '0%',
    'menuBarClass', 'keramik_menuBar',
    'menuElementClass', 'keramik_menuElement',
    'menuElementHoverClass', 'keramik_menuElementHover',
    'menuElementActiveClass', 'keramik_menuElementHover',
    'subMenuBarClass', 'keramik_subMenuBar',
    'subMenuElementClass', 'keramik_subMenuElement',
    'subMenuElementHoverClass', 'keramik_subMenuElementHover',
    'subMenuElementActiveClass', 'keramik_subMenuElementHover',
    'subMenuMinWidth', 'auto',
    'horizontalSubMenuOffsetX', -5,
    'horizontalSubMenuOffsetY', 3,
    'distributeSpace', false,
    'openMouseoverMenuDelay', -1,
    'openMousedownMenuDelay', 0,
    'closeClickMenuDelay', 0,
    'closeMouseoutMenuDelay', -1,
    'expandMenuArrowUrl', 'arrow.gif'
));

// }}}
// {{{ domMenu_BJ: data

domMenu_data.set('domMenu_BJ', domMenu_data.elementData['domMenu_keramik']);

// }}}
// {{{ domMenu_BJ: settings

domMenu_settings.set('domMenu_BJ', new Hash(
    'menuBarWidth', '0%',
    'menuBarClass', 'BJ_menuBar',
    'menuElementClass', 'BJ_menuElement',
    'menuElementHoverClass', 'BJ_menuElementHover',
    'menuElementActiveClass', 'BJ_menuElementActive',
    'subMenuBarClass', 'BJ_subMenuBar',
    'subMenuElementClass', 'BJ_subMenuElement',
    'subMenuElementHoverClass', 'BJ_subMenuElementHover',
    'subMenuElementActiveClass', 'BJ_subMenuElementHover',
    'subMenuMinWidth', 'auto',
    'distributeSpace', false,
    'openMouseoverMenuDelay', -1,
    'openMousedownMenuDelay', 0,
    'closeClickMenuDelay', 0,
    'closeMouseoutMenuDelay', -1,
    'expandMenuArrowUrl', 'arrow.gif'
));

// }}}
// {{{ domMenu_vertical: data

domMenu_data.set('domMenu_vertical', new Hash(
    1new Hash(
        'contents', 'Home',
        'uri', 'http://mojavelinux.com',
        'target', '_self',
        'statusText', 'Mojavelinux.com homepages',
        1new Hash(
            'contents', 'News',
            'uri', 'http://mojavelinux.com',
            'target', '_blank',
            'statusText', 'Latest mojavelinux.com news'
        ),
        2new Hash(
            'contents', 'Cooker',
            'uri', 'http://www.navioo.com',
            'statusText', 'Released open source programs'
        ),
        3new Hash(
            'contents', 'Demos',
            'uri', 'http://www.navioo.com',
            'statusText', 'Program demos'
        ),
        4new Hash(
            'contents', 'Pictures',
            'uri', 'http://www.navioo.com',
            'statusText', 'Pictureview picture catalog'
        ),
        5new Hash(
            'contents', 'Tutorials',
            'uri', 'http://www.navioo.com',
            'statusText', 'Various tutorials I have put together'
        ),
        6new Hash(
            'contents', 'Stats',
            'uri', 'http://www.navioo.com',
            'statusText', 'website statistics'
        )
    ),
    2new Hash(
        'contents', 'Forums',
        'uri', '',
        'statusText', 'Mojave forums',
        1new Hash(
            'contents', 'Cooker',
            'uri', 'http://www.navioo.com',
            'statusText', 'Released programs'
        ),
        2new Hash(
            'contents', 'phpBB Mods',
            'uri', 'http://www.navioo.com',
            'statusText', 'phpBB Forum Modifications'
        ),
        3new Hash(
            'contents', 'MyCalendar Mod',
            'uri', 'http://www.navioo.com',
            'statusText', 'MyCalendar add-on for phpBB'
        )
    ),
    3new Hash(
        'contents', 'Demos',
        'uri', '',
        'statusText', 'Demo Sites',
        1new Hash(
            'contents', 'DOM Menu',
            'uri', 'http://www.navioo.com',
            'statusText', 'Dynamic hierarchial menu using the DOM'
        ),
        2new Hash(
            'contents', 'DOM Tooltip',
            'uri', 'http://www.navioo.com',
            'statusText', 'Dynamic tooltips using the DOM'
        ),
        3new Hash(
            'contents', 'Popup Calendar',
            'uri', 'http://www.navioo.com',
            'statusText', 'Date selector popup calendar'
        )
    ),
    4new Hash(
        'contents', 'Tutorials',
        'uri', '',
        'statusText', 'Various tutorials',
        1new Hash(
            'contents', 'Hash Tables',
            'uri', 'http://www.navioo.com',
            'statusText', 'Creating hash tables in javascript'
        ),
        2new Hash(
            'contents', 'Understanding Events',
            'uri', 'http://www.navioo.com',
            'statusText', 'Understanding Events in javascript'
        ),
        3new Hash(
            'contents', 'Using setTimeout',
            'uri', 'http://www.navioo.com',
            'statusText', 'Using the setTimeout method in javascript'
        ),
        4new Hash(
            'contents', 'Tips & Tricks',
            'uri', 'http://www.navioo.com',
            'statusText', 'Random tips and tricks'
        )
    ),
    5new Hash(
        'contents', 'Pictures',
        'uri', 'http://',
        'statusText', 'Picture sites',
        1new Hash(
            'contents', 'Pictureview',
            'uri', 'http://',
            'statusText', 'status text'
        ),
        2new Hash(
            'contents', 'Chintoons',
            'uri', 'http://',
            'statusText', 'status text'
        )
    ),
    6new Hash(
        'contents', 'Stats',
        'uri', 'http://',
        'statusText', 'status text',
        1new Hash(
            'contents', 'Overall Site Statistics',
            'uri', 'http://',
            'statusText', 'Overall statistics for'
        )
    )
));

// }}}
// {{{ domMenu_vertical: settings

domMenu_settings.set('domMenu_vertical', new Hash(
    'axis', 'vertical',
    'subMenuWidthCorrection', -1,
    'verticalSubMenuOffsetX', -1,
    'verticalSubMenuOffsetY', -1,
    'horizontalSubMenuOffsetX', 0,
    'horizontalSubMenuOffsetY', 0,
    'expandMenuArrowUrl', 'arrow.gif'
));

// }}}

    </script>
    <script language="javascript">
function showFlash(obj) {
  obj.style.visibility = 'visible';
}

function hideFlash(obj) {
  obj.style.visibility = 'hidden';
}
    </script>
  </head>
  <body>
    <div class="title">Example 6: Flash Hiding</div>
    <div class="main">
        <div class="p">
        <div id="domMenu_main"></div>
        <script language="javascript">
domMenu_activate('domMenu_main');
        </script>
        </div>
        <div class="p">
        <div style="width: 450px; height: 150px; background: url(banner.jpg) no-repeat;">
        <object id="flash" type="application/x-shockwave-flash" data="banner.swf" width="450px" height="150px" pluginspage="http://www.macromedia.com/go/getflashplayer">
          <param name="movie" value="banner.swf" />
          <param name="wmode" value="opaque" />
          <img src="banner.jpg" alt="Banner" width="450" height="150" />
        </object>
        </div>
        </div>
        <div class="p">
        <input type="button" value="Hide" onclick="hideFlash(document.getElementById('flash'));" />
        <input type="button" value="Show" onclick="showFlash(document.getElementById('flash'));" />
        </div>
        <div class="p">The <em>Hide</em> and <em>Show</em> buttons demonstrate what will happen when the flash animation has been determined to be in the way of the menu.  Since the flash object is wrapped in a div of equal size with a washed out background image, so it should show through when the flash is being hidden.</div>
    </div>
  </body>
</html>

           
       

Download : Download nav_dommenu-0.3.5.zip nav_dommenu-0.3.5.zip


-

Leave a Comment / Note


 
Verification is used to prevent unwanted posts (spam). .

Follow Navioo On Twitter

JAVASCRIPT DHTML TUTORIALS

 Navioo GUI Components
» Menu