This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
http://www.w3.org/TR/html5/common-dom-interfaces.html#domtokenlist-0 DOMTokenList should be able to add/remove multiple tokens at once. In particular, element.classList should be able to add or remove more than one class at once. For example, following should be possible: element.classList.add("lorem ipsum dolor"); element.classList.remove("lorem ipsum dolor"); Additionally, it may make sense to allow to use Array instead of string as argument: element.classList.add(["lorem", "ipsum", "dolor"]); element.classList.remove(["lorem", "ipsum", "dolor"]); Currently, DOMTokenList is almost useless since element.classList is _slower_ than pure-script implementation when adding/removing multiple classes at once. For example, jQuery _intentionally drops_ using element.classList exactly for this reason: http://bugs.jquery.com/ticket/5087 Adding multiple classes is widely used, for example, in jQuery UI. Thanks.
What do other libraries do with this? jQuery only allows a single class to be added/removed at a time. Of course, it allows you to chain addClass() calls, while you can't chain classList.add() calls. Would it make more sense to change things so that DOMTokenList returns itself from add/remove/toggle? The performance of classList is an implementation detail. There's no particular reason for it to be slower, except that jQuery doesn't actually implement the spec (there are a bunch of requirements that you need to be careful about).
(In reply to comment #1) > jQuery only allows a single class to be added/removed at a time. You are wrong. See http://api.jquery.com/addClass/#example-1 http://api.jquery.com/removeClass/#example-1
(In reply to comment #1) > The performance of classList is an implementation detail. There's no > particular reason for it to be slower. One of major reasons is that consequent adding classes one by one causes multiple rendering-reflows. (Each reflow is quite time-expensive operation.) Opposite to this, adding multiple classes at once causes only one reflow.
Whoops, you're right. jQuery *does* allow multiple classes. I was misled by a quick skim. (In reply to comment #3) > (In reply to comment #1) > > > The performance of classList is an implementation detail. There's no > > particular reason for it to be slower. > > One of major reasons is that consequent adding classes one by one causes > multiple rendering-reflows. (Each reflow is quite time-expensive operation.) > > Opposite to this, adding multiple classes at once causes only one reflow. I agree with the reasoning; I was just looking for precedent for good ways to do it.
(In reply to comment #3) > One of major reasons is that consequent adding classes one by one causes > multiple rendering-reflows. (Each reflow is quite time-expensive operation.) I don't think this is true. Reflows are generally batched up and happen only once when the script is finished doing what it's doing (except in Opera if the script is taking a long time), unless you force a reflow by asking for layout with .offsetLeft or so between adding your classes.
(In reply to comment #5) Multiple consequent calls to a function are always slower than one call to the same function. Even if a specific browser does not do reflows after each function-call.
The question is whether it is slower by any sort of relevant measure. One CPU cycle slower, for example, really seems irrelevant for a function such as this. But if each call takes 10 seconds, that's a big deal. The reflow thing is definitely not an issue. Nothing happens of that nature until the scripts have ended. Anyway, DOMTokenList is no longer my problem. ->DOM Core.
FYI: My tentative plan is to resolve this by doing the simplest thing possible. Extend add() and remove() to take a space-separated string.
(In reply to comment #8) > FYI: My tentative plan is to resolve this by doing the simplest thing possible. > Extend add() and remove() to take a space-separated string. Thanks, that's nice. And how about also supporting Array as argument? Ability to pass multiple items as Array (native data-type to store multiple items) looks very natural and intuitive.
(In reply to comment #9) > Thanks, that's nice. And how about also supporting Array as argument? Ability > to pass multiple items as Array (native data-type to store multiple items) > looks very natural and intuitive. el.classList(arr.join(' ')) would give you that ability as well. But maybe since the difference is so minimal it's worth adding it? I'm not sure to what degree an array is as or more intuitive than a space separated string, but something like Array.isArray(classes) ? classes.join(" ") : classes would allow both.
Another possible approach would be to follow the precedent set by Array.prototype.push: make classList.add() a variable arity function - after all, it's essentially "push"ing onto the token list. el.classList.add( token[, token... ] ); This also allows a user to do fun stuff like... var classes = [ "foo", "bar", "baz" ]; // ... some program stuff that adds or substracts tokens from `classes`... el.classList.add.apply( null, classes );
(In reply to comment #3) > (In reply to comment #1) > > > The performance of classList is an implementation detail. There's no > > particular reason for it to be slower. There are reasons that makes classList slower. None of the JS frameworks validate the input. Validation of the input is required by the spec for DOMTokenList. > One of major reasons is that consequent adding classes one by one causes > multiple rendering-reflows. (Each reflow is quite time-expensive operation.) This is not true. However, it does serialize the DOMTokenList to a string. That string is then used in setAttribute('class', string) since there might be mutation listeners etc.
(In reply to comment #11) > Another possible approach would be to follow the precedent set by > Array.prototype.push: make classList.add() a variable arity function - after > all, it's essentially "push"ing onto the token list. > > el.classList.add( token[, token... ] ); > > This also allows a user to do fun stuff like... > > var classes = [ "foo", "bar", "baz" ]; > > // ... some program stuff that adds or substracts tokens from `classes`... > > el.classList.add.apply( null, classes ); And with ES6 this will be even easier. el.classList.add(...classes) I'm opposed to space separated string since it is not well structured. Having structure hidden in the string is less clear than taking multiple arguments. Also, I can easily flip the join argument to use split el.classList.add(...someString.split(/\s+/)) another reason why add should not take a space separated string is that className already supports this: el.className += ' ' + spaceSeparatedString;
Rest params and spread are in the ES6 draft and are available in Firefox. I want to start implementing this as interface DOMTokenList { void add(in DOMString... tokens); void remove(in DOMString... tokens); } Any objections?
+1
There are no objections. We are just waiting for ES6 to be stable enough. It is now?
http://dom.spec.whatwg.org/#domtokenlist https://github.com/whatwg/dom/commit/91fcd602fc31310aee487ebf809451195f64af9e