Атрибуты и свойства: DOM и отличия в Internet Explorer

Атрибуты и свойства в модели DOM

Для каждого тега в XML и HTML может быть указано произвольное количество атрибутов. Атрибут представляет из себя пару строк имя/значение и задается в коде документа:

<input id="textField" type="text" value="5" />

Здесь у тега input три атрибута: id, type и value со значениями textField, text и 5 соответственно. Заметим, что в HTML регистр букв в имени атрибута не имеет значения, в отличие от XML/XHTML.

DOM позволяет читать атрибуты из скриптов с помощью методов hasAttribute() и getAttribute():

var inputTag = document.getElementById("textField");
var defaultValue = "";
if (inputTag.hasAttribute("value")) // если есть атрибут value
defaultValue = inputTag.getAttribute("value"); // читаем атрибут value

Можно и менять атрибуты, для этого существуют методы setAttribute() и removeAttribute():

inputTag.removeAttribute("value"); // удаляем значение по умолчанию
inputTag.setAttribute("type", "submit"); // меняем тип поля на submit

В наших примерах мы работает с объектом inputTag, который соответствует тегу input документа. У этого объекта есть ряд свойств, некоторые из которых названы так же, как и атрибуты тега:

if (inputTag.type == "text") // проверяем тип поля
inputTag.type = "submit"; // меняем тип поля на submit

Если судить по этому примеру, то атрибут type и свойство type ничем не отличаются. У них всегда одно и то же значение, а результат при изменении атрибута такой же, как и при изменении свойства. Более того, если изменить атрибут, то меняется и свойство:

inputTag.setAttribute("type", "submit");
alert(inputTag.type); // показывает: submit

Можно изменить и свойство, атрибут тоже автоматически изменится. Это связано с тем, что браузер автоматически синхронизирует значения атрибутов и свойств. И все же они не всегда идентичны:

inputTag.setAttribute("type", "abrakadabra");     // присваиваем атрибуту недопустимое значение
alert(inputTag.getAttribute("type"));             // показывает: abrakadabra
alert(inputTag.type);                             // показывает: text

Это хорошо показывает разницу атрибута и свойства: атрибут может быть любой строкой, он лишь показывает, что написано в исходном коде документа. Свойства же отображают текущее состояние тега, они не могут содержать недопустимых значений.

Еще более явной становится разница, если посмотреть на атрибут value и свойство value.

inputTag.setAttribute("value", "10");             // не меняет текст в текстовом поле
inputTag.value = 20;                              // пишет строку 20 в текстовое поле

Здесь атрибут и свойство имеют разные значения: атрибут value определяет начальное значение для текстового поля. Текущее же значение хранится в свойстве value и меняется через него же.

Не всегда у атрибута и связанного с ним по смыслу свойства одинаковые названия. Типичным исключением является атрибут class, которому соответствует свойство className. Часто отличается и тип данных, к примеру значение атрибута onclick (как и в принципе всех атрибутов) строкового типа, а у соответствующего свойства onclick значением является функция.

Реализация атрибутов в Internet Explorer

Разработчики Internet Explorer упростили модель DOM до предела уравняв атрибуты и свойства. В этом браузере следующие две строки абсолютно эквивалентны:

inputTag.setAttribute("abraKadabra", "abcd");
inputTag.abraKadabra = "abcd";

При таком подходе немедленно возникает множество осложнений. Первое связано с тем, что регистр букв в имени свойст играет роль, в то время как в имени атрибутов он игнорируется (как минимум в HTML). В Internet Explorer же следующие две строки вдруг приобретают разное значение:

inputTag.setAttribute("abrakadabra", "abcd1");
inputTag.setAttribute("abraKadabra", "abcd2");

Эти строки устанавливают два разных свойства объекта. Возникает вопрос — что вернет в этой ситуации inputTag.getAttribute("ABRAKADABRA")? Ответ: либо abcd1, либо abcd2. В Internet Explorer getAttribute() ищет первое свойство с именем, которое соответствует запрошенному атрибуту за вычетом регистра букв. Если таких свойст несколько, то невозможно сказать, какое именно он вернет.

Следующее осложнение возникает с атрибутами, название которых не идентично названию свойства:

inputTag.setAttribute("class", "my-class");

Эта строчка корректно изменит класс тега во всех браузерах. Лишь в Internet Explorer она установит свойство class, не имеющее никакого значение — нужное свойство называется className. С этой проблемой сталкиваются настолько часто, что она даже заслужила упоминания в MSDN<.nofollow:

When setting the CLASS attribute using this method, set the sName to be "className", which is the corresponding Dynamic HTML (DHTML) property.

Иначе говоря, для изменения класса рекомендуется установить несуществующий атрибут className (менять регистр букв нельзя!). С такой рекомендацией Microsoft сложно согласиться — в кроссбраузерных приложениях придется устанавливать два атрибута, один из которых не имеет никакого смысла. Проще изменить свойство className, это работает одинаково надежно во всех браузерах.

Но на этом проблемы не кончаются. Как уже было сказано, тип атрибутов и свойств не обязательно одинаков. Чаще всего проблемы возникают при установке обработчиков событий:

inputTag.setAttribute("onclick", "alert('clicked')");

После выполнения этого кода в Internet Explorer щелчки на текстовом поле не вызовут никакой реакции. Причина станет ясна, если сравнить значения свойства onclick в Internet Explorer и каком-нибудь другом браузере:

alert(typeof inputTag.onclick);
alert(inputTag.onclick);

Это покажет, что Internet Explorer записал в свойство onclick строку, в то время как другие браузеры корректно преобразовали значение атрибута в функцию. А при возникновении события Internet Explorer не находит в свойстве onclick функции, которую можно выполнить. Чтобы присвоить обработчик события в Internet Explorer надо написать:

inputTag.setAttribute("onclick", function() {alert('clicked')});

Стандарт DOM, однако, явно предписывает, что второй параметр метода setAttribute() является строкой. Такой код, опять же, не станет работать ни в одном браузере, корректно реализующем стандарты.

Выводы

К сожалению, Internet Explorer на данный момент все еще является лидером на рынке браузеров. Из-за этого в большинстве веб-приложений приходится поддерживать Internet Explorer, то есть использование атрибутов весьма усложнено. Internet Explorer 7.0, который должен скоро выйти, вряд ли улучшит ситуацию, серьезных улучшений движка до версии 8.0 точно не будет (да и там это еще очень сомнительно). Вытеснение этого браузера из интернета в ближайшее время тоже не ожидается.

Проще всего, конечно, вообще отказаться от использования атрибутов и пользоваться только свойствами. Для большинства приложений этого достаточно, но существуют задачи, где без атрибутов не обойтись (к примеру копирование DOM-дерева с параллельным его изменением). В таких случаях можно выполнять для Internet Explorer другой код, который дает похожий результат (возможно, что не идеальный, но лучше, чем вообще никакого результата):

document.body.setAttribute("class", "attribute-test");
if (document.body.className == "attribute-test")
{
  // Атрибуты работают корректно (не Internet Explorer или будущая исправленная версия)

  // Работаем с атрибутами
}
else
{
  // Использовать атрибуты нельзя (Internet Explorer)

  // Альтернативный код только для Internet Explorer



Page: [1] [2] [3] [4] [5]
Магазин подарков часы Casio protrek купить часы omega. | горящие туры греция | opera скачать бесплатно
 
 

статистика сайта
Page created in 0,03845 seconds Powered by LastoBlog