Главная » Статьи » Web-программирование » Java Script

Атрибуты и свойства: реализация, методы и отличия в Internet Explorer

Реализация атрибутов в Internet Explorer радикально отличается от той, которую предписывает стандарт DOM и которая реализована во всех остальных браузерах. Internet Explorer (здесь и далее, речь идёт о IE версии ниже 8) не различает атрибуты и свойства, что делает работу с атрибутами весьма затруднительной.
Более того, это способствует тому, что некоторые начинающие веб-программисты не понимают разницы между атрибутами и свойствами.

Этот материал объясняет назначение атрибутов и свойств и представляет примеры их использования.

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


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

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

Code (HTML)
<input id="textField" type="text" value="5" />

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

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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
var defaultValue = "";
if (inputTag.hasAttribute("value")) /* если естьатрибут value */
defaultValue = inputTag.getAttribute("value"); /* читаем атрибут value */
</script>

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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.removeAttribute("value"); /* удаляем значение по умолчанию */
inputTag.setAttribute("type", "submit"); /* меняем тип поля на submit */
</script>

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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
if (inputTag.type == "text") /* проверяем тип поля */
inputTag.type = "submit"; /* меняем тип поляна submit */
</script>

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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("type", "submit");
alert(inputTag.type); /* показывает: submit */
</script>

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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("type", "abrakadabra");/* присваиваем атрибуту недопустимое значение */
alert(inputTag.getAttribute("type")); /* показывает:abrakadabra */
alert(inputTag.type); /* показывает: text */
</script>

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


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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("value", "10"); /* не меняет текст в текстовом поле */
inputTag.value = 20; /* пишет строку 20 в текстовое поле */
</script>

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


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


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

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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("abraKadabra", "abcd");
inputTag.abraKadabra = "abcd";
</script>

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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("abrakadabra", "abcd1");
inputTag.setAttribute("abraKadabra", "abcd2");
</script>

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


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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("class", "my-class");
</script>


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

Иначе говоря, для изменения класса проще изменить свойство className, это работает одинаково надежно во всех браузерах.


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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("onclick", "alert('clicked')");
</script>


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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("onclick", "alert('clicked')");
alert(typeof inputTag.onclick);
alert(inputTag.onclick);
</script>


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

Code (HTML)
<input id="textField" type="text" value="5" />
<script type="text/javascript">
var inputTag = document.getElementById("textField");
inputTag.setAttribute("onclick", function() {alert('clicked')});
</script>


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


Выводы

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

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

}
else
{
// Использовать атрибуты нельзя (Internet Explorer версии меньше 8)
// Альтернативный код только для Internet Explorer

}

Источник: Xpoint.ru




Источник: Атрибуты и свойства,реализация, методы,отличия,Internet Explorer, модель, DOM, JavaScript
Категория: Java Script | Добавил: likbezz (04.08.2011)
Просмотров: 9911 | Теги: свойства, модель, реализация, атрибуты, отличия, Internet Explorer, Java, методы, DOM, Script
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]