Какой лучший способ получить массив всех элементов в html-документе с определенным классом CSS с использованием javascript?
Здесь прямо сейчас не разрешены фреймворки javascript, такие как jQuery, и я мог бы зацикливать все элементы и проверять их вручную. Я надеюсь на что-нибудь более элегантное.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете включить функцию getElementsByClass или использовать селектор jQuery.
Обновлено:выполнение, упомянутый @ Shog9, вероятно, лучше, чем это выше.
Класса CSS не существует. В CSS есть наборы правил и селекторы (включая селектор классов).
Вы имеете в виду HTML-класс? Обычный способ - перебрать каждый элемент в документе (using document.getElementsByTagName('*') (для эффективности используйте определенное имя тега, если вы знаете, что класс будет применяться только к элементам определенного типа) и протестировать свойство className каждого (отмечая, что свойство содержит список имен классов, разделенных пробелами, а не одно имя класса).
В ряде библиотек (таких как jQuery или Юй) есть функции для этого.
Вы имеете в виду селектор CSS? Это становится более сложным, и почти наверняка лучше обратиться к библиотеке. Опять же, jQuery или Юй - достойный выбор.
1) Получить все элементы в документе (document.getElementsByTagName ('*'))
2) Сопоставьте регулярное выражение с атрибутом className элемента для каждого элемента
Согласовано. Похоже, что в SO существует предвзятость JS-фреймворка до такой степени, что предложения чистого Javascript смотрят свысока. Рекомендовать и указывать на решения в рамках фреймворков - это нормально, но и автономные решения Javascript - тоже.
Конечно, проповедовать хору - мне нравится использовать фреймворк, но факт в том, что не все хотят его использовать или могут. Я думаю, что некоторые из тех, кто использует фреймворки, не знают достаточно, чтобы знать, как это сделать без него, поэтому они видят эти ответы и понижают их из-за невежества, гордости или чего-то подобного.
@ Джейсон: В большинстве случаев я бы согласен, но в этом случае существует множество существующих реализаций, доработанных и отточенных за последние несколько лет, и поэтому написание собственного просто кажется мазохистским - как написание собственного типа процедура, когда qsort () работает нормально. (Я не голосовал против)
Приведенному ниже ответу сейчас исполнилось четыре года, поэтому стоит отметить, что поддержка getElementsByClassName() в собственном браузере стала лучше много. Но если вам необходимо поддерживать старые браузеры, тогда ...
Используйте тот, который уже был написан. Большинство основных JS-библиотек включают одну в той или иной форме, но если вы не используете одну из них, я могу порекомендовать отличную реализацию Роберта Наймана:
http://code.google.com/p/getelementsbyclassname/
http://www.robertnyman.com/2008/05/27/the-ultimate-getelementsbyclassname-anno-2008/
Есть слишком много способов сделать эту (концептуально простую) подпрограмму медленный и глючный, чтобы оправдать написание вашей собственной реализации на данном этапе.
Используйте jquery, удобнее не бывает.
$ (". класс") или же $ (". theclass"), makeArray (), если вам нужен собственный массив JS
Просто чтобы продолжить, я основал свой код на реализации Роберта Наймана, опубликованной Shog9, но немного отошел от его точной версии по трем причинам:
document.getElementById() или document.getElementsByTagName().Обратите внимание, что я по-прежнему в основном полагался на его код. Очевидно, что его навыки работы с javascript намного превосходят мои собственные. Я пытался исключить некоторые избыточные переменные, но это все.
Имея это в виду, вот что у меня получилось (кажется для работы в IE6, IE7, Firefox 3 и Chrome см. новую заметку в конце):
if (!document.getElementsByClassName)
document.getElementsByClassName = function (className)
{
var classes = className.split(" ");
var classesToCheck = "";
var returnElements = [];
var match, node, elements;
if (document.evaluate)
{
var xhtmlNamespace = "http://www.w3.org/1999/xhtml";
var namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace:null;
for(var j=0, jl=classes.length; j<jl;j+=1)
classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
try
{
elements = document.evaluate(".//*" + classesToCheck, document, namespaceResolver, 0, null);
}
catch(e)
{
elements = document.evaluate(".//*" + classesToCheck, document, null, 0, null);
}
while ((match = elements.iterateNext()))
returnElements.push(match);
}
else
{
classesToCheck = [];
elements = (document.all) ? document.all : document.getElementsByTagName("*");
for (var k=0, kl=classes.length; k<kl; k+=1)
classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
for (var l=0, ll=elements.length; l<ll;l+=1)
{
node = elements[l];
match = false;
for (var m=0, ml=classesToCheck.length; m<ml; m+=1)
{
match = classesToCheck[m].test(node.className);
if (!match) break;
}
if (match) returnElements.push(node);
}
}
return returnElements;
}
Обновлять:
Одно новое примечание по этому поводу. С тех пор я перечитал примечания к исходной реализации и теперь понимаю, что мой код может упасть в случае, если существующий браузер имеет собственную реализацию, потому что реализации по умолчанию возвращают список узлов, в котором он возвращает массив. Это включает в себя более свежие браузеры Firefox, Safari и Opera. В большинстве случаев это не имеет значения, но в некоторых ситуациях может. Это объясняет пункт 2 из списка выше.
Это означает, что хотя мой код технически работает везде, он может привести к слегка различающимся (читай: трудным для отладки) поведением в разных местах, а это нехорошо. Я должен исправляю это, чтобы либо также вернуть список узлов, либо переопределить предоставленный метод для возврата массива (что и сделал оригинал). Вероятно, первое было бы проще, но второе - лучше.
Однако на данный момент он работает в среде локальной интрасети (почти все IE), поэтому пока я оставлю исправление в качестве упражнения для читателя.
Имейте в виду, что по крайней мере в FF3 уже есть собственная реализация getElementsByClassName afaik.
Если вы собираетесь реализовать собственное решение, возможно, вам стоит попытаться найти решение xpath, поскольку все современные браузеры имеют встроенную поддержку xpath.
Ага: Я уже обновляю свой пост, но это займет немного времени, разложит на несколько правок.
При использовании фреймворка все они имеют выбор с помощью селекторов CSS. Иначе.
var getElementsByClassName = function(cls, sc){
//Init
var elements, i, results = [], curClass;
//Default scope is document
sc = sc || document;
//Get all children of the scope node
elements = sc.getElementsByTagName('*');
for( i=0; i < elements.length; i++ ){
curClass = elements[i].getAttribute('class');
if (curClass != null){
curClass = curClass.split(" ");
for( j=0; j < curClass.length; j++){
if (curClass[j] === cls){
results.push( elements[i] );
break;
}
}
}
}
return results;
};
Просто написал это прямо сейчас, специально для вас. :) Смело пользуйтесь.
Старый вопрос, но ничего страшного. Единственная проблема здесь в том, что если у вас есть такие классы, как «navarea-top» и «navarea», и вы просто ищете «navarea», вы также найдете все элементы «navarea-top».
Правда. Чтобы расширить его, можно получить атрибут class и использовать для проверки регулярное выражение вместо indexOf.
Зафиксированный. :) Спасибо за ваш отзыв
Если вы хотите что-то сделать для всех элементов с одинаковым идентификатором в документе. Хотя это просто, но иногда разум не дает зеленых сигналов
var x = document.getElementById(elementid);
while(x){
document.removechild(x);
x = document.getElementById(elementid);
}
Если у вас есть несколько элементов с одним и тем же идентификатором, вы делаете что-то не так.
@ shog9, @ user28742, @bdukes - Я занимаюсь специальной разработкой в SharePoint для модульной вещи (определение настраиваемого поля), я надеюсь, что ее можно будет повторно использовать на многих сайтах.
Поскольку я не могу заранее знать, будет ли на каком-либо сайте SharePoint доступная jQuery или какая-либо другая библиотека --- мне все еще нужно писать вещи в необработанном javascript, чтобы я мог быть уверен, что функциональность, которую я попытка достичь будет стоять сама по себе.
Спасибо Дмитрию за вашу конкретную реализацию. Достаточно коротко для моих целей.
В других недавних попытках мне пришлось модифицировать магазин электронной коммерции (по выбору моего клиента), и некоторые из моих попыток встроить в него jQuery фактически противоречили тем пользовательским библиотекам, которые они использовали ранее. Я мог бы проявить настойчивость и найти способ внедрить jQuery в их проприетарную систему ... или ... даже быстрее ... просто написать какой-нибудь старый добрый javascript.
Библиотеки - НЕ ВСЕГДА ЛУЧШИЙ ОТВЕТ !!!!!!!!!!!!!!!!
(а я люблю jQuery больше, чем свою бабушку)
Проголосовали за: Технически это не ответ на этот вопрос, но это хороший ответ для людей, которые настаивают на том, чтобы добавить свою любимую библиотеку в эти вопросы.
грустная бабушка, мне ее жалко
Почему это было отклонено? Это отлично подходит для решения, полностью основанного на JavaScript.