How to Write a Basic Dropdown Menu in JQuery

Filed under: Client-Side Scripting — Rosalind Wills on December 26, 2009 @ 3:56 pm

Recently for a project for a friend, I needed some dropdown menus in a horizontal bar which would appear by a slideDown animation when the mouse hovered over them. Since most of the code snippets I found on the subject appeared on mouse click rather than on mouse hover and would need some tweaking anyway, I decided to go ahead and try to write my own version, which I now present here for anyone who wants to use it.

<!-- MARKUP -->
<div id="menu">
<ul class="level1">
<li id="home"><a href="#">HOME</a></li>
<li id="news"><a href="#">NEWS</a></li>
<li id="html"><a class="has_drop" href="#">HTML</a>
	<ul class="level2">
	<li><a href="#">HEADINGS</a></li>
	<li><a href="#">PARAGRAPHS</a></li>
	<li><a href="#">IMAGES</a></li>
	<li><a href="#">ANCHORS</a></li>
	</ul></li>
<li id="css"><a class="has_drop" href="#">CSS</a>
	<ul class="level2">
	<li><a href="#">SELECTORS</a></li>
	<li><a href="#">PROPERTIES</a></li>
	<li><a href="#">STYLESHEETS</a></li>
	</ul></li>
<li id="javascript"><a class="has_drop" href="#">JAVASCRIPT</a>
	<ul class="level2">
	<li><a href="#">JQUERY</a></li>
	<li><a href="#">FUNCTIONS</a></li>
	</ul></li></ul>

</div><!-- END MENU -->
 /* ========= STYLING ============ */
