jQuery – Requisite Navigation Drop-down Menu!

Everyone on the internet has their own jQuery navigation menu, but this one is mine. It’s very simple, but it’s also easy to expand on. Plus, I’ll explain why I did it the way I did it.

First off, here’s the demo.

First, the overview – the navmenu is an unordered list (<UL>) containing list items (<LI>) containing anchors (<A>) which serve as the menu categories. The list items  in turn contain unordered lists which contain list items which contain anchors which serve as the menu choices. Catch your breath. I know I said my menu is very simple, but no doubt you’ve seen this method before. Pretty much every other jQuery or generic JavaScript menu – be they drop-down, slide-out, jump-up, dance-around, or never-appear menus – use the same HTML basis.

But why?!? I think the answer is simple, but no one really explains it. The unordered list is the natural semantic choice for a menu, and for a menu of submenus of items, it makes sense to nestle a UL inside of the LIs of another UL. In a screen-reader or text to speech situation, it’s likely this is going to make sense to the user. If you design your links properly, you can also make it so that those dastardly villains who disable JavaScript can still navigate your site (by making the “menu categories” link to pages where the “submenu” items can be found as prominent links).

And anchors with the display:block property are just fun (actually, display:block on an anchor tag means the user doesn’t have to precisely and accurately place the mouse over the text to make the menu pop – they can hover anywhere in the block).

Next, the HTML. Here’s a shortened version of just the navmenu UL.

<ul id="navmenu">
   <li class="menubutton"><a href="">Home</a></li>
   <li class="menubutton"><a href="">Menu One</a>
   <ul class="submenu">
      <li><a href="">Item One</a></li>
      <li><a href="">Item Two</a></li>
      <li><a href="">Item Three</a></li>
      <li><a href="">Item Four</a></li>
      <li><a href="">Item Five</a></li>
   </ul>
   </li>
   <li class="menubutton"><a href="">Menu Two</a>
      <ul class="submenu">
         <li><a href="">Item One</a></li>
         <li><a href="">Item Two</a></li>
         <li><a href="">Item Three</a></li>
         <li><a href="">Item Four</a></li>
         <li><a href="">Item Five</a></li>
      </ul>
   </li>
</ul><!-- end #navmenu ul -->

Of course, this HTML is simple, which is exactly what it should be. The only really important parts are where the few class declarations are… and there are few of them because the jQuery does most of that work for us (as you’ll see later).

Now, let’s look at the CSS. It’s long, so let’s go in chunks.

#my-header { width: 800px; margin: 20px auto 0px auto; border: 1px solid black; background-color: #BBBBDD;}

This div defines the theoretical header of my page. It’s fixed-width, centered with auto margins, and bordered. Woo-hoo.

#my-header > h1 {line-height: 70px; margin: 0px 20px;}

The H1 for my header div. Note two things – first, it’s an H1, not just some P tag. Semantic HTML is good for everybody. Second, and more important, I used a “>” – the child selector. I look at a lot of code, and I never see this selector used when it should be. The way I’ve implemented this menu, we want to be careful the properties we apply to the first set of list items isn’t inherited by the second set of list items (the “grandchildren” of the first LI tags). The child selector limits the “cascade” to the immediate children. This should become more obvious as we go on.

#my-header > #navmenu { height: 30px; margin: 0px; padding: 0px; background-color:#99BBEE; border-bottom: 1px solid black; border-top: 1px solid black; }

#navmenu is a UL tag. We take out its padding and margins because it’s really just functioning as a neutral container for us. It’s got the top and bottom border covered – the A blocks will have the right borders, which makes the rectangles.

#my-header > #navmenu > li {float: left; list-style-type: none; margin: 0px 0px 0px 0px; position: relative;}

Here, we float the list items left (so that they “stack” starting on the left edge and going to the right). This is just plain easier than pretty much any other method, even though I find it somewhat troublesome (“This isn’t what float is for!”). We also strip out the list-style-type, of course. But why is this position:relative? Simple – it’s relative so that its second child, a UL which will be position:absolute, will use it as the basis for its absolute positioning.

#my-header > #navmenu > li > a {display: block; line-height: 30px; border-right: 1px solid #749; padding: 0px 15px; color: #330066; text-decoration: none;}

And here we have the anchor tag. Again, by making it a block, we let the user mouse over any of its space to open the menu.

#my-header > #navmenu > li > ul {display: none; background-color: #EEEEFF; color: #330066; border: 1px solid #306; margin: 0px; padding: 5px 0px 0px 0px; position: absolute; top: 30px; z-index: 99; float: left; width: 225px;}

Here we have the next unordered list which makes up the actual menus that appear. It’s display:none, which will be changed by the jQuery script. With its absolute position, it doesn’t mess up the flow of the tags around it. Its z-index doesn’t really need to exist, but it’s just there to set an initial value. The jQuery will modify the z-index, too. I added some padding to the top just to bring the menu items down a little.

#my-header > #navmenu > li > ul > li {display: block; list-style-type: none; margin: 1px; padding: 9px; position: relative; top: 0px; text-indent: 10px;}

Now we’re almost all the way down the ladder, to the list items inside the menus themselves. These are fairly boring.

#my-header > #navmenu > li > ul > li:hover {background-color: #9999CC; }
#my-header > #navmenu > li > ul > li > a {color: #203050;}

And finally, the anchors in those list items.

Phew.

So, last of all, the jQuery. Thankfully, it’s short!

