Saturday, December 1, 2012
0 comments

jQuery Rich Media Dropdown Menu

10:21 AM
Today’s tutorial combines two good friends, jQuery and dropdown menus! “That boring old combination”, I hear you cry. But wait, this is a dropdown menu with a difference! It takes away all menus from your website, except for one easy to navigate list of top level links, with one dropdown menu for each, containing as menu child categories and as much rich media as you want!  Don’t take my word for it, go and try the demo yourself.

The Plan

The jQuery rich media dropdown menu is going to take away the usual clutter of menus we are used to seeing on ecommerce websites and allow products the space they deserve. In this tutorial, we will write a script that does just that, making sure it is cross browser compatible, easy to navigate and degrades gracefully in the absence of JavaScript or CSS. Go nab the demo to tinker with yourself if you haven’t already or carry on reading to find out what all of that code means! If you want to skip all of that, shoot straight to the demo.

The HTML

The HTML is rather simple (as HTML should be!). Infact, it’s just a big unordered list with a couple of classes thrown in for good measure. We’ll get to those classes later on, for now, here’s a snippet of the HTML:
1<ul id="nav">
2    <li><a href="#">Home</a></li>
3    <li><a href="#">DVD</a>
4        <ul>
5            <li><span>Shop By Category</span>
6            <ul>
7                <li><a href="#">Family</a>
8                    <ul>
9                        <li><a href="#">Comedy</a></li>
10                        <li><a href="#">Action</a></li>
11                        <li><a href="#">Cartoons</a></li>
12                        <li><a href="#">Interactive</a></li>
13                    </ul>
14                </li>
15                <li><a href="#">Drama</a>
16                    <ul>
17                        <li><a href="#">Period</a></li>
18                        <li><a href="#">Modern</a></li>
19                    </ul>
20                </li>
21            </ul>
22            </li>
23            <li><span>Browse DVD</span>
24                <ul>
25                    <li><a href="#">A-Z</a></li>
26                    <li><a href="#">Now Available</a></li>
27                    <li><a href="#">Top Sellers</a></li>
28                    <li><a href="#">Coming Soon</a></li>
29                    <li><a href="#">Pre-Order Chart</a></li>
30                    <li><a href="#">Special Offers</a></li>
31                </ul>
32            </li>
33            <li><span>Latest Releases</span>
34                <ul>
35                    <li><a href="#">Titanic</a></li>
36                    <li><a href="#">Alien Vs Predator</a></li>
37                    <li><a href="#">Terminator 2</a></li>
38                    <li><a href="#">Meet the Parents</a></li>
39                </ul>
40            </li>
41            <li><span>Hottest Title</span>
42            <ul>
43                <li><a href="#"><img src="images/dvd.jpg" width="123" alt="DVD" />DVD</a><span class="price">£1.99</span></li>
44            </ul>
45            </li>
46        </ul>
47    </li>
48</ul>
Let’s take a look at what that code means:
1<ul id="nav">
2    <li><a href="#">Home</a></li>
3    <li><a href="#">DVD</a>
4        <ul>
Level of links
Level of links
We begin with an unordered list that contains top level links for our websites categories. The ‘Home’ link doesn’t have any sub categories but the ‘DVD’ link does, so we nest another unordered list inside of it.
1</p>
2
3<p>&lt;li&gt;&lt;span&gt;Shop By Category&lt;/span&gt;
4            &lt;ul&gt;
5                &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Family&lt;/a&gt;
6                    &lt;ul&gt;
7                        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Comedy&lt;/a&gt;&lt;/li&gt;
8                        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Action&lt;/a&gt;&lt;/li&gt;
9                        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Cartoons&lt;/a&gt;&lt;/li&gt;
10                        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Interactive&lt;/a&gt;&lt;/li&gt;
11                    &lt;/ul&gt;
12                &lt;/li&gt;
13                &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Drama&lt;/a&gt;
14                    &lt;ul&gt;
15                        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Period&lt;/a&gt;&lt;/li&gt;
16                        &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Modern&lt;/a&gt;&lt;/li&gt;
17                    &lt;/ul&gt;
18                &lt;/li&gt;
19            &lt;/ul&gt;
20            &lt;/li&gt;
21            &lt;li&gt;&lt;span&gt;Browse DVD&lt;/span&gt;
22                &lt;ul&gt;
23                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;A-Z&lt;/a&gt;&lt;/li&gt;
24                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Now Available&lt;/a&gt;&lt;/li&gt;
25                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Top Sellers&lt;/a&gt;&lt;/li&gt;
26                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Coming Soon&lt;/a&gt;&lt;/li&gt;
27                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Pre-Order Chart&lt;/a&gt;&lt;/li&gt;
28                    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Special Offers&lt;/a&gt;&lt;/li&gt;
29                &lt;/ul&gt;
30            &lt;/li&gt;
Inside of that unordered list, we have various ways to browse the DVD section, ie, “Shop by Category”, “Browse DVD” etc.
Rich media
Images in the dropdown menu
We can also include in the dropdown menu media such as images:
1<li><span>Hottest Title</span>
2            <ul>
3                <li><a href="#"><img src="images/dvd.jpg" width="123" alt="DVD" />DVD</a><span class="price">£1.99</span></li>
4            </ul>
5            </li>
Above we have another unordered list inside the DVD category, with it’s own unordered list that contains images for the “Hottest Title”.

