Traduzione in corso.

Element.classList è una proprietà di sola lettura che restituisce la DOMTokenList raccolta delle classi dell'elemento.

L'utilizzo di classList è una comoda alternativa all'accesso all'elenco di classi di un elemento come stringa delimitata dallo spazio tramite element.className.

Syntax

const elementClasses = elementNodeReference.classList;

elementClasses è un DOMTokenList che rappresenta l'attributo di classe di elementNodeReference. Se l'attributo class non è stato impostato o è vuoto elementClasses.length ritorna 0. element.classList è di sola lettura, sebbene sia possibile modificarlo utilizzando i metodi add()remove().

Metodi

add( String [, String [, ...]] )
Aggiunge classi specificate. Se queste classi esistono già, vengono ignorate.
remove( String [, String [, ...]] )
Rimuove le classi specificate.
Nota: la rimozione di una classe inesistente NON genera un errore.
item( Number )
Restituisce il valore della classe per indice in collezione.
toggle( String [, force] )
Quando è presente un solo argomento aggiunge / rimuove il valore della classe; ad esempio, se la classe esiste quando la rimuove ritorna false, altrimenti, aggiunge essa e ritorna true.
Quando è presente un secondo argomento: Se il secondo argomento restituisce true, aggiunge un valore di classe specificato rimuoverlo.
contains( String )
Verifica se esiste la classe specificata è presente nell'attributo dell'elemento.
replace( oldClass, newClass )
Sostituisce una classe esistente con una nuova classe.

Esempi

const div = document.createElement('div');
div.className = 'foo';

// il nostro stato iniziale: <div class="foo"></div>
console.log(div.outerHTML);

// usa l'API classList per rimuovere e aggiungere classi
div.classList.remove("foo");
div.classList.add("anotherclass");

// <div class="anotherclass"></div>
console.log(div.outerHTML);

// se "visibile" è impostato rimuovilo, altrimenti aggiungilo
div.classList.toggle("visible");

// aggiungi / rimuovi "visibile", a seconda del test condizionale, i meno di 10
div.classList.toggle("visible", i < 10 );

console.log(div.classList.contains("foo"));

// aggiungere o rimuovere più classi
div.classList.add("foo", "bar", "baz");
div.classList.remove("foo", "bar", "baz");

// aggiungere o rimuovere più classi utilizzando la sintassi di diffusione
const cls = ["foo", "bar"];
div.classList.add(...cls); 
div.classList.remove(...cls);

// sostituire la classe "foo" con la classe "bar"
div.classList.replace("foo", "bar");

Le versioni di Firefox precedenti alla 26 non implementano l'uso di diversi argomenti nei metodi add / remove / toggle. Vedi https://bugzilla.mozilla.org/show_bug.cgi?id=814014

Polyfill

L'evento legacy onpropertychange può essere utilizzato per creare un mockup di classList live in considerazione del fatto che esiste una proprietà Element.prototype.className che genererà questo evento quando modificato. Il seguente polyfill implementerà sia classList che la sua DOMFokenList corrispondente. Il seguente polyfill garantisce la piena conformità agli standard per tutti i metodi DOMTokenList e l'accesso a Element.prototype.classList in IE10-IE11 e in più il comportamento "abbastanza standard" (per la maggior parte delle applicazioni generali) in IE6-9.

