Edited on the 25th March 2009 due to errors in the post and amendments to the code, apologies to anyone who has run into any problems, it should all go smoothly now.

Introduction

During the development of this tutorial, I discovered that my previous post on jQuery Expandable Navigation actually described a method to allow unlimited level expanding navigation, instead of two tiers like I initially thought. As I have improved upon that method I will be posting a Revised version of that post to use the jQuery that I will detail in this tutorial. It is essentially the same, however it is cleaner and offers the choice of an animated toggle/a class based one.

Aim

What I am going to explain today is how to utilise this piece of code in conjunction with the Click-Show-Hide Categories plugin for Zen Cart. Whilst this plugin states it is for Zen Cart 1.3.7 it is fully compatible with 1.3.8 as well. There are several files that you will need to edit so pay close attention, especially if you’re new to Zen Cart. I will not be going into detail about how to install Zen Cart or style the list once it is in place, I will simply be explaining how to enable the functionality. Please note that the instructions that follow are only relevant if you are inplementing this manually and not using the .zip I have provided at the end of this post as I have completed most of the process for you in the .zip.

Get & install the plugin

The first step is to download the plugin zip which can be downloaded from here. I’d like to say thank you to the author of this plugin, Cameron Clark, as without this plugin I wouldn’t be writing this post. Install the plugin by following these steps:

  1. Unzip the package, retaining the folder structure.
  2. Rename “YOUR_TEMPLATE” folders to match the name of your custom template. Copy files to your existing zencart folder. No core files are overwritten on a “vanilla” install of Zencart 1.3.8.
  3. In Admin > Tools > Layout Boxes Controller, you should now have a new sidebox called sideboxes/YOUR_TEMPLATE/categories_css.php. Enable it and disable the standard categories sidebox.

Once the new categories box is displaying on your site we can now start to change this to a jQuery menu

Including jQuery in Zen Cart

As we are using jQuery, the first thing we need to do is include it in the head, the file you need to edit is /includes/templates/YOUR_TEMPLATE/common/html_header.php . Place your jQuery file in /includes/templates/YOUR_TEMPLATE/jscripts/ and then add in the following code to html_header.php, replacing the jQuery file name with the version you are using if it isn’t 1.3.2:

<script type="text/javascript" src="includes/templates/YOUR_THEME/jscript/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
	document.getElementsByTagName('html')[0].className = 'js';
</script>

Alternatively you may wish to link to the Google CDN version of jQuery, this does have several benefits, the main one being speed as if your user has visited a site that links to the Google version of jQuery they will already have it cached and won’t need to download the file again. You can get the paths to do this from the Google Ajax Libraries API Page.

You’ve probably noticed that I’ve added an extra script block. This is to remove the Flash of Unstyled Content that this script will cause on large pages, if you wish to understand this in more depth please read my previous post on jQuery Expandable Navigation as I’ll be ensuring it doesn’t occur with my code, but not explaining it in detail.

Editing the javascript

Delete all of the Javascript from the following file: /includes/templates/YOUR_TEMPLATE/jscript/categories_css.js . The code that you want to place within this file is as follows:

$(function() {			   
	   
	$('li').children('ul').hide();
	
	$('li:has(ul)').children('a').click(function() {
												 
		// $(this).parent('li').children('ul').toggle();
		$(this).parent('li').children('ul').slideToggle();
		
		return false;		
		
	});	
	
	$('html').removeClass('js');
	
	/* the following two lines will ensure that the UL opens to the section that you had open on
 the navigation when you left the page, if you wish the navigation to simply revert back to all the
 categories being closed when you leave a page then remove the two lines of code below */
	
	$('a.on').parent('li').children('ul').show();
	
	$('a.on').parent('li').parent('ul').show();

});

Now you may be wondering why some lines are commented out, basically the default functionality is to toggle a sliding animation when the category expands to display its sub categories, you can change this to simply show/hide the category by uncommenting the following line…

// $(this).parent('li').children('ul').toggle();

… and then commenting out the line below it. To switch between animation and toggle functionality it is as simple as commenting one of these lines out depending on what you wish to happen. It makes sense to keep the animation in considering the original plugin works like this by default however I thought I would keep the option there for anyone that wanted it. If you wish the animation to take a specific amount of time to compete, pass a parameter into the slideToggle like so:

