How to dynamically set and modify CSS in JavaScript? - 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.

Related

script that applies a style to newly created elements

I am writing a tampermonkey script that changes the style of an element whose class starts with "blocked". So i have this code:
var blockedelements = document.querySelectorAll("[class^=blocked]");
var element = blockedelements[0];
element.style.display="none";
for simplicity this is only for the first element but i know how to iterate through each one and this code as it is works. the webapp dynamically creates new elements with this class and i want the script to execute for each newly created element which is what i don't know how to do. I want a pure JS solution, not jquery. Is this what a listener is for? i don't know much about javascript.
I would appreciate any pointers, thanks
Instead of manually changing the display value for every instance of the element, you could use JavaScript to add a page-wide style rule to hide all of them. That way you can let the browser handle applying the rule to both existing and future instances of the element for you.
Rough idea:
var rule = "[class^=blocked] { display: none }";
var styleElement = document.createElement("style");
styleElement.type = "text/css";
if (styleElement.style.cssText) {
styleElement.style.cssText = rule;
} else {
styleElement.appendChild(document.createTextNode(rule));
}
document.getElementsByTagName("head")[0].appendChild(styleElement);

Chrome not handling .style = "background-color:#333223;"

In the code included below, the script is toggling a div on and off. The .style
code, controls the background color of the the parent element of the div being toggled
on and off. The code works in Opera but not in Chrome, and I haven't been able to
research (search) a solution.
I can of course move on and write other code and achieve what I need, but this has my
curiosity up now.
function CheckOutOpn(){
var Inny = document.getElementById("RightPaneASxOrderForm");
MVxCheckOutForm();
CDxButtonOpnChkOut();
MVxCLOSExBttnChkout();
Inny.style = "background-color:#332223;";
}
function CLOSExCheckOut(){
var Inny = document.getElementById("RightPaneASxOrderForm");
MVxButtonOpnChkOut();
CDxCLOSExBttnChkout();
CDxOrderFormItself();
Inny.style = "background-color:#33B32E;";
}
I think you should be using:
Inny.style.backgroundColor = "#332223";
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.style
... Except in Opera, styles can not be set by assigning a string to the
(read only) style property, as in elt.style = "color: blue;". This is
because the style attribute returns a CSSStyleDeclaration object.
If you want to set the style of an element textually, you need to use either
Inny.style.cssText="background-color:#33B32E"
or
Inny.setAttribute("style","background-color:#33B32E")
or you can set the properties directly:
Inny.style.backgroundColor = "#33B32E";
I think this will work for you fine. only mistake you are doing is, when you are adding the css properties to the element.
function CheckOutOpn(){
var Inny = document.getElementById("RightPaneASxOrderForm");
MVxCheckOutForm();
CDxButtonOpnChkOut();
MVxCLOSExBttnChkout();
Inny.style.backgroundColor = "#332223";
}

changing css class model using JavaScript

Is it in any way possible, to change a css class model using JavaScript?
Pseudo code:
function updateClass(className, newData) {
cssInterface.alterClass(className, newData);
}
className being the name of the class, which is supposed to be changed (like ".footer") and newData being the new class content (like border: "1px solid pink;").
The target is, actually, just to save space: I am working with CSS3-animations, so changing one attribute of an element, which is affected by it's class, will terminate the animation of of it - The (in my case) font size won't change anymore. Using different classes will require an entire new set of classes for all affected elements, I'd like to avoid this.
I am not searching for a change via
element.className = "foo";
or
element.style.fontSize = "15pt";
Thanks for your help, guys :)
Here's my function to do this...
function changeCSS(typeAndClass, newRule, newValue) // modify the site CSS (if requred during scaling for smaller screen sizes)
{
var thisCSS=document.styleSheets[0] // get the CSS for the site as an array
var ruleSearch=thisCSS.cssRules? thisCSS.cssRules: thisCSS.rules // work out if the browser uses cssRules or not
for (i=0; i<ruleSearch.length; i++) // for every element in the CSS array
{
if(ruleSearch[i].selectorText==typeAndClass) // find the element that matches the type and class we are looking for
{
var target=ruleSearch[i] // create a variable to hold the specific CSS element
var typeExists = 1;
break; // and stop the loop
}
}
if (typeExists)
{
target.style[newRule] = newValue; // modify the desired class (typeAndClass) element (newRule) with its new value (newValue).
}
else
{
alert(typeAndClass + " does not exist.");
}
}
Called with (example)
changeCSS("div.headerfixed","-moz-transform-origin", "100% 0%");
hope this helps.
See my answer here. To answer your question: Yes, it's possible.
#CSS3: I tried exactly the same in one of my html5 experiments. I created an extra <style> element, and changed its contentText to the CSS class definitions I needed. Of course changing the cssRule object would be much cleaner :-)
As far as I can tell the CSS object model cannot easily tell you whether you already have an existing style rule for a particular class, but you can easily append a new rule for that class and it will override any previous declaration of that style.
I found an example of creating dynamic stylesheets.
You should take a look at dojo, it has some nice features where you can do just that..
require(["dojo/dom-class"], function(domClass){
// Add a class to some node:
domClass.add("someNode", "anewClass");
});
http://dojotoolkit.org/reference-guide/1.7/dojo/addClass.html

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.

How can I undo the setting of element.style properties?

I have an element in my document that has a background color and image set through a regular CSS rule.
When a certain event happens, I want to animate that item, highlighting it (I'm using Scriptaculous, but this question applies to any framework that'll do the same).
new Effect.Highlight(elHighlight, { startcolor: '#ffff99', endcolor: '#ffffff', afterFinish: fnEndOfFadeOut });
The problem i'm facing is that after the animation is done, the element is left with the following style (according to FireBug):
element.style {
background-color:transparent;
background-image:none;
}
Which overrides the CSS rule, since it's set at the element level, so I'm losing the background that the item used to have...
What I'm trying to do is, in the callback function I'm running after the animation is done, set the style properties to a value that'll make them "go away".
var fnEndOfFadeOut = function() {
elHighlight.style.backgroundColor = "xxxxx";
elHighlight.style.backgroundImage = "xxxxx";
}
What I'm trying to figure out is what to put in "xxxx" (or how to do the same thing in a different way).
I tried 'auto', 'inherit', and '' (blank string), and neither worked (I didn't really expect them to work, but I'm clueless here).
I also tried elHighlight.style = ""; which, expectably, threw an exception.
What can I do to overcome this?
I know I can put a span inside the element that I'm highlighting and highlight that span instead, but I'm hoping I'll be able to avoid the extra useless markup.
Chances are you're not setting the style on the correct element. It's probably being set somewhere up the line in a parent node.
elHighlight.style.backgroundColor = "";
elHighlight.style.backgroundImage = "";
You can also remove all the default styling by calling:
elHighlight.style.cssText = "";
In any case, you'll still have to do this on the specific element that is setting these properties, which means you may need to do a recursion on parentNode until you find it.
Try
elHighlight.style.removeProperty('background-color')
elHighlight.style.removeProperty('background-image')
have you tried elHightlight.style.background = "";?
I have a highlighter code on my site and this works
function highlight(id) {
var elements = getElementsByClass("softwareItem");
for (var ix in elements){
elements[ix].style.background = ""; //This clears any previous highlight
}
document.getElementById(id).style.background = "#E7F3FA";
}
An HTML element can have multiple CSS classes. Put your highlight information inside a CSS class. Add this class to your element to highlight it. Remove the class to undo the effect.

Categories

Resources