An advanced, cross-browser, simple-to-use and accessible list-based DHTML Menu / JavaScript Menu
©2006 Vadikom - Bulgarian company settled in Plovdiv
This is a quite detailed manual and you most probably do not need to read everything. A good approach is to initially read carefully just the next couple of sections ("2 Glossary" and "3 Configuration fundamentals") before configuring the script on your pages and use all other parts of the manual as a reference - only when you need something. Note that everything you need to set in the configuration file (c_config.js) is also well commented.
You will meet the following terms on many places in this manual. Please take a look at these short descriptions so that you know what is referred to when these terms are used.
Below are described the basic steps to configure the SmartMenus 6 script.
First you need to create the menu definition unordered list structure on your page. Please take a look at the source of the example page to see how a valid structure looks like. Note that you have to use A elements inside all LI tags.
If you want to leave any menu item without link, just don't set the A element's href attribute and set its class attribute to NOLINK - e.g.:
<li><a class="NOLINK">text</a>...
You can also forbid the rollover effect for any menu item if you set the A element's class attribute to NOROLL - e.g.:
<li><a class="NOROLL" href="URL">text</a>...
Combination is also possible - e.g.:
<li><a class="NOLINK NOROLL">text</a>...
After you have created the unordered list structure set the id and class attributes of the root UL element to a desired value (it is better to use rather short values). Also if you plan to use separators between the menu items of your main menu(s) (not the sub menus), set the NOSEPARATOR class to the last LI element of the root UL element - e.g.:
<li class="NOSEPARATOR"><a href="URL">text</a>...
Please leave at least one new line or white space symbol after the closing </ul> tag of the root UL element of the menu tree. This will allow the browsers to initialize the menu tree as soon as it is loaded and not wait for the page load event to start the initialization.
Make sure you have linked the SmartMenus config (c_config.js) and script core (c_smartmenus.js) files in the head section of your page (preferably just before the closing </head> tag). Only in case you are using the "onload" attribute of the BODY element, you need to put the links to "c_config.js" and "c_smartmenus.js" after the opening <body> tag in the source.
The SmartMenus 6 configuration file (c_config.js) has 3 sections.
In the first section there are some variables controlling global functions of the script (like show/hide timeouts, highlight behavior etc.). There are 3 variables that may be a bit confusing for you (c_findCURRENT, c_findCURRENTTree and c_overlapControlsInIE) - if you like, you can learn what they can be used for in "5.4 About the c_findCURRENT and c_findCURRENTTree..." and "5.5 About the c_overlapControlsInIE...".
In the second section you will find some JS arrays that represent the CSS classes to be used for the menus. Here is where you can tweak the style of your menu tree(s).
Please note that the menu box styles are not applied to the main menus, they are only applied to the sub menus. This is due to some browser bugs and cross-browser inconsistencies (like the box-model differences). You can try setting the desired properties (e.g. border, padding, background) to the container of your main menu instead.
You can add new CSS classes if you need - just copy/paste one of the already defined. The CSS classes are assigned globally to the specific menu tree(s) in the third section of the configuration file (i.e. MENU TREE FEATURES). If you like, you can also set a custom class to any sub menu - please take a look at the "4.3 Setting custom style class for any sub menu" howto if you would like to learn how you can do this.
The third section is where you can set the specific features of your main menu(s) and their sub menus. Here you can set their position, item's arrangement, CSS classes etc. One thing deserves special attention in this section - make sure the CSS class you set for your main menu(s) is the same as the one you have set to the root UL element of your menu tree(s) in the page source.
The configuration file includes many useful comments so, hopefully, you should not have problems with it.
Q: What is this and why you may want to use it?
A: The core CSS for your main menu(s) is generated from the settings in the configuration file (c_config.js) and is the minimum required CSS code to make the main menu(s) look the same in all modern browsers. When included on the page this CSS code will ensure that your main menu(s) will remain styled for the users that have JavaScript support disabled in their browsers. If you do not include this CSS code on your page, your menu tree(s) will appear completely unstyled (as an unstyled list) for the users that have JavaScript support disabled in their browsers.
When you have finished tweaking the appearence of your menu tree(s), use the button below to display the core CSS. Please note that the file of the manual (manual.html) must be placed in the same directory as your configuration file (c_config.js) and the SmartMenus script core file (c_smartmenus.js) in order this button to function correctly.
Once the core CSS is generated just put it in an external .css file and link it in the head section of your page - just make sure it is placed before the link to the SmartMenus script core file (c_smartmenus.js) in the page source.
Normally you would probably need just one menu tree (i.e. one main menu with sub menus) on your pages. But you are actually not limited to just one - you can have as many menu trees as you like because the SmartMenus script supports adding unlimited number of menu trees on the same page.
If you would like to add a new menu tree, you will just need to copy/paste one of the config blocks from the third section (i.e. MENU TREE FEATURES) of the configuration file (c_config.js) and configure it for another menu tree. For instance, let's say the UL element that you want to transform into your new menu tree has the "MyMenu" id - e.g.:
<ul id="MyMenu" class="someClass">
...
</ul>
this means that you should simply update the config block you copied for your new menu tree like this:
c_menus['MyMenu']=[ // the UL element with id="MyMenu"
[
// MAIN-MENU FEATURES
...
and then configure the rest of the config block as you like.
Please note that you are allowed to include in your configuration file (c_config.js) config blocks for menu trees that don't exist on all of your pages. If a given menu tree is defined in the configuration file but its UL element is not available on the current page, the script will simply neglect the menu tree definition in the configuration file and will not produce a JavaScript error.
Removing a menu tree is as simple as deleting its config block from the third section (i.e. MENU TREE FEATURES) of the configuration file (c_config.js).
The CSS classes that can be used for the menu tree(s) are defined in section 2 of the configuration file (c_config.js). In the example found in the SmartMenus 6 download file there are just 2 style classes defined by default ("MM" is used for the main menu and "SM" is used for the sub menus). The CSS classes are assigned globally to the specific menu tree(s) in the third section of the configuration file (i.e. MENU TREE FEATURES).
However, you are not limited to just these global style classes for all menus. If you like, you can set custom style class for any sub menu. For the purpose, you will first need to define a new class in the configuration file - just copy/paste one of the already defined and update it as you prefer. Let's say you have defined the new "MyClass" style class - e.g.:
c_styles['MyClass']=[
[
// MENU BOX STYLE
...
You can assign this new class to any sub menu you like by setting the class attribute to the UL element that represents the sub menu:
<ul class="MyClass"...
Please note that this new custom style class will also be inherited by all sub menus of the menu it has been applied to.
Regardless of the global setting for width of the sub menus you have in the configuration file (c_config.js) - e.g.:
],[
// SUB-MENUS FEATURES
5, // X SubMenuOffset (pixels)
1, // Y SubMenuOffset
'auto', // Width ('auto',values in CSS valid units - px,em,ex)
...
you can still set custom width for any sub menu by using the "width" CSS property for the UL element that represents the sub menu:
<ul style="width:10em;"...
If you would like to customize any menu item (e.g. set it a different background, color, padding etc.), you can do this by setting an id to the item's A element - e.g.:
<li><a id="myItem" href="URL">text</a>...
and using some additional CSS - for the item's normal state:
#myItem, #myItem:visited {
/* any declaration(s) here */
}
If you would like to set different style for the visited state, you can, of course, create separate rules for #myItem and #myItem:visited. And for the item's hover/focus state:
#myItem:hover, #myItem:focus, #myItem:active, #myItem.XXO, #myItem.XXO:visited {
/* any declaration(s) here */
}
The interesting part here is the "XXO" class. This is the class that the SmartMenus script uses for highlighting the items when c_keepHighlighted is set true. The name of this class is generated from the name of the style class that is used for the menu that contains the item we are customizing and the letter "O" suffix. This means that if you are customizing an item from the main menu, you should replace "XXO" with "MMO" and if you are customizing an item from a sub menu, you should replace "XXO" with "SMO" as the classes for the main menu and the sub menus are named "MM" and "SM" by default. If you have changed the default names of the menu classes or you are using a custom class for the menu that contains the item you are customizing, you should change "XXO" accordingly.
If you would like to add an icon to a single menu item, you can do this by customizing the menu item (please take a look at the previous howto "4.5 Customizing any menu item") - setting it a custom background-image and some padding to free space for the icon. Just set an id to the item's A element - e.g.:
<li><a id="myItem" href="URL">text</a>...
and use some additional CSS:
#myItem, #myItem:visited {
padding-left:24px;
background-image:url(source_of_the_icon_image);
background-repeat:no-repeat;
background-position:4px 50%;
}
If you like, you can also set a rollover for the icon:
#myItem:hover, #myItem:focus, #myItem:active, #myItem.XXO, #myItem.XXO:visited {
background-image:url(rollover_source_of_the_icon_image);
}
The interesting part here is the "XXO" class. You can find a description about it in the previous howto above "4.5 Customizing any menu item".
When you use rollover for the icon, you may want to preload the image for the "on" state of the icon to make the rollover effect fast and smooth even the first time. You can use some JavaScript like this:
img1 = new Image;
img1.src = "rollover_source_of_the_icon_image";
If you want to add icons to more than one menu item, it is more practical to create a CSS class for the purpose to reduce the size of the CSS code needed. For instance, like this:
.hasIcon {
padding-left:24px !important;
background-repeat:no-repeat;
background-position:4px 50%;
}
The "!important" declaration is used for padding-left to make it take precedence over the default padding for the items. Then you need to set it to the menu items that you want to have icons:
<li><a id="myItem1" class="hasIcon" href="URL">text</a>...
<li><a id="myItem2" class="hasIcon" href="URL">text</a>...
After that you just need to set different background-image for the different items:
#myItem1, #myItem1:visited {
background-image:url(source_of_the_icon_image_for_myItem1);
}
#myItem2, #myItem2:visited {
background-image:url(source_of_the_icon_image_for_myItem2);
}
Adding a rollover for the icons can be done just like in the example above for adding an icon to a single menu item.
You can easily add tooltips to any menu item by setting the A element's title attribute - e.g.:
<li><a title="Tooltip for this menu item" href="URL">text</a>...
Please download this separate example/tutorial. It includes detailed step-by-step instructions for building a main menu from images with rollovers instead of text.
Please note that the menu box styles are not applied to the main menus, they are only applied to the sub menus. This is due to some browser bugs and cross-browser inconsistencies (like the box-model differences). You can try setting the desired properties (e.g. border, padding, background) to the container of your main menu instead.
SmartMenus 6 includes a couple of features that particularly affect the performance of the script. If you are not happy with the script's speed, you may consider disabling any of these features to improve the performance.
When activated this feature affects quite notably the initial load speed. But you probably wouldn't worry much about it as it is pretty good even on pages with really many menus/items.
This feature may also affect seriously the runtime speed (i.e. unfolding the sub menus) if configured in a particular way and if you have menus with many arrow images (i.e. with many items that have sub menus). The runtime performance of the script is seriously affected particularly when SubMenuImageVAlign is set to 'middle' in the style arrays in c_config.js - e.g.:
'middle', // SubMenuImageVAlign ('pixels from item top','middle')
Simply setting this to a pixel value:
'7', // SubMenuImageVAlign ('pixels from item top','middle')
will significantly improve the runtime speed of the script when sub menu indicator images are used. You can, of course, adjust the value so that the arrow image would appear vertically centered on most menu items. It will not be centered only on items that have 2 or more lines of text (but this is not a big issue and is even actually how the menus function in most Operating Systems).
If you are not happy with the script's speed as a whole when this feature is activated, you can disable it completely (although this is not recommended) by setting the following in the style arrays in c_config.js:
false, // UseSubMenuImage (true,false)
When the width for the sub menus is set to 'auto' the runtime speed of the script is quite notably affected for sub menus that have pretty many items (e.g. more than 10). So setting fixed width for the sub menus in the MENU TREE FEATURES section of the configuration file might be a good option in such cases - e.g.:
'15em', // Width ('auto',values in CSS valid units - px,em,ex)
Please note that even when you set global fixed width for all sub menus, you can still set custom width for any sub menu - please take a look at the "4.4 Setting custom width for any sub menu" howto to see how you can do this.
"CURRENT" is a special style class that can be used to highlight the item that links to the current location. The script can be configured to find that item automatically (if c_findCURRENT is set true) or you can manually set the class to any menu item - e.g.:
<li><a class="CURRENT" href="URL">text</a>...
If c_findCURRENT is set true, a special function will find the item that links to the current location of the window and will automatically apply it the "CURRENT" style class. The c_findCURRENTTree variable controls whether the parent items of the menu that contains the "CURRENT item" should also be applied the "CURRENT" style.
This variable controls a special feature of the SmartMenus script that solves a common problem in IE5/6 on Windows - the SELECT boxes in IE/Windows are special OS controls and DHTML layers cannot be displayed over them. This means that if any menu is to be displayed on a position where a SELECT box is placed, it will be partially hidden beneath the SELECT box.
To make sure this doesn't happen SmartMenus 6 relies on a couple of workarounds. In IE5.5+ the menus will simply appear on top of the SELECT boxes thanks to a built-in fix for the issue. However, in IE5.0x this is not possible and a function will hide all SELECT boxes found on the page when a menu is shown and will show the SELECT boxes again when the menu is hidden.
Please note that the runtime performance of the script in IE is a bit better when this feature is disabled.
The menu items (the LI elements) of a horizontal main menu are floated. This means that if you are using a horizontal relatively positioned main menu, you will have to clear the root UL element so that the main menu box takes its place correctly. You can do this by putting your root UL element inside a DIV element with the "clearFix" class set - e.g.:
<div class="clearFix">
<ul id="Menu1" class="MM">
...
</ul>
</div>
and using the following CSS:
.clearFix:after { /* for modern browsers */
content:".";
display:block;
height:0;
clear:both;
visibility:hidden;
}
.clearFix { /* for IE7/Win */
max-width:999999px;
}
* html .clearFix { /* for IE5-6/Win */
height:1px;
}
* html>body .clearFix { /* for IE5/Mac */
height:auto;
display:inline-block;
}
The above CSS code is a slightly modified version of the great technique for clearing floats without structural markup published on Position Is Everything and originally developed by Tony Aslett, of csscreator.com.
If you are using the "onload" attribute of the BODY element for some handler, it will overwrite the SmartMenus 6 onload event handler, which is crucial for some browsers.
An easy solution for this issue is to place the links to the SmartMenus 6 script files (c_config.js and c_smartmenus.js) after the opening <body> tag instead of in the head section of the page. This should solve the problem and will not harm any onload event handlers you currently use, as the SmartMenus script registers its onload event handler by preserving any previous existing event handlers and not replacing them.
Please visit the SmartMenus JavaScript Menu forums or email smartmenus {at} smartmenus [.] org. Thank you!