使用特定的CSS类在HTML文档中获取所有元素

时间:2008-10-16 21:27:37

标签: javascript html css

使用javascript获取具有特定CSS类的html文档中所有元素数组的最佳方法是什么?

现在不允许使用像jQuery这样的javascript框架,我可以循环所有元素并自己手动检查它们。我希望有一些更优雅的东西。

10 个答案:

答案 0 :(得分:38)

1)获取文档中的所有元素(document.getElementsByTagName('*'))
2)对每个元素的元素的className属性执行正则表达式匹配

答案 1 :(得分:36)

以下答案现在推迟了四年,所以值得注意的是getElementsByClassName()的原生浏览器支持已经更好地获得了批次。但是如果你必须支持旧的浏览器,那么......

使用已经写过的。大多数主要的JS库都包含某种形式的库,但如果您不使用其中一种,那么我可以推荐Robert Nyman的优秀实现:

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

有太多方法可以使这个(概念上很简单的)例程慢和错误来证明在这一点上编写自己的实现。

答案 2 :(得分:7)

您可以添加getElementsByClass功能,也可以使用a jQuery selector

更新: @ implementation提到的Shog9可能比上面的更好。

答案 3 :(得分:6)

为了做一些跟进,我将我的代码基于Shog9发布的Robert Nyman实现,但由于三个原因而离开了他的确切版本:

  1. 他允许您选择根元素和标记类型来过滤结果。我不需要该功能,因此通过删除它,我能够显着简化代码。
  2. 他的代码所做的第一件事就是看看有问题的函数是否已经存在,如果确实存在,他仍然会提供自己的实现。那似乎......很奇怪。我知道他正在为原版添加功能,但又一次:我没有使用这些功能。
  3. 我想要一些额外的句法糖 - 能够像我打电话给document.getElementById()document.getElementsByTagName()一样打电话。
  4. 请注意,我仍然主要依赖他的代码。他的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;
    }
    

    <强>更新
    关于此的一个新注释。我已经重新阅读了原始实现的注释,现在我明白,在现有浏览器拥有自己的实现的情况下,我的代码可能会失败,因为默认实现返回一个nodelist,返回一个数组。这包括更新的firefox和safari,以及opera浏览器。大部分时间都无关紧要,但在某些情况下却可以。这解释了上面列表中的第2项。

    这意味着虽然我的代码在技术上确实可以在任何地方工作,但它可能会导致在不同的地方产生微妙的不同(读取:难以调试)行为,这并不好。我应该修复此问题,或者返​​回一个nodelist或覆盖提供的方法以返回一个数组(这是原始的)。可能前者会更简单,但后者会更好。

    然而,它现在正在本地内部网环境中工作(几乎所有的IE),所以暂时我会把修复程序作为读者练习。

答案 4 :(得分:5)

如果使用框架,它们都可以使用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;
};

现在就为你而写。 :)随意使用。

答案 5 :(得分:2)

使用jquery,这样会更方便。

$( “theClass描述”) 要么 $(“。theclass”),makeArray()如果​​你想要一个原生的JS数组

答案 6 :(得分:2)

请记住,至少FF3已经具有getElementsByClassName afaik的本机实现。

如果您要实现自己的解决方案,也许您应该尝试找到xpath解决方案,因为所有现代浏览器都支持xpath。

答案 7 :(得分:1)

@ shog9,@ user28742,@ bdukes - 我正在SharePoint中进行一些自定义开发,用于模块化事物(自定义字段定义)我希望可以在许多站点上重复使用。

由于我无法提前知道任何给定的SharePoint站点是否有jQuery或任何其他可用的库 - 我仍然需要用原始javascript编写内容以便我对该功能有一定程度的信心我正努力实现自己的立场。

感谢Dmitri的具体实施。足够短我的目的。

在最近的其他努力中,我不得不修改一个电子商务商店(我的客户选择),我尝试将jQuery绑定到它的一些实际上与他们之前装配的任何自定义库相冲突。我本可以坚持不懈,并将jQuery实现到他们的专有系统中......或者......更快......只需写一些好的'时尚的javascript。

图书馆并不总是最好的答案!!!!!!!!!!!!!!!!

(我比祖母更喜欢jQuery)

答案 8 :(得分:0)

没有CSS类这样的东西。 CSS有规则集和选择器(包括类选择器)。

你的意思是HTML课程吗?通常的方法是遍历文档中的每个元素(using document.getElementsByTagName('*')(为了提高效率,如果您知道该类只应用于某种类型的元素,则使用特定的标记名称)并测试{{1}每个属性(注意该属性包含一个空格分隔的类名列表,而不是一个类名)。

许多库(例如jQueryYUI)都具有此功能。

你的意思是CSS选择器吗?这变得更加复杂,转向图书馆几乎肯定是正确的做法。同样,jQuery或YUI是不错的选择。

答案 9 :(得分:0)

如果您想为文档中具有相同ID的所有元素执行某些操作。 虽然简单,但有时候心灵不会给出绿色信号

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