views:

536

answers:

5

I have a single image with 9 different states and the appropriate background-position rules set up as classes to show the different states. I can't use the :hover pseudo-selector because the background image being changed is not the same element that is being hovered over. I have defined the classes this way:

#chooser_nav {width:580px; height:38px; background:transparent url(/assets/images/chooser-tabs.jpg) 0 0 no-repeat; margin-left:34px;}
#chooser_nav.feat {background-position:0 0;}
#chooser_nav.inv {background-position:0 -114px;}
#chooser_nav.bts {background-position:0 -228px;}
#chooser_nav.featinv {background-position:0 -38px;}
#chooser_nav.featbts {background-position:0 -76px;}
#chooser_nav.invfeat {background-position:0 -152px;}
#chooser_nav.invbts {background-position:0 -190px;}
#chooser_nav.btsfeat {background-position:0 -266px;}
#chooser_nav.btsinv {background-position:0 -304px;}

Then, using jQuery, I have a series of hover rules based on a previous click event (the here-undeclared "cur" variable is properly declared elsewhere):

  $("#featured_races a").hover(function(){
    cur == "feat" ? $("#chooser_nav").attr("class", cur) : $("#chooser_nav").attr("class", cur+"feat");
  }, function(){
    $("#chooser_nav").attr("class", cur);
  });

  $("#invitational_races a").hover(function(){
    cur == "inv" ? $("#chooser_nav").attr("class", cur) : $("#chooser_nav").attr("class", cur+"inv");
  }, function(){
    $("#chooser_nav").attr("class", cur);
  });

  $("#behind_the_scenes a").hover(function(){
    cur == "bts" ? $("#chooser_nav").attr("class", cur) : $("#chooser_nav").attr("class", cur+"bts");
  }, function(){
    $("#chooser_nav").attr("class", cur);
  });

So, in Moz and WebKit browsers, this works fine. The classes are applied and the background image changes accordingly. Works in IE7 as well. However, in IE6, the background image never changes. The classes get applied appropriately, I verified this with the DOM viewer in MS's web dev tool. So, the jQuery is working. The class is getting applied, but no change is visibly occurring.

I'm kinda stumped here... Help me, Crackoverflow... you're my only hope...

EDIT: As far as className vs. setAttribute... the class is changing. attr("class", cur) is working. However, once the class is changed, the resulting rules are not applied visually... but the change of class is occurring.

EDIT 2: As for jQuery's class-specific methods: I originally had them in the code, and the result was the same. Again, the problem is not with the class not getting applied to the element... this has been verified to be happening. it's that once the class is on the element, for some reason, the element is not following the CSS rules set for that class...

A: 

Use className DOM property. setAttribute() is utterly broken in IE < 8.

porneL
+2  A: 

Guess one: Rendering bug 1

Make sure that you have triggered hasLayout on the elements. You can do this by giving them a height or, if that isn't a posibility then position = relative & z-index = 1, will also trigger hasLayout. Try it for these elements + suspect parent elements.

/* fix hasLayout bug for IE */
div#id {
  _height : 0;
  min-height : 0;
}

Guess two: Rendering bug 2

Sometimes, it may be necessary to force more rendering calculation than what the browser has decided. You can give the DOM a good kick by touching the body class:

document.body.className += '';

Guess three: Selector problems

IE6 doesn't support multiple class selectors, and maybe ID+Class except in some cases.

div.class1.class2 {
  border : 1px solid red; /* this will normally not work in IE6 */
}

I don't have IE to test with at the moment and can't remember weather #id.class is supposed to work (I feel it should), but I generally avoid any such things for IE6. You may need to change your selectors.

You'll need to set up a test to see if your selectors are working at all.

Variations that might work:

.inv#chooser_nav { background-position : 0 -114px; }

Or you might need to single the element out by a parent:

#someparent .inv { background-position : 0 -114px; }

IE6 additionally has problems with hover, so that might also be a factor.

Hope this helps. I'm sorry I can't be more definite, but getting past IE6's quirks is largely done with good old methods of trial and error, brute force, guessing, and a generous helping of patience.

Borgar
A: 

I ran into a similar problem; the class name was applied, the text colot changed as expected, however the background images did not immediately update. After I hovered over or out of the actual element the background was updated.

It turned out to be a conflict with the DD_belatedPNG library.

Can you elaborate a bit more on this? I've run into the same issue, and am also using the DD_belatedPNG library, so I guess it's the same issue you had.Did you manage to fix it at all? If so, how?
Ian Devlin
Never mind, sorted it myself.In case anyone else comes across this, I wrote a quick blog post about it: http://www.iandevlin.com/blog/2010/04/webdev/dynamically-changing-the-background-image-applied-with-the-dd_belatedpng-ie6-script
Ian Devlin
+1  A: 

IE6 has problems with the "double" css rules you are using.

#chooser_nav.bts {background-position:0 -228px;}

You are selecting an element with ID chooser_nav and class bts. This (very useful) construct just isn't reliable in IE6. If you can remove the ID-specifier, or target a parent element instead, that should fix your problem:

.bts {background-position:0 -228px;}

or

#chooser_nav_parent .bts {background-position:0 -228px;}
Magnar
A: 

I had this problem in ie7.

basically i was changing a class on a parent element to hide some elements and show others. the class changed and the element that was showing when the page was loaded was hiding and showing fine but the element that was not showing when the page was loaded never showed.

i noticed this only happened in some scenarios (god only knows to predict it).

my solution was to only hide the elements after the page was loaded with javascript.

daniel lehmann