// this animation will last for 400 milliseconds, simply change the number to edit this or leave it blank for the default animation
$(this).parent('li').children('ul').slideToggle(400);

Editing the appearance

As the original plugin was styled using the CSS included with the plugin, we can now delete this file (/includes/templates/YOUR_TEMPLATE/css/categories_css.css) and also make a couple of changes to the php file which tells Zen Cart where to find the styling for the new sidebox.

Open up /includes/templates/YOUR_TEMPLATE/sideboxes/tpl_categories_css.php and remove the following piece of code:

// Load CSS file if this sidebox is enabled
$content .= '<link rel="stylesheet" type="text/css" href="' . $template->get_template_dir('.css',DIR_WS_TEMPLATE, $current_page_base,'css') . '/categories_css.css" />'."\n";

We can remove this reference as I am going to style the navigation using the main Zen Cart stylesheet file which can be located at /includes/templates/YOUR_TEMPLATE/css/stylesheet.css . The next step is to edit the following piece of code in the same file:

// Load containing UL and content
$content .= '<ul class="bullet-menu" id="siteMenu">';

The important thing to edit the class and remove the id. The class that I have added (foo) will be used to style the navigation. Your code should now look like the code below, with foo replaced with the class name you wish to use:

// Load containing UL and content
$content .= '<ul class="foo">';

Before we close this file and save the changes, you also need to remove the following code from the bottom of the script as it no longer serves a function due to the changes we have made to the javascript (it causes a JS error if you leave it in, so for validation purposes make sure to remove it):

// Preload menu images when page loads (won't affect IE, which never caches CSS images)
$m = $template->get_template_dir('.gif', DIR_WS_TEMPLATE, $current_page_base,'images/menu').'/';
$content .= '<script type="text/javascript">addDOMEvent(window,"load",function() {preloadImages("'.$m.'branch.gif","'.$m.'leaf-end-on.gif","'.$m.'leaf-end.gif","'.$m.'leaf-on.gif","'.$m.'leaf.gif","'.$m.'node-end-on.gif","'.$m.'node-end.gif","'.$m.'node-on.gif","'.$m.'node-open-end-on.gif","'.$m.'node-open-end.gif","'.$m.'node-open-on.gif","'.$m.'node-open.gif","'.$m.'node.gif")}, false);</script>'."\n";

Now we have made these changes we can edit /includes/templates/YOUR_TEMPLATE/css/stylesheet.css and use the class we assigned to the UL to style it’s appearance. Finally, add the following line of CSS to your stylesheet:

.js ul.foo { display: none; }

This will stop the FOUC. Another benefit that this snippet of CSS gives us is that it will hide the Navigation until the jQuery has run due to the class of js not being removed until the end of the script. This will stop users clicking on the navigation before the jQuery has run.

Config

By default the navigation is configured to go up to 5 subcategories deep, but can be set to however deep you desire by modifying $max_level var in categories_ul_generator.php. Many thanks to Cameron again as without his work this wouldn’t be possible.

Degredation

I’m sure many people are reading along and wondering, “this is all well and good, but what happens when the user disables Javascript?”. Well the nice thing about this solution is that as long as we add one new CSS rule into our stylesheet it will degrade nicely for users with Javascript off:

ul.foo li ul { display: none; }

This hides the sub UL’s that appear when Javascript is off because the full navigation gets generated and this piece of CSS then hides the sub category UL’s. If you’re wondering if this is accessible or not, then breathe a sigh of relief as the navigation will now take you to the “Categories” page where you can navigate deeper into your shop in the traditional Zencart manner.

Conclusion

So, there we have it, incorporating jQuery expandable navigation into a Zen Cart installation. You can view an example of this at h2omudnsnow and also a bare bones example. I Hope someone finds this useful!

I will be developing this solution to have visual indicators as to whether the li is expandable or not as this is the main advantage of the original solution, so expect another blog post in the near future.

Don’t really fancy doing it yourself? Download one I made earlier and simply enable the new sidebox in the Zen Cart admin (Admin > Tools > Layout Boxes Controller). The UL has been given a class of jqNavigation for you to style it with. There are a couple of changes you need to make to avoid overwriting core files with the default ones so please read the Readme carefully!