Mega Code Archive

 
Categories / JavaScript DHTML / GUI Components
 

[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 6 :: 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.png) repeat-x;      color: #0F0F0F;     text-align: center;     height: 28px;     line-height: 28px;     vertical-align: middle; } div.domMenu_menuElementHover {     background: url(gradient_hover.png) repeat-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.gif) repeat-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.gif) repeat-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') != -1 || 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 <= 1 && !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 == 1 || 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') >= 0 && 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') == 1 && settings.get('verticalExpand') == 'north' && settings.get('axis') == 'horizontal' ? numSiblings + 1 - 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') >= 0 && 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 >= 0 && 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') == 1 ? 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') == 1 ? 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') == 1 && 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') == 1 ? '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') == 1 ? '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 == 2 && 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 == 2 && 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(     1, new Hash(         'contents', 'Home',         'contentsHover', 'Home',         'uri', 'http://mojavelinux.com',         'target', '_self',         'statusText', 'Mojavelinux.com homepages',         1, new Hash(             'contents', 'News',             'uri', 'http://mojavelinux.com',             'target', '_blank',             'statusText', 'Latest mojavelinux.com news'         ),         2, new Hash(             'contents', 'Cooker',             'uri', 'http://www.rntsoft.com',             'statusText', 'Released open source programs',             1, new Hash(                 'contents', 'Demos',                 'uri', 'http://www.rntsoft.com',                 'statusText', 'Program demos'             ),             2, new Hash(                 'contents', 'Beta',                 'uri', 'http://www.rntsoft.com',                 'statusText', 'Program betas'             )         ),         3, new Hash(             'contents', 'Pictures',             'uri', 'http://www.rntsoft.com',             'statusText', 'Pictureview picture catalog'         ),         4, new Hash(             'contents', 'Tutorials',             'uri', 'http://www.rntsoft.com',             'statusText', 'Various tutorials I have put together'         ),         5, new Hash(             'contents', 'Stats',             'uri', 'http://www.rntsoft.com',             'statusText', 'website statistics')),     2, new Hash(         'contents', 'Forums',         'contentsHover', 'Forums',         'uri', '',         'statusText', 'Mojave forums',         1, new Hash(             'contents', 'Cooker',             'uri', 'http://www.rntsoft.com',             'statusText', 'Released programs'         ),         2, new Hash(             'contents', 'phpBB Mods',             'uri', 'http://www.rntsoft.com',             'statusText', 'phpBB Forum Modifications'         ),         3, new Hash(             'contents', 'MyCalendar Mod',             'uri', 'http://www.rntsoft.com',             'statusText', 'MyCalendar add-on for phpBB')),     3, new Hash(         'contents', 'Demos',         'contentsHover', 'Demos',         'uri', '',         'statusText', 'Demo Sites',         1, new Hash(             'contents', 'DOM Menu',             'uri', 'http://www.rntsoft.com',             'statusText', 'Dynamic hierarchial menu using the DOM'         ),         2, new Hash(             'contents', 'DOM Tooltip',             'uri', 'http://www.rntsoft.com',             'statusText', 'Dynamic tooltips using the DOM'         ),         3, new Hash(             'contents', 'Popup Calendar',             'uri', 'http://www.rntsoft.com',             'statusText', 'Date selector popup calendar')),     4, new Hash(         'contents', 'Tutorials',         'contentsHover', 'Tutorials',         'uri', '',         'statusText', 'Various tutorials',         1, new Hash(             'contents', 'Hash Tables',             'uri', 'http://www.rntsoft.com',             'statusText', 'Creating hash tables in javascript'         ),         2, new Hash(             'contents', 'Understanding Events',             'uri', 'http://www.rntsoft.com',             'statusText', 'Understanding Events in javascript'         ),         3, new Hash(             'contents', 'Using setTimeout',             'uri', 'http://www.rntsoft.com',             'statusText', 'Using the setTimeout method in javascript'         ),         4, new Hash(             'contents', 'Tips & Tricks',             'uri', 'http://www.rntsoft.com',             'statusText', 'Random tips and tricks')),     5, new Hash(         'contents', 'Pictures',         'contentsHover', 'Pictures',         'uri', 'http://www.rntsoft.com',         'statusText', 'Picture sites',         1, new Hash(             'contents', 'Pictureview',             'uri', 'http://www.rntsoft.com',             'statusText', 'Mojavelinux.com picture catalog'         ),         2, new Hash(             'contents', 'Chintoons',             'uri', 'http://www.rntsoft.com',             'statusText', 'Chinchilla cartoons')),     6, new Hash(         'contents', 'Stats',         'contentsHover', 'Stats',         'uri', 'http://www.rntsoft.com',         'statusText', 'Mojavelinux.com site statistics',         1, new Hash(             'contents', 'Overall Site Statistics for mojavelinux.com',             'uri', 'http://www.rntsoft.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(     1, new Hash(         'contents', 'Home',         'uri', '',         'statusText', 'Home',         1, new Hash(             'contents', 'Main Page',             'uri', 'http://www.rntsoft.com',             'statusText', 'Mojave Page'         ),         2, new Hash(             'contents', 'Contact mojavelinux.com',             'uri', '',             'statusText', 'Contact mojavelinux.com',             1, new Hash(                 'contents', 'Dan',                 'uri', 'http://www.rntsoft.com',                 'statusText', 'Dan'             ),             2, new Hash(                 'contents', 'Sarah',                 'uri', 'http://www.rntsoft.com',                 'statusText', 'Sarah'             )         ),         3, new Hash(             'contents', 'Terms of Use',             'uri', 'http://www.rntsoft.com',             'statusText', 'Terms of Use'         ),         4, new Hash(             'contents', 'Search this site',             'uri', 'http://www.rntsoft.com',             'statusText', 'Search this site'         ),         5, new Hash(             'contents', 'Customize',             'uri', '',             'statusText', 'Customize',             1, new Hash(                 'contents', 'Style Schemas',                 'uri', '',                 'statusText', 'Style Schemas'             ),             2, new Hash(                 'contents', 'Blue',                 'uri', 'http://rntsoft.com',                 'statusText', 'Blue'             ),             3, new Hash(                 'contents', 'Green',                 'uri', 'http://rntsoft.com',                 'statusText', 'Green',                 1, new Hash(                     'contents', 'Green',                     'uri', 'http://rntsoft.com',                     'statusText', 'Green'                 )             )         )     ),     2, new Hash(         'contents', 'CSS',         'uri', '',         'statusText', 'CSS',         1, new Hash(             'contents', 'Tutorials',             'uri', '',             'statusText', 'Tutorial Links'         ),         2, new Hash(             'contents', 'Using Stylesheets',             'uri', 'http://www.rntsoft.com',             'statusText', ''         ),         3, new Hash(             'contents', 'CSS Positioning',             'uri', 'http://www.rntsoft.com',             'statusText', 'Learning how to position elements with CSS'         )     ),     3, new Hash(         'contents', 'JavaScript',         'uri', '',         'statusText', 'JavaScript Section',         1, new Hash(             'contents', 'Tutorials',             'uri', '',             'statusText', 'JavaScript Tutorials'         ),         2, new Hash(             'contents', 'Custom Hash() Class',             'uri', 'http://www.rntsoft.com',             'statusText', 'Making your own associative arrays in javascript'         )     ),     4, new Hash(         'contents', 'DHTML',         'uri', '',         'statusText', 'Dynamic HTML',         1, new Hash(             'contents', 'Tutorials',             'uri', '',             'statusText', 'Dynamic HTML Tutorials'         ),         2, new Hash(             'contents', 'DOM Tooltip',             'uri', 'http://www.rntsoft.com',             'statusText', 'Making custom tooltips using the DOM'         )     ),     5, new Hash(         'contents', 'PHP',         'uri', '',         'statusText', 'PHP Section',         1, new Hash(             'contents', 'Tutorials',             'uri', '',             'statusText', 'PHP Tutorials'         ),         2, new Hash(             'contents', 'Handling actions',             'uri', 'http://www.rntsoft.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(     1, new Hash(         'contents', 'Home',         'uri', 'http://mojavelinux.com',         'target', '_self',         'statusText', 'Mojavelinux.com homepages',         1, new Hash(             'contents', 'News',             'uri', 'http://mojavelinux.com',             'target', '_blank',             'statusText', 'Latest mojavelinux.com news'         ),         2, new Hash(             'contents', 'Cooker',             'uri', 'http://www.rntsoft.com',             'statusText', 'Released open source programs'         ),         3, new Hash(             'contents', 'Demos',             'uri', 'http://www.rntsoft.com',             'statusText', 'Program demos'         ),         4, new Hash(             'contents', 'Pictures',             'uri', 'http://www.rntsoft.com',             'statusText', 'Pictureview picture catalog'         ),         5, new Hash(             'contents', 'Tutorials',             'uri', 'http://www.rntsoft.com',             'statusText', 'Various tutorials I have put together'         ),         6, new Hash(             'contents', 'Stats',             'uri', 'http://www.rntsoft.com',             'statusText', 'website statistics'         )     ),     2, new Hash(         'contents', 'Forums',         'uri', '',         'statusText', 'Mojave forums',         1, new Hash(             'contents', 'Cooker',             'uri', 'http://www.rntsoft.com',             'statusText', 'Released programs'         ),         2, new Hash(             'contents', 'phpBB Mods',             'uri', 'http://www.rntsoft.com',             'statusText', 'phpBB Forum Modifications'         ),         3, new Hash(             'contents', 'MyCalendar Mod',             'uri', 'http://www.rntsoft.com',             'statusText', 'MyCalendar add-on for phpBB'         )     ),     3, new Hash(         'contents', 'Demos',         'uri', '',         'statusText', 'Demo Sites',         1, new Hash(             'contents', 'DOM Menu',             'uri', 'http://www.rntsoft.com',             'statusText', 'Dynamic hierarchial menu using the DOM'         ),         2, new Hash(             'contents', 'DOM Tooltip',             'uri', 'http://www.rntsoft.com',             'statusText', 'Dynamic tooltips using the DOM'         ),         3, new Hash(             'contents', 'Popup Calendar',             'uri', 'http://www.rntsoft.com',             'statusText', 'Date selector popup calendar'         )     ),     4, new Hash(         'contents', 'Tutorials',         'uri', '',         'statusText', 'Various tutorials',         1, new Hash(             'contents', 'Hash Tables',             'uri', 'http://www.rntsoft.com',             'statusText', 'Creating hash tables in javascript'         ),         2, new Hash(             'contents', 'Understanding Events',             'uri', 'http://www.rntsoft.com',             'statusText', 'Understanding Events in javascript'         ),         3, new Hash(             'contents', 'Using setTimeout',             'uri', 'http://www.rntsoft.com',             'statusText', 'Using the setTimeout method in javascript'         ),         4, new Hash(             'contents', 'Tips & Tricks',             'uri', 'http://www.rntsoft.com',             'statusText', 'Random tips and tricks'         )     ),     5, new Hash(         'contents', 'Pictures',         'uri', 'http://',         'statusText', 'Picture sites',         1, new Hash(             'contents', 'Pictureview',             'uri', 'http://',             'statusText', 'status text'         ),         2, new Hash(             'contents', 'Chintoons',             'uri', 'http://',             'statusText', 'status text'         )     ),     6, new Hash(         'contents', 'Stats',         'uri', 'http://',         'statusText', 'status text',         1, new 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>                     dommenu-0.3.5.zip( 113 k)