#menu { height: 44px; background: #03134e; }
#menu ul { list-style: none; font-family: Arial; }
ul.level1 li { float: left; margin: 4px 0 0 0; height: 35px; position: relative; }
ul.level1 li a { padding: 11px 43px 0; color: #fff; display: block; height: 27px; text-decoration: none; float: left; }
ul.level1 li a:hover { background: #f9a01b; }
ul.level2 { position: absolute; left: 0; top: 38px; background: #010724; margin: 0; padding: 0; display: none; float: left; width: 170px; border: 1px solid #03134e; border-bottom: none; }
#html .level2, #html .level2 a { width: 128px; }
#css .level2, #css .level2 a {width: 118px; }
#javascript .level2, #javascript .level2 a {width: 180px; }
ul.level2 li { border-bottom: 1px solid #03134e; margin: 0; padding: 0; }
ul.level2 li a { text-align: center; padding: 0; margin: 0;	height: 25px; padding-top: 10px; }
ul.level2 li a:hover { background: #f9a01b; }
// *************** SCRIPTING ******************

$(document).ready(function(){  

	//runs dropdowns on hover
	$('ul.level1 li').hover(function() {
         $(this).children('ul.level2').slideDown('medium');
	}, function() {
		$(this).children('ul.level2').slideUp('medium');
	});

	//when submenus are hovered over, top li remains lit
	$('ul.level2').hover(function() {
         $(this).parent('li').find("a.has_drop").css('background', '#010724');
	}, function() {
		$(this).parent('li').find("a.has_drop").css('background', '');
	});

	//ul level1 links with level2 do not go anywhere
	$('a.has_drop').click(function(e) {
		e.preventDefault();
		})
		.hover(function() {
				$(this).css('cursor', 'default');
				},
				 {

		});
});

Not particularly complicated, so let’s see what’s going on here.

As always, the first level is the markup. It’s a basic unordered list with an ID, a set of “level1″ list items, also with id’s, and some “level2″ lists nested within. This is then styled into a horizontal menu bar with some color and appropriate hover behaviors, and the level 2 lists are absolutely positioned beneath their parent list and hidden initially when the page loads.

Now, for the meat of it — the JQuery…

//runs dropdowns on hover
	$('ul.level1 li').hover(function() {
         $(this).children('ul.level2').slideDown('medium');
	}, function() {
		$(this).children('ul.level2').slideUp('medium');
	});

On document ready, the first thing we do is set the dropdowns behavior to run when the first level list items are hovered over. Using the JQuery selector syntax, we identify all LI children of level1 ULs, and then use the hover method to force any submenus to slideDown (become visible) on mouseover and slideUp (become hidden) on mouseout. Needless to say, if the LI does not have a submenu with the appropriate class, the function will do nothing.

//when submenus are hovered over, top li remains lit
	$('ul.level2').hover(function() {
         $(this).parent('li').find("a.has_drop").css('background', '#010724');
	}, function() {
		$(this).parent('li').find("a.has_drop").css('background', '');
	});

From the CSS we already have our links changing color when the mouse hovers over them. However, we might want our level1 LI elements to remain changed when our mouse is on the submenus. This is accomplished via a chain of JQuery commands, first to ID that the mouse is on the submenu — $(‘ul.level2′) and, later, $(this) — then to its parent LI — $(this).parent(‘li’) — then to the link within that LI which has the class “has_drop” — $(this).parent(‘li’).find(‘a.has_drop’) . This last bit is necessary because a simple .find(‘a’) would identify all of the links which are children of the LI in question, which would also include those in the dropdown itself.

//ul level1 links with level2 do not go anywhere
	$('a.has_drop').click(function(e) {
		e.preventDefault();
		})
		.hover(function() {
				$(this).css('cursor', 'default');
				},
				 {

		});

This part more relates to accessibility than anything else. It is potentially possible that someone might view your site without Javascript enabled — if this were the case, the dropdown menus would be impossible to see. Thus, within the markup, the LIs with dropdowns also contain a link (with the class “has_drop”) which could take the user perhaps to a menu where they could view the options. In the case in which I was using this, I didn’t want to spend too much time on that menu page, so I wanted it only for the people who didn’t have JS enabled; thus, as part of my JQuery code, I disable those links which have that class via the “preventDefault()” method, then cause the cursor not to show a pointer (further discouraging distracting clicks) when those links are hovered over.

And that’s that! Easily styled further and pretty simple in its behavior. Suited my needs and will hopefully be useful to you as well.

Click here to view an example of what the code above produces.

If you have any improvements, spot any errors or points of difficulty, or just want to add something to the discussion, please leave a comment — I’d love to hear from you!


On the (Un)Necessity of Dreamweaver

Filed under: Coding — Rosalind Wills on December 20, 2009 @ 10:50 pm

When I first obtained Adobe Creative Suite 4 Web Premium, I was in a state of intense excitement. This was mostly in reference to the fact that I was finally going to be obtaining Photoshop and Illustrator, an image of Mecca to someone who had been working with GIMP for almost four years. GIMP’s a phenomenal program, and well-worth downloading for anyone who doesn’t have the money or career interest to get hold of PS, but there’s also no question that it has its pitfalls (the gradient tool, for instance, is quite weak in comparison to PS’s) and I was very glad to be getting better tools in the photo editing and vector department. However, I was also pleased to realize that this suite came with Adobe Dreamweaver, which I had heard mentioned more than once as being a very powerful coding tool.

I didn’t really know much about Dreamweaver when I began using it, and I’m quite sure I’m still not aware of the full extent of its capabilities. I remember being extremely excited by the tag completion feature and the ability to write my CSS in a GUI manner rather than doing it by hand. I will say that the CSS graphical interface on Dreamweaver was definitely responsible for improving my awareness of how to use many of CSS’s key element properties, and it certainly smoothed some of my early road into a deeper understanding of the language.

However, the more I’ve used it, the more I’ve also come to realize its weaknesses. The CSS utilities are limited in what they allow you to do, and while the code they produce is generally standards compliant, depending on it stagnates you, which is extremely dangerous in this field in general and especially during this period, where CSS3 and HTML5 are beginning to poke their heads out and turn the markup and styling arena entirely upside-down. When I realized the limitations of the CSS functions and realized that there were plenty of text-based editors out there which also had the tag completion feature, my opinion of Dreamweaver soured somewhat. The more I learn about it, the more I have come to identify it, generally, as an extremely expensive (and, in its defense, much-better-than-average) WYSIWYG editor.

My movement away from Dreamweaver was complete when I began suffering issues with my RAM; I constantly had too many programs open for my laptop and so downloaded a text editor called Smultron (an excellent — and free — simple editor for Mac which is unfortunately no longer being updated that I can tell) because Dreamweaver set my fans roaring, often froze, and generally was providing more trouble than it was worth during this period.

The more I used Smultron, the more I came to realize that there was nothing that I wanted to do with it that would have required Dreamweaver to actually complete; as a matter of fact, it was a somewhat freeing experience. I began to investigate further into the CSS properties that were available rather than trusting to Dreamweaver’s system, and began to work at a more markup-before-styling process, and in general I just found that there was really no reason for me to go *back* to Dreamweaver, having left it. The one remaining potential attraction that it held was the close connection between the file editing and the FTP connection, but there are other text programs that do that as well (I fell in love with the demo version of Coda but haven’t yet been able to afford the full version) and in the meantime, Cyberduck (another excellent Mac freeware program) does the job just fine.

I’d be interested to hear feedback from other designers on their experience with Dreamweaver — I’m sure there are elements of its usefulness I am missing. If you have any thoughts on this — or on recommendations for good web development editors — I’d love to hear them, so leave a comment! I’d like to take the time to compile a list of recommended ones, if I can hear from enough people.


Image Accessibility Via Alt Text

Filed under: Uncategorized — Rosalind Wills on December 13, 2009 @ 11:40 pm

I’ve written before about progressive enhancement and the idea of providing, if not the same experience, then at least an equally useable one, for users on all browsers. This leads to plenty of hair-tearing as regards things like IE6 hacks or backups for unsupported CSS properties, but one thing which it is easy to forget is the necessity of being accessible to those users with disabilities, screen-readers, text-based browsers, and the like — users not experiencing your visual content in the generally accepted way.

One of the most important ways to ensure that your visual content is accessible to all visitors is the use of the “alt” attribute in any tags. After all, if your images are not being displayed for any reason — broken link, screen-reading technology, images disabled, etc. — the alt text will be the only thing which will be left to provide them with the same user experience you intended to offer. Any image which exists in the context of an HTML markup should always have an alt-text attribute, bar none; a screen-reader accessing an image without alt text will read off a long string of incoherent gibberish related to the image’s source.

In general you will have two different kinds of images you may be working with in a website — images which are used to disseminate information and images which are to be used purely for decoration, and each should be treated somewhat differently. An image used purely for decoration should be given null alt-text, an empty string:

<img src=”images/img1.jpg” alt=”" />

This might be useful, for example, if you are using breaker images to separate paragraphs, or have an image inserted to provide mood or affect the general feel, where an announcement of the image’s presence by a screen-reader would break up the flow of the page rather than provide any real enhancement.

On the other hand, often your images provide actual supplementary content. You might have an image which displays a graph backing up the main textual content; in this case you would want your alt-text to provide appropriate information which would compensate for the lack of the visual cue:

<img src=”images/graph1.jpg” alt=”Graph displaying experimental results and showing that x% of visitors to a given site use screen readers” />

Navigational and link image elements, since they will be identified as links, should be given alt text corresponding directly to their purpose, without too much extraneous data:

<img src=”images/home.jpg” alt=”Home” />
<img src=”images/about.jpg” alt=”About Us” />

In general, the idea is to provide a smooth “reading” experience for any visitor to the site. Alt text should provide only as much information as it needs too — not too much, which would distract from the rest of the content, or too little, which would prevent the site from fulfilling its ultimate purpose, which is to give the user information.


Even-Length Columns with CSS

Filed under: Coding, Markup and Styling — Rosalind Wills on December 6, 2009 @ 7:23 pm

Even-length columns with HTML/CSS

Recently I’ve found it necessary in a couple of my projects to set up a layout with more than one column of lengths which would vary between pages (i.e. on one page the right-hand column might be longer, on another the left-hand might be). In my searches for a solution I found a couple of different schools of thought on the best way to go about this, but I wanted to pass along the way which has seemed to work best for me.

Here’s the basic markup and styling for a simple two-column layout:

<html>
<head>
<title>Two columns!</title>
<style type="text/css">
     #wrap { width: 800px; }
     #column1 { width: 350px; background-color: #f00; float: left;  }
     #column2 { width: 425px; float: left; margin-left: 25px; background-color: #00f; }
</style>
</head>

<body>
    <div id="wrap">
         <div id="column1">
              <ul>
              <li>Menu Item 1</li>
              <li>Menu Item 2</li>
              <li>Menu Item 3</li>
              <li>Menu Item 4</li>
              <li>Menu Item 5</li>
              </ul>
         </div><!– End Column 1 –>

         <div id="column2">
              <p>Pellentesque habitant morbi tristique senectus et netus et
              malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat
              vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet
              quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat
              eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra.
              Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit
              amet, wisi.</p>

              <p>Pellentesque habitant morbi tristique senectus et netus et
              malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat
              vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet
              quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat
              eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra.
              Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit
              amet, wisi.</p>
         </div><!– End column 2 –>

    </div><!– End wrap –>

</body>
</html> 

As you can see, the right-hand column is considerably longer than the left-hand one, which might cause some problems with your layout if you’re trying to go, say, for one cohesive square.

To get started, you need to add enough padding to both columns that they will each absolutely be longer than their fellow column no matter how much longer they might be. Therefore, to each column, add some ridiculously large padding number, like so:

#column1, #column2 { padding-bottom: 5000em; }

Reload your page and you’ll find that the columns now stretch an absurdly long amount. We can counteract that by adding a negative margin of the same amount as the padding…

#column1, #column2 { padding-bottom: 5000em; margin-bottom: -5000em; }

…and causing the container div to hide the excess space with the “overflow” property.

#wrap { width: 800px; overflow: hidden; }

And there you have it. Simple even-columned layout which will remain even, no matter which column has more content at any given time.

If you have a thought on a way to improve this, notice a typo or other error, or have another method you use for this purpose, please feel free to leave a message and let me know!