Using jQuery’s hover() event to the fullest

Using jQuery’s hover() event to the fullest

The problem

Today at work I was given the task of using jQuery to create a very specific effect. I have an unordered list with three list items. When the user rolls over one of them, the item gets a class which sets the background to a new color, while any other item that has that class, has it removed. On top of that, if the container the list is in loses focus (meaning the cursor leaves the container), the last list item hovered on should retain the background changing class. On top of THAT, whenever one of those said list items is hovered over, one of three content divs below it should go from hidden to visible. Oh, and I have to have the second item started off as looking like the hover state. This one took me a while to figure out. I could get the normal rollover, but the keeping the class thing when the list item lost focus through me for a loop.

Click here to take a look at the final working jQuery. You’ll see what I was trying to do if you roll over and out and what not.

Code Red

The html is simple enough, but if you want to follow along with what I did, here you go:

<div id="container">
	<ul id="buttons">
    	<li>Box 1</li>
        <li>Box 2</li>
        <li>Box 3</li>
    </ul>
</div>
<div id="content">
	<div id="cont1">Content 1 box</div>
    <div id="cont2">Content 2 box</div>
    <div id="cont3">Content 3 box</div>
</div>

The CSS is irrelevant other than the ‘over’ class (which just changes the list item background color to purple), so I won’t list it, but here is the jQuery:

$('#cont1, #cont3').hide();
	$('#cont2').show();
	$('#buttons li:nth(1)').addClass('over');
	var cont1 = $('#cont1');
	var cont2 = $('#cont2');
	var cont3 = $('#cont3');
	var button = $('#buttons li').focus();
 
	$('#buttons li').hover(function() {	
			var target = button.index(this);
			$('#buttons li').removeClass('over');
			$(this).addClass('over');
 
			if(target == 0) {
				cont1.show()
				cont2.hide();
				cont3.hide();
			} else if (target == 1){
				cont1.hide()
				cont2.show();
				cont3.hide();
			} else {
				cont1.hide()
				cont2.hide();
				cont3.show();
			};
 
	}, function () {
			$(this).removeClass('over');
			if($('#buttons').blur()) {
				$(this).addClass('over');
			} else {
				$(this).removeClass('over');	
			}
	});

The Solution

Let me first say that there is probably a more efficient way to do this, and I’ll post updates as I shave some of the code down. This works though, so if you are ever in need of doing something like this, or parts of it, here goes the explanation.

The first two lines are to get the second content div to show, while the other two are hidden. The third line (shown below) is to get the second list item the over class, which is the rollover state (purple color).

$('#buttons li:nth(1)').addClass('over');

After that, I am setting three variables that I will use later in the if/else state. The last line in that section is to set a variable (button) to whatever list item has focus:

var button = $('#buttons li').focus();

The fun part!

Onto the actual hover! Obviously I am setting the hover onto the ‘li’, and right after that, I have another variable called target. This is equal to the index value of whatever list item has focus. Directly after that I am removing the class ‘over’ from all of the list items (kind of like a reset), and then re-adding the ‘over’ class to the hovered over li. This takes care of the color switch while rolling over any of the list items while staying within the ul element.

if(target == 0) {
				cont1.show()
				cont2.hide();
				cont3.hide();
			} else if (target == 1){
				cont1.hide()
				cont2.show();
				cont3.hide();
			} else {
				cont1.hide()
				cont2.hide();
				cont3.show();
			};

What is all that crap? That is to show and hide the content divs. This is where my code can probably be a lot better, but I’m under a time crunch, and I worked on it at home. If the index value of the list items (which is what target is set to) is equal to 0, show the first content div (cont1), and hide the other two. The else if shows the middle, and the else shows the third. That takes care of the hover. Now onto the…well, un-hover.

What happens when I move my mouse away from that garbage?

}, function () {
			if($('#buttons').blur()) {
				$(this).addClass('over');
			} else {
				$(this).removeClass('over');	
			}
	});

When the user rolls off of the list item, it checks to see: did they leave the unordered list? If they did, add the class back to the list item they were on last, otherwise remove the class ‘over’, because it means they are rolling over a different list item.

*NOTE – blur() is the opposite of focus(). The blur event is sent to an element when it loses focus.

Conclusion

This was one of those times where it really hit home to think about what you need things to do before just jumping into writing the code. I did it in small chuncks, starting with what needs to start hidden/shown. Then broke it down into the hover section, and the un-hover chunck. Is this the perfect solution? No, I know I can trim this down. Maybe with a case switch? Or better variables for the content divs? Delegate? If you see something I can improve, let me know. I’ll personally keep working on refining it, and I’ll let you know when I come up with something better. I think that, since this post dealt with jQuery, I’ll leave off the jQuery junkBox section tonight. I don’t want to overload your mind.

As always, let me know if you have any questions.

Coupon Code: webmachine

Tags: ,

Leave a Reply