I have an element that already has a class:
<div class="someclass">
<img ... id="image1" name="image1" />
</div>
Now, I want to create a JavaScript function that will add a class to the div (not replace, but add).
How can I do that?
If you're only targeting modern browsers:
Use element.classList.add to add a class:
element.classList.add("my-class");
And element.classList.remove to remove a class:
element.classList.remove("my-class");
If you need to support Internet Explorer 9 or lower:
Add a space plus the name of your new class to the className property of the element. First, put an id on the element so you can easily get a reference.
<div id="div1" class="someclass">
<img ... id="image1" name="image1" />
</div>
Then
var d = document.getElementById("div1");
d.className += " otherclass";
Note the space before otherclass. It's important to include the space otherwise it compromises existing classes that come before it in the class list.
See also element.className on MDN.
The easiest way to do this without any framework is to use element.classList.add method.
var element = document.getElementById("div1");
element.classList.add("otherclass");
Edit:
And if you want to remove class from an element -
element.classList.remove("otherclass");
I prefer not having to add any empty space and duplicate entry handling myself (which is required when using the document.className approach). There are some browser limitations, but you can work around them using polyfills.
find your target element "d" however you wish and then:
d.className += ' additionalClass'; //note the space
you can wrap that in cleverer ways to check pre-existence, and check for space requirements etc..
Add Class
Cross Compatible
In the following example we add a classname to the <body> element. This is IE-8 compatible.
var a = document.body;
a.classList ? a.classList.add('classname') : a.className += ' classname';
This is shorthand for the following..
var a = document.body;
if (a.classList) {
a.classList.add('wait');
} else {
a.className += ' wait';
}
Performance
If your more concerned with performance over cross-compatibility you can shorten it to the following which is 4% faster.
var z = document.body;
document.body.classList.add('wait');
Convenience
Alternatively you could use jQuery but the resulting performance is significantly slower. 94% slower according to jsPerf
$('body').addClass('wait');
Removing the class
Performance
Using jQuery selectively is the best method for removing a class if your concerned with performance
var a = document.body, c = ' classname';
$(a).removeClass(c);
Without jQuery it's 32% slower
var a = document.body, c = ' classname';
a.className = a.className.replace( c, '' );
a.className = a.className + c;
References
jsPerf Test Case: Adding a Class
jsPerf Test Case: Removing a Class
Using Prototype
Element("document.body").ClassNames.add("classname")
Element("document.body").ClassNames.remove("classname")
Element("document.body").ClassNames.set("classname")
Using YUI
YAHOO.util.Dom.hasClass(document.body,"classname")
YAHOO.util.Dom.addClass(document.body,"classname")
YAHOO.util.Dom.removeClass(document.body,"classname")
Another approach to add the class to element using pure JavaScript
For adding class:
document.getElementById("div1").classList.add("classToBeAdded");
For removing class:
document.getElementById("div1").classList.remove("classToBeRemoved");
2 different ways to add class using JavaScript
JavaScript provides 2 different ways by which you can add classes to HTML elements:
Using element.classList.add() Method
Using className property
Using both methods you can add single or multiple classes at once.
1. Using element.classList.add() Method
var element = document.querySelector('.box');
// using add method
// adding single class
element.classList.add('color');
// adding multiple class
element.classList.add('border', 'shadow');
.box {
width: 200px;
height: 100px;
}
.color {
background: skyblue;
}
.border {
border: 2px solid black;
}
.shadow {
box-shadow: 5px 5px 5px gray;
}
<div class="box">My Box</div>
2. Using element.className Property
Note: Always use += operator and add a space before class name to add class with classList method.
var element = document.querySelector('.box');
// using className Property
// adding single class
element.className += ' color';
// adding multiple class
element.className += ' border shadow';
.box {
width: 200px;
height: 100px;
}
.color {
background: skyblue;
}
.border {
border: 2px solid black;
}
.shadow {
box-shadow: 5px 5px 5px gray;
}
<div class="box">My Box</div>
document.getElementById('some_id').className+=' someclassname'
OR:
document.getElementById('some_id').classList.add('someclassname')
First approach helped in adding the class when second approach didn't work.
Don't forget to keep a space in front of the ' someclassname' in the first approach.
For removal you can use:
document.getElementById('some_id').classList.remove('someclassname')
When the work I'm doing doesn't warrant using a library, I use these two functions:
function addClass( classname, element ) {
var cn = element.className;
//test for existance
if( cn.indexOf( classname ) != -1 ) {
return;
}
//add a space if the element already has class
if( cn != '' ) {
classname = ' '+classname;
}
element.className = cn+classname;
}
function removeClass( classname, element ) {
var cn = element.className;
var rxp = new RegExp( "\\s?\\b"+classname+"\\b", "g" );
cn = cn.replace( rxp, '' );
element.className = cn;
}
Assuming you're doing more than just adding this one class (eg, you've got asynchronous requests and so on going on as well), I'd recommend a library like Prototype or jQuery.
This will make just about everything you'll need to do (including this) very simple.
So let's say you've got jQuery on your page now, you could use code like this to add a class name to an element (on load, in this case):
$(document).ready( function() {
$('#div1').addClass( 'some_other_class' );
} );
Check out the jQuery API browser for other stuff.
You can use the classList.add OR classList.remove method to add/remove a class from a element.
var nameElem = document.getElementById("name")
nameElem.classList.add("anyclss")
The above code will add(and NOT replace) a class "anyclass" to nameElem.
Similarly you can use classList.remove() method to remove a class.
nameElem.classList.remove("anyclss")
To add an additional class to an element:
To add a class to an element, without removing/affecting existing values, append a space and the new classname, like so:
document.getElementById("MyElement").className += " MyClass";
To change all classes for an element:
To replace all existing classes with one or more new classes, set the className attribute:
document.getElementById("MyElement").className = "MyClass";
(You can use a space-delimited list to apply multiple classes.)
If you don't want to use jQuery and want to support older browsers:
function addClass(elem, clazz) {
if (!elemHasClass(elem, clazz)) {
elem.className += " " + clazz;
}
}
function elemHasClass(elem, clazz) {
return new RegExp("( |^)" + clazz + "( |$)").test(elem.className);
}
I too think that the fastest way is to use Element.prototype.classList as in es5: document.querySelector(".my.super-class").classList.add('new-class')
but in ie8 there is no such thing as Element.prototype.classList, anyway you can polyfill it with this snippet (fell free to edit and improve it):
if(Element.prototype.classList === void 0){
function DOMTokenList(classes, self){
typeof classes == "string" && (classes = classes.split(' '))
while(this.length){
Array.prototype.pop.apply(this);
}
Array.prototype.push.apply(this, classes);
this.__self__ = this.__self__ || self
}
DOMTokenList.prototype.item = function (index){
return this[index];
}
DOMTokenList.prototype.contains = function (myClass){
for(var i = this.length - 1; i >= 0 ; i--){
if(this[i] === myClass){
return true;
}
}
return false
}
DOMTokenList.prototype.add = function (newClass){
if(this.contains(newClass)){
return;
}
this.__self__.className += (this.__self__.className?" ":"")+newClass;
DOMTokenList.call(this, this.__self__.className)
}
DOMTokenList.prototype.remove = function (oldClass){
if(!this.contains(newClass)){
return;
}
this[this.indexOf(oldClass)] = undefined
this.__self__.className = this.join(' ').replace(/ +/, ' ')
DOMTokenList.call(this, this.__self__.className)
}
DOMTokenList.prototype.toggle = function (aClass){
this[this.contains(aClass)? 'remove' : 'add'](aClass)
return this.contains(aClass);
}
DOMTokenList.prototype.replace = function (oldClass, newClass){
this.contains(oldClass) && this.remove(oldClass) && this.add(newClass)
}
Object.defineProperty(Element.prototype, 'classList', {
get: function() {
return new DOMTokenList( this.className, this );
},
enumerable: false
})
}
To add, remove or check element classes in a simple way:
var uclass = {
exists: function(elem,className){var p = new RegExp('(^| )'+className+'( |$)');return (elem.className && elem.className.match(p));},
add: function(elem,className){if(uclass.exists(elem,className)){return true;}elem.className += ' '+className;},
remove: function(elem,className){var c = elem.className;var p = new RegExp('(^| )'+className+'( |$)');c = c.replace(p,' ').replace(/ /g,' ');elem.className = c;}
};
var elem = document.getElementById('someElem');
//Add a class, only if not exists yet.
uclass.add(elem,'someClass');
//Remove class
uclass.remove(elem,'someClass');
I know IE9 is shutdown officially and we can achieve it with element.classList as many told above but I just tried to learn how it works without classList with help of many answers above I could learn it.
Below code extends many answers above and improves them by avoiding adding duplicate classes.
function addClass(element,className){
var classArray = className.split(' ');
classArray.forEach(function (className) {
if(!hasClass(element,className)){
element.className += " "+className;
}
});
}
//this will add 5 only once
addClass(document.querySelector('#getbyid'),'3 4 5 5 5');
You can use modern approach similar to jQuery
If you need to change only one element, first one that JS will find in DOM, you can use this:
document.querySelector('.someclass').className += " red";
.red {
color: red;
}
<div class="someclass">
<p>This method will add class "red" only to first element in DOM</p>
</div>
<div class="someclass">
<p>lorem ipsum</p>
</div>
<div class="someclass">
<p>lorem ipsum</p>
</div>
<div class="someclass">
<p>lorem ipsum</p>
</div>
Keep in mind to leave one space before class name.
If you have multiple classes where you want to add new class, you can use it like this
document.querySelectorAll('.someclass').forEach(function(element) {
element.className += " red";
});
.red {
color: red;
}
<div class="someclass">
<p>This method will add class "red" to all elements in DOM that have "someclass" class.</p>
</div>
<div class="someclass">
<p>lorem ipsum</p>
</div>
<div class="someclass">
<p>lorem ipsum</p>
</div>
<div class="someclass">
<p>lorem ipsum</p>
</div>
This might be helpful for WordPress developers etc.
document.querySelector('[data-section="section-hb-button-1"] .ast-custom-button').classList.add('TryMyClass');
Just to elaborate on what others have said, multiple CSS classes are combined in a single string, delimited by spaces. Thus, if you wanted to hard-code it, it would simply look like this:
<div class="someClass otherClass yetAnotherClass">
<img ... id="image1" name="image1" />
</div>
From there you can easily derive the javascript necessary to add a new class... just append a space followed by the new class to the element's className property. Knowing this, you can also write a function to remove a class later should the need arise.
I think it's better to use pure JavaScript, which we can run on the DOM of the Browser.
Here is the functional way to use it. I have used ES6 but feel free to use ES5 and function expression or function definition, whichever suits your JavaScript StyleGuide.
'use strict'
const oldAdd = (element, className) => {
let classes = element.className.split(' ')
if (classes.indexOf(className) < 0) {
classes.push(className)
}
element.className = classes.join(' ')
}
const oldRemove = (element, className) => {
let classes = element.className.split(' ')
const idx = classes.indexOf(className)
if (idx > -1) {
classes.splice(idx, 1)
}
element.className = classes.join(' ')
}
const addClass = (element, className) => {
if (element.classList) {
element.classList.add(className)
} else {
oldAdd(element, className)
}
}
const removeClass = (element, className) => {
if (element.classList) {
element.classList.remove(className)
} else {
oldRemove(element, className)
}
}
Sample with pure JS. In first example we get our element's id and add e.g. 2 classes.
document.addEventListener('DOMContentLoaded', function() {
document.getElementsById('tabGroup').className = "anyClass1 anyClass2";
})
In second example we get element's class name and add 1 more.
document.addEventListener('DOMContentLoaded', function() {
document.getElementsByClassName('tabGroup')[0].className = "tabGroup ready";
})
For those using Lodash and wanting to update className string:
// get element reference
var elem = document.getElementById('myElement');
// add some classes. Eg. 'nav' and 'nav header'
elem.className = _.chain(elem.className).split(/[\s]+/).union(['nav','navHeader']).join(' ').value()
// remove the added classes
elem.className = _.chain(elem.className).split(/[\s]+/).difference(['nav','navHeader']).join(' ').value()
Shortest
image1.parentNode.className+=' box';
image1.parentNode.className+=' box';
.box { width: 100px; height:100px; background: red; }
<div class="someclass">
<img ... id="image1" name="image1" />
</div>
You can use the API querySelector to select your element and then create a function with the element and the new classname as parameters. Using classlist for modern browsers, else for IE8. Then you can call the function after an event.
//select the dom element
var addClassVar = document.querySelector('.someclass');
//define the addclass function
var addClass = function(el,className){
if (el.classList){
el.classList.add(className);
}
else {
el.className += ' ' + className;
}
};
//call the function
addClass(addClassVar, 'newClass');
In my case, I had more than one class called main-wrapper in the DOM, but I only wanted to affect the parent main-wrapper. Using :first Selector (https://api.jquery.com/first-selector/), I could select the first matched DOM element. This was the solution for me:
$(document).ready( function() {
$('.main-wrapper:first').addClass('homepage-redesign');
$('#deals-index > div:eq(0) > div:eq(1)').addClass('doubleheaderredesign');
} );
I also did the same thing for the second children of a specific div in my DOM as you can see in the code where I used $('#deals-index > div:eq(0) > div:eq(1)').addClass('doubleheaderredesign');.
NOTE: I used jQuery as you can see.
The majority of people use a .classList.add on a getElementById, but I i wanted to use it on a getElementByClassName. To do that, i was using a forEach like this :
document.getElementsByClassName("class-name").forEach(element => element.classList.add("new-class"));
But it didn't work because i discovered that getElementsByClassName returns a HTML collection and not an array. To handle that I converted it to an array with this code :
[...document.getElementsByClassName("class-name")].forEach(element => element.classList.add("new-class"));
first, give the div an id. Then, call function appendClass:
<script language="javascript">
function appendClass(elementId, classToAppend){
var oldClass = document.getElementById(elementId).getAttribute("class");
if (oldClass.indexOf(classToAdd) == -1)
{
document.getElementById(elementId).setAttribute("class", classToAppend);
}
}
</script>
This js code works for me
provides classname replacement
var DDCdiv = hEle.getElementBy.....
var cssCNs = DDCdiv.getAttribute('class');
var Ta = cssCNs.split(' '); //split into an array
for (var i=0; i< Ta.length;i++)
{
if (Ta[i] == 'visible'){
Ta[i] = 'hidden';
break;// quit for loop
}
else if (Ta[i] == 'hidden'){
Ta[i] = 'visible';
break;// quit for loop
}
}
DDCdiv.setAttribute('class',Ta.join(' ') ); // Join array with space and set class name
To add just use
var cssCNs = DDCdiv.getAttribute('class');
var Ta = cssCNs.split(' '); //split into an array
Ta.push('New class name');
// Ta.push('Another class name');//etc...
DDCdiv.setAttribute('class',Ta.join(' ') ); // Join array with space and set class name
To remove use
var cssCNs = DDCdiv.getAttribute('class');
var Ta = cssCNs.split(' '); //split into an array
for (var i=0; i< Ta.length;i++)
{
if (Ta[i] == 'visible'){
Ta.splice( i, 1 );
break;// quit for loop
}
}
DDCdiv.setAttribute('class',Ta.join(' ') ); // Join array with space and set class name
Hope this is helpful to sombody
In YUI, if you include yuidom, you can use
YAHOO.util.Dom.addClass('div1','className');
HTH
Related
Is it possible to make changes to a CSS rule-set dynamically (i.e. some JS which would change a CSS rule-set when the user clicks a widget)
This particular CSS rule-set is applied to lots of elements (via a class selector) on the page and I want to modify it when the user clicks the widget, so that all the elements having the class change.
You can, but it's rather cumbersome. The best reference on how to do it is the following article: Totally Pwn CSS with Javascript (web archive link).
I managed to get it to work with Firefox and IE - I couldn't in Chrome, though it appears that it supports the DOM methods.ricosrealm reports that it works in Chrome, too.
This is a modern version based on Totally Pwn CSS with Javascript. It's ES6 I hope don't mind.
function getCSSRule(ruleName) {
ruleName = ruleName.toLowerCase();
var result = null;
var find = Array.prototype.find;
find.call(document.styleSheets, styleSheet => {
result = find.call(styleSheet.cssRules, cssRule => {
return cssRule instanceof CSSStyleRule
&& cssRule.selectorText.toLowerCase() == ruleName;
});
return result != null;
});
return result;
}
This function returns a CSSStyleRule that you can use like this:
var header = getCSSRule('#header');
header.style.backgroundColor = 'red';
Also document.styleSheets list references of the CSSStylesSheets Objects. Other way to acces a specific sytleSheet in the page is by assigning an id to the style or link element in the html code, and get it in javascript using document.getElementById('my-style').sheet. This are some useful methods:
Major Browsers and IE9+ : insertRule(), deleteRule(), removeProperty().
Major Browsers, Firefox? and IE9+ : setProperty().
<stye id="my-style" ...
....
var myStyle = document.getElementById('my-style').sheet
myStyle.insertRule('#header { background: red; }', 0);
It is also possible to dynamically create a new style element to store dynamic created styles, I think should be way to avoid conflicts.
You can edit CLASS in document styleshets as follows
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
function edit() {
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
}
.box {
margin: 10px;
padding: 10px;
background: yellow;
}
<button onclick="edit()" >Click me</button>
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
I tried the code via link from #alex-gyoshev comment, but it dosn't work
it fails on the CSS rules with Google fonts in Chrome
it fails on FireFox security checks
So I changed it slightly, but deleted delete functionality since it wasn't needed for me. Checked in IE 11, FireFox 32, Chrome 37 and Opera 26.
function getCSSRule(ruleName) { // Return requested style object
ruleName = ruleName.toLowerCase(); // Convert test string to lower case.
var styleSheet;
var i, ii;
var cssRule = false; // Initialize cssRule.
var cssRules;
if (document.styleSheets) { // If browser can play with stylesheets
for (i = 0; i < document.styleSheets.length; i++) { // For each stylesheet
styleSheet = document.styleSheets[i];
if (!styleSheet.href) {
if (styleSheet.cssRules) { // Browser uses cssRules?
cssRules = styleSheet.cssRules; // Yes --Mozilla Style
} else { // Browser usses rules?
cssRules = styleSheet.rules; // Yes IE style.
} // End IE check.
if (cssRules) {
for (ii = 0; ii < cssRules.length; ii++) {
cssRule = cssRules[ii];
if (cssRule) { // If we found a rule...
// console.log(cssRule);
if (cssRule.selectorText) {
console.log(cssRule.selectorText);
if (cssRule.selectorText.toLowerCase() == ruleName) { // match ruleName?
return cssRule; // return the style object.
}
}
}
}
}
}
}
}
return false; // we found NOTHING!
}
Depending on what you're trying to achieve, a better solution might be to change/add a class to a containing element (body would do!), and define classes accordingly.
.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#wrapper.bar .yourclass { color: blue }
then you can just use
document.getElementById('wrapper').className='foo';
(or your chosen js framework's wrapper for the same) to change everything with class yourclass inside whatever your wrapper element is.
The APIs for editing stylesheets with JS are, sadly, not consistent across browsers. The YUI Stylesheet Utility attempts to smooth over these differences so you could just use that. You could also look at the source code to figure out how it works if you don't want to use YUI itself.
give your style tag an id, like <style id="ssID">
if someonelse is making your styles for you
tell THAT person to give the style tag an id -
that way you can access it directly without
scrambling around wondering what its index is
// create a hash table
var cssHash = {};
// loop through and populate the hash table
for (let i in (r = ss0.sheet.rules)) {
// selectorText is the name of the rule - set the value equal to the rule
cssHash[r[i].selectorText] = r[i];
}
now you have a hash table for everything in the style sheet -
note that some values will be undefined, but not for
any of the things you care about
if you have, for instance, a class called #menuItem
and you want to change its color to black, do this
cssHash['#menuItem'].style.color = #000;
that line will set the color of the style of the rule
whose index was looked up in the hash table (cssHash)
by the name '#menuItem'
more importantly, you probably have several different
classes that you want to change all at once
kind of like when you switched majors in college
let's say you have four different classes
and you want to set all of their background colors
to the same value, that some user selected from an input
the color selector tag is <input id="bColor" type="color">
and the class rules you want to change are called
#menuItem .homeAddr span and #vacuum:hover
// create a listener for that color selector
bColor.addEventListener('input', function (e) {
// loop through a split list of the four class names
'#menuItem .homeAddr span #vacuum:hover'.split(' ').forEach(function (obj) {
// use the hash table to look up the index of each name
// and set the background color equal to the color input's value
cssHash[obj].style.backgroundColor = bColor.value;
});
}, false); // false added here for the sake of non-brevity
While setAttribute is nice, there is a standard way of doing this across most browsers:
htmlElement.className = 'someClass';
To do it over many elements, you will need a cross browser solution:
function getElementsByClassName( className, context, tagName ) {
context = context || document;
if ( typeof context.getElementsByClassName === 'function' )
return context.getElementsByClassName( className );
if ( typeof context.getElementsByTagName !== 'function' )
return [];
var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
context.getElementsByTagName('*'),
ret = [];
for ( var i = 0, il = elements.length; i < il; i++ )
if ( elements[ i ].className.match( className ) )
ret.push( elements[ i ] );
return ret;
}
var elements = getElementsByClassName('someClass');
for ( var i = 0, il = elements.length; i < il; i++ )
elements[ i ].className = 'newClass';
You may want to replace the line:
if ( elements[ i ].className.match( className ) )
With some Regular Expression, but you will have to escape special characters in that case.
To check all stylesheets for the rule and set it:
Your rule:
.aaa: {
background-color: green
}
[...document.styleSheets].flatMap(s=>[...s.cssRules])
.find(i=>i.selectorText=='.aaa').style.backgroundColor = 'red';
Note that the css styles, when accessed through javascript, do not have dashes in them. In the example above, background-color becomes backgroundColor
Is it possible to make changes to a CSS rule-set dynamically (i.e. some JS which would change a CSS rule-set when the user clicks a widget)
This particular CSS rule-set is applied to lots of elements (via a class selector) on the page and I want to modify it when the user clicks the widget, so that all the elements having the class change.
You can, but it's rather cumbersome. The best reference on how to do it is the following article: Totally Pwn CSS with Javascript (web archive link).
I managed to get it to work with Firefox and IE - I couldn't in Chrome, though it appears that it supports the DOM methods.ricosrealm reports that it works in Chrome, too.
This is a modern version based on Totally Pwn CSS with Javascript. It's ES6 I hope don't mind.
function getCSSRule(ruleName) {
ruleName = ruleName.toLowerCase();
var result = null;
var find = Array.prototype.find;
find.call(document.styleSheets, styleSheet => {
result = find.call(styleSheet.cssRules, cssRule => {
return cssRule instanceof CSSStyleRule
&& cssRule.selectorText.toLowerCase() == ruleName;
});
return result != null;
});
return result;
}
This function returns a CSSStyleRule that you can use like this:
var header = getCSSRule('#header');
header.style.backgroundColor = 'red';
Also document.styleSheets list references of the CSSStylesSheets Objects. Other way to acces a specific sytleSheet in the page is by assigning an id to the style or link element in the html code, and get it in javascript using document.getElementById('my-style').sheet. This are some useful methods:
Major Browsers and IE9+ : insertRule(), deleteRule(), removeProperty().
Major Browsers, Firefox? and IE9+ : setProperty().
<stye id="my-style" ...
....
var myStyle = document.getElementById('my-style').sheet
myStyle.insertRule('#header { background: red; }', 0);
It is also possible to dynamically create a new style element to store dynamic created styles, I think should be way to avoid conflicts.
You can edit CLASS in document styleshets as follows
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
function edit() {
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.background= 'red';
}
.box {
margin: 10px;
padding: 10px;
background: yellow;
}
<button onclick="edit()" >Click me</button>
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
I tried the code via link from #alex-gyoshev comment, but it dosn't work
it fails on the CSS rules with Google fonts in Chrome
it fails on FireFox security checks
So I changed it slightly, but deleted delete functionality since it wasn't needed for me. Checked in IE 11, FireFox 32, Chrome 37 and Opera 26.
function getCSSRule(ruleName) { // Return requested style object
ruleName = ruleName.toLowerCase(); // Convert test string to lower case.
var styleSheet;
var i, ii;
var cssRule = false; // Initialize cssRule.
var cssRules;
if (document.styleSheets) { // If browser can play with stylesheets
for (i = 0; i < document.styleSheets.length; i++) { // For each stylesheet
styleSheet = document.styleSheets[i];
if (!styleSheet.href) {
if (styleSheet.cssRules) { // Browser uses cssRules?
cssRules = styleSheet.cssRules; // Yes --Mozilla Style
} else { // Browser usses rules?
cssRules = styleSheet.rules; // Yes IE style.
} // End IE check.
if (cssRules) {
for (ii = 0; ii < cssRules.length; ii++) {
cssRule = cssRules[ii];
if (cssRule) { // If we found a rule...
// console.log(cssRule);
if (cssRule.selectorText) {
console.log(cssRule.selectorText);
if (cssRule.selectorText.toLowerCase() == ruleName) { // match ruleName?
return cssRule; // return the style object.
}
}
}
}
}
}
}
}
return false; // we found NOTHING!
}
Depending on what you're trying to achieve, a better solution might be to change/add a class to a containing element (body would do!), and define classes accordingly.
.yourclass { color: black }
#wrapper.foo .yourclass { color: red }
#wrapper.bar .yourclass { color: blue }
then you can just use
document.getElementById('wrapper').className='foo';
(or your chosen js framework's wrapper for the same) to change everything with class yourclass inside whatever your wrapper element is.
The APIs for editing stylesheets with JS are, sadly, not consistent across browsers. The YUI Stylesheet Utility attempts to smooth over these differences so you could just use that. You could also look at the source code to figure out how it works if you don't want to use YUI itself.
give your style tag an id, like <style id="ssID">
if someonelse is making your styles for you
tell THAT person to give the style tag an id -
that way you can access it directly without
scrambling around wondering what its index is
// create a hash table
var cssHash = {};
// loop through and populate the hash table
for (let i in (r = ss0.sheet.rules)) {
// selectorText is the name of the rule - set the value equal to the rule
cssHash[r[i].selectorText] = r[i];
}
now you have a hash table for everything in the style sheet -
note that some values will be undefined, but not for
any of the things you care about
if you have, for instance, a class called #menuItem
and you want to change its color to black, do this
cssHash['#menuItem'].style.color = #000;
that line will set the color of the style of the rule
whose index was looked up in the hash table (cssHash)
by the name '#menuItem'
more importantly, you probably have several different
classes that you want to change all at once
kind of like when you switched majors in college
let's say you have four different classes
and you want to set all of their background colors
to the same value, that some user selected from an input
the color selector tag is <input id="bColor" type="color">
and the class rules you want to change are called
#menuItem .homeAddr span and #vacuum:hover
// create a listener for that color selector
bColor.addEventListener('input', function (e) {
// loop through a split list of the four class names
'#menuItem .homeAddr span #vacuum:hover'.split(' ').forEach(function (obj) {
// use the hash table to look up the index of each name
// and set the background color equal to the color input's value
cssHash[obj].style.backgroundColor = bColor.value;
});
}, false); // false added here for the sake of non-brevity
While setAttribute is nice, there is a standard way of doing this across most browsers:
htmlElement.className = 'someClass';
To do it over many elements, you will need a cross browser solution:
function getElementsByClassName( className, context, tagName ) {
context = context || document;
if ( typeof context.getElementsByClassName === 'function' )
return context.getElementsByClassName( className );
if ( typeof context.getElementsByTagName !== 'function' )
return [];
var elements = typeof tagName === 'string' ? context.getElementsByTagName( tagName ) :
context.getElementsByTagName('*'),
ret = [];
for ( var i = 0, il = elements.length; i < il; i++ )
if ( elements[ i ].className.match( className ) )
ret.push( elements[ i ] );
return ret;
}
var elements = getElementsByClassName('someClass');
for ( var i = 0, il = elements.length; i < il; i++ )
elements[ i ].className = 'newClass';
You may want to replace the line:
if ( elements[ i ].className.match( className ) )
With some Regular Expression, but you will have to escape special characters in that case.
To check all stylesheets for the rule and set it:
Your rule:
.aaa: {
background-color: green
}
[...document.styleSheets].flatMap(s=>[...s.cssRules])
.find(i=>i.selectorText=='.aaa').style.backgroundColor = 'red';
Note that the css styles, when accessed through javascript, do not have dashes in them. In the example above, background-color becomes backgroundColor
I have made a script to clone elements in js but this only selects the first element. Here is the code :
function clone(sel) {
var rVxyz = document.querySelector(sel);
var rVabc = rVxyz.cloneNode(true);
document.body.appendChild(rVabc) ||
document.documentElement.appendChild(rVabc);
};
Yes I know I have used querySelector but I was not able to use it with querySelectorAll. I wrote something like this :
function clone(sel, num) {
var rVxyz = document.querySelectorAll(sel)[num];
var rVabc = rVxyz.cloneNode(true);
document.body.appendChild(rVabc) ||
document.documentElement.appendChild(rVabc);
};
This only works when num = 0, otherwise it doesn't.
Thanks in advance.
This will depend on what exactly you pass to your function as sel. If you are passing the id of an element, like this: #someID, there can only be 0 elements or 1 element in rVxyz as ids must be unique. So you can't clone that element, unless you include some code to change the ID, in which case it's not really a clone anyway.
Of course, if you are selecting by class, by passing something like .someClass to sel, then there can be any number of elements, from 0 to n.
I think it honestly makes more sense to clone all matching elements, rather than trying to pass an index to your function. So the clone() would use forEach instead.
function clone(sel)
{
var rVxyz = document.querySelectorAll(sel);
rVxyz.forEach(function(element) {
let rVabc = element.cloneNode(true);
document.body.appendChild(rVabc) ||
document.documentElement.appendChild(rVabc);
});
};
clone("#biz");
clone(".boi");
clone(".boi:nth-child(2)");
The HTML for test:
<div id="biz"><p>1 Unique thing</p></div>
<div class="boi"><p>2 hi</p></div>
<div class="boi"><p>hello there</p></div>
The output is:
1 Unique thing
2 hi
3 hello there
2 hi
3 hello there
2 hi
The first element is not cloned because IDs must be unique. Also, notice in the second call to clone(), I used the nth-child selector, so only the second matching element within each parent element is cloned. The nice thing about this is that you can even select every second, third, fourth, etc. element if you want.
As long as the elements are within the same parent container element, this will work.
Here's some more info about nth-child.
But your original approach would work as well if you actually want to clone the nth match. E.g. the 2nd match. You just need to check that you aren't going beyond the end of the NodeList rVxyz.
function clone(sel, num)
{
var rVxyz = document.querySelectorAll(sel);
var limit = rVxyz.length;
if (num < limit)
{
var rVabc = rVxyz[num].cloneNode(true);
document.body.appendChild(rVabc) ||
document.documentElement.appendChild(rVabc);
}
else
{
console.log(limit);//Do nothing or output error message here.
}
};
clone(".boi", 1);
This clones the second matching element only, as long as there are 2 or more elements found.
But your code works... You just could add a few lines, to get less errors.
function clone(sel, num) {
num = parseInt(num);
var id = !!sel.match('#');
var elem = (id) ? document.querySelector(sel) : document.querySelectorAll(sel)[num];
if (elem) {
var clone = elem.cloneNode(true);
clone.classList.add('demo'); // just for demo (remove);
if (id || elem.id) {
clone.id = elem.id + '-bubuClone';
console.log( `New clone id="${clone.id}"` );
}
document.body.appendChild(clone) || document.documentElement.appendChild(clone);
} else {
console.log(
'Didn\'t found element to clone: ("' + sel + '")' + ( !id ? '[' + num + ']' : '' )
);
}
}
clone('.test', 2);
clone('.test', 5);
clone('.test', 9);
clone('.test', 15);
clone('#bubu', 15);
clone('#check');
.test, .test-id {
display: inline-block;
border: 2px solid orange;
padding: 5px;
margin: 5px;
}
.demo {
border-color: red;
}
<div class="test-id" id="bubu">bubu</div>
<div class="test">0</div>
<div class="test">1</div>
<div class="test" id="test007">2</div>
<div class="test">3</div>
<div class="test">4</div>
<div class="test">5</div>
<div class="test">6</div>
<div class="test">7</div>
<div class="test">8</div>
<div class="test">9</div>
<br>
Or, add the third parameter to function, which will define the search type ( selector / selectorAll )
I need to read elements class name. I have elements like this:
<article class="active clrone moreclass">Article x</article>
<article class="active clrtwo moreclass">Article y</article>
<article class="active clrthree moreclass moreclass">Article z</article>
<article class="active clrone moreclass">Article xyza</article>
I need to parse out class name that starts with clr. So if second element was clicked then I would need to get clrtwo className.
You can use a regular expression match on the class name of the clicked item to find the class that begins with "clr" like this:
$("article").click(function() {
var matches = this.className.match(/\bclr[^\s]+\b/);
if (matches) {
// matches[0] is clrone or clrtwo, etc...
}
});
Here is solution for you:
$('article').click(function () {
var className = this.className.split(' ');
for (var i = 0; i < className.length; i+=1) {
if (className[i].indexOf('clr') >= 0) {
alert(className[i]);
}
}
});
http://jsfiddle.net/vJfT7/
There's no matter how you're going to order the different classes. The code will alert you a class name only of there's 'clr' as a substring in it.
Best regards.
If you don't need to find elements based on these classes (e.g. doing $('.clrtwo')) it would be nicer to store the data as a data-clr attribute. This is standards-compliant from HTML5, and is supported by jQuery using the .data() function.
In this instance, I would modify your HTML in this way:
<article class="active moreclass" data-clr="one">Article x</article>
<article class="active moreclass" data-clr="two">Article y</article>
<article class="active moreclass moreclass" data-clr="three">Article z</article>
<article class="active moreclass" data-clr="one">Article xyza</article>
I would then use Javascript like this:
$('article.active').click(function() {
console.log($(this).data('clr'));
});
jsFiddle example
If it is always the second class name which is of interest you can do this:
$("article").click(function () {
// split on the space and output the second element
// in the resulting array
console.log($(this)[0].className.split(" ")[1]);
});
http://jsfiddle.net/karim79/Z3qhW/
<script type="text/javascript">
jQuery(document).ready(function(){
$("article").click(function(){
alert($(this).attr('class').match(/\bclr[^\s]+\b/)[0]);
});
});
</script>
This should jquery script should do what you asked (tested on jsfiddle):
$(document).ready(function () {
function getClrClass(elem) {
var classes = elem.getAttribute('class').split(' ');
var i = 0;
var cssClass = '';
for (i = 0; i < classes.length; i += 1) {
if (classes[i].indexOf('clr') === 0) {
cssClass = classes[i];
i = classes.length; //exit for loop
}
}
return cssClass;
};
$('article').click(function (e) {
var cssClass = getClrClass($(this)[0]);
alert(cssClass);
e.preventDefault();
return false;
});
});
Hope this helps.
Pete
Use an attribute selector to get those that have class names that contain clr.
From there:
extract the class name (string functions)
analyze the position
determine the next element
The latter two might be best served by a translation array if you only had a few classes.
UPDATE
I agree with lonesomeday, you'd be far better off using data-* attribute to handle such logic. Using CSS as JavaScript hooks is a thing of the past.
http://jsfiddle.net/4KwWn/
$('article[class*=clr]').click(function() {
var token = $(this).attr('class'),
position = token.indexOf('clr');
token = token.substring(position, token.indexOf(' ', position));
alert(token);
});
How do I add a class for the div?
var new_row = document.createElement('div');
This answer was written/accepted a long time ago. Since then better, more comprehensive answers with examples have been submitted. You can find them by scrolling down. Below is the original accepted answer preserved for posterity.
new_row.className = "aClassName";
Here's more information on MDN: className
Use the .classList.add() method:
const element = document.querySelector('div.foo');
element.classList.add('bar');
console.log(element.className);
<div class="foo"></div>
This method is better than overwriting the className property, because it doesn't remove other classes and doesn't add the class if the element already has it.
You can also toggle or remove classes using element.classList (see the MDN documentation).
Here is working source code using a function approach.
<html>
<head>
<style>
.news{padding:10px; margin-top:2px;background-color:red;color:#fff;}
</style>
</head>
<body>
<div id="dd"></div>
<script>
(function(){
var countup = this;
var newNode = document.createElement('div');
newNode.className = 'textNode news content';
newNode.innerHTML = 'this created div contains a class while created!!!';
document.getElementById('dd').appendChild(newNode);
})();
</script>
</body>
</html>
3 ways to add a class to a DOM element in JavaScript
There are multiple ways of doing this. I will show you three ways to add classes and clarify some benefits of each way.
You can use any given method to add a class to your element, another way to check for, change or remove them.
The className way - Simple way to add a single or multiple classes and remove or change all classes.
The classList way - The way to manipulate classes; add, change or remove a single or multiple classes at the same time. They can easily be changed at any time in your code.
The DOM way - When writing code according to the DOM model, this gives a cleaner code and functions similar to the className way.
The className way
This is the simple way, storing all classes in a string. The string can easily be changed or appended.
// Create a div and add a class
var new_row = document.createElement("div");
new_row.className = "aClassName";
// Add another class. A space ' ' separates class names
new_row.className = "aClassName anotherClass";
// Another way of appending classes
new_row.className = new_row.className + " yetAClass";
If an element has a single class, checking for it is simple:
// Checking an element with a single class
new_row.className == "aClassName" ;
if ( new_row.className == "aClassName" )
// true
Removing all classes or changing them is very easy
// Changing all classes
new_row.className = "newClass";
// Removing all classes
new_row.className = "";
Searching for or removing a single class when multiple classes are used is difficult. You need to split the className string into an array, search them through one by one, remove the one you need and add all others back to your element. The classList way addresses this problem and can be used even if the class was set the className way.
The classList way
It is easy to manipulate classes when you need to. You can add, remove or check for them as you wish! It can be used with single or multiple classes.
// Create a div and add a class
var new_row = document.createElement("div");
new_row.classList.add( "aClassName" );
// Add another class
new_row.classList.add( "anotherClass" );
// Add multiple classes
new_row.classList.add( "yetAClass", "moreClasses", "anyClass" );
// Check for a class
if ( new_row.classList.contains( "anotherClass" ) )
// true
// Remove a class or multiple classes
new_row.classList.remove( "anyClass" );
new_row.classList.remove( "yetAClass", "moreClasses" );
// Replace a class
new_row.classList.replace( "anotherClass", "newClass" );
// Toggle a class - add it if it does not exist or remove it if it exists
new_row.classList.toggle( "visible" );
Removing all classes or changing to a single class is easier done the className way.
The DOM way
If you write code the DOM way, this looks cleaner and stores classes in a string by setting the class attribute.
// Create a div, add it to the documet and set class
var new_row = document.createElement( "div" );
document.body.appendChild( new_row );
new_row.setAttribute( "class", "aClassName anotherClass" );
// Add some text
new_row.appendChild( document.createTextNode( "Some text" ) );
// Remove all classes
new_row.removeAttribute( "class" );
Checking for a class is simple, when a single class is being used
// Checking when a single class is used
if ( new_row.hasAttribute( "class" )
&& new_row.getAttribute( "class" ) == "anotherClass" )
// true
Checking for or removing a single class when multiple classes are used uses the same approach as the className way. But the classList way is easier to accomplish this and can be used, even if you set it the DOM way.
If doing a lot of element creations, you can create your own basic createElementWithClass function.
function createElementWithClass(type, className) {
const element = document.createElement(type);
element.className = className
return element;
}
Very basic I know, but being able to call the following is less cluttering.
const myDiv = createElementWithClass('div', 'some-class')
as opposed to a lot of
const element1 = document.createElement('div');
element.className = 'a-class-name'
over and over.
If you want to create multiple elements all with in one method.
function createElement(el, options, listen = [], appendTo){
let element = document.createElement(el);
Object.keys(options).forEach(function (k){
element[k] = options[k];
});
if(listen.length > 0){
listen.forEach(function(l){
element.addEventListener(l.event, l.f);
});
}
appendTo.append(element);
}
let main = document.getElementById('addHere');
createElement('button', {id: 'myBtn', className: 'btn btn-primary', textContent: 'Add Alert'}, [{
event: 'click',
f: function(){
createElement('div', {className: 'alert alert-success mt-2', textContent: 'Working' }, [], main);
}
}], main);
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
<div id="addHere" class="text-center mt-2"></div>
var newItem = document.createElement('div');
newItem.style = ('background-color:red');
newItem.className = ('new_class');
newItem.innerHTML = ('<img src="./profitly_files/TimCover1_bigger.jpg" width=50 height=50> some long text with ticker $DDSSD');
var list = document.getElementById('x-auto-1');
list.insertBefore(newItem, list.childNodes[0]);
Cross-browser solution
Note: The classList property is not supported in Internet Explorer 9. The following code will work in all browsers:
function addClass(id,classname) {
var element, name, arr;
element = document.getElementById(id);
arr = element.className.split(" ");
if (arr.indexOf(classname) == -1) { // check if class is already added
element.className += " " + classname;
}
}
addClass('div1','show')
Source: how to js add class
var new_row = document.createElement('div');
new_row.setAttribute("class", "YOUR_CLASS");
This will work ;-)
source
It is also worth taking a look at:
var el = document.getElementById('hello');
if(el) {
el.className += el.className ? ' someClass' : 'someClass';
}
If you want to create a new input field with for example file type:
// Create a new Input with type file and id='file-input'
var newFileInput = document.createElement('input');
// The new input file will have type 'file'
newFileInput.type = "file";
// The new input file will have class="w-95 mb-1" (width - 95%, margin-bottom: .25rem)
newFileInput.className = "w-95 mb-1"
The output will be: <input type="file" class="w-95 mb-1">
If you want to create a nested tag using JavaScript, the simplest way is with innerHtml:
var tag = document.createElement("li");
tag.innerHTML = '<span class="toggle">Jan</span>';
The output will be:
<li>
<span class="toggle">Jan</span>
</li>
<script>
document.getElementById('add-Box').addEventListener('click', function (event) {
let itemParent = document.getElementById('box-Parent');
let newItem = document.createElement('li');
newItem.className = 'box';
itemParent.appendChild(newItem);
})
</script>