IE6 throwing “Access is denied” when concatenating to styleSheet.cssText
-
03-07-2021 - |
Question
There is a dynamically created <style>
tag and I'm concatenating an additional piece of css to it. This is part of a larger framework for dynamically loading modules.
Originally it created new style tags but due to the famous "31 stylesheet limit" this is no longer an option, so I decided to recycle existing style tags (unless they contain too many rules or if the new string contains @import, in which case a new one has to be created regardless).
Anyway, I got it working in all major browsers (FF2+, Chrome14+, Opera10+, IE7+, Safari 4.0+) and now IE6 is giving me headaches.
I am familiar with this error from other scenarios, but I've never seen in this this context. Also, don't bother any IE6-timeywimey, I'm well aware of it. But this is unfortunately an exceptional case where IE6 support is still required.
Note that the bracket count is solely for estimating and debugging purposes. The try/catch wasn't around the cssText +=
originally, I added it because I found it throwing an exception in IE6.
Solution
I found the answer to my own question. It turns out IE6 has an obscure security measure that disallows manipulation of elements indirectly created by other scripts (even if they come from the exact same origin/domain).
In this case the simplified method was working fine, but the actual code was failing. The only difference was that the actual code was using jQuery to store data, create elements and insert elements. That last action (inserting elements) was the problem.
I changed
/**
* @param {jQuery|HTMLElement} $nextnode
*/
function addStyleTag( text, $nextnode ) {
var s = document.createElement( 'style' );
// IE: Insert into document before setting cssText
if ( $nextnode ) {
// If a raw element, create a jQuery object, otherwise use directly
if ( $nextnode.nodeType ) {
$nextnode = $( $nextnode );
}
$nextnode.before( s );
/* ... */
to:
/**
* @param {jQuery|HTMLElement} nextnode
*/
function addStyleTag( text, nextnode ) {
var s = document.createElement( 'style' );
// IE: Insert into document before setting cssText
if ( nextnode ) {
// If a jQuery object, get raw element, otherwise use directly
if ( nextnode.jquery ) {
nextnode = nextnode.get( 0 );
}
nextnode.parentNode.insertBefore( s, nextnode );
/* ... */
And that fixed the problem.