// 1. String.prototype.trim polyfill
if (!"".trim) String.prototype.trim = function(){ return this.replace(/^[s]+|[s]+$/g, ''); };
(function(window){"use strict"; // previene l'inquinamento dello spazio dei nomi globale
function checkIfValidClassListEntry(O, V){
if (V === "") throw new DOMException(
  "Impossibile eseguire '" + O + "' su 'DOMTokenList': Il token fornito non deve essere vuoto." );
if((wsI=V.search(wsRE))!==-1)throw new DOMException("Impossibile eseguire '"+O+"' su 'DOMTokenList': "+
"Il token fornito ('"+V[wsI]+"') contiene caratteri spazio HTML, che non sono validi nei token.");
  }
// 2. Implementa il polyfill vivacità di barebone DOMTokenList
if (typeof DOMTokenList !== "function") (function(window){
    var document = window.document, Object = window.Object, hasOwnProp = Object.prototype.hasOwnProperty;
    var defineProperty = Object.defineProperty, allowTokenListConstruction = 0, skipPropChange = 0;
    var Element = window.Element, wsI = 0, wsRE = /[\11\12\14\15\40]/; // WhiteSpace Regular Expression
    function DOMTokenList(){
        if (!allowTokenListConstruction) throw TypeError("Illegal constructor"); // lasciarlo passare internamente
    }
    DOMTokenList.prototype.toString = DOMTokenList.prototype.toLocaleString = function(){return this.value};
    DOMTokenList.prototype.add = function(){
        a: for(var v=0, argLen=arguments.length,val="",ele=this["uCL"],proto=ele[" uCLp"]; v!==argLen; ++v) {
            val = arguments[v] + "", checkIfValidClassListEntry("add", val);
            for (var i=0, Len=proto.length, resStr=val; i !== Len; ++i)
                if (this[i] === val) continue a; else resStr += " " + this[i];
            this[Len] = val, proto.length += 1, proto.value = resStr;
        }
        skipPropChange = 1, ele.className = proto.value, skipPropChange = 0;
    };
    DOMTokenList.prototype.remove = function(){
        for (var v=0, argLen=arguments.length,val="",ele=this["uCL"],proto=ele[" uCLp"]; v !== argLen; ++v) {
            val = arguments[v] + "", checkIfValidClassListEntry("remove", val);
            for (var i=0, Len=proto.length, resStr="", is=0; i !== Len; ++i)
                if(is){ this[i-1]=this[i] }else{ if(this[i] !== val){ resStr+=this[i]+" "; }else{ is=1; } }
            if (!is) continue;
            delete this[Len], proto.length -= 1, proto.value = resStr;
        }
        skipPropChange = 1, ele.className = proto.value, skipPropChange = 0;
    };
    window.DOMTokenList = DOMTokenList;
    function whenPropChanges(){
        var evt = window.event, prop = evt.propertyName;
        if ( !skipPropChange && (prop==="className" || (prop==="classList" && !defineProperty)) ) {
            var target = evt.srcElement, protoObjProto = target[" uCLp"], strval = "" + target[prop];
            var tokens=strval.trim().split(wsRE), resTokenList=target[prop==="classList"?" uCL":"classList"];
            var oldLen = protoObjProto.length;
            a: for(var cI = 0, cLen = protoObjProto.length = tokens.length, sub = 0; cI !== cLen; ++cI){
                for(var innerI=0; innerI!==cI; ++innerI) if(tokens[innerI]===tokens[cI]) {sub++; continue a;}
                resTokenList[cI-sub] = tokens[cI];
            }
            for (var i=cLen-sub; i < oldLen; ++i) delete resTokenList[i]; //remove trailing indexs
            if(prop !== "classList") return;
            skipPropChange = 1, target.classList = resTokenList, target.className = strval;
            skipPropChange = 0, resTokenList.length = tokens.length - sub;
        }
    }
    function polyfillClassList(ele){
        if (!ele || !("innerHTML" in ele)) throw TypeError("Illegal invocation");
        srcEle.detachEvent( "onpropertychange", whenPropChanges ); // prevenire il loop infinito del gestore duplicato
        allowTokenListConstruction = 1;
        try{ function protoObj(){} protoObj.prototype = new DOMTokenList(); }
        finally { allowTokenListConstruction = 0 }
        var protoObjProto = protoObj.prototype, resTokenList = new protoObj();
        a: for(var toks=ele.className.trim().split(wsRE), cI=0, cLen=toks.length, sub=0; cI !== cLen; ++cI){
            for (var innerI=0; innerI !== cI; ++innerI) if (toks[innerI] === toks[cI]) { sub++; continue a; }
            this[cI-sub] = toks[cI];
        }
        protoObjProto.length = Len-sub, protoObjProto.value = ele.className, protoObjProto[" uCL"] = ele;
        if (defineProperty) { defineProperty(ele, "classList", { // IE8 e IE9 consentono defineProperty sul DOM
            enumerable:   1, get: function(){return resTokenList},
            configurable: 0, set: function(newVal){
                skipPropChange = 1, ele.className = protoObjProto.value = (newVal += ""), skipPropChange = 0;
                var toks = newVal.trim().split(wsRE), oldLen = protoObjProto.length;
                a: for(var cI = 0, cLen = protoObjProto.length = toks.length, sub = 0; cI !== cLen; ++cI){
                    for(var innerI=0; innerI!==cI; ++innerI) if(toks[innerI]===toks[cI]) {sub++; continue a;}
                    resTokenList[cI-sub] = toks[cI];
                }
                for (var i=cLen-sub; i < oldLen; ++i) delete resTokenList[i]; // rimuovere gli indici finali
            }
        }); defineProperty(ele, " uCLp", { // per accedere al prototype nascosto
            enumerable: 0, configurable: 0, writeable: 0, value: protoObj.prototype
        }); defineProperty(protoObjProto, " uCL", {
            enumerable: 0, configurable: 0, writeable: 0, value: ele
        }); } else { ele.classList=resTokenList, ele[" uCL"]=resTokenList, ele[" uCLp"]=protoObj.prototype; }
        srcEle.attachEvent( "onpropertychange", whenPropChanges );
    }
    try { // Versione molto più veloce e pulita per IE8 e IE9:
        // Dovrebbe funzionare in IE8 perché Element.prototype instanceof Node è true in base alle specifiche
        window.Object.defineProperty(window.Element.prototype, "classList", {
            enumerable: 1,   get: function(val){
                                 if (!hasOwnProp.call(ele, "classList")) polyfillClassList(this);
                                 return this.classList;
                             },
            configurable: 0, set: function(val){this.className = val}
        });
    } catch(e) { // Fallback meno performante per i browser più vecchi (IE 6-8):
        window[" uCL"] = polyfillClassList;
        // il codice sottostante assicura che polyfillClassList venga applicato a tutti gli elementi attuali e futuri nel documento.
        document.documentElement.firstChild.appendChild(document.createElement('style')).styleSheet.cssText=(
            '_*{x-uCLp:expression(!this.hasOwnProperty("classList")&&window[" uCL"](this))}' + //  IE6
            '[class]{x-uCLp/**/:expression(!this.hasOwnProperty("classList")&&window[" uCL"](this))}' //IE7-8
        );
    }
})();
// 3. Patch per i metodi non supportati in DOMTokenList
(function(DOMTokenListProto, testClass){
    if (!DOMTokenListProto.item) DOMTokenListProto.item = function(i){
        function NullCheck(n) {return n===void 0 ? null : n} return NullCheck(this[i]);
    };
    if (!DOMTokenListProto.toggle || testClass.toggle("a",0)!==false) DOMTokenListProto.toggle=function(val){
        if (arguments.length > 1) return (this[arguments[1] ? "add" : "remove"](val), !!arguments[1]);
        var oldValue = this.value;
        return (this.remove(oldToken), oldValue === this.value && (this.add(val), true) /*|| false*/);
    };
    if (!DOMTokenListProto.replace || typeof testClass.replace("a", "b") !== "boolean")
        DOMTokenListProto.replace = function(oldToken, newToken){
            checkIfValidClassListEntry("replace", oldToken), checkIfValidClassListEntry("replace", newToken);
            var oldValue = this.value;
            return (this.remove(oldToken), this.value !== oldValue && (this.add(newToken), true));
        };
    if (!DOMTokenListProto.contains) DOMTokenListProto.contains = function(value){
        for (var i=0,Len=this.length; i !== Len; ++i) if (this[i] === value) return true;
        return false;
    };
    if (!DOMTokenListProto.forEach) DOMTokenListProto.forEach = function(f){
        if (arguments.length === 1) for (var i = 0, Len = this.length; i !== Len; ++i) f( this[i], i, this);
        else for (var i=0,Len=this.length,tArg=arguments[1]; i !== Len; ++i) f.call(tArg, this[i], i, this);
    };
    if (!DOMTokenListProto.entries) DOMTokenListProto.entries = function(){
        var nextIndex = 0, that = this;
        return {next: function() {
            return nextIndex<that.length ? {value: [nextIndex, that[nextIndex]], done: false} : {done: true};
        }};
    };
    if (!DOMTokenListProto.values) DOMTokenListProto.values = function(){
        var nextIndex = 0, that = this;
        return {next: function() {
            return nextIndex<that.length ? {value: that[nextIndex], done: false} : {done: true};
        }};
    };
    if (!DOMTokenListProto.keys) DOMTokenListProto.keys = function(){
        var nextIndex = 0, that = this;
        return {next: function() {
            return nextIndex<that.length ? {value: nextIndex, done: false} : {done: true};
        }};
    };
})(window.DOMTokenList.prototype, window.document.createElement("div").classList);
})(window);

