Получить все элементы в документе HTML с определенным классом CSS

Какой лучший способ получить массив всех элементов в html-документе с определенным классом CSS с помощью javascript?

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

Ответ 1

Следующий ответ теперь прогоняет четыре года, поэтому стоит отметить, что поддержка родного браузера для getElementsByClassName() стала намного лучше. Но если вы должны поддерживать старые браузеры, то...

Используйте тот, который уже был написан. Большинство основных JS-библиотек включают в себя тот или иной формат, но если вы не используете один из них, я могу рекомендовать Robert Nyman отличную реализацию:

http://code.google.com/p/getelementsbyclassname/
http://www.robertnyman.com/2008/05/27/the-ultimate-getelementsbyclassname-anno-2008/

Есть слишком много способов сделать эту (концептуально-простую) процедуру медленной и багги, чтобы оправдать написание вашей собственной реализации на этом этапе.

Ответ 2

1) Получить все элементы в документе (document.getElementsByTagName('*'))
2) Соответствует ли регулярное выражение атрибуту elementName элемента для каждого элемента

Ответ 4

Чтобы сделать некоторые последующие действия, я основывал свой код на реализации Robert Nyman, опубликованный 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;
}

Update:
Одно новое замечание. С тех пор я перечитал заметки об исходной реализации, и теперь я понимаю, что мой код может упасть в случае, когда существующий браузер имеет свою собственную реализацию, потому что реализации по умолчанию возвращают нодлист, где это возвращает массив. Это включает в себя более свежие Firefox и Safari, а также операционные браузеры. Большую часть времени это не имеет значения, но в некоторых ситуациях это может быть. Это объясняет пункт № 2 из приведенного выше списка.

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

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

Ответ 5

Если вы используете фреймворк, все они имеют выбор с помощью CSS Selectors. В противном случае.

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;
};

Просто написал это прямо сейчас, только для вас.:) Не стесняйтесь использовать.

Ответ 6

Используйте jquery, это не может быть более удобно.

$( "theclass" ) или $ ( ".class" ), makeArray(), если вы хотите создать собственный массив JS

Ответ 7

Имейте в виду, что atlyast FF3 уже имеет встроенную реализацию getElementsByClassName afaik.

Если вы собираетесь реализовать свое собственное решение, возможно, вам стоит попытаться найти xpath-решение, поскольку весь современный браузер имеет встроенную поддержку xpath.

Ответ 8

@shog9, @user28742, @bdukes - Я делаю некоторые пользовательские разработки в SharePoint для модульной вещи (определение пользовательского поля) Я надеюсь, что можно повторно использовать на многих сайтах.

Поскольку я не могу заранее знать, будет ли у какого-либо данного сайта SharePoint доступным jQuery или любая другая библиотека, мне все равно нужно писать вещи в необработанном javascript, чтобы я мог быть уверен в том, что функциональность Я пытаюсь достичь, будет стоять на нем.

Спасибо Дмитрию за вашу конкретную реализацию. Достаточно короткий для моих целей.

В других недавних усилиях мне пришлось изменить магазин электронной коммерции (моего клиента), и некоторые из моих попыток получить jQuery, сфальсифицированные в нем, фактически противоречили тем, какие ранее созданные библиотеки были сфальсифицированы. Я мог бы быть настойчивым и удалил способ реализовать jQuery в своей проприетарной системе.. или.. еще быстрее.. просто напишите хороший модный javascript.

Либераторы НЕ ВСЕГДА ЛУЧШИЙ ОТВЕТ!!!!!!!!!!!!!!!!

(и я люблю jQuery больше, чем бабушка)

Ответ 9

Нет такой вещи, как класс CSS. CSS имеет наборы правил и селекторы (включая селектор классов).

Вы имеете в виду класс HTML? Обычный способ состоит в том, чтобы перебирать каждый элемент документа (using document.getElementsByTagName('*') (для эффективности используйте определенное имя тега, если вы знаете, что класс будет применяться только к элементам определенного типа) и протестировать свойство className каждого (отметив, что свойство содержит пробельный список имен классов, а не одно имя класса).

Несколько библиотек (например, jQuery или YUI) имеют функции просто для этого.

Вы имеете в виду селектор CSS? Это становится более сложным, и обращение к библиотеке почти наверняка будет правильным. Опять же, jQuery или YUI являются достойными выборами.

Ответ 10

Если вы хотите сделать что-то для всего элемента с тем же идентификатором в документе. Хотя простой, но иногда разум не дает зеленых сигналов

var x = document.getElementById(elementid);
while(x){
document.removechild(x);
x = document.getElementById(elementid);
}