1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
|
---
title: Element.classList
slug: Web/API/Element/classList
tags:
- API
- DOM
- Element
- Proprietà
- Read-only
- Referenza
translation_of: Web/API/Element/classList
---
<div>{{APIRef("DOM")}}</div>
<p>La proprietà <code><strong>Element.classList</strong></code> di sola lettura restituisce una raccolta {{domxref("DOMTokenList")}} dinamica delle classi dell'elemento.</p>
<p>L'utilizzo di <code>classList</code> è una comoda alternativa all'accesso all'elenco di classi di un elemento come stringa delimitata dallo spazio tramite {{domxref("element.className")}}.</p>
<h2 id="Sintassi">Sintassi</h2>
<pre class="syntaxbox">const <var>elementClasses</var> = elementNodeReference.classList;
</pre>
<p><em>elementClasses</em> è una {{domxref("DOMTokenList")}} che rappresenta l'attributo class di <em>elementNodeReference</em>. Se l'attributo class non è stato impostato o è vuoto <em>elementClasses.length</em> ritorna <code>0</code>. <code>element.classList</code> è di sola lettura, sebbene sia possibile modificarlo utilizzando i metodi <code>add()</code> e <code>remove()</code>.</p>
<h2 id="Metodi">Metodi</h2>
<dl>
<dt><code>add( String [, String [, ...]] )</code></dt>
<dd>Aggiunge le classi specificate. Se queste classi esistono già nell'attributo <code>class</code> dell'elemento, vengono ignorate.</dd>
<dt><code>remove( String [, String [, ...]] )</code></dt>
<dd>
<p>Rimuove le classi specificate.</p>
<div class="note"><strong>Nota:</strong> La rimozione di una classe inesistente NON genera un errore.</div>
</dd>
<dt><code><strong>item</strong>( Number )</code></dt>
<dd>Restituisce il valore della classe per indice nella collezione.</dd>
<dt><code><strong>toggle</strong>( String [, force] )</code></dt>
<dd>Quando è presente un solo argomento: aggiunge/rimuove il valore della classe; ad esempio, se la classe esiste, la rimuove e restituisce <code>false</code>, altrimenti, la aggiunge e restituisce <code>true</code>.<br>
<br>
Quando è presente un secondo argomento: Se il secondo argomento restituisce <code>true</code>, aggiunge la classe specificata; se restituisce <code>false</code>, la rimuove.</dd>
<dt><code>contains( String )</code></dt>
<dd>Verifica se il valore di classe specificato esiste nell'attributo <code>class</code> dell'elemento.</dd>
<dt><code>replace( vecchiaClasse, nuovaClasse )</code></dt>
<dd>Sostituisce una classe esistente con una nuova classe.</dd>
</dl>
<h2 id="Esempi">Esempi</h2>
<pre class="brush: js">const div = document.createElement('div');
div.className = 'foo';
// il nostro stato iniziale: <div class="foo"></div>
console.log(div.outerHTML);
// usare 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 visible è impostato rimuovilo, altrimenti aggiungilo
div.classList.toggle("visible");
// aggiungi/rimuovi visible, 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 spread syntax
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");</pre>
<div class="note">
<p>Le versioni di Firefox precedenti alla 26 non implementano l'uso di diversi argomenti nei metodi add/remove/toggle. Vedi <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=814014" rel="noopener">https://bugzilla.mozilla.org/show_bug.cgi?id=814014</a></p>
</div>
<dl>
</dl>
<h2 id="Polyfill">Polyfill</h2>
<p>L'evento legacy <code><a href="https://msdn.microsoft.com/en-us/windows/ms536956(v=vs.71)">onpropertychange</a></code> può essere utilizzato per creare un mockup dinamico di <code>classList</code> dinamico grazie alla proprietà <code>Element.prototype.className</code> che attiva l'evento specificato una volta modificato.</p>
<p>Il seguente polyfill sia per <code>classList</code> che per <code>DOMTokenList</code> garantisce <strong>la piena</strong> conformità (copertura) per tutti i metodi e le proprietà standard di <code>Element.prototype.classList</code> per i browser <strong>IE10-IE11</strong> oltre ad un comportamento <em>quasi</em> conforme per <strong>IE 6-9</strong>. Controlla:</p>
<pre class="brush: js">// 1. String.prototype.trim polyfill
if (!"".trim) String.prototype.trim = function(){ return this.replace(/^[\s]+|[\s]+$/g, ''); };
(function(window){"use strict"; // prevent global namespace pollution
if(!window.DOMException) (DOMException = function(reason){this.message = reason}).prototype = new Error;
var wsRE = /[\11\12\14\15\40]/, wsIndex = 0, checkIfValidClassListEntry = function(O, V) {
if (V === "") throw new DOMException(
"Failed to execute '" + O + "' on 'DOMTokenList': The token provided must not be empty." );
if((wsIndex=V.search(wsRE))!==-1) throw new DOMException("Failed to execute '"+O+"' on 'DOMTokenList': " +
"The token provided ('"+V[wsIndex]+"') contains HTML space characters, which are not valid in tokens.");
}
// 2. Implement the barebones DOMTokenList livelyness polyfill
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;
function DOMTokenList(){
if (!allowTokenListConstruction) throw TypeError("Illegal constructor"); // internally let it through
}
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");
ele.detachEvent( "onpropertychange", whenPropChanges ); // prevent duplicate handler infinite loop
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 = cLen-sub, protoObjProto.value = ele.className, protoObjProto[" uCL"] = ele;
if (defineProperty) { defineProperty(ele, "classList", { // IE8 & IE9 allow defineProperty on the 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]; //remove trailing indexs
}
}); defineProperty(ele, " uCLp", { // for accessing the hidden prototype
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; }
ele.attachEvent( "onpropertychange", whenPropChanges );
}
try { // Much faster & cleaner version for IE8 & IE9:
// Should work in IE8 because Element.prototype instanceof Node is true according to the specs
window.Object.defineProperty(window.Element.prototype, "classList", {
enumerable: 1, get: function(val){
if (!hasOwnProp.call(this, "classList")) polyfillClassList(this);
return this.classList;
},
configurable: 0, set: function(val){this.className = val}
});
} catch(e) { // Less performant fallback for older browsers (IE 6-8):
window[" uCL"] = polyfillClassList;
// the below code ensures polyfillClassList is applied to all current and future elements in the doc.
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
);
}
})(window);
// 3. Patch in unsupported methods 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(oldValue), 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);
</pre>
<h3 id="Avvertenze">Avvertenze</h3>
<p>Il polyfill ha funzionalità limitate. Al momento non è in grado di eseguire il polyfill fuori dagli elementi del documento (ad esempio elementi creati da <code>document.createElement</code> prima di essere appesi su un nodo padre) in IE6-7.</p>
<p>Tuttavia, dovrebbe funzionare bene in IE9. Una discrepanza maggiore tra la versione polyfilled di <code>classList</code> e le specifiche W3 è che per IE6-8, non esiste un modo per creare un oggetto immutabile (un oggetto le cui proprietà non possono essere modificate direttamente). In IE9, tuttavia, è possibile estendere il prototipo, 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 fino alla scansione di una lumaca, rendendo queste modifiche completamente impraticabili per questo polyfill.</p>
<p>Una nota minore è che in IE6-7, questo polyfill usa la proprietà <code>window[" uCL"]</code> sull'oggetto window per comunicare con le espressioni CSS, la proprietà css <code>x-uCLp</code> su tutti gli elementi e la proprietà <code>element[" uCL"]</code> su tutti gli elementi per consentire la raccolta di garbadge e migliorare le prestazioni. In tutti i browser polyfilled (IE6-9), una proprietà aggiuntiva <code>element[" uCLp"]</code> viene aggiunta all'elemento per garantire la prototipazione conforme agli standard e una proprietà <code>DOMTokenList[" uCL"]</code> viene aggiunta ad ogni oggetto <code>element["classList"]</code> per garantire che la DOMTokenList sia limitata al proprio elemento.</p>
<h2 id="Specifiche">Specifiche</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Specifica</th>
<th scope="col">Stato</th>
<th scope="col">Commento</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName("DOM WHATWG", "#dom-element-classlist", "Element.classList")}}</td>
<td>{{Spec2("DOM WHATWG")}}</td>
<td>Definizione iniziale</td>
</tr>
<tr>
<td>{{SpecName("DOM4", "#dom-element-classlist", "Element.classList")}}</td>
<td>{{Spec2("DOM4")}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="Compatibilità_con_i_browser">Compatibilità con i browser</h2>
<p>{{Compat("api.Element.classList")}}</p>
<h2 id="Vedi_anche">Vedi anche</h2>
<ul>
<li>{{domxref("element.className")}}</li>
<li>{{domxref("DOMTokenList")}}</li>
</ul>
|