The jQuery

Firstly, as with all jQuery scripts, we’ll reference the script itself in the HTML document as well as the jQuery library:
1<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
2<script src="dropdown-menu.js" type="text/javascript"></script>
Now, let’s take a look at dropdown-menu.js. We begin the script unfortunately, having to fix Internet Explorer 6′s (IE6) shortcomings:
1$("#nav > li").css({"display": "inline", "background-color": "#ececec", "margin": "0 10px"});
2$("#nav > li > ul").css({"padding": "5px", "position": "absolute", "width": "auto"});
3$("#nav > li > ul > li").css({"color": "black", "height": "100%", "padding": "0 0 0 5px", "width": "175px"});
Our script relies on child selectors in the CSS which IE6 doesn’t support. Simply by applying that CSS via jQuery though, we can step around that issue. If IE6 doesn’t have JavaScript enabled, we don’t need this particular CSS anyway so all is good.
The CSS is setup to make the navigation usable in case JavaScript is disabled. If it is enabled though, we want to use different CSS to create the styling for our dropdown menus. We simply do that as follows:
1$(&quot;#nav li &gt; ul&quot;).css({&quot;background&quot;: &quot;white&quot;, &quot;border&quot;: &quot;#ccc solid 2px&quot;});
2$(&quot;#nav ul ul&quot;).css({&quot;background&quot;: &quot;none&quot;, &quot;border&quot;: &quot;none&quot;});
3$(&quot;#nav li &gt; ul&quot;).css({&quot;color&quot;: &quot;#999&quot;, &quot;display&quot;: &quot;block&quot;, &quot;float&quot;: &quot;left&quot;, &quot;margin&quot;: 0, &quot;padding&quot;: &quot;10px&quot;, &quot;left&quot;: &quot;auto&quot;});
4$(&quot;span&quot;).css(&quot;display&quot;,&quot;block&quot;);
5$(&quot;#nav li&quot;).css({&quot;display&quot;: &quot;inline&quot;});
6$(&quot;li li&quot;).css({&quot;float&quot;: &quot;left&quot;, &quot;margin&quot;: &quot;0&quot;, &quot;font-size&quot;: &quot;12px&quot;});
7$(&quot;.show ul li ul&quot;).css({&quot;display&quot;:&quot;block&quot;});</p>
8
9<p>$(function() {
10    $('#nav &gt; li').hover( function(){
11    $(this).css('background-color', '#ccc');
12},
13function(){
14    $(this).css('background-color', '#ececec');
15});
16});
Lines 1 – 7 simply apply the CSS required to style the dropdown menus. Lines 9 – 16 are a hover event that changes the background colours of our top level links when the user hovers over them.
1$("#nav > li").children("ul").css("display", "none");
Finally, for the CSS, we hide all of the dropdown menus (because we don’t want them to appear until the user hovers over a link).
Now we get down to adding some functionality to the script. Firstly, an important variable that determines the vertical position of where each dropdown menu should appear:
1var top = $("#nav > li").position().top + $("#nav > li").height();
We want each dropdown menu to appear directly below its respective navigation link. We can find that position by getting the position of the navigation link relative to the top of the document and then find the height of that link and add the two values together.
Once we’ve worked out where to position each dropdown menu, we create a hover event that triggers when a user hovers over any of the navigation links:
1$("#nav > li").hover(
2    function () {
This sets up the event to wait for the user to hover over a link. When the event is triggered we must work out the left position of where we want to place the dropdown menu, as well as determining if the dropdown menu will be too wide for the page:
1var left = $(this).position().left;
2var offset = $(this).offset().left;
3var width = $(this).children("ul").width();
4var over = (left + width) - 940;
The first line gets the left position of the navigation link that the user is hovering over (relative it’s parent, the <body> ).
The second line gets the left position of that same link but this time, relative to the overall document.
The third line gets the width of that navigation link’s respective dropdown menu.
Finally, the fourth line works out how much the dropdown menu will overhang the <body> of the page. If there is an overhang, we’ll need to adjust the left position to keep it ontop of the webpage, as opposed to disappearing off the screen.
1if(left + width > 940){
Our next line checks to see if indeed, the dropdown menu is going to be wider than the website. In that case we need to do the following:
1$(this).children("ul").css("display", "block");
2$(this).children("ul").css({left:left-over, top:top});
We begin by showing the dropdown menu. We then set it’s position using the variables we’ve already determined. Because we know the dropdown menu is going to overhang the page, we take that amount of overhang from it’s left position, meaning it gets nudged to the left a little and sits flush with the right of the page.
A note about Internet Explorer here: Internet Explorer has terrible support for jQuery’s .offset method so instead, I’ve used .css. There is a bug in Internet Explorer 8 which means the .offset or .css methods won’t work without a ‘top’ value specified. Hence, the extra bit of coding to find that out. The .css method is also more cross browser compatible too (the values you give it work the same in all browsers).
Once we’ve dealt with a dropdown menu that overhangs, well deal with dropdown menus that won’t overhang:
1}else{
2    $(this).children("ul").css("display", "block");
3    $(this).children("ul").css({left:left, top:top});
4}
As you can see, this is almost the same as the overhang version. The only difference is we don’t need to adjust the left position of the dropdown menu because it fits nicely into the webpage.
Our final piece of jQuery is an event for when the user moves their mouse out of the dropdown menu:
1function () {
2    $(this).children("ul").css("display", "none");
3}
This simply hides the dropdown menu when the user moves their mouse outside of it. That’s it!

Graceful Degradation

With any script, it’s important to make sure it offers a working version if JavaScript is disabled. As stated earlier on, the CSS of the script is setup to act as if the JavaScript is disabled but if it isn’t, the JavaScript overwrites that CSS so it can get its jiggy on regardless.
Without the JavaScript, we can’t have fancy hover events or dropdown menus, so instead, we’ll return to a more traditional navigation menu, simply listing the top level navigation links as well as the second level links for whatever page the user is on.
Graceful Degradation
How the menu looks without JavaScript enabled
This is where we use a few extra classes in the HTML to let the browser know which child links we want to display.
Let’s say for example, the user is on the “Clothing” page, as demonstrated in the image above. We need to make that tab a different colour and show just one child list of links (remember there’s more than one list of child links). We can do that using the classes “active” and “show”:
1<li class="active"><a href="#">Clothing</a>
2        <ul>
3            <li class="show"><span>Shop By Category</span>
4            <ul>
5                <li><a href="#">Mens</a></li>
6                <li><a href="#">Womens</a></li>
7                <li><a href="#">Shirts</a></li>
8                <li><a href="#">Ties</a></li>
9                <li><a href="#">Shoes</a></li>
10                <li><a href="#">Fancy Dress</a></li>
11            </ul>
12            </li>
13            <li><span>Browse Clothing</span>
14                <ul>
15                    <li><a href="#">Mens</a></li>
16                    <li><a href="#">Womens</a></li>
17                    <li><a href="#">Top Sellers</a></li>
18                    <li><a href="#">Coming Soon</a></li>
19                    <li><a href="#">Special Offers</a></li>
20                </ul>
21            </li>
class=”active” is the current page the user is on. It changes the colour of the tab to signify where the user is amongst those links.
class=”show” will display the child list of the “active” tab as a second level menu. It makes the most sense to display a list of categories as the second level menu but the script will allow you to choose whatever second level you want, simply by moving class=”show”.
What about the <span> tags, you say? We don’t want the title of the second level list to show in the absence of JavaScript, so in the CSS we have made anything in a <span> tag display: none. Amazing, huh?

The Conclusion

The script is a great way to remove all of that hefty navigation from the page, letting your products do the talking. At the same time, the website is still accessible with semantic and W3C valid HTML. If you were to use this in a live website, the classes “show” and “active” could be applied dynamically.

0 comments:

 
Toggle Footer