PDA

View Full Version : Script to make :hover work in IE



alexjewell
04-09-2006, 12:16 AM
I have a drop down menu (flamehtmlstudios.com/amanda/beta) that wont work in IE because IE doesn't support to :hover atrribute on anything but links. I need a JavaScript that will make the :hover work, maybe as a mouseover or something...but I'd like it to still keep my html web standard and everything.

Anyway, I'm not sure where to go or what to do, so maybe someone could hook me up?

It's for my gf...and she's getting a little upset because it's not working yet...lol

There's also already a script there I tried writing myself to fix the issue...but it's not working...so just disregard that...

And maybe this is even possible with php? Who knows...

ddadmin
04-09-2006, 01:42 AM
Instead of trying to modify your existing code, I'll just point you to suckerfish (http://www.alistapart.com/articles/dropdowns/), which basically a CSS menu with some JavaScript thrown in to account for IE. A cut and paste version is available here (http://www.cssdrive.com/index.php/examples/exampleitem/css_drop_down_menu/).

alexjewell
04-09-2006, 02:12 AM
Ah...I prefer writing the stuff myself.
And unbelievably: I just looked at my script and there's: not a whole lot different. I'm still looking for a script.

mwinter
04-09-2006, 02:49 PM
flamehtmlstudios.com/amanda/beta (http://flamehtmlstudios.com/amanda/beta/)Before we get into the question at hand, a few general notes and criticisms.


You overstate the case regarding IE and CSS. Yes, it's true that IE doesn't support CSS 3, but that's not the issue; most browsers don't support CSS 3 (except, for example, the opacity property) and much of CSS 3 hasn't reached Recommendation, yet. The problem with IE is that it fails to support many CSS 2 features, and that which is supported contains numerous bugs.
Don't serve XHTML as HTML. It's utterly pointless and a bandwagon worth ignoring. There's nothing wrong - quite the opposite, in fact - in using HTML 4.01.
The class attributes on two of the links in your navigation list are superfluous. Remove them. Similarly, the empty list items should be removed. Replace them with top padding on the nested list elements.
The title attributes on your links (in general) doesn't really add any value. If you expanded them to more than the link text, then there might be a reason to keep them. For example, the Portfolio title could be, "Examples of Amanda's recent work".
There's a typo in 'Sciptures' [sic] :)
Rather than emitting a meta element, you'd be better off getting the server configured properly.
The lang and xml:lang attribute values on the html element are 'pl', however the document seems to be very much English, to me. The lang attribute should reflect the content. Whether you, Amanda, or anyone else is Polish is irrelevant. The document isn't.
Your style sheet could benefit from much tidying. For example, consider starting with the rule,



* {
margin: 0;
padding: 0;
}
and then redefine margins and padding as necessary, rather than removing both in numerous others places. There are also many instances where you go about using separate properties, rather than the shorthand, or needlessly over-specify values within a shorthand. For instance, the body rule could be reduced to:



padding: 0 10%;
margin: 0; /* This could be removed if you followed the suggestion above. */

font: 12px/1.6 tahoma, sans-serif;
letter-spacing: 1px;

background: #cccccc url(images/bg2.gif) repeat-y left fixed;
color: #444444;

There are instances (in the navigation menu, for example) where you use pixels to define widths related to text. Don't. Use em units, which are relative to the font size applied to that element. The use of absolute units tends to lead to fragile designs when a different font size is used by the visitor.
On a similar thread, don't use pixels to define font sizes. IE can't resize them, which is a problem for accessibility. Use percentages, instead. Ideally, body text should remain at 100%, and nothing should end up smaller than 85% of that (including copyright notices and other legalese).
You have a rule near the end of your style sheet to style span elements with an underline class attribute value. First of all, underlining should generally be avoided, and reserved only for links. Secondly, class names should be semantic, not presentational. As you don't actually use that rule, I can't suggest a definitive alternative, but use the em element for emphasis, replacing the italic style with something else, if necessary.
Finally, and this one's awkward, make sure that you aren't relying on default colours to acheive your colour scheme. Generally, a color declaration should always be accompanied by a background (or background-color) declaration, and visa versa.



I need a JavaScript that will make the :hover work, maybe as a mouseover or something...but I'd like it to still keep my html web standard and everything.Fixing your script is trivial, but the aftermath has thrown me for a loop. For some reason, hiding and showing the submenus causes IE to reflow the entire menu, making it wider. I can't see the cause, even after stripping out much of the style sheet. I would take ddadmin's suggestion of using an existing solution. I can understand why you'd want to write something from the ground up - I tend to enjoy it myself - but I don't see anything special regarding what you're trying to achieve, so it seems foolhardy. Perhaps you'll see the cause, though. I only spent a few moments on it.

I'll first walk through your code, highlighting general problems and specifically why it fails in this case. I'll then present a replacement.



startList = function() {
All variables should be explicitly declared using var statements. Not only is it good form, but it can avoid problems in IE.

If you really needed to access this function by name, and you don't necessarily, then it should be defined with a function declaration:



function startList() {
However, if you only intend to assign it to some other property, then:



this.onload = function() {
will do.



if (document.getElementById) {
Feature testing the getElementById method is good, but you should go further. Other DOM properties should be examined before you use them, and you it's wise to check the return values of methods that can return null.



navRoot = document.getElementById("nav");
This is once again an example of a variable that's missing a var declaration (the variables i and node are the same). Omitting the declaration will make these variables global, which is not desirable.



for (i=0; i<navRoot.childNodes.length; i++) {
Your biggest problem is the use of the childNodes collection, which you seem to have misunderstood. It contains the children of the node, not its descendents. In your markup, the only children of the containing navigation div element is a couple of whitespace text nodes, and the list element.



node.onmouseover=function() {
this.className+=" over";
}
Evaluation of this assignment expression, and the one that follows it, on each iteration of the loop will create new function objects. At the moment, that means you'd create four objects, though only two are necessary.

The alternative to that is:



if (document.getElementById)
this.onload = function() {
var className = 'over',
pattern = new RegExp('(^|\\s+)' + className + '(\\s+|$)'),
navigation, elements;

function showSubmenu() {
if (!pattern.test(this.className))
this.className += ' ' + className;
}
function hideSubmenu() {
this.className = String(this.className).replace(pattern, ' ');
}
function hasSubmenu(element) {
var nodes;

if ((nodes = element.childNodes))
for (var i = 0, n = nodes.length; i < n; ++i)
if (nodes[i].tagName == 'UL')
return true;
return false;
}

if ((navigation = document.getElementById('nav'))
&& navigation.getElementsByTagName) {
elements = navigation.getElementsByTagName('li');

for (var i = 0, n = elements.length; i < n; ++i)
if (hasSubmenu(elements[i])) {
elements[i].onmouseover = showSubmenu;
elements[i].onmouseout = hideSubmenu;
}
}
navigation = elements
= null;
};
If you have questions about its operation, feel free to ask. I didn't comment it to save time, and for the sake of space (this post is already long enough :)).


And maybe this is even possible with php? Who knows...No, it's not. This issue must be fixed client-side.

Mike