Получить все элементы в документе HTML с определенным классом CSS - PullRequest
37 голосов
/ 17 октября 2008

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

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

Ответы [ 10 ]

38 голосов
/ 17 октября 2008

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

36 голосов
/ 17 октября 2008

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

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

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

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

7 голосов
/ 17 октября 2008

Вы можете включить функцию getElementsByClass или использовать селектор jQuery .

ОБНОВЛЕНИЕ: Реализация , упомянутая в @ Shog9 , вероятно, лучше, чем описанная выше.

6 голосов
/ 17 октября 2008

Просто чтобы продолжить, я основал свой код на реализации Роберта Наймана, опубликованной Shog9, но немного отошел от его точной версии по трем причинам:

  1. Он позволил вам выбрать корневой элемент и тип тега для фильтрации ваших результатов. Мне не нужна эта функциональность, поэтому, удалив ее, я смог значительно упростить код.
  2. Первое, что делает его код, это проверяет, существует ли рассматриваемая функция, и если он это делает, он все равно предоставляет свою собственную реализацию. Это только казалось ... странным. Я понимаю, что он добавляет функциональность к оригиналу, но опять же: я не использую эти функции.
  3. Я хотел, чтобы дополнительный кусочек синтаксического сахара мог вызывать его так, как я бы назвал 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), поэтому пока я оставлю исправление в качестве упражнения для читателя.

5 голосов
/ 14 мая 2009

При использовании фреймворка все они имеют выборки с использованием 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;
};

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

2 голосов
/ 06 ноября 2008

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

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

2 голосов
/ 17 октября 2008

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

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

1 голос
/ 27 января 2011

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

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

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

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

ЛИБАРИИ НЕ ВСЕГДА ЛУЧШИЙ ОТВЕТ !!!!!!!!!!!!!!!!

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

0 голосов
/ 12 ноября 2010

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

var x = document.getElementById(elementid);
while(x){
document.removechild(x);
x = document.getElementById(elementid);
}
0 голосов
/ 17 октября 2008

Класса CSS не существует. У CSS есть наборы правил и селекторы (включая селектор классов).

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

Ряд библиотек (например, jQuery или YUI ) имеют функции для простого выполнения этой задачи.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...