patternjavascriptMinor
Wrapping the classList API to add/remove array of classes
Viewed 0 times
thearrayremovewrappingclassesapiaddclasslist
Problem
I've written a function that wraps the classList API, allowing you to pass an array of classes to add/remove, or the variable arguments already supported by
The methods are the following:
Usage:
I'm wondering if there's some better way to implement this function, say without using the
Is it possible to write this more succinctly, whilst keeping all of the use cases?
classList.The methods are the following:
var flatten = function(array) {
return Array.prototype.concat.apply([], array);
};
var classMethod = function(method) {
return function(element /*, classes... */) {
return flatten(Array.prototype.slice.call(arguments, 1)).forEach(function(klass) {
element.classList[method](klass);
});
}
};
var addClass = classMethod('add');
var removeClass = classMethod('remove');Usage:
var elem = document.querySelector('.box');
addClass(elem, 'class1');
addClass(elem, 'class2', 'class3');
addClass(elem, ['class2', 'class3']);
removeClass(elem, 'class1');
removeClass(elem, 'class2', 'class3');
removeClass(elem, ['class2', 'class3']);I'm wondering if there's some better way to implement this function, say without using the
forEach call and instead using Function.prototype.apply, but I get a TypeError: Illegal invocation when trying to refactor this into, say:var classMethod = function(method) {
return function(element /*, classes... */) {
element.classList[method].apply(element, flatten(Array.prototype.slice.call(arguments, 1)));
}
};Is it possible to write this more succinctly, whilst keeping all of the use cases?
Solution
Interesting question,
I've been looking at this for a while, I dont think there is a more succinct way. I've been playing with reconstructing
The core reason for that is default JS does not have enough convenience methods for arrays. If you were open to use something like LoDash, you could do this:
Other than that I really like your code; proper naming, indenting, size of functions, etc.
Update on illegal invocation, you are passing
And then that works.. My mind is still boggling at that, but there you go.
I've been looking at this for a while, I dont think there is a more succinct way. I've been playing with reconstructing
className from the add or remove function calls but it became a less succinct and terrible hack.The core reason for that is default JS does not have enough convenience methods for arrays. If you were open to use something like LoDash, you could do this:
var addClass = function addClass(element /*, classes... */){
element.className = _.uniq( element.className.split(' ').concat( _.flatten( _.rest( arguments ) ) ) ).join(' ');
};
var removeClass = function removeClass(element /*, classes... */){
element.className = _.difference( element.className.split(' '), _.flatten( _.rest( arguments ) ) ).join(' ');
};Other than that I really like your code; proper naming, indenting, size of functions, etc.
Update on illegal invocation, you are passing
element as this to a function that is attached to classList, if you pass classList, then there will be no exception.var classMethod = function(method) {
return function(element /*, classes... */) {
var classList = element.classList;
element.classList[method].apply(classList,flatten(Array.prototype.slice.call(arguments, 1)));
};
};And then that works.. My mind is still boggling at that, but there you go.
Code Snippets
var addClass = function addClass(element /*, classes... */){
element.className = _.uniq( element.className.split(' ').concat( _.flatten( _.rest( arguments ) ) ) ).join(' ');
};
var removeClass = function removeClass(element /*, classes... */){
element.className = _.difference( element.className.split(' '), _.flatten( _.rest( arguments ) ) ).join(' ');
};var classMethod = function(method) {
return function(element /*, classes... */) {
var classList = element.classList;
element.classList[method].apply(classList,flatten(Array.prototype.slice.call(arguments, 1)));
};
};Context
StackExchange Code Review Q#70303, answer score: 3
Revisions (0)
No revisions yet.