getElementsByName в IE7
У меня есть код, делающий это:
var changes = document.getElementsByName(from);
for (var c=0; c<changes.length; c++) {
var ch = changes[c];
var current = new String(ch.innerHTML);
etc.
}
Это отлично работает в FF и Chrome, но не в IE7. Предположительно, потому что getElementsByName не работает в IE. Какой лучший обходной путь?
7 ответов
Если вы не знаете, почему это не работает в IE, вот документация MSDN по этой функции:
При использовании метода getElementsByName возвращаются все элементы в документе, которые имеют указанный атрибут NAME или значение атрибута ID.
Элементы, которые поддерживают как атрибут NAME, так и атрибут ID, включены в коллекцию, возвращаемую методом getElementsByName, но элементы с расширением NAME не включены в коллекцию; поэтому этот метод нельзя использовать для получения пользовательских тегов по имени.
Firefox позволяет getElementsByName()
чтобы получить элементы, которые используют NAME expando, поэтому он работает. Является ли это Good Thing™ или нет, может быть спорным, но это реальность этого.
Итак, одним из вариантов является использование getAttribute()
Метод DOM, чтобы запросить атрибут NAME, а затем проверить значение, чтобы увидеть, является ли оно тем, что вы хотите, и, если да, добавить его в массив. Однако для этого потребуется выполнить итерацию по всем узлам на странице или, по крайней мере, в подразделе, что не будет наиболее эффективным. Вы могли бы ограничить этот список заранее, используя что-то вроде getElementsByTagName()
возможно.
Другой способ сделать это, если вы контролируете HTML-код страницы, - это присвоить всем интересующим элементам идентификатор, который изменяется только числом, например:
<div id="Change0">...</div>
<div id="Change1">...</div>
<div id="Change2">...</div>
<div id="Change3">...</div>
И затем есть JavaScript, как это:
// assumes consecutive numbering, starting at 0
function getElementsByModifiedId(baseIdentifier) {
var allWantedElements = [];
var idMod = 0;
while(document.getElementById(baseIdentifier + idMod)) { // will stop when it can't find any more
allWantedElements.push(document.getElementById(baseIdentifier + idMod++));
}
return allWantedElements;
}
// call it like so:
var changes = getElementsByModifiedId("Change");
Это, конечно, хак, но он сделает ту работу, которая вам нужна, и не будет слишком неэффективной по сравнению с другими хакерами.
Если вы используете какой-то фреймворк / инструментарий JavaScript, ваши варианты намного лучше, но у меня нет времени вдаваться в эти подробности, если вы не укажете, что используете его. Лично я не знаю, как люди живут без них, они экономят столько времени, усилий и разочарований, что вы не можете позволить себе их не использовать.
Есть пара проблем:
- IE действительно сбивает с толку
id=""
сname=""
name=""
не допускается на<span>
Чтобы исправить, я предлагаю:
- Изменить все
name=""
вclass=""
- Измените свой код следующим образом:
-
var changes = document.getElementById('text').getElementsByTagName('span');
for (var c=0; c<changes.length; c++) {
var ch = changes[c];
if (ch.className != from)
continue;
var current = new String(ch.innerHTML);
Не очень часто можно найти элементы, используя свойство NAME. Я бы порекомендовал перейти на свойство ID.
Однако вы можете найти элементы с определенным именем, используя jQuery:
$("*[name='whatevernameYouWant']");
это вернет все элементы с указанным именем.
Еще одна ошибка DOM в IE:
Ошибка 1: http://webbugtrack.blogspot.com/2007/08/bug-411-getelementsbyname-doesnt-work.html
Ошибка 2: http://webbugtrack.blogspot.com/2008/04/bug-403-another-getelementsbyname-bugs.html
Временное решение
var listOfElements = document.getElementsByName('aName'); // Replace aName with the name you're looking for
// IE hack, because it doesn't properly support getElementsByName
if (listOfElements.length == 0) { // If IE, which hasn't returned any elements
var listOfElements = [];
var spanList = document.getElementsByTagName('*'); // If all the elements are the same type of tag, enter it here (e.g.: SPAN)
for(var i = 0; i < spanList.length; i++) {
if(spanList[i].getAttribute('name') == 'aName') {
listOfElements.push(spanList[i]);
}
}
}
getElementsByName поддерживается в IE, но есть ошибки. В частности, он возвращает элементы, чей "id" соответствует заданному значению, а также "name". Не могу сказать, если это проблема у вас без немного контекста, кода и реальных сообщений об ошибках, хотя.
В общем, getElementsByName, вероятно, лучше избегать, поскольку атрибут "name" в HTML имеет несколько перекрывающихся целей, которые могут привести к путанице. Использование getElementById намного надежнее. При конкретной работе с полями формы вы можете более надежно использовать form.elements[name] для извлечения искомых полей.
Я успешно использовал оболочку для возврата массива элементов. Работает в IE 6 и 7 тоже. Имейте в виду, что это не на 100% то же самое, что document.getElementsByName, так как это не NodeList. Но для чего мне это нужно, а именно для запуска цикла for на массиве элементов для выполнения простых вещей, таких как установка.disabled = true, это работает достаточно хорошо.
Хотя эта функция все еще использует getElementsByName, она работает, если используется таким образом. Посмотреть на себя.
function getElementsByNameWrapper(name) {
a = new Array();
for (var i = 0; i < document.getElementsByName(name).length; ++i) {
a.push(document.getElementsByName(name)[i]);
}
return a;
}