web-dev-qa-db-fra.com

Est-il possible d'ajouter/supprimer plusieurs classes dans une seule instruction avec classList?

Jusqu'ici je dois faire ceci:

elem.classList.add("first");
elem.classList.add("second");
elem.classList.add("third");

Bien que cela soit faisable dans jQuery, comme ceci

$(elem).addClass("first second third");

J'aimerais savoir s'il existe un moyen natif d'ajouter ou de supprimer.

102
elem.classList.add("first");
elem.classList.add("second");
elem.classList.add("third");

est égal

elem.classList.add("first","second","third");
207
iwege

Le nouvel opérateur spread facilite l’application de plusieurs classes CSS en tant que tableau:

const list = ['first', 'second', 'third'];
element.classList.add(...list);
41
morkro

La propriété classList garantit que les classes en double ne sont pas ajoutées inutilement à l'élément. Afin de conserver cette fonctionnalité, si vous n'aimez pas les versions longhand ou jQuery, nous vous suggérons d'ajouter une fonction addMany et removeMany à DOMTokenList (type classList):

DOMTokenList.prototype.addMany = function(classes) {
    var array = classes.split(' ');
    for (var i = 0, length = array.length; i < length; i++) {
      this.add(array[i]);
    }
}

DOMTokenList.prototype.removeMany = function(classes) {
    var array = classes.split(' ');
    for (var i = 0, length = array.length; i < length; i++) {
      this.remove(array[i]);
    }
}

Celles-ci seraient alors utilisables comme ceci:

elem.classList.addMany("first second third");
elem.classList.removeMany("first third");

Mettre à jour

Selon vos commentaires, si vous souhaitez écrire uniquement une méthode personnalisée pour ceux-ci dans le cas où ils ne sont pas définis, essayez ce qui suit:

DOMTokenList.prototype.addMany = DOMTokenList.prototype.addMany || function(classes) {...}
DOMTokenList.prototype.removeMany = DOMTokenList.prototype.removeMany || function(classes) {...}
18
Rich O'Kelly

Étant donné que la méthode add() de la classList permet uniquement de transmettre des arguments séparés et non un seul tableau, vous devez invoquer add() à l'aide de apply. Pour le premier argument, vous devrez passer la référence classList du même nœud DOM et, en tant que second argument, le tableau de classes que vous souhaitez ajouter:

element.classList.add.apply(
  element.classList,
  ['class-0', 'class-1', 'class-2']
);
12
Andrés Carreño

Pour ajouter une classe à un élément

document.querySelector(elem).className+=' first second third';

METTRE À JOUR:

Supprimer une classe

document.querySelector(elem).className=document.querySelector(elem).className.split(class_to_be_removed).join(" ");
6
user1432124

Les versions plus récentes de la spécification DOMTokenList autorisent plusieurs arguments pour add() et remove(), ainsi qu'un second argument pour toggle() pour forcer l'état.

Au moment de la rédaction de ce document, Chrome prend en charge plusieurs arguments pour add() et remove(), mais aucun autre navigateur ne le fait. IE 10 et inférieur, Firefox 23 et inférieur, Chrome 23 et inférieur et les autres navigateurs ne supportent pas le deuxième argument de toggle()

J'ai écrit le petit polyfill suivant pour me guider jusqu'à ce que le support augmente:

(function () {
    /*global DOMTokenList */
    var dummy  = document.createElement('div'),
        dtp    = DOMTokenList.prototype,
        toggle = dtp.toggle,
        add    = dtp.add,
        rem    = dtp.remove;

    dummy.classList.add('class1', 'class2');

    // Older versions of the HTMLElement.classList spec didn't allow multiple
    // arguments, easy to test for
    if (!dummy.classList.contains('class2')) {
        dtp.add    = function () {
            Array.prototype.forEach.call(arguments, add.bind(this));
        };
        dtp.remove = function () {
            Array.prototype.forEach.call(arguments, rem.bind(this));
        };
    }

    // Older versions of the spec didn't have a forcedState argument for
    // `toggle` either, test by checking the return value after forcing
    if (!dummy.classList.toggle('class1', true)) {
        dtp.toggle = function (cls, forcedState) {
            if (forcedState === undefined)
                return toggle.call(this, cls);

            (forcedState ? add : rem).call(this, cls);
            return !!forcedState;
        };
    }
})();

