The other day I was reading this good article from ilovecolors, talking about how to do a folding menu for Wordpress with jQuery. As I wasn't really happy with the classic nested menu that Shopp offers by default, I though that this would be great and no so hard to acheive...
In fact, if you don't have any sub-categories in your website, you don't need this at all. But if, like me, you have a lot of products and you want to organise them in different categories and sub-categories, then you will understand the need of having a better solution than the default nested menu that Shopp offers at start.
Before to start, please keep in mind that I'm not a pro at coding, I'm more of a designer. So feel free to correct me if needed or to help by providing something better.
Oh, you also need to include jQuery, but normally it should be the case already with Wordpress or Shopp.
Let's go! Here is the first version.
jQuery(document).ready(function(){
jQuery(".children").hide();
jQuery(".active").slideDown();
});
As you can see the first version is quite short ^_^
I'm using the built-in classes from the Shopp's nested menu (using either the widget or shopp('catalog','category-list') tag). The children instances have all the .children class and when you are in a category's page, this instance has the .active class. So with this really short piece of code, you already have an easy way to hide all your sub-categories and to make them visible only in the category you're in.
Ok, so now that we have a basic way to handle or sub-categories, let's add a little bit fun.
I though it would be great to have a "roll-over" action on the categories. The goal would be to show sub-categories when the user goes over a category with his mouse. When he goes out the category, the sub-categories should be hidden again. Of course I want to use the slideDown() and slideUp() functions from jQuery to add some nice movements.
Here is the second version.
jQuery(document).ready(function(){
// Roll over functions
jQuery(".shopp_categories li").hover(
function() {
jQuery(this).children(".children").slideDown(); // Show the sub-categories
},
function() {
if(jQuery(this).children("ul").hasClass(".active") == false) {
jQuery(this).children(".children").slideUp(); // Hide sub-categories if we are not in the current category
}
}
); // End roll over
jQuery(".children").hide();
jQuery(".active").slideDown();
});
Using the hover() function from jQuery, I've added 2 functions. The first one will show the sub-categories when you roll-over a category. The second one will hide them if we are not in the current category. So if you click on a category or a sub-category, the menu will stay open, but if you just roll-out from this category without clicking, the sub-categories will disapear again in a smooth movement.As the CSS classes are always the same for children instances or active instances, this script should work for an unlimited number of levels.
Now, if you have tried the code above, perhaps you've noticed a little problem. It is too sensitive.
To avoid the accidental movements or very quick movements of the mouse, we should add a delay to the animations. Just try to go from one category to another and you will see what I mean. I could have used a simple timeout function, but why do that when a really nice jQuery plugin exists? The plugin is called hoverIntent and this is what the author, Brian Cherne, says about it:
"hoverIntent is a plug-in that attempts to determine the user's intent... like a crystal ball, only with mouse movement! It works like (and was derived from) jQuery's built-in hover. However, instead of immediately calling the onMouseOver function, it waits until the user's mouse slows down enough before making the call.Why? To delay or prevent the accidental firing of animations or ajax calls. Simple timeouts work for small areas, but if your target area is large it may execute regardless of intent."
To use it, download the script on the author's page and include it in your theme like a normal javascript (after jQuery). Then we just have to use the function hoverIntent() in place of hover() and that's all!
Here is the third and last version.
jQuery(document).ready(function(){
// Roll over functions (you can comment all the roll over part if you don't want it)
jQuery(".shopp_categories li").hoverIntent(
function() {
jQuery(this).children(".children").slideDown();
},
function() {
if(jQuery(this).children("ul").hasClass(".active") == false) {
jQuery(this).children(".children").slideUp();
}
}
); // End roll over
jQuery(".children").hide();
jQuery(".active").slideDown();
});
Now when we roll over a category, we have a short delay before the animation goes on.
Edit: I've just noticed that by default the timeout delay is 0 in hoverIntent.js
I will add two more steps to this article, one to simplify the script (rewriting) and the other to add the hoverIntent.js configuration.
Here we go:
Rewriting
jQuery(document).ready(function(){
// Roll over functions (you can comment all the roll over part if you don't want it)
jQuery(".shopp_categories li").hoverIntent(roll_over,roll_out);
// Roll over and roll out functions
function roll_over() {
jQuery(this).children(".children").slideDown();
}
function roll_out() {
if(jQuery(this).children("ul").hasClass(".active") == false) {
jQuery(this).children(".children").slideUp();
}
} // End roll over
jQuery(".children").hide();
jQuery(".active").slideDown();
});
As you can see I've just put the slideDown() and slideUp() functions out of the hoverIntent. Like this it's more easy to read and to modify if needed.
Finally I will add the hoverIntent configuration's object.
Final final version.
jQuery(document).ready(function(){
// Roll over functions (you can comment all the roll over part if you don't want it)
jQuery(".shopp_categories li").hoverIntent(
{
sensitivity: 7,
interval: 100,
over: roll_over,
timeout: 300, // Ajust timeout to your needs
out: roll_out
}
);
// Roll over and roll out functions
function roll_over() {
jQuery(this).children(".children").slideDown();
}
function roll_out() {
if(jQuery(this).children("ul").hasClass(".active") == false) {
jQuery(this).children(".children").slideUp();
}
} // End roll over
jQuery(".children").hide();
jQuery(".active").slideDown();
});
With this last version, I'm able to modify the hoverIntent's default configuration. The most important parameter for me is timeout. With 300 as a value, I'm sure that there won't be any hover loops when someone goes from one category to another.
I've updated the zip file below with this last version.
Here is a demo (see the left navigation menu, under "Notre Catalogue").
Here is a zip file to download with the 2 scripts, just in case you had some problems to copy and past from this page:
To install I think the easier is to open your Wordpress theme header.php file and to include the 2 javascripts just before the </head> tag.
Of course you can use this script as you want without any restriction.
Feel free to comment this article if you find it usefull or not, and perhaps to correct my English if needed ;-)



















Thank you so very much for sharing this. You saved my day!!!!!!
This works wonderful!