Now updated for horizontal, vertical and tertiary menus.
All Browsers are different. Case closed. But the W3C DOM has improved things (or is it just a high quality Gecko implementation) - which actually only makes the differences more annoying!
We have changed our cross-browser philosophy (big word) 'cos:
Here's what we are doing now and all the code reflects (more or less!!) this policy:
There is ton of stuff out there about the W3C DOM but the best, by far, that we found is in the 'Resources' side-bar under 'Life Savers' and in our links pages.
The holy grail of the HTML, XHTML and XML object worlds is the W3C Document Object Model DOM Versions 1 and 2 (see Resources and forget DOM 1).
Confusingly Microsoft uses two terms: the DHTML Object Model (a DOM) and the W3C'ish Document Object Model (another DOM). They are different. The DHTML Object Model was supported from IE4, the W3C DOM 'ish from IE 5.5+.
Our minimum browser choice is IE4 so we use the DHTML Object Model (backward compatibility is very strong with MSIE so all that crummy old code will still work in MSIE 6+).
The MSIE Event model 'bubbles-up' vs Gecko/NS 'top down' event model.
A very W3C compliant browser which is a pleasure to work with and with some excellent documentation - normally the achilles heel of Open Source projects. If you are not using it you should be. The event model is largely based on the NS4.x philosophy but without the event generation limits.
We came to do the update for the version 5 browsers having read all the stuff about W3C DOM compatibility and thinking it would be a breeze - and it wasn't.
We have some simple text rollover effects and they work in both browsers (MSIE and Gecko) unmodified. Very impressive. One hour and the site was updated.
We are going to lay out our pages as follows:
NOTE: In the descriptions below you will be offered two forms of each file. A Cross-Browser version containing code/definitions for all browser families we support and which is conditionally generated using Apache Server Side Includes statements and a Browser specific version which shows you the code that is supplied for, and is unique to, the browser you are using.
The current implementation of our Cross Browser CSS definitions are here (loads in a separate window as a text file, use the 'save as' browser button to save as an .SHTML file) or you can view your browser specific Pop-Out menu CSS definitions here. They both load in a separate window so you can read the accompanying text and look at the code.
You will notice three major differences in CSS definition:
Point Size: e.g. 'n-l-o' and 'codegray' styles differ only in font point size on MSIE and Gecko/NS4.x. The rendering below 10pt is so poor on NS/Gecko that we generally have to add 1 more point for NS/Gecko than MSIE. Note: It is generally NOT a good thing to use an explicit point size but rather the relative values 'small' or 'x-small' etc. since it facilitates 'accessibility' options. Since there is no consistency in implementation of point size to 'small' etc. we use point size far more frequently than we should.
NS4.x Style Limitations 'popup' is defined for NS and 'n-p-o' is its equivalent style for MSIE/Gecko. If you run our Home Page with both browsers you will see a 'HighLight' text rollover in MSIE/Gecko but none in NS4.x. You cannot apply a 'class' style when changing an NS4.x layer value, you must instead apply separate 'bgColor' and 'Color' attributes to the layer. Since this defeats the objective of using CSS we chose to avoid using it completely in NS4.x.
The current implementation of our Cross Browser 'Primary' DHTML definitions are here (use the 'save as' browser feature to save as an .SHTML file) or you can view your browser specific 'Primary' Menu definitions here. They both load in a separate window so you can read the accompanying text and look at the code (wow - at the same time).
There are a number of points of difference here:
To get full width for any 'text rollover highlight' in NS4.x you need to define a layer with 'width="100%"'. That clinched the decision to use the 'LAYER' TAG (even though we finally decided against use of 'highlighting' in NS4.x (see CSS notes above). Here we must point out a life-saving article on the topic of text rollovers in NS4.x. We managed to crash NS4.x repeatedly until we found this article.
The current implementation of our Cross Browser 'Secondary' (Pop-Out) DHTML definitions are here (loads in a separate window as a text file, use the 'save as' browser button to save as an .SHTML file) or you can view your browser specific 'Secondary' (Pop-Out) Menu definitions here. They both load in a separate window so you can read the accompanying text and look at the code.
This set of definitions includes the initially invisible tables that are 'pop'd out' when the user 'mouses over' the various menus. There are significant differences here reflecting the differing browser philosophies:
We use a 'DIV' TAG for MSIE/Gecko and apply the class style 'p-n-h' which gives each table the attributes 'position:absolute' and 'visibility:hidden' (among others). The initial values of both 'top' and 'left' are arbitrary (its hidden - does it matter where!). Note the 'onmouseout' event in each table cell for MSIE. See note above.
We use the 'LAYER' TAG (NS4.x only) and explicitly define in the layer the attributes we want (VISIBILITY, TOP and LEFT). The attribute POSITION="ABSOLUTE" is implicit in the use of LAYER (if you wanted POSITION="RELATIVE" you would use an 'ILAYER' TAG instead). The documentation says that 'DIV' TAGs can be used in NS4.x but we could never get them to work. NOTE: There are no defined 'onmouseout' events for NS4.x. See DHTML notes above.
The code mostly reflects the various differences in manipulation of the object models and consists of eight functions, pop() (all browsers), popdown() (Gecko/NS4.x only), clip()(MSIE/Gecko only), unpop() (MSIE/Gecko only), unpop() (Gecko/MSIE only), swapout() (MSIE only , null function for Gecko), popclean() (MSIE/Gecko only), mousemoved() (NS4.x only, provides same functionality as Gecko popdown()).
Note: The functions swap() and lock() are generic text rollover functions we use extensively, gotourl() is a simple redirect - none have anything to do with this article.
The function pop() takes three parameters 'p' (the menu level), 's' (the id value of the menus to be made visible) and 'axis' which may be 'h' = horizontal or 'v' = vertical. Primary, secondary and tertiary menus are are all identified with 'id="hx" or id="sx" values so the calling parameters are simple numbers. This function generates the 'clipping area' used by the swapout() or popdown() functions i.e the visible area covered by the 'Primary' and 'Secondary' menus. You will see various 'fudge' factors all over the place which provide various 'guard bands' after much experimentation. One day we will clean this code up and provide a reasonable explanation. When this function is called it now makes sure that all other menus are 'off' (via the popclean() function), 'cos we had menus getting stuck from time to time (a bug - no way!!). Finally to make this code generic we have used arrays to hold all the global objects and clip data. In theory this means we are unlimited in the menu levels we can support (oh really!).
In the NS4.x version of pop() you will find the 'captureEvent(Events.MOUSEMOVE)' which hooks the 'mousemove' events to the mousemoved() until you are out of the clipping area. In MSIE this is done with a standard onmouseout event. In Gecko we use a W3C obj.addEventListener() to the popdown() function.
The function swapout() is an MSIE only function (which does the same as the mousemoved()/popdown() functions of NS/Gecko). The purpose is to capture the current position of the mouse from the 'window.event' object and if it has moved OUT of the clipping area to 'pop-down' the relevant menu and turn off the highlight. The only other wrinkle of note is the use of the window.body.scrollTop and scrollLeft which are essential to ensure everything works when you scroll the page.
popdown() in Gecko (and it's mousemoved() NS equivalent) is functionaly equivalent to swapout() of MSIE. Its purpose is to capture the current position of the mouse and if it has moved OUT of the clipping areas to 'pop-down' the 'Secondary' menu.
W3C'ish support We tried to use a single 'onmouseout='swapout();'' function but we couldn't find the mouse co-ordinates in Gecko in about 3 hours reading. Then we found the 'relatedObject' property but it did not provide reliable results in Gecko. Since MSIE is religious about backward compatibility we left its code untouched and now generate conditional code for Gecko only ('isW3C' and NOT 'isIE'). In the pop() function we set up the 'clipping area' as normal and then hook the onmouseout events for the menu areas using the addEventListener property into the popdown() function which automatically supplies the 'event' object from which we obtain the mouse co-ordinates. If we are outside the 'clipping area' we hide the relevant menus, change the 'className' properties and remove the 'onmouseout' events via the removeEventListener property of the object.
All a bit disappointing and maybe if we had a lot more time we could find a better solution.
Problems, comments, suggestions, corrections (including broken links) or something to add? Please take the time from a busy life to 'mail us' (at top of screen), the webmaster (below) or info-support at zytrax. You will have a warm inner glow for the rest of the day.
If you are happy it's OK - but your browser is giving a less than optimal experience on our site. You could, at no charge, upgrade to a W3C standards compliant browser such as Firefox