I use these JavaScript-code to change classes in my script:
var toggleDirection = function() {
group.classList.toggle('left-to-right');
group.classList.toggle('right-to-left');
}
In my example there a only two classes to change but could be also multiple classes...
So therefore: Does anyone know a way to write the example less redundant?
No it is not possible using Element.classList
API directly. Looking at API you can read:
toggle ( String [, force] ) When only one argument is present: Toggle class value; ie, if class exists then remove it, if not, then add it. When a second argument is present: If the second argument is true, add specified class value, and if it is false, remove it.
You could potentially write your own "utility" function (in vanilla JS) which does what you want, below a very simple demonstrative example which work on top of the classList
API:
var superToggle = function(element, class0, class1) {
element.classList.toggle(class0);
element.classList.toggle(class1);
}
And you call it in this way:
superToggle(group,'left-to-right', 'right-to-left');
For anyone looking for a short answer, you can do this on one line using the rest parameter introduced in ES6/ES2015:
const toggleCSSclasses = (el, ...cls) => cls.map(cl => el.classList.toggle(cl))
This is pretty close to @attacomsian's answer , but taking advantage of the fact that the rest parameter will return an array - no matter how many arguments is being passed to the function. Which means we can skip the part where we detect whether we're working with a string or an array.
const toggleCSSclasses = (el, ...cls) => cls.map(cl => el.classList.toggle(cl)); const one = document.querySelector(".one"); one.addEventListener("click", () => { toggleCSSclasses(one, "class1"); }); const two = document.querySelector(".two"); two.addEventListener("click", () => { toggleCSSclasses(two, "class1", "class2"); });
.class1 { text-decoration: underline } .class2 { background: steelblue }
<p class="one">Click to toggle one class</p> <p class="two">Click to toggle two classes</p>
just use the map array.
like
['left-to-right', 'right-to-left'].map(v=> group.classList.toggle(v) )
You can extend the DOMTokenList
object with the following multiToggle
if (window["DOMTokenList"]) //check if DOMTokenList is an existing object.
{
//multitoggle
DOMTokenList.prototype.multiToggle = function()
{
if (arguments.length > 0) // there needs to be at least one object
{
for (argument in arguments) //loop all arguments
{
var argument = arguments[argument];
//All primitives are allowed as input (Symbol not included). If not a primitive, raise error.
if (Object.prototype.toString.call(argument) !== "[object Undefined]" && Object.prototype.toString.call(argument) !== "[object Null]" && Object.prototype.toString.call(argument) !== "[object String]" && Object.prototype.toString.call(argument) !== "[object Number]" && Object.prototype.toString.call(argument) !== "[object Boolean]")
{
throw new SyntaxError;
}
else
{
if (this.contains(argument)) //check if classList contains the argument.
{
this.remove(argument); //if so remove
}
else
{
this.add(argument); //if not add
}
}
}
}
else
{
throw new Error("The argument is not optional");
}
return undefined; //return undefined as with add and remove.
}
}
multiToggle
does not have the force
ability of the original toggle
. It just turns class names on and off for as many arguments as supplied.
Warning, expanding fixed Objects can cause troubles in the future . When an object gets deprecated or changed your functionality could break, requiring to more maintenance.
There is no direct way but you can create a helper function:
const toggleClass = (el, cls) => {
if (Array.isArray(cls)) {
cls.map((cl) => {
el.classList.toggle(cl);
});
} else {
el.classList.toggle(cls);
}
};
Now just call toggleClass()
like below:
// single class
toggleClass(document.querySelector('body'), 'left-to-right');
//multiple classes
toggleClass(document.querySelector('body'), ['left-to-right', 'right-to-left']);
If I need to toggle multiple classes I just create an array and then iterate through it.
var classes = [
"red",
"blue",
"green",
"purple"
]
for (var i = 0; i < classes.length; i++){
p.classList.toggle(classes[i])
}
Here is ES6 version of solution
const classToggle = (el, ...args) => args.map(e => el.classList.toggle(e))
const classToggle = (el, ...args) => { args.map(e => el.classList.toggle(e)) }
.a { color: red } .b { background: black } .c { border-color: yellow }
<button onclick="classToggle(this,'a', 'c','b')" class="abc ">Click me</button>
And here's old JS code:
var classToggle = function classToggle(el) {
for (
var _len = arguments.length,
args = new Array(_len > 1 ? _len - 1 : 0),
_key = 1;
_key < _len;
_key++
) {
args[_key - 1] = arguments[_key];
}
args.map(function (e) {
return el.classList.toggle(e);
});
};
Answer from year 2020 here!
Found this article helpful from 4/2021
Can use comma separated list of classes like this:
const button = document.getElementById('button')
button.classList.add('btn', 'btn-primary', 'btn-primary--footer')
button.classList.remove('btn', 'btn-primary', 'btn-primary--footer')
or even spread syntax from a list of classes:
const button = document.getElementById('button')
const classes = ['btn', 'btn-primary', 'btn-primary--footer']
button.classList.add(...classes)
button.classList.remove(...classes)
Assuming that myElement is a valid DOM Element, this works:
['right-to-left', 'left-to-right'].forEach(function(className){
this.classList.toggle(className);
}, myElement);
This Worked for me
let superToggle = (element, class0, class1) => {
element.classList.toggle(class0);
element.classList.toggle(class1);
};
const toggleClasses = (e, classes) => {
classes.forEach((className) => {
e.classList.toggle(className)
});
}
const classes = [
'hidden',
'bg-white',
]
toggleClasses(element, classes)
The following should work; granted that these class-names are defined in your CSS and some elements on the current page have these classNames:
var toggleDirection = function()
{
var ltr, rtl, lst, cls;
ltr = 'left-to-right';
rtl = 'right-to-left';
lst = [].slice.call(document.getElementsByClassName(ltr));
lst = ((lst.length > 0) ? lst : [].slice.call(document.getElementsByClassName(rtl)));
lst.forEach
(
function(node)
{
cls = node.getAttribute('class');
if (cls.indexOf(ltr) > -1)
{ cls.split(ltr).join(rtl); }
else
{ cls.split(rtl).join(ltr); }
node.setAttribute('class', cls);
}
);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.