Книга: JavaScript. Подробное руководство, 6-е издание
16.5. CSS-классы
16.5. CSS-классы
Альтернативой использованию отдельных CSS-стилей через свойство style
является управление значением HTML-атрибута class. Изменение класса элемента изменяет набор селекторов стилей, применяемых к элементу, что может приводить к изменениям значений сразу нескольких CSS-свойств. Предположим, например, что вам требуется привлечь внимание пользователя к отдельным абзацам (или другим элементам) в документе. В этом случае можно было бы сначала определить особый стиль оформления для любых элементов с классом «attention»:
.attention { /* Стили для элементов, требующих внимания пользователя */
background-color: yellow; /* Желтый фон */
font-weight: bold; /* Полужирный шрифт */
border: solid black 2рх; /* Черная рамка */
}
Идентификатор class
в языке JavaScript является зарезервированным словом, поэтому HTML-атрибут class
в JavaScript-сценариях доступен в виде свойства с именем className
. Ниже приводится пример, который устанавливает и очищает свойство className
элемента, добавляя и убирая класс «attention»:
function grabAttention(e) { е.className = "attention"; }
function releaseAttention(e) { e.className = ""; }
HTML-элементы могут быть членами более чем одного CSS-класса - атрибут class
может содержать целый список имен классов, разделенных пробелами. Имя className
не совсем точно отражает смысл свойства: правильнее было бы дать ему имя classNames
. Функции выше предполагают, что свойство className
будет определять ноль или одно имя класса, и они непригодны в случаях, когда может использоваться более одного имени класса. Если элемент уже принадлежит некоторому классу, вызов функции grabAttention()
для этого элемента затрет имя класса, присутствующее в свойстве className
.
Стандарт HTML5 решает эту проблему, определяя свойство classList
во всех элементах. Значением этого свойства является объект DOMTokenList
: подобный массиву объект (раздел 7.11), доступный только для чтения, элементы которого содержат отдельные имена классов, присвоенных элементу. Однако самыми важными в нем являются не элементы массива, а методы add()
и remove(),
добавляющие и удаляющие отдельные имена классов из атрибута class элемента. Метод toggle()
добавляет имя класса, если оно отсутствует, и удаляет в противном случае. Наконец, метод contains()
проверяет присутствие указанного имени класса в атрибуте class.
Подобно другим классам коллекций в модели DOM, объект DOMTokenList
является «живым» представлением множества классов в элементе, а не статическим слепком, который был действителен только в момент обращения к свойству classList
. Если сценарий получит объект DOMTokenList
, обратившись к свойству classList
элемента, и затем изменит свойство className
этого элемента, то выполненные изменения немедленно отразятся на полученном объекте DOMTokenList
. Аналогично любые изменения, выполненные в объекте DOMTokenList
, немедленно отразятся на значении свойства className
.
На момент написания этих строк свойство classList
не поддерживалось ни одним из текущих броузеров. Однако эту удобную функциональность легко можно реализовать самому, как показано в примере 16.5. Подобная реализация, позволяющая интерпретировать атрибут class
элемента как множество имен классов, существенно упрощает выполнение многих задач, связанных с обработкой CSS.
Пример 16.5. classList()
: интерпретирует className
, как множество CSS-классов
//
* Возвращает свойство classList элемента е. если оно содержит один класс.
* Иначе возвращает объект, имитирующий интерфейс DOMTokenList.
* Возвращаемый объект имеет методы contains(), add(), remove(), toggle() и toString(),
* позволяющие проверять и изменять набор классов элемента е. Если свойство classList
* имеет встроенную поддержку в броузере, функция возвращает объект, подобный массиву,
* который имеет свойство length и поддерживает возможность индексирования массива.
* Имитация объекта DOMTokenList не подобна массиву, но имеет метод toArray().
* который возвращает истинный массив имен классов элемента.
*/
function classList(e) {
if (е.classList) return e.classList; // Вернуть e.classList, если имеется
else return new CSSClassList(e); // Иначе попытаться подделать его
}
// CSSClassList - класс JavaScript, имитирующий объект DOMTokenList
function CSSClassList(e) { this.e = e; }
// Возвращает true, если e.className содержит класс с, иначе - false
CSSClassList.prototype.contains = function(c) {
// Проверить, является ли с допустимым именем класса
if (с.length === 0 || c.indexOf(" ") != -1)
throw new Error("Недопустимое имя класса: + с + .....);
// Сначала проверить общие случаи
var classes = this.e.className;
if (!classes) return false; // e вообще не имеет классов
if (classes === c) return true; // e имеет единственный класс,
// имя которого точно совпадает с искомым
// Иначе использовать RegExp для поиска с как отдельного слова
// b - в регулярных выражениях соответствует границе слова,
return classes.search(”b" + с + "b") != -1;
};
// Добавляет имя класса с в е.className, если оно отсутствует в списке
CSSClassList.prototype.add = function(c) {
if (this.contains(c)) return; // Ничего не делать, если имя уже в списке
var classes = this.e.className;
if (classes && classes[classes.length-1] != " ")
c = " " + с; // Добавить пробел, если необходим
this.е.className += с; // Добавить имя с в className
};
// Удаляет все вхождения с из е.className
CSSClassList.prototype.remove = function(c) {
// Убедиться, что с - допустимое имя класса
if (с.length === 0 || c.indexOf(" ") != -1)
throw new Error("Недопустимое имя класса: + с + .....);
// Удалить все вхождения имени с как слова и все завершающие пробелы
var pattern = new RegExp("b" + с + 'bs*' "g");
this.e.className = this.e.className.replace(pattern, "");
};
// Добавляет имя с в e.className, если оно отсутствует в списке, и возвращает true.
// Иначе удаляет все вхождения имени с из e.className и возвращает false.
CSSClassList.prototype.toggle = function(c) {
if (this.contains(c)) { // Если e.className содержит c
this.remove(c); // удалить его.
return false;
}
else { // Иначе:
this.add(c); // добавить его.
return true;
}
};
// Возвращает само значение e.className
CSSClassList.prototype.toString = function() { return this.e.className; };
// Возвращает имена из e.className
CSSClassList.prototype.toArray = function() {
return this.e.className.match(/bw+b/g) || [];
};
- 19.2.3. Чтение и запись CSS-классов
- 11.10. Псевдоклассы текста
- 9.1. Классы и прототипы
- Классы сертификатов
- Статические классы
- 9.8. Классы в ECMAScript 5
- 9.7.4. Иерархии классов и абстрактные классы
- Классы синхронизации, внедренные в версии .NET Framework 4.0
- Классы для программирования графики
- Больше CSS3-селекторов
- У14.6 Отложенные классы и прототип
- Совет 38. Проектируйте классы функторов для передачи по значению