Forum Moderators: open

Message Too Old, No Replies

Opera's Upward Style Cascade

Peculiar results from the Nordic user-agent

         

Rambo Tribble

1:47 am on Jan 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



For a hoot (yes, I don't get out much) I put together a function to do a generic style flip-flop, toggling between the original style attribute value and one passed to the function.

As different browsers use different attribute value formats for color and font size, I set the function up to convert the passed parameter to the native format. To do this, the function applies the style attribute on an empty span (created, as needed, by the script), then reads back the value from the span, the browser having converted the values in the process.

All of this works delightfully until you start using ems on Opera. If the containers for the target element are either not styled for font-size or given font-size values of 1em (or 100%), the script fails. Even more curious are the values returned when this occurs. For real fun, set the base font to 1.2em and see what the returned values are. The script works, then, but for the wrong reason.

Perhaps even more enigmatic, a well-placed alert brings results back in line, but it's not where a timeout should make any difference.

I present this anomaly for your consideration (I have set it up initially with a px specification for the body's base font-size, so it will work as it should):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Style Toggling Script 1/7/05</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<style type="text/css">
body{font-size:16px;} /* change to 1em to break script in Opera */
#divOne{display:block;height:300px;width:500px;background:#dde;}
#divTwo{height:100px;width:100%;text-align:center;padding-top:2em;}
#divThree{height:80px;width:300px;background:#ccaaaa;margin:auto;
border:4px groove #fff;text-align:center;padding-top:20px;font-size:1em;}/*another opportunity to play*/
</style>
<script type="text/javascript">
/*
styTog() -- a function to toggle CSS style attributes
This function accepts four parameters from the calling event:
targ_id, which is the id of the target element;
sty_attrJ, which is the style attribute's name in JavaScript syntax;
sty_attrC, which is the style attribute's name in CSS syntax;
set_val, which is the second toggle state value;

The element id, "zedSpan" is reserved for this function's use.
Note: Opera fails to properly read the base font value, if it is expressed
as ems or %. This causes the function to fail for font-size changes,
if the base font is not set or is expressed as 1em or 100%.
*/
function styTog(targ_id,sty_attrJ,sty_attrC,set_val){
var targ=document.getElementById(targ_id);
var targ_stat="";
var targ_sty="";
var attr_chk=sty_attrC.toLowerCase()
var excp_flag=0;
if(attr_chk.indexOf("color")!=-1 ¦¦ attr_chk.indexOf("font")!=-1){
excp_flag=1;
if(!document.getElementById("zedSpan")){
var insSpan=document.createElement("span");
insSpan.setAttribute("id","zedSpan");
document.body.appendChild(insSpan);
}
var zS=document.getElementById("zedSpan").style;
zS[sty_attrJ]=set_val;
}
if(targ.currentStyle){ //code for IE
if(excp_flag==1)set_val=zS[sty_attrJ];
targ_stat=targ.currentStyle[sty_attrJ];
}else{ //code for W3C-spec-compatible
if(excp_flag==1){
var tst_span=document.getElementById("zedSpan");
var tst_sty=document.defaultView.getComputedStyle(tst_span,"");
set_val=tst_sty.getPropertyValue(sty_attrC);
//alert(''); // uncomment this alert to get proper functionality in Opera, this alert
// can be anywhere from here to above the assignment of targ_stat to work
excp_flag=0;
}
targ_sty=document.defaultView.getComputedStyle(targ,"");
targ_stat=targ_sty.getPropertyValue(sty_attrC);
}
//alert(targ_stat+"\n"+set_val); // uncomment this alert to see values
targ_stat!=set_val? targ.style[sty_attrJ]=set_val : targ.style[sty_attrJ]="";
}
</script>
</head>
<body>
<!-- the four parameters being passed to the styTog() function are: the target element's id,
the JavaScript attribute name, the CSS attribute name, and the value for the second toggle state -->
<button onclick="styTog('divOne','visibility','visibility','hidden');">block see / no-see</button>
<button onclick="styTog('span1Div2','display','display','none');">inline see / no-see</button>
<button onclick="styTog('divThree','marginTop','margin-top','40px');">vertical shift</button>
<button onclick="styTog('divThree','backgroundColor','background-color','#0be');">color shift</button>
<button onclick="styTog('span1Div3','fontSize','font-size','2em');">font-size shift</button>
<div id="divOne">
<div id="divTwo">
Text, with a<span id="span1Div2">n inline span, as the</span> target.
</div>
<div id="divThree"><span id="span1Div3">Text</span>
</div>
</div>
</body>
</html>

Rambo Tribble

3:09 pm on Jan 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I should mention that it occurred to me that the problem might stem from the HTML-rendering engine not being called betwixt the getPropertyValue() calls, but insertion of an innerHTML command that writes to the display, in place of the appropriate alert, has no effect.

Rambo Tribble

4:00 am on Jan 14, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Gee, kinda quiet around here. Any thoughts? Should I report this to those fine folks at Opera? (No, Bernard, not the silence, the apparent bug.)

Bernard Marx

12:59 pm on Jan 20, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ah yes. Apologies, Mr. Tribble.

I'm not not often online at the moment, spending rather too much time on an isolated laptop in my student cell away from home. I have saved your code, but I won't be able to express an opinion until said laptop is introduced to Opera.

Rambo Tribble

3:35 pm on Jan 20, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I appreciate your attention to the matter, Mr. Marx. I was toying with submitting it to Opera, but it would be nice to have some input. After all, as some luminary said, "All eyes are shallow, given enough bugs." Oh, wait, that's not it. How did it go? Well, in the context of my code, that probably works.