> From: Erik Beeson
> 
> That's what I get for not testing IE6 with my more complicated example
> :) I'm not surprised that IE has issues with this. Creating 
> dynamic script tags has been an issue too. IE seems to have a 
> lot of trouble modifying stuff in the head.

I'm not aware of any general problems with IE modifying elements in the
head. In particular, dynamic script tags have always worked fine for me -
and my widget JSON code relies heavily on them. I'd be curious to know any
specific problems you've seen in in this area.

The problem you ran into is specific to a style element (and would affect a
style element whether it's in the head or body). More on that in a minute.

> Here's a version that works on IE, FF, and Safari:
> 
> http://erikandcolleen.com/erik/projects/jquery/cssinject/cssinject3.html

That's a clever way to finesse the problem with IE - simply delete the
script element and create a new one. You could probably do that for all
browsers and skip the IE check.

The problem with IE is actually that it doesn't support DOM methods such as
appendChild and replaceChild on a style element. Instead, you have to use
the style.styleSheet property to manipulate the style element's contents.

To illustrate, here is the code I've been using for a while to do this. I
use these two functions:

   // Add a stylesheet to the document and return a reference to it
   function addStyle( css ) {
      var style = document.createElement( 'style' );
      style.type = 'text/css';
      var head = document.getElementsByTagName('head')[0];
      head.appendChild( style );
      if( style.styleSheet )  // IE
         style.styleSheet.cssText = css;
      else  // other browsers
         style.appendChild( document.createTextNode(css) );
      return style;
   }
   
   // Replace the entire contents of a stylesheet
   function changeStyle( style, css ) {
      if( style.styleSheet )  // IE
         style.styleSheet.cssText = css;
      else  // other browsers
         style.replaceChild( document.createTextNode(css), style.firstChild
);
      return style;
   }

To initialize things, I call:

   var styles = addStyle( '' );

Then, each time I want to reload the styles, I make this call:

   changeStyle( styles, css );

Where css is the text of one or more CSS rules - not including any <style>
tags, just the CSS itself.

(I could specify styles in the addStyle call, but usually I leave it empty
and add them in the changeStyle call.)

This code is very efficient - certainly more so than the jQuery code - but
in practical terms that may not make any difference.

-Mike

Reply via email to