按类名获取所有元素并更改类名

时间:2013-05-27 17:24:24

标签: javascript

我想......

  1. 扫描文档以查找具有特定班级名称的所有元素
  2. 在该元素的innerHTML上执行一些关键功能
  3. 更改该元素的类名,这样如果我稍后再进行一次扫描,则不会重做该元素
  4. 我认为这段代码可以工作,但由于某种原因它在第一个实例之后打破了循环,并且元素的类名永远不会改变。没有框架请。

    function example()
    {
        var elementArray;
    
        elementArray = document.getElementsByClassName("exampleClass");
    
        for(var i = 0; i < elementArray.length; i++)
        {
            // PERFORM STUFF ON THE ELEMENT
            elementArray[i].setAttribute("class", "exampleClassComplete");
            alert(elementArray[i].className);
        }   
    }
    

    编辑(最终答案) - 这是最终产品以及我如何在我的网站中实施@ cHao的解决方案。目标是在页面上抓取各种时间戳并将其更改为时间。谢谢大家的帮助,我从这个问题中学到了很多。

    function setAllTimeAgos()
    {
        var timestampArray = document.getElementsByClassName("timeAgo");
    
        for(var i = (timestampArray.length - 1); i >= 0; i--)
        {
            timestampArray[i].innerHTML = getTimeAgo(timestampArray[i].innerHTML);
            timestampArray[i].className = "timeAgoComplete";
        }
    }
    

5 个答案:

答案 0 :(得分:14)

问题是返回给你的NodeList是“实时” - 它会随着你改变类名而改变。也就是说,当您更改第一个元素上的类时,列表会立即缩短一个元素。

试试这个:

  while (elementArray.length) {
    elementArray[0].className = "exampleClassComplete";
  }

(没有必要使用setAttribute()来设置“class”值 - 只需更新“className”属性。在旧版本的IE中使用setAttribute()无论如何都无法工作。)

或者,将NodeList转换为普通数组,然后使用索引迭代:

  elementArray = [].slice.call(elementArray, 0);
  for (var i = 0; i < elementArray.length; ++i)
    elementArray[i].className = "whatever";

正如评论中所指出的,这具有依赖对NodeList对象的语义的优点。 (另请注意,再次感谢评论,如果您需要在旧版本的Internet Explorer中使用它,则必须编写一个显式循环来将NodeList中的元素引用复制到数组中。)

答案 1 :(得分:8)

大多数返回元素列表的DOM函数返回NodeList而不是数组。最大的区别是NodeList通常是 live ,这意味着更改文档会导致节点神奇地出现或消失。这可能导致节点移动一点,并抛出一个不考虑它的循环。

不是将列表转换为数组或其他任何内容,而是可以简单地在列表中向后循环。

function example()
{
    var elements = document.getElementsByClassName("exampleClass");

    for(var i = elements.length - 1; i >= 0; --i)
    {
        // PERFORM STUFF ON THE ELEMENT
        elements[i].className = "exampleClassComplete";

        // elements[i] no longer exists past this point, in most browsers
    }   
}

此时NodeList的活跃性并不重要,因为从中移除的唯一元素将是之后的。在它之前出现的节点不会受到影响。

答案 2 :(得分:1)

另一种方法可能是使用选择器:

var arr = document.querySelectorAll('.exampleClass');
for (var i=0;i<arr.length;i++) {
    arr.innerHTML = "new value";
}

虽然它与旧版浏览器不兼容,但如果webcontent适用于现代浏览器,它也可以解决问题。

答案 3 :(得分:0)

你也可以使用2个数组,将数据推送到第一个数组,然后做你需要做的事情[比如改变元素的类]:

function example()
{
    var elementArray=[];
    var elementsToBeChanged=[];
    var i=0;

    elementArray = document.getElementsByClassName("exampleClass");

    for( i = 0; i < elementArray.length; i++){
        elementsToBeChanged.push(elementArray[i]);
    }

    for( i=0; i< elementsToBeChanged.length; i++)
    {
        elementsToBeChanged[i].setAttribute("class", "exampleClassComplete");
    }
}

答案 4 :(得分:0)

另一种可能性,也应该是跨浏览器,使用手动taylored getElementsByClassName,它将固定节点列表作为数组返回。这应该支持IE5.5及更高版本。

function getElementsByClassName(node, className) {
    var array = [],
        regex = new RegExp("(^| )" + className + "( |$)"),
        elements = node.getElementsByTagName("*"),
        length = elements.length,
        i = 0,
        element;

    while (i < length) {
        element = elements[i];
        if (regex.test(element.className)) {
            array.push(element);
        }

        i += 1;
    }

    return array;
}