www.webdeveloper.com
Results 1 to 3 of 3

Thread: workaround for dynamic stylesheets in chrome

  1. #1
    Join Date
    Feb 2007
    Location
    New Zealand
    Posts
    190

    workaround for dynamic stylesheets in chrome

    i recently ran into this bug in chrome, and i was wondering if anyone can think of a workaround.

    i have tried using innerHTML/appendChild to add style/link element to the body/head.

    the following snippet has two links which SHOULD change the background

    Code:
    <!DOCTYPE html>
    <html>
    	<head>
    		<title>test</title>
    		<style type="text/css" title="not me"></style>
    		<script type="text/javascript">
    			// method to easily create elements
    			function createElement(nodeName, params){
    				// create element
    				var o = document.createElement(nodeName);
    				document.body.appendChild(o);
    				// attach all the params
    				for (var param in params){
    					// look for param in the style object
    					if (o.style[param] !== undefined){
    						o.style[param] = params[param];
    					}
    					// add the param to the object
    					else {
    						o.setAttribute(param, params[param]);
    					}
    				}
    				// return the new object
    				return o;
    			}
    			// add missing reference to head element
    			if (!document.head){
    				document.head = document.getElementsByTagName('head').item(0);
    			}
    			// method to dynamically add styles
    			var cssSheet;
    			function addStyle(selector, attributes){
    				// error wrapper
    				try {
    					// create the stylesheet if needed
    					if (cssSheet === undefined){
    						// create a blank stylesheet
    						document.head.insertBefore(createElement('style', {
    							type: 'text/css',
    							title: 'dynamicSheet',
    							media: 'screen'
    						}), document.head.firstChild);
    						// find the corresponding css stylesheet object
    						for (var i = 0; i < document.styleSheets.length; i++){
    							if (document.styleSheets[i].title === 'dynamicSheet'){
    								cssSheet = document.styleSheets[i];
    								break;
    							}
    						}
    						// show error if unable to create stylesheet
    						if (cssSheet === undefined){
    							throw new Error('Error creating dynamic stylesheet');
    						}
    						// firefox creates stylesheet as disabled, so enable it
    						cssSheet.disabled = false;
    					}
    					// w3c
    					if (cssSheet.insertRule !== undefined){
    						cssSheet.insertRule(selector + '{' + attributes + '}', cssSheet.cssRules.length);
    					}
    					// ie
    					else {
    						cssSheet.addRule(selector, attributes);
    					}
    				}
    				// show error
    				catch (e) {
    					alert(e.stack);
    				}
    			}
    		</script>
    	</head>
    	<body>
    		<a href="javascript:void(0);" onclick="addStyle('body', 'background-color:yellow;');">test</a>
    		<a href="javascript:void(0);" onclick="addStyle('body', 'background-color:green;');">test</a>
    	</body>
    </html>
    Last edited by toenailsin; 02-19-2011 at 11:29 PM.

  2. #2
    Join Date
    Feb 2007
    Location
    New Zealand
    Posts
    190
    i tried appending the rules to an existing stylesheet, creating one if none exist (this chrome bug doesn't appear when there is a single stylesheet) and keeping a reference to the added rules in an array. the problem with this is that IE 6 consistently outputs -1 from the addRule function.

  3. #3
    Join Date
    Feb 2007
    Location
    New Zealand
    Posts
    190
    heres the code regarding my last post. i welcome any input into this matter.

    Code:
    <!DOCTYPE html>
    <html>
    	<head>
    		<title>test</title>
    		<style type="text/css" title="not me"></style>
    		<script type="text/javascript">
    			// method to easily create elements
    			function createElement(nodeName, params){
    				// create element
    				var o = document.createElement(nodeName);
    				document.body.appendChild(o);
    				// attach all the params
    				for (var param in params){
    					// look for param in the style object
    					if (o.style[param] !== undefined){
    						o.style[param] = params[param];
    					}
    					// add the param to the object
    					else {
    						o.setAttribute(param, params[param]);
    					}
    				}
    				// return the new object
    				return o;
    			}
    			// add missing reference to head element
    			if (!document.head){
    				document.head = document.getElementsByTagName('head').item(0);
    			}
    			// method to dynamically add styles
    			var cssRules = [];
    			function addStyle(selector, attributes){
    				// error wrapper
    				try {
    					// grab a stylesheet from the page
    					for (var i = 0; i < document.styleSheets.length; i++){
    						var sheet = document.styleSheets[i];
    						break;
    					}
    					// attempt to create one
    					if (sheet === undefined){
    						var style = document.head.appendChild(createElement('style', {
    							type: 'text/css',
    							media: 'screen'
    						}));
    						var sheet = (style.sheet !== undefined) ? style.sheet : style.styleSheet;
    					}
    					// w3c
    					if (sheet.insertRule !== undefined){
    						var i = sheet.insertRule(selector + '{' + attributes + '}', sheet.cssRules.length);
    						cssRules.push(sheet.cssRules[i]);
    					}
    					// ie
    					else {
    						var i = sheet.addRule(selector, attributes);
    						if (i === -1){
    							alert('IE 6 encountered');
    						}
    						else {
    							cssRules.push(sheet.cssRules[i]);
    						}
    					}
    				}
    				catch (e) {
    					alert(e.stack);
    				}
    			}
    		</script>
    	</head>
    	<body>
    		<a href="javascript:void(0);" onclick="addStyle('body', 'background-color:yellow;');">test</a>
    		<a href="javascript:void(0);" onclick="addStyle('body', 'background-color:green;');">test</a>
    	</body>
    </html>
    i'm currently thinking that i might implement both these methods. the first one works in all browsers except chrome due to its bug. Chrome is easily detectable, so i should be able to switch it to the second method pretty easily
    Last edited by toenailsin; 02-20-2011 at 02:23 PM.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles