Adding #import statement in a dynamic stylesheet for IE7+ - javascript

I have a problem with adding a dynamic style element with #import statements for IE. Try this:
var string = '#import url(test.css)';
var style = document.createElement('style');
if (style.styleSheet) { // IE
style.styleSheet.cssText = string;
} else {
var cssText = document.createTextNode(string);
style.appendChild(cssText);
}
document.getElementsByTagName('head')[0].appendChild(style);
This works for FF/Chrome but not IE. It seems to recognize style.styleSheets.imports, but it will not apply the imported stylesheet. Is this a bug or limitation?

Many older browsers can't process varying forms of the #import directive, this can be used to hide css from them. Check http://www.w3development.de/css/hide_css_from_browsers/import/ for details.
The #import directives must come first in a style sheet, or else they'll be ignored. however IE doesn't ignore misplaced #import directives.
Edit: See the addImport method for injecting style sheets in IE.

Related

Final cross browser way to dynamically insert style elements into the DOM

Although inserting style nodes into the DOM sounds rather trivial, I have found many contradictory ways to do so. So I decided to look it up on stackoverflow and it appears that many posts offer methodologies that do what I need, however they do not necessarily agree with each other.
I came across the following javascript methods:
Returns a style element, and apparently does not have the "styleSheet" property in older browsers.
document.createElement("style")
Returns a styleSheet object, although I do not know how you would subsequently access the style element (which you will need to insert into the DOM).
document.createStyleElement()
The first three methods below work on styleSheets, others are "hacks" that work directly on the style nodes.
styleSheet.cssText
styleSheet.addRule
styleSheet.insertRule
style.createTextNode
style.innerHTML
I also had a hard time finding the correct syntax to use on (at least) the first three styleSheet methods. E.g. whether or not it is mandatory to include the curly braces and semicolons.
Also, these properties are used for accessing a styleSheet in various browsers:
document.styleSheets[index]
element.styleSheet
element.sheet
What would be the correct bundle of methods to use for a cross browser approach on inserting style elements? This should cover older browsers like IE6, subselectors (such as :visited) and !important statements.
Processed from this question:
var css = 'h1 { background: red; }',
head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet)
style.styleSheet.cssText = css;
else
style.appendChild(document.createTextNode(css));
head.appendChild(style);
It says it was tested in IE 7-9, Firefox, Opera, and Chrome, so it's pretty compatible.
And here are two links that might help:
Dynamic style - manipulating CSS with JavaScript - W3C Wiki
W3C DOM Compatibility - CSS
My proposal:
var elem = document.createElement('style');
elem.innerHTML = 'body { background: green }';
document.body.appendChild(elem);
Live demo: http://jsfiddle.net/simevidas/bhX86/
I'm looking into how to make this work in IE8.
You mean something like this? This should be cross-browser.
HTML
<div id="target">text</div>
Javascript
function injectStyle(data, attributes, inBody) {
attributes = attributes || {};
inBody = inBody || false;
var inject = document.createElement("style"),
i;
inject.type = "text/css";
for (i in attributes) {
if (attributes.hasOwnProperty(i)) {
inject[i] = attributes[i];
}
}
inject.appendChild(document.createTextNode(data));
if (inBody) {
return document.body.appendChild(inject);
}
return (document.head || document.getElementsByTagName("head")[0] || document.documentElement).appendChild(inject);
}
injectStyle("#target { border-style: solid; border-width: 5px; }", {
id: "injectedStyle"
});
on jsfiddle

document.write style css javascript

I'm pulling a bit of html and css from a database, and it happens to contain a bit of css wrapped in a style tag. I then set some innerhtml to the string variable and display it.
The html is rendered properly, but ie will not display the content with the css - of course firefox will. Below is an abbreviated example of the code
var outputString = '<style type="text/css">.fontRed{color:red;}</style><span class="fontRed">red</span>'
I then set it to the innerHTML
document.getElementById('bilbo').innerHTML = outputString;
This displays properly (the color red) in FF, however does not in IE.
Is there a character I need to escape for IE? The rest of the html works, and even inline styles work correctly in IE.
Any assistance would be most welcome.
Thanks
Try this Approach .. Tested in IE7 and above
// Create the Style Element
var styleElem = document.createElement('style');
styleElem.type = 'text/css' ;
var css = '.fontRed{color:red;}' ;
if(styleElem.styleSheet){
styleElem.styleSheet.cssText = css;
}
else{
styleElem.appendChild(document.createTextNode(css));
}
// Append the Style element to the Head
var head = document.getElementsByTagName('head')[0] ;
head.appendChild(styleElem);
// Append the span to the Div
var container = document.getElementById('bilbo');
container.innerHTML = '<span class="fontRed">red</span>' ;​
Check FIDDLE
Append the <style type="text/css">.fontRed{color:red;}</style> to the head tag first.
Just put <body> at the start of the output string. i.e.
document.getElementById('bilbo').innerHTML = '<body>' + outputString;
See http://jsfiddle.net/ScEZ4/1/ for a working demo.
Tested and working IE6, IE7, IE8, IE9, FF16, Chrome22, Opera12

How to dynamically set and modify CSS in JavaScript?

I have some JavaScript code that creates some div elements and it sets their CSS properties.
Because I would like to decouple CSS logic from my JavaScript code and because CSS is easier to read in its own .css file, I would like to set the CSS className of my element and then dynamically inject some values into the defined CSS property.
Here is what I would like to do :
style.css:
.myClass {
width: $insertedFromJS
}
script.js:
var myElement = document.createElement("div");
myElement.className = "myClass";
I want to do something like this but at that point myElement.style.width is empty
myElement.style.width.replaceAll("$insertedFromJS", "400px");
I think my problem here is that after the call to myElement.className = "myClass", the CSS is not yet applied.
If I understand your question properly, it sounds like you're trying to set placeholder text in your css file, and then use javascript to parse out the text with the css value you want to set for that class. You can't do that in the way you're trying to do it. In order to do that, you'd have to grab the content of the CSS file out of the dom, manipulate the text, and then save it back to the DOM. But that's a really overly-complicated way to go about doing something that...
myElement.style.width = "400px";
...can do for you in a couple of seconds. I know it doesn't really address the issue of decoupling css from js, but there's not really a whole lot you can do about that. You're trying to set css dynamically, after all.
Depending on what you're trying to accomplish, you might want to try defining multiple classes and just changing the className property in your js.
Setting the style, might be accomplished defining the inner-page style declaration.
Here is what i mean
var style = document.createElement('style');
style.type = 'text/css';
style.cssText = '.cssClass { color: #F00; }';
document.getElementsByTagName('head')[0].appendChild(style);
document.getElementById('someElementId').className = 'cssClass';
However the part of modifying it can be a lot of tricky than you think. Some regex solutions might do a good job. But here is another way, I found.
if (!document.styleSheets) return;
var csses = new Array();
if (document.styleSheets[0].cssRules) // Standards Compliant {
csses = document.styleSheets[0].cssRules;
}
else {
csses = document.styleSheets[0].rules; // IE
}
for (i=0;i<csses.length;i++) {
if ((csses[i].selectorText.toLowerCase()=='.cssClass') || (thecss[i].selectorText.toLowerCase()=='.borders'))
{
thecss[i].style.cssText="color:#000";
}
}
could you use jQuery on this? You could use
$(".class").css("property", val); /* or use the .width property */
There is a jQuery plugin called jQuery Rule,
http://flesler.blogspot.com/2007/11/jqueryrule.html
I tried it to dynamically set some div sizes of a board game. It works in FireFox, not in Chrome. I didn't try IE9.

jquery: create/read .css styles at runtime

I have an application where I'm using jQuery + maphilight
, and in addition to the highlighting of image map segments, I would like to highlight certain HTML elements dynamically, based on mouseover/mouseout events for the image maps.
I know how to do all of it (just the appropriate calls to addClass and removeClass for the HTML element that I want to highlight) except for one thing. I want to do either of the following:
create a CSS style at runtime that mirrors the maphilight visual settings (line/fill style + opacity)
set the maphilight plugin to mirror a CSS style that I have set up.
I'd prefer to do the latter and configure it in a .css file, but at present I don't know how do to either.
Can anyone help me?
edit: I'm looking for an answer that includes how to read or write styles from the jQuery maphilight plugin, since it doesn't have much documentation.
It may only change header style sheets. This technique is superior when used correctly. It should never replace a proper class assignment.
var renderDropArea = function(renderMe) {
var dropSheet = document.getElementById('dropAllowedDisplay');
if (renderMe) {
// IE 7 & 8
if (dropSheet.styleSheet) {
dropSheet.styleSheet.addRule('.dropAllowedHead','background-color:#72F193;');
dropSheet.styleSheet.addRule('.dropAllowed','background-color:#72F193;');
} else {
document.getElementById('dropAllowedDisplay').innerHTML =
".dropAllowedHead { background-color:#72F193; } .dropAllowed { background-color:#72F193; }";
}
} else {
// IE 7 & 8
if (dropSheet.styleSheet) {
if (dropSheet.styleSheet.rules.length) {
dropSheet.styleSheet.removeRule(0);
dropSheet.styleSheet.removeRule(0);
}
} else {
document.getElementById('dropAllowedDisplay').innerHTML = '';
}
}
}

How to check if a css rule exists

I need to check if a CSS rule exists because I want to issue some warnings if a CSS file is not included.
What is the best way of doing this?
I could filter through window.document.styleSheets.cssRules, but I'm not sure how cross-browser this is (plus I notice on Stack Overflow that object is null for styleSheet[0]).
I would also like to keep dependencies to a minimum.
Is there a straightforward way to do this? Do I just have to create matching elements and test the effects?
Edit: If not, what are the cross-browser concerns of checking window.document.styleSheets?
I don't know if this is an option for you, but if it's a single file you want to check, then you can write your error message and toggle the style to hide it in that file.
<span class="include_error">Error: CSS was not included!</span>
CSS file:
.include_error {
display: none;
visibility: hidden;
}
I test for proper CSS installation using javascript.
I have a CSS rule in my stylesheet that sets a particular id to position: absolute.
#testObject {position: absolute;}
I then programmatically create a temporary div with visibility: hidden with that ID and get the computed style position. If it's not absolute, then the desired CSS is not installed.
If you can't put your own rule in the style sheet, then you can identify one or more rules that you think are representative of the stylesheet and not likely to change and design a temporary object that should get those rules and test for their existence that way.
Or, lastly, you could try to enumerate all the external style sheets and look for a particular filename that is included.
The point here is that if you want to see if an external style sheet is included, you have to pick something about that style sheet that you can look for (filename or some rule in it or some effect it causes).
Here is what I got that works. It's similar to the answers by #Smamatti and #jfriend00 but more fleshed out. I really wish there was a way to test for rules directly but oh well.
CSS:
.my-css-loaded-marker {
z-index: -98256; /*just a random number*/
}
JS:
$(function () { //Must run on jq ready or $('body') might not exist
var dummyElement = $('<p>')
.hide().css({height: 0, width: 0})
.addClass("my-css-loaded-marker")
.appendTo("body"); //Works without this on firefox for some reason
if (dummyElement.css("z-index") != -98256 && console && console.error) {
console.error("Could not find my-app.css styles. Application requires my-app.css to be loaded in order to function properly");
}
dummyElement.remove();
});
I would use a css selector like this from within your jquery widget.
$('link[href$="my-app.css"]')
If you get a result back it means there is a link element that has a href ending with "my-app.css"
Next use this function to validate a specific css property on an element you are depending on. I would suggest something specific to you styles like the width of a container rather something random like -9999 zindex
var getStyle = function(el, styleProp) {
var x = !!el.nodeType ? el : document.getElementById(el);
if (x.currentStyle)
var y = x.currentStyle[styleProp];
else if (window.getComputedStyle)
var y = document.defaultView.getComputedStyle(x, null).getPropertyValue(styleProp);
return y;
}
Like this
getStyle($('#stats-container')[0], "width")
or
getStyle("stats-container", "width")
If you are worried about not being able to edit other people's stylesheets, you can proxy them through a stylesheet of your own, using import
#import url('http://his-stylesheet.css');
.hideErrorMessage{ ... }
This is enough if you just want to know if your code is trying to load the stylesheet but won't help if you need to know if the foreign stylesheet was then loaded correctly.

Categories

Resources