Si prega di notare che il polyfill sopra è limitato nelle sue funzionalità. Al momento non è in grado di eseguire il polyfill fuori dagli elementi del documento (ad esempio, elementi creati da document.createElement prima di essere appendChild su un nodo padre) in IE 6-7. Tuttavia, dovrebbe funzionare bene in IE9. Una notevole discrepenza tra la versione polyfilled di classList e le specifiche W3 è in IE6-8, non c'è modo di creare un oggetto immutabile (un oggetto le cui proprietà non possono essere modificate direttamente). In IE9, tuttavia, è possibile estendere il prototye, congelando l'oggetto visibile e sovrascrivendo i metodi di proprietà native. Tuttavia, tali azioni non funzionerebbero in IE6-IE8 e, in IE9, rallenterebbero le prestazioni dell'intera pagina Web in una scansione di lumache, rendendo queste modifiche completamente poco pratiche per questo polyfill. Una nota minore è che in IE6-7 questo polyfill usa la proprietà window[" uCL"] sull'oggetto window per comunicare con le espressioni CSS, la proprietà css x-uCLp su tutti gli elementi e la proprietà element[" uCL"] su tutti gli elementi per consentire la garbage collection e aumentare le prestazioni. In tutti i browser con Polyfill (IE6-9), un ulteriore  proprietà element[" uCLp"] viene aggiunta all'elemento per garantire la prototipazione conforme agli standard e alla proprietà DOMTokenList[" uCL"] viene aggiunto a ogni elemento in element["classList"] per assicurare che il DOMTokenList sia limitato al proprio elemento.

Specificazioni

Specificazione Stato Commento
DOM
The definition of 'Element.classList' in that specification.
Living Standard Initial definition
DOM4
The definition of 'Element.classList' in that specification.
Obsolete  

Compatibilità con i browser

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support8

16

121

3.610 Yes5.1
toggle() method's second argument241224 No157
Multiple arguments for add() & remove()241226 No157
replace()61 ?49 No ? No
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support Yes Yes12 Yes ?5 ?
toggle() method's second argument Yes Yes1224 ?7 ?
Multiple arguments for add() & remove() Yes Yes1226 ?7 ?
replace() ?61 ?49 ? No ?

1. Not supported for SVG elements.

Guarda anche

Tag del documento e collaboratori

Hanno collaborato alla realizzazione di questa pagina: LBreda, IsibisiDev
Ultima modifica di: LBreda,