Removing an expression set in a stylesheet

J

Jim Ley

Hi,

IE has the ability to setExpressions on stylesheets so you can
calculate the value of the css property through script.

For various reasons I'm wanting to use a side-effect of this to attach
an event to every element of a class in a document (I'm including
content from a lot of large 3rd party content, and iterating over the
entire DOM searching for the classes and then attaching the event is
proving too slow, aswell as being too late post-load as the pages are
long and interaction would ideally occur before onload fires, it's an
embedded IE only solution.)

The solution I'm using is:
<URL: http://jibbering.com/2004/1/setExpression.html >

<style type="text/css">
.chicken {
color:green;
moomin:expression(snork(this));
}
</style>
<script type="text/jscript">
statusCount=0;
function snork(el) {
el.onclick=handler;
window.status=++statusCount;
}
function handler() {
alert("Hi!");
}
</script>
</head>
<body>
<p class="chicken">
A paragraph.
</p>

Obviously this is far from ideal as it means that the onclick handler
is attached everytime the css is evaluated (and this is often!) so I
need to remove the rule after attaching it. However I can't find a
way of doing this!

Changing the className of the objects to something else doesn't
achieve it, playing with the style or runtimeStyle of the object
doesn't, calling removeExpression on the elements style doesn't do
anything. So nothing on the element itself seems to achieve it.

Turning to the stylesheet, none of disabling the entire stylesheet,
removing the rule, changing the cssText etc. seem to do anything and

styleSheetRule.style.removeExpression does not exist which would've
been the assumed way of doing it.

Does anyone know of a way? Setting the snork function to an empty
function does make performance reasonable, but with hundreds of these
classes on the page, it's still too slow - and I'm dealing with big
pages which is why parsing the DOM is too slow.

Jim.
 
R

Richard Cornford

Obviously this is far from ideal as it means that the onclick
handler is attached everytime the css is evaluated (and this
is often!) so I need to remove the rule after attaching it.
However I can't find a way of doing this!
<snip>

I couldn't find a way of removing/disabling the expression either and
having added an additional 4 thousand odd chicken class paragraphs to
the test page I could easily see how the expression was a problem as it
renders the rest of the JScript execution sluggish to say the least
(took ages for the handler function to put up the alert).

However, I experimented with adding another styleSheet entry after the
existing ones with a chicken class that would overload the -
moomin:expression(snork(this)); - with - moomin:expression(void 0); -
and when that worked it significantly improved the performance of the
handler function on my modified test page.

Using a test css file:-
---------------- expTest.css ----------------------
..chicken {
moomin:expression(void 0);
}
--------------------------------------------------------
- calling the IE createStyleSheet function in the onload handler:-

document.createStyleSheet('expTest.css');

- or creating an additional link element with the "disabled" attribute
set:-

<link rel="stylesheet" href="expTest.css" type="text/css" disabled>

-and then enabling it in the onload handler with:-

document.styleSheets[2].disabled = false;

- both seemed to broadly work, while creating a disabled STYLE element
and then enabling it in the same way as the link element did not work at
all.

Unfortunately I can only describe this as broadly working because I
notice that on initially loading/enabling the overloading
moomin:expression CSS file with the onload handler caused some of the 4
thousand odd paragraphs not to have the onclick handler set (the ones
toward the end of the HTML). Re-loading the test page resulted in all of
the paragraph onclick handlers being assigned and clearing IE's cache
resurrected the initial problem. Microsoft's documentation implies that
calling - document.recalc - should result in the expressions being
recalculated for all elements (so assigning the onclick handler) but
that did not help.

Richard.
 
J

Jim Ley

However, I experimented with adding another styleSheet entry after the
existing ones with a chicken class that would overload the -
moomin:expression(snork(this)); - with - moomin:expression(void 0); -
and when that worked it significantly improved the performance of the
handler function on my modified test page.

hmm, I think that's equivalent in performance to my snork=function()
{} onload, and I still think that's noticeably a bit slow... It's
very annoying it's such a neat solution...

Cheers,

Jim.
 
R

Richard Cornford

hmm, I think that's equivalent in performance to my
snork=function() {} onload, and I still think that's
noticeably a bit slow... It's very annoying it's such
a neat solution...

I tried a version of - snork=function(){}; - but I thought the void
expression was still much quicker (probably because there is no overhead
in calling the function).

However, kicking the problem about a bit more revealed some possibly
useful information. I had changed the status line report to:-

window.status=++statusCount+' '+el.style.getExpression("moomin");

- and unsurprisingly that just appended "undefined" to the status
report, until one of my experiments caused me to change the snork
function to return a string (but any non-undefined return value seems to
work). When I had done that I noticed that the first (4 thousand odd)
call(s) to snork appended "undefined" but from then on "snork(this)"
was appended. That means that with the first call to snork with a return
value the expression is somehow attached to the P element's style
object.

That prompted me to try calling - removeExpression - on the style
object. It appears that IE will not put up with - removeExpression -
being called from within snork so I did a quick experiment with
recording the P element's style objects in an array and then using
onload to run through the array calling - removeExpression("moomin"); -
on each recorded style object. That actually appears to work, but only
in combination disabling - document.styleSheets[0]; -.

This is the page I was testing with (I was testing locally so the URL
for the external CSS is not the original, and I have cut most of the P
elements from the test page):-

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>removeExpression Demo.</title>
<style type="text/css">
.chicken {
color:green;
moomin:expression(snork(this));
}
</style>
<link rel="StyleSheet" href="jibbering2.css" type="text/css">
<script type="text/jscript">
var toRemoveExp = [];
statusCount=0;
function snork(el) {
el.onclick=handler;
window.status=++statusCount+' '+el.style.getExpression("moomin");
if(el.style.getExpression("moomin")){
toRemoveExp[toRemoveExp.length] = el.style;
}
return 1;
}
function handler() {
alert("Hi! "+this.style.getExpression("moomin"));
}
window.onload=function() {
var ss=document.styleSheets[0];
ss.disabled=true;
for(var c = toRemoveExp.length;c--;){
toRemoveExp[c].removeExpression("moomin");
}
}
</script>

</head>
<body>
<h1></h1>
<p class="intro">An example of removeExpression failing in IE6,
this is an IE proprietary feature, so expect to see nothing
much if you're using other browsers.</p>

<div id="content">

<p class="chicken">
A paragraph.
</p>
<p class="chicken">
Another paragraph.
</p>
<!-- Repeat the previous 6 lines 2000 times -->

</div>
<p class="footer">Jim Ley - <a
href="mailto:[email protected]">[email protected]</a>, <a
href="/">Jibbering.com</a></p>
</body>
</html>

There are more elegant and efficient ways of arranging which style
objects to call - removeExpression - on, and I did notice that the
problem with some of the final P elements no getting the onclck handler
assigned on the initial load was still happening, but at least this does
demonstrate that the expressions can be removed.

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,145
Messages
2,570,824
Members
47,371
Latest member
Brkaa

Latest Threads

Top