SitePoint Sponsor

User Tag List

Results 1 to 10 of 10

Thread: Expanding Menu

  1. #1
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Ohio
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Expanding Menu

    Hi all,

    I am new here and desperately seeking the answer to my question.

    I want to create an expanding menu similar to this. I have been told that in order to make it accessible to users with Javascript turned off, I need to create the menus expanded, then hide them with JS so that when JS is not available, it would show expanded. I just don't have a clue how to do this. Is there anyone here that can help me?

    I also want to make sure the menu is accessible to keyboard navigators and screenreaders. Does this look like a good one?

    Thanks in advance for any help.

    ~Susan

  2. #2
    SitePoint Zealot
    Join Date
    Nov 2005
    Posts
    113
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A little modification will do the trick, the original code uses class="hide" to hide all the submenus
    <div id="mymenu1" class="hide">

    Remove class="hide" on all the submenus so it becomes:
    <div id="mymenu1">
    ...
    <div id="mymenu5">

    Your menu will be expanded permenently after that, next add some code to hide it with Javascript. Since we are using JS to hide the menus, they will remain open if JS is off.

    Add this code right after of your menu code or at the end of the page (not the beginning.)
    Code:
    <script type="text/javascript">
      // You need to list all your submenus as an array in this manner
      var hide_these = ['mymenu1','mymenu2','mymenu3','mymenu4','mymenu5'];
      
      // This will loop through all the listed menus and hide them
      for ( i = 0; i<hide_these.length; i++ )
      {		  
        document.getElementById(hide_these[i]).style.display='none';
      }
    </script>

  3. #3
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Ohio
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks so much for your help. I feel like I'm one step closer. But I found out that the menu I linked in my first post is completely inaccessible. Is it possible to apply this javascript to any menu? For example, if I were to create a definition list as my navigation, could I apply it to that?
    Susan
    Auxano Creative (formerly The WebDesign Loft)

  4. #4
    SitePoint Zealot
    Join Date
    Nov 2005
    Posts
    113
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yikes, just found out my JS needs a little tweak, otherwise the menu won't expand, you see, the original author used CSS class switcher, whereas I manipulated the elements style directly, (switching class is better!) Long story short, use this javascript instead of my last one!
    Code:
    <script type="text/javascript">
      // // You need to list all your submenus as an array in this manner
      var hide_these = ['mymenu1','mymenu2','mymenu3','mymenu4','mymenu5'];
    	
      for ( i = 0; i<hide_these.length; i++ )
      {
        // ** UPDATED ** \\
        document.getElementById(hide_these[i]).className = 'hide'; 
      }
    </script>
    Aside from that, it will work with <dl> just as well, the CSS for hiding the block does not care what element its hiding!

    HTML Code:
    <dl id="mymenu1">
      <dt><a href="#" class="submenu">Link One here</a></dt>
      ...
    </dl>

  5. #5
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Ohio
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you. I appreciate your help. I'm so unfamiliar with using Javascript that I've been so lost.

    I created a <dl> menu last night and I was wondering how this script would be applied to it.

    <dl class="nav">
    <dt>Link</dt>
    <dt>Link</dt>
    <dd>Link</dd>
    <dd>Link</dd>
    <dt>Link</dt>
    <dd>Link</dd>
    <dd>Link</dd>
    <dd>Link</dd>
    <dt>Link</dt>
    <dt>Link</dt>
    <dt>Link</dt>
    </dl>
    Last edited by SusanTWDL; Aug 27, 2007 at 15:54. Reason: Mistake
    Susan
    Auxano Creative (formerly The WebDesign Loft)

  6. #6
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Ohio
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh, shoot. lol I see that you answered the question about using a <dl>. Sorry for not paying attention. I appreciate the help and now I understand what to do! Thank you again!
    Susan
    Auxano Creative (formerly The WebDesign Loft)

  7. #7
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Ohio
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm back again. I thought I knew what to do, but I don't. Here's what I have.

    HTML:

    <dl class="nav">
    <dt><a href="">Link</a></dt>
    <dt><a href="">Link</a></dt>
    <dd><a href="">Link</a></dd>
    <dd><a href="">Link</a></dd>
    <dt><a href="">Link</a></dt>
    <dd><a href="">Link</a></dd>
    <dd><a href="">Link</a></dd>
    <dd><a href="">Link</a></dd>
    <dt><a href="">Link</a></dt>
    <dt><a href="">Link</a></dt>
    <dt><a href="">Link</a></dt>
    </dl>

    And my CSS:

    .nav {
    margin: 15px 0 0 20px;
    }

    .nav dt {
    font-weight: normal;
    margin-top: 0;
    }

    .nav dd {
    margin-left: 15px;
    margin-bottom: 0;
    font-size: 90&#37;;
    }

    .nav dd a, .nav dd a:visited, .nav dt a, .nav dt a:visited {
    color: #9b8a80;
    text-decoration: none;
    }

    .nav dd a:focus, .nav dd a:hover, .nav dd a:active, .nav dt a:focus, .nav dt a:hover, .nav dt a:active {
    color: #9b8a80;
    text-decoration: underline;
    }

    Is there a way to do this with what I have?
    Last edited by SusanTWDL; Aug 27, 2007 at 15:54. Reason: Removing links
    Susan
    Auxano Creative (formerly The WebDesign Loft)

  8. #8
    SitePoint Zealot
    Join Date
    Nov 2005
    Posts
    113
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Susan, quite a few modification on the script and a whole lot of explanation , so here goes.

    Something is missing from your code, no hooks for JavaScript to retrieve! Its the CSS ID selector.

    document.getElementById('block_name')
    points to
    <dl id="block_name">

    Your dl blocks for sub-menus is missing a wrapper element, we need this so that we can hide the whole block by toggling the wrapper display style.

    On the CSS side, since you already defined the styles for your <dl> and its childs (nice), the original script's use of switching classes on the fly does not fit.

    I have modified the original script and yours to show a possible approach taking into account your requirements for accessibility and degradability. The function calls are now done in the "unobtrusive" style where the actual element event calling is not embedded in the HTML tags; No more <div onclick="js_function();"> just <div id="eleName">

    So here is the modified JavaScript code, I am using a naming convention that names the parent a base name, while the child to be expanded has that identical name but with a suffix "Sub"

    Code JavaScript:
    <script type="text/javascript">
     
    function showHide()
    {
      var sub_menu = this.id+'Sub'; // Child block has suffix 'Sub'
      var current = document.getElementById(sub_menu);
     
      if (document.getElementById)
      {
        var switch_id = document.getElementById(sub_menu);
     
        if ( current.style.display != 'block' )
        {
          current.style.display = 'block';
          this.innerHTML = '[-]'; // Change this to an image tag or any other symbol!
        }
        else
        {
          current.style.display = 'none';
          this.innerHTML = '[+]'; // Ditto for this
        }
      }
    }
     
    </script>

    HTML Code:
    <dl class="nav">
      <dt><a href="index.php">Home</a></dt>
      <dt>
        <!-- I am adding an extra hotspot that users click on to expand the submenu, you can change this to a graphic -->
        <span id="FnPortrait" class="expMkr">[+]</span>
        <a href="#">Fine Portraiture</a>
      </dt>
        <div id="FnPortraitSub">
          <dd><a href="#">Gallery</a></dd>
          <dd><a href="#">Procedure</a></dd>
        </div>
      <dt>
        <span id="FnArts" class="expMkr" >[+]</span>
        <a href="#">Fine Art</a>
      </dt>
        <div id="FnArtsSub"> 
          <dd><a href="#">Gallery</a></dd>
          <dd><a href="#">Gicl&eacute;e Prints</a></dd>
          <dd><a href="#">Art for Good</a></dd>
        </div>
      <dt><a href="#">Biography</a></dt>
      <dt><a href="#">Blog</a></dt>
      <dt><a href="#">Contact</a></dt>
    </dl>
    
    <script type="text/javascript">
    // Old browsers that don't support getElementById() will see what people with Javascript off sees
    if (document.getElementById)
    {
      var hide_these = ['FnPortraitSub','FnArtsSub'];
      for ( i = 0; i<hide_these.length; i++ )
      {
        document.getElementById(hide_these[i]).className = 'hide';
      }
    	
      // Catch events, unobstrusive style, seperated script from content
      document.getElementById('FnArts').onclick = showHide;
      document.getElementById('FnPortrait').onclick = showHide;
    }
    </script>
    Last edited by abb; Aug 27, 2007 at 17:50. Reason: description cleanup

  9. #9
    SitePoint Enthusiast
    Join Date
    Jun 2007
    Location
    Ohio
    Posts
    54
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    abb, thank you very much for your time! I appreciate this so much.
    Susan
    Auxano Creative (formerly The WebDesign Loft)

  10. #10
    SitePoint Zealot
    Join Date
    Nov 2005
    Posts
    113
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Actually SusanTWDL, I just found out that you cannot have a <div> within a <dl>, you can actually only have <dd> and <dt>, well at least it will not pass the W3 validator if you put anything else in it.

    So the example I have there is just no good, <dl> is not suitable simply because we need an element that can wrap around child elements.

    My conclusion is that using lists, <ul><li> is a better choice.

    HTML Code:
    <ul class="nav">
      <li><a href="index.php">Home</a></li>
      <li>
        <span id="FnPortrait" class="expMkr">[+]</span>
        <a href="#">Fine Portraiture</a>
      </li>
      <li>
        <ul id="FnPortraitSub">
          <li><a href="#">Gallery</a></li>
          <li><a href="#">Procedure</a></li>
        </ul>
      </li>
    ...
    </ul>
    Also the W3 validator will not validate JavaScript code unless you escape them with HTML comments ... like this
    Code JavaScript:
    <script type="text/javascript">
    <!--
      // Above, below are the open and close HTML comments, javascript here
    //-->
    </script>

    You can also put the JavaScript within the head tag if you prefer.
    Code JavaScript:
    windows.onload = function ()
    {
      // place the original end of page script here, and within <head>
      // windows.onload means only execute code when the whole page is loaded
      // this is actually slower interaction wise, since viewer has to wait until full page load to expand the menu
    }

    Boy that was looong, but fun hope it was useful.
    Last edited by abb; Aug 27, 2007 at 17:51.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •