xMenu4 Vertical - Cascading menus from nested ULs

Intro

This is still experimental. ;-)

Also have a look at the xMenu4 Horizontal demo.

This code will turn a set of nested ULs into a cascading dhtml menu. It is completely downgradeable. Disable javascript and reload the page - you'll see the nested ULs with my downgrade css applied.

Revisions

2 Mar 04
No changes to xMenu4.js, but I moved the menu to a page with a different layout and experimented with a few things - so it may be a little less cross-browser right now. There's plenty of tweaking that could still be done - but I'm tired of foolin with it for now ;-)

See the horizontal demo for more revision info.

Javascript

The js is in two files. One is for page-related js - the loader and onload listener, the other is the menu system code.

xmenu4.js - the menu system, don't rename this file.

xmenu4_2.js - your page onload code, rename this to 'myPage.js'. The contents of this file follow.

////--- Loader

if (!xIE4 && !xNN4) {
  document.write("<"+"link rel='stylesheet' type='text/css' href='xmenu4_1_dhtml.css'>");
  window.onload = xOnload;
}

////--- Load Event Listener

function xOnload()
{
  var me = xGetElementById('myMenu1');
  if (!xDef(me.nodeName, me.firstChild, me.nextSibling)) {
    return;
  }
  
  var mo = new xMenu4(
    me,                       // id str or ele obj of outermost UL
    true,                     // outer UL position: true=absolute, false=static
    false,                    // main label positioning: true=horizontal, false=vertical
    0, 1,                     // box horizontal and vertical offsets
    [-3, -10, -6, -10],       // lbl focus clip array
    [-30, null, null, null],  // box focus clip array
    // css class names:
    'xmBar', 'xmBox',
    'xmBarLbl', 'xmBarLblHvr',
    'xmBarItm', 'xmBarItmHvr',
    'xmBoxLbl', 'xmBoxLblHvr',
    'xmBoxItm', 'xmBoxItmHvr'
  );

  xMnuMgr.add(mo);
  xMnuMgr.load();
  xmWinOnResize();
  xAddEventListener(window, 'resize', xmWinOnResize, false);
}

////--- Window Resize Event Listener

function xmWinOnResize()
{
  // !!!
  var me = xMnuMgr.activeMenu.ele;
  var rc = xGetElementById('rightColumn');
  var mm = xGetElementById('menuMarker');
  var mmp = xParent(mm);
  xMoveTo(me, xPageX(mmp)-xPageX(rc), xPageY(mmp)-xPageY(rc));
  xMnuMgr.paint();
}

CSS

The css is in two files. One supplies default and downgrade mode styles, the other supplies dhtml-related style rules.

xmenu4_1.css - default and downgrade styles, rename this to 'myPage.css'.

xmenu4_1_dhtml.css - dhtml-related styles, rename this to 'myPage_dhtml.css'.

XHTML

No IDs are required, except for the outermost UL. The inline class names are for downgrade mode. Non-downgrade mode class names are passed to the menu object constructor. When Javascript and/or CSS are disabled the menu downgrades to standard nested ULs.

<ul id='myMenu1' class='myBar'> <!-- Begin myMenu1 -->

  <!-- Bar Label 1 -->

  <li><a class='myBarLblA' href=''>lbl-1</a>
    <ul class='myBox'>

      <li><a href=''>item 1-1</a></li>
      <li><a href=''>item 1-2</a></li>

      <li><a class='myBoxLblA' href=''>lbl-1-1</a>
        <ul class='myBox'>
          <li><a href=''>item 1-1-1</a></li>
          <li><a href=''>item 1-1-2</a></li>
        </ul> <!-- end box-1-1 -->
      </li> <!-- end lbl-1-1 -->

      <li><a class='myBoxLblA' href=''>lbl-1-2</a>
        <ul class='myBox'>
          <li><a href=''>item 1-2-1</a></li>
          <li><a href=''>item 1-2-2</a></li>

          <li><a class='myBoxLblA' href=''>lbl-1-2-1</a>
            <ul class='myBox'>
              <li><a href=''>item 1-2-1-1</a></li>
              <li><a href=''>item 1-2-1-2</a></li>
            </ul> <!-- end box-1-2-1 -->
          </li> <!-- end lbl-1-2-1 -->

        </ul> <!-- end box-1-2 -->
      </li> <!-- end lbl-1-2 -->

    </ul> <!-- end box-1 -->
  </li> <!-- end lbl-1 -->

  <!-- Bar Label 2 -->

  <li><a class='myBarLblA' href=''>lbl-2</a>
    <ul class='myBox'>

      <li><a href=''>item 2-1</a></li>
      <li><a href=''>item 2-2</a></li>

      <li><a class='myBoxLblA' href=''>lbl-2-1</a>
        <ul class='myBox'>
          <li><a href=''>item 2-1-1</a></li>
          <li><a href=''>item 2-1-2</a></li>

          <li><a class='myBoxLblA' href=''>lbl-2-1-1</a>
            <ul class='myBox'>
              <li><a href=''>item 2-1-1-1</a></li>
              <li><a href=''>item 2-1-1-2</a></li>
            </ul> <!-- end box-2-1-1 -->
          </li> <!-- end lbl-2-1-1 -->

        </ul> <!-- end box-2-1 -->
      </li> <!-- end lbl-2-1 -->

      <li><a class='myBoxLblA' href=''>lbl-2-2</a>
        <ul class='myBox'>
          <li><a href=''>item 2-2-1</a></li>
          <li><a href=''>item 2-2-2</a></li>
        </ul> <!-- end lbl-2-2 -->
      </li> <!-- end box-2-2 -->

    </ul> <!-- end box-2 -->
  </li> <!-- end lbl-2 -->

  <!-- Bar Item 1 -->

  <li><a class='myBarItmA' href=''>item-1</a></li>

</ul> <!-- end myMenu1 -->