JavaScript. Подробное руководство, 6-е издание, стр. 244

Подобно другим классам коллекций в модели DOM, объект

<b>DOMTokenList</b>
является «живым» представлением множества классов в элементе, а не статическим слепком, который был действителен только в момент обращения к свойству
<b>classList</b>
. Если сценарий получит объект
<b>DOMTokenList</b>
, обратившись к свойству
<b>classList</b>
элемента, и затем изменит свойство
<b>className</b>
этого элемента, то выполненные изменения немедленно отразятся на полученном объекте
<b>DOMTokenList</b>
. Аналогично любые изменения, выполненные в объекте
<b>DOMTokenList</b>
, немедленно отразятся на значении свойства
<b>className</b>
.

На момент написания этих строк свойство

<b>classList</b>
не поддерживалось ни одним из текущих броузеров. Однако эту удобную функциональность легко можно реализовать самому, как показано в примере 16.5. Подобная реализация, позволяющая интерпретировать атрибут
<b>class</b>
элемента как множество имен классов, существенно упрощает выполнение многих задач, связанных с обработкой CSS.

Пример 16.5.

<b>classList()</b>
: интерпретирует
<b>className</b>
, как множество CSS-классов

<b>//</b>

<b>* Возвращает свойство classList элемента е. если оно содержит один класс.</b>

<b>* Иначе возвращает объект, имитирующий интерфейс DOMTokenList.</b>

<b>* Возвращаемый объект имеет методы contains(), add(), remove(), toggle() и toString(),</b>

<b>* позволяющие проверять и изменять набор классов элемента е. Если свойство classList</b>

<b>* имеет встроенную поддержку в броузере, функция возвращает объект, подобный массиву,</b>

<b>* который имеет свойство length и поддерживает возможность индексирования массива.</b>

<b>* Имитация объекта DOMTokenList не подобна массиву, но имеет метод toArray().</b>

<b>* который возвращает истинный массив имен классов элемента.</b>

<b>*/</b>

<b>function classList(e) {</b>

<b>  if (е.classList) return e.classList; // Вернуть e.classList, если имеется</b>

<b>  else return new CSSClassList(e); // Иначе попытаться подделать его</b>

<b>}</b>

<b>// CSSClassList - класс JavaScript, имитирующий объект DOMTokenList </b>

<b>function CSSClassList(e) { this.e = e; }</b>

<b>// Возвращает true, если e.className содержит класс с, иначе - false </b>

<b>CSSClassList.prototype.contains = function(c) {</b>

<b>  // Проверить, является ли с допустимым именем класса </b>

<b>  if (с.length === 0 || c.indexOf(&quot; &quot;) != -1)</b>

<b>    throw new Error(&quot;Недопустимое имя класса: + с + .....);</b>

<b>  // Сначала проверить общие случаи</b>

<b>  var classes = this.e.className;</b>

<b>  if (!classes) return false; // e вообще не имеет классов</b>

<b>  if (classes === c) return true; // e имеет единственный класс,</b>

<b>                                  // имя которого точно совпадает с искомым</b>

<b>  // Иначе использовать RegExp для поиска с как отдельного слова </b>

<b>  // \b - в регулярных выражениях соответствует границе слова,</b>

<b>  return classes.search(”\\b&quot; + с + &quot;\\b&quot;) != -1;</b>

<b>};</b>

<b>// Добавляет имя класса с в е.className, если оно отсутствует в списке </b>

<b>CSSClassList.prototype.add = function(c) {</b>

<b>  if (this.contains(c)) return; // Ничего не делать, если имя уже в списке</b>

<b>  var classes = this.e.className;</b>

<b>  if (classes &amp;&amp; classes[classes.length-1] != &quot; &quot;)</b>

<b>    c = &quot; &quot; + с; // Добавить пробел, если необходим</b>

<b>  this.е.className += с; // Добавить имя с в className</b>

<b>};</b>

<b>// Удаляет все вхождения с из е.className </b>

<b>CSSClassList.prototype.remove = function(c) {</b>

<b>  // Убедиться, что с - допустимое имя класса </b>

<b>  if (с.length === 0 || c.indexOf(&quot; &quot;) != -1)</b>

<b>    throw new Error(&quot;Недопустимое имя класса: + с + .....);</b>

<b>  // Удалить все вхождения имени с как слова и все завершающие пробелы</b>

<b>  var pattern = new RegExp(&quot;\\b&quot; + с + '\\b\\s*'\ &quot;g&quot;);</b>

<b>  this.e.className = this.e.className.replace(pattern, &quot;&quot;);</b>

<b>};</b>

<b>// Добавляет имя с в e.className, если оно отсутствует в списке, и возвращает true.</b>

<b>// Иначе удаляет все вхождения имени с из e.className и возвращает false.</b>