Un navigateur moderne avec la conformité ES5 et DOMTokenList est attendu, mais j'utilise ce polyfill dans plusieurs environnements spécifiquement ciblés. Cela fonctionne donc très bien pour moi, mais il faudra peut-être peaufiner les scripts qui s'exécutent dans des environnements de navigateur hérités tels que IE 8 et moins.

6
Andy E

Voici un moyen de contourner le problème pour les utilisateurs de IE 10 et 11, qui semblait assez simple.

var elem = document.getElementById('elem');

['first','second','third'].map(item => elem.classList.add(item));
<div id="elem">Hello World!</div>

Ou

var elem = document.getElementById('elem'),
    classes = ['first','second','third'];

classes.map(function(item) {
    return elem.classList.add(item);
});
<div id="elem">Hello World!</div>

2
colecmc

La définition standard ne permet que d’ajouter ou de supprimer une seule classe. Quelques petites fonctions d'emballage peuvent faire ce que vous demandez:

function addClasses (el, classes) {
  classes = Array.prototype.slice.call (arguments, 1);
  console.log (classes);
  for (var i = classes.length; i--;) {
    classes[i] = classes[i].trim ().split (/\s*,\s*|\s+/);
    for (var j = classes[i].length; j--;)
      el.classList.add (classes[i][j]);
  }
}

function removeClasses (el, classes) {
  classes = Array.prototype.slice.call (arguments, 1);
  for (var i = classes.length; i--;) {
    classes[i] = classes[i].trim ().split (/\s*,\s*|\s+/);
    for (var j = classes[i].length; j--;)
      el.classList.remove (classes[i][j]);
  }
}

Ces wrappers vous permettent de spécifier la liste de classes en tant qu'arguments séparés, en tant que chaînes avec des éléments séparés par des espaces ou une virgule, ou une combinaison. Pour un exemple, voir http://jsfiddle.net/jstoolsmith/eCqy7

2
HBP

Un autre polyfill pour element.classList est here . Je l'ai trouvé via MDN .

J'inclus ce script et utilise element.classList.add("first","second","third") comme prévu.

0
Rafi

J'ai aimé la réponse de @ rich.kelly, mais je voulais utiliser la même nomenclature que classList.add() (chaînes séparées par des virgules), donc une légère déviation.

DOMTokenList.prototype.addMany = DOMTokenList.prototype.addMany || function() {
  for (var i = 0; i < arguments.length; i++) {
    this.add(arguments[i]);
  }
}
DOMTokenList.prototype.removeMany = DOMTokenList.prototype.removeMany || function() {
  for (var i = 0; i < arguments.length; i++) {
    this.remove(arguments[i]);
  }
}

Vous pouvez alors utiliser:

document.body.classList.addMany('class-one','class-two','class-three');

Je dois tester tous les navigateurs, mais cela a fonctionné pour Chrome.
Devrions-nous vérifier quelque chose de plus spécifique que l'existence de DOMTokenList.prototype.addMany? Qu'est-ce qui cause exactement l'échec de classList.add() dans IE11?

0
Jason Lydon

En supposant que vous ayez un tableau de classes à ajouter, vous pouvez utiliser la syntaxe de propagation ES6:

let classes = ['first', 'second', 'third']; elem.classList.add(...classes);

0
Dong Nguyen

Une solution très simple, peu sophistiquée, mais qui fonctionne, que je devrais croire, est très multi-navigateur:

Créer cette fonction

function removeAddClasses(classList,removeCollection,addCollection){
    for (var i=0;i<removeCollection.length;i++){ 
        classList.remove(removeCollection[i]); 
    }
    for (var i=0;i<addCollection.length;i++){ 
        classList.add(addCollection[i]); 
    }
}

Appelez-le comme suit: RemoveAddClasses (node.classList, arrayToRemove, arrayToAdd);

... où arrayToRemove est un tableau de noms de classe à supprimer: ['myClass1', 'myClass2'], etc.

... et arrayToAdd est un tableau de noms de classes à ajouter: ['myClass3', 'myClass4'] etc.

0
Soren