krycek
10-27-2006, 04:33 PM
I have some code that relies upon the manipulation of element attributes. A very simple example is to use mousedown to set a "state" attribute to "down", and then mouseup to set it back to "default". The CSS rules would then use [state=down] to make specific differences for the down state.
Probably best if I produce some example code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
.thing {
cursor: default;
background-color: #eeeeee;
border: 2px solid #000000;
height: 20px;
width: 150px;
padding: 2px 8px;
display: block;
position: relative;
}
.thing[state=down] {
background-color: #bbbbcc;
}
</style>
</head>
<body>
<div id="thing" class="thing">Click me!</div>
<div class="thing" state="down">Don't click me.</div>
<script type="text/javascript">
var thing = document.getElementById("thing");
thing.onmousedown = function() {
if (thing.setAttribute) thing.setAttribute("state", "down");
else thing.state = "down";
}
thing.onmouseup = function() {
if (thing.setAttribute) thing.setAttribute("state", "default");
else thing.state = "default";
}
</script>
</body>
</html>
The code above is a very simplified version of what's happening in my code. We're only bothered with one element here, so I've hard-coded a reference to that element being clicked, in order to keep everything to a minimum, rather than handle the event in a more sophisticated way.
The code works fine in Firefox, and the div's background colour changes.
However, in IE7, nothing happens.
I included a second element with the state attribute pre-set to "down", to show that IE7 is indeed properly applying the rules. It just doesn't seem to be doing so when I change the attribute dynamically.
A point of interest - if I attach the behaviour to the mouseover and mouseout events, the same thing happens (i.e. nothing!). However, if I include a rule anywhere that uses :hover - even if no elements exist to match the rule - then it will suddenly work. To see what I mean, change "onmousedown" to "onmouseover", and "onmouseup" to "onmouseout" in the JavaScript code above - no behavioural change. Then add a CSS rule - ".something:hover {}" - and suddenly it works.
This has led me to believe that IE7 has some code somewhere under the hood that only recalculates styles on mouseover/mouseout if one or more :hover selectors are used. Bizarre, but that's Microsoft!
The question therefore seems to be, how can I force IE7 to recalculate the CSS being applied? I don't really mind if I have to call some function every time I change an attribute - although it would be a bit of a pain, I just want this stuff to work. I've been Googling about this for over a week, on and off, and not found anything. I've also not come up with any fixes or alternatives.
Otherwise, if I'm doing something wrong, please could someone point it out! :)
[EDIT:] I just want to point out that I'm aware I could add/remove a class to the element's class/className attribute to achieve the effect that way. It's just that using attribute selectors is less messy, and more semantic.
Probably best if I produce some example code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
.thing {
cursor: default;
background-color: #eeeeee;
border: 2px solid #000000;
height: 20px;
width: 150px;
padding: 2px 8px;
display: block;
position: relative;
}
.thing[state=down] {
background-color: #bbbbcc;
}
</style>
</head>
<body>
<div id="thing" class="thing">Click me!</div>
<div class="thing" state="down">Don't click me.</div>
<script type="text/javascript">
var thing = document.getElementById("thing");
thing.onmousedown = function() {
if (thing.setAttribute) thing.setAttribute("state", "down");
else thing.state = "down";
}
thing.onmouseup = function() {
if (thing.setAttribute) thing.setAttribute("state", "default");
else thing.state = "default";
}
</script>
</body>
</html>
The code above is a very simplified version of what's happening in my code. We're only bothered with one element here, so I've hard-coded a reference to that element being clicked, in order to keep everything to a minimum, rather than handle the event in a more sophisticated way.
The code works fine in Firefox, and the div's background colour changes.
However, in IE7, nothing happens.
I included a second element with the state attribute pre-set to "down", to show that IE7 is indeed properly applying the rules. It just doesn't seem to be doing so when I change the attribute dynamically.
A point of interest - if I attach the behaviour to the mouseover and mouseout events, the same thing happens (i.e. nothing!). However, if I include a rule anywhere that uses :hover - even if no elements exist to match the rule - then it will suddenly work. To see what I mean, change "onmousedown" to "onmouseover", and "onmouseup" to "onmouseout" in the JavaScript code above - no behavioural change. Then add a CSS rule - ".something:hover {}" - and suddenly it works.
This has led me to believe that IE7 has some code somewhere under the hood that only recalculates styles on mouseover/mouseout if one or more :hover selectors are used. Bizarre, but that's Microsoft!
The question therefore seems to be, how can I force IE7 to recalculate the CSS being applied? I don't really mind if I have to call some function every time I change an attribute - although it would be a bit of a pain, I just want this stuff to work. I've been Googling about this for over a week, on and off, and not found anything. I've also not come up with any fixes or alternatives.
Otherwise, if I'm doing something wrong, please could someone point it out! :)
[EDIT:] I just want to point out that I'm aware I could add/remove a class to the element's class/className attribute to achieve the effect that way. It's just that using attribute selectors is less messy, and more semantic.