$(document).ready(function() {
   $(".submenu").hide(0);
   $(".menubutton").hover(
      function() {
         $(this).children("a").css(
            {'background-color': '#223377', 'color':'#EEEEEE'});
         $(this).find("ul.submenu").slideDown(100).show();
         $(this).find("ul.submenu").css("z-index","10");
      },
      function () {
         $(this).children("a").css(
            {'background-color': '#99BBEE', 'color':'#330066'});
         $(this).find("ul.submenu").slideUp(200);
         $(this).find("ul.submenu").css("z-index","5");
         }
   );
   $(".submenu").children().hover(
      function() {
         $(this).animate({
            "text-indent": "0px",
            }, 300);
         },
         function() {
            $(this).animate({
            "text-indent": "10px",
            }, 300);
      }
   );
});

On the whole, I used the hover() method to pop open the menus… because it’s easy. It handles both “mouseover” and “mouseout” events, so it shortens the work. When you mouseover the menubutton LIs, it slideDown()s the UL. On mouseout, it slideUp()s the UL. The second hover() method covers the “back and forth” slide animation of the actual menu items. This visual cue is just a tiny enhancement which I accomplished by manipulating the text-indent css property.

By the by, the children() method makes life a little easier, since we don’t have to set a class for every tag. find() is also a great method for pinning down the tags you’re looking for (although we didn’t really need it here, it’s good to know). The only question you’re likely to have is… why do the hover() functions change the z-index? It’s pretty simple – when the user opens a new menu, I want that menu to be on top (because these menus definitely overlap each other). So, by switching around z-indexes (z-indices?), we assure the user always sees the right menu (even if it’s only for a few hundred milliseconds).

Alright, that’s it! It’s not winning me a Nobel prize, but I find a lot of people throwing out code samples for these things without explaining their decisions… so uh… I did the best I could with that.

Filed under Code Demos, jQuery

Posted on January 18th, 2012

Code Demo – Presidents Chronology Test

This is just a fun sample I whipped together for my web portfolio. I call in the Presidents Chronology Test, but it could just be called, “A demo of jQuery and AJAX.”

View the demo…

Here’s how it works:

First, the PHP in the page selects 7 presidents, randomly, from a database of presidents I set up. I put the rows fetched into an array of their name and number (“number” meaning “where they fall in a chronological order”). I copy that into an array that is sorted, and the sorted array is stored as a session variable. The unsorted array is used to initialize the random list.

As for the test itself, jQuery makes the draggable boxes a snooze. All you have to do is set it in your $(document).ready function:

$(“#presidents”).sortable();
$(“#presidents”).disableSelection();

The first line makes the entire UL (id=”presidents”) sortable, so all the elements within can be rearranged. There are a lot of fun tricks that go along with “sortable” plugin, but we don’t need most of them for this. The second line makes the text of the boxes non-selectable. This makes the boxes easier to drag, and it prevents weird selection highlights from appearing while you’re arranging your presidents.

The button calls the jQuery load() method, which makes asynchronous requests a cinch. The load() method asks a tiny PHP script to check the order of the LI elements on the page versus the $_SESSION[] variable that the page set when it loaded. It then returns either a “CORRECT!” result or a “Sorry! Try again.”

“But why in the world does the AJAX take a full half-second to load?” Because I told it to! The AJAX was much too fast. From a human-computer relations standpoint, without a delay, the user gets no feedback that the computer “heard” and “understood” their request. I used a setTimeout to create a half-second delay purely so the user sees “Checking…” before receiving a response. Without the delay, it’s really hard to tell if hitting the button did anything, and this could leave the user confused or frustrated.

Obviously, this test isn’t doing much for anyone on its own. But, considering the very short time it took me to put it together (about an hour or two, with another hour or two  fiddling with how I wanted it to work), it is a wonderful UI device for something like Condorcet voting, ordering of items for a custom menu, or even a very unique CAPTCHA.

Filed under Code Demos

Posted on January 13th, 2012

The li Tag – Bullets Done Better

Let’s face it – the default look of the <li> tag is awful for every mainstream browser. Not only is the indentation generally too extreme, the bullet is big and ugly. Sure, you can fiddle with list-style-type to change the bullet, or even make a custom image for it, but there’s a more elegant solution out there that I’m going to show you. It makes the bullet less obstructive, and it allows you the style of a custom image without too much finagling.

The Basic Rundown – You change list-style-type to none, then add a text-indent and a background-image to li.

Here’s how your CSS might look:

li {
background-image: url(‘/images/new-bullet-b.png’);
background-position: left center;
background-repeat: no-repeat;
list-style-type: none;
text-indent: 25px;
}

I created new-bullet-b.png at 16 pixels wide by 11 pixels high. I indented the list item 25 pixels to give us a little space. Additionally, it’s important we don’t repeat the background image, and that it’s left and center. Sometimes, you might need to fiddle with the background-position property to get it just right – different bullet shapes may look better in different positions. Here’s what my list looks like now…

  • Item Number 1
  • Item Number 2
  • Item Number 3

Not bad! Now, me being myself, I would continue to mess with the line-height and background-position until I got it juuuuuust right… but for a demo, that’s good enough!

Filed under Stupid CSS Tricks

Posted on January 8th, 2012

Welcome to the New Teragen.org!

Hello and welcome! Teragen.org is back in a new format, with a new, directed purpose. Please excuse the mess as we bring the site back in line and re-post some old content.

Teragen.org is a repository for my ideas and code samples for web development – whether it’s a fun way to use jQuery or a simple how-to on PHP. I hope you enjoy it, I hope I do it right, and I hope every visitor can learn something!

Filed under General Updates

Posted on January 5th, 2012