Реализация атрибутов в 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")) defaultValue = inputTag.getAttribute("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"); </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"; </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); </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")); alert(inputTag.type); </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; </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") {
} else {
}
Источник: Атрибуты и свойства,реализация, методы,отличия,Internet Explorer, модель, DOM, JavaScript |