The method toggle
of Element.classList
expects a parameter which names a CSS-class.
You can't assign multiple classes at once by using for example an array.
So you have to write something like ...
div.classList.toggle("hidden-element");
div.classList.toggle("border-defs");
div.classList.toggle("green-theme");
Therefore I've made an function to which a list of classes can be passed.
var toggleButton = document.querySelector('.toggle-classes');
/**
* Adds / removes CSS-class(es) from an HTML-element.
* 1. String: CSS-class or a list of CSS-classes. Within a list
* the single values have to be separated by a space.
* 2. String: A CSS-selector pointing to the HTML-element upon
* which the class(es) shall be added / removed.
* Returns true to indicate success.
* Throws Error in case of failure.
*/
function toggleClasses(cssSelector, listOfClasses) {
var element;
var classes;
if (arguments.length !== toggleClasses.length)
throw new Error('Lack of required parameter.');
if (typeof listOfClasses !== 'string' || listOfClasses.length === 0)
throw new Error('List of CSS-classes is not valid.');
classes = listOfClasses.split(/\s/);
if (typeof cssSelector !== 'string' || cssSelector.length === 0)
throw new Error('Given CSS-selector is not valid.');
element = document.querySelector(cssSelector);
if (element === null)
throw new Error('No HTML-element with selector ' + cssSelector + ' found.');
classes.forEach(function(classItem, i) {
element.className.indexOf(classItem) === -1
? element.classList.add(classItem)
: element.classList.remove(classItem);
});
return true
}
// ------ USAGE EXAMPLE --------------------------------------------
var listPos = 'shadows font-special red-theme blue-theme misc-foo';
toggleButton.addEventListener('click', function() {
try {
toggleClasses('.demo', listPos);
} catch (e) {
console.error(e.message);
}
});
.wrap {
margin: 20px auto;
width: 900px;
background-color: rgba(245, 245, 245, 1.0);
padding: 20px 30px;
}
.demo {
width: 150px;
height: 80px;
line-height: 80px;
text-align: center;
margin: 10px 0;
}
.blue-theme {
border: 3px solid pink;
background-color: teal;
color: white;
font-weight: 800;
}
.red-theme {
border: 3px solid teal;
background-color: pink;
}
.shadows {
text-shadow: 3px 3px 3px white;
box-shadow: 3px 3px 3px grey;
}
.font-special {
color: grey;
font-weight: bold;
font-family: georgia;
}
.misc-foo {
border-radius: 12px;
transform: skewY(5deg);
}
<div class="wrap">
<button class="toggle-classes">Toggle classes</button>
<div class="demo blue-theme">Demonstration</div>
</div>
I'm still not sure if I shall stay with the way of assigning the classes. One could also use an array instead of a space-separated string.
Or make it optional? If an array is assigned then that is used. If an string is assigned then it is separated.
Or would it be rather confusing to offer multiple options and better to stick with just one?
I also ask myself if my approach of throwing errors isn't a bit too drastically.
The CSS-classes are just for styling. So an application could go on with it's main purpose even if the function fails. It isn't really necessary to react so hard. Should I use something else instead? Returning, for example, a specified value?
Any hints and suggestions concerning flaws and possible improvements welcome.