Подтвердить что ты не робот

Получить все элементы по ClassName и изменить ClassName

Я хотел бы...

  • Сканировать документ для всех элементов, имеющих определенное имя класса
  • Выполните некоторые ключевые функции в innerHTML этого элемента
  • Измените имя класса для этого элемента, чтобы, если я сделаю другое сканирование позже, я не переделаю этот элемент

Я думал, что этот код будет работать, но по какой-то причине он прерывает цикл после первого экземпляра, а имена классов классов никогда не меняются. Без рамок пожалуйста.

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

EDIT (FINAL ANSWER). Вот окончательный продукт и то, как я реализовал решение @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";
    }
}
4b9b3361

Ответ 1

Проблема в том, что возвращаемый вам NodeList является "live" - он изменяется при изменении имени класса. То есть, когда вы меняете класс на первом элементе, список сразу на один элемент короче, чем он был.

Попробуйте следующее:

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

(Нет необходимости использовать setAttribute() для установки значения "class" - просто обновите свойство "className". Использование setAttribute() в старых версиях IE не будет работать в любом случае.)

В качестве альтернативы, преобразуйте NodeList в простой массив, а затем используйте свою индексированную итерацию:

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

Как отмечено в комментарии, это имеет то преимущество, что не полагается на семантику объектов NodeList. (Отметьте также, еще раз спасибо комментарию, что если вам нужно, чтобы это работало в более старых версиях Internet Explorer, вам пришлось бы писать явный цикл для копирования ссылок на элементы из NodeList в массив.)

Ответ 2

Большинство функций DOM, которые возвращают список элементов, возвращают NodeList, а не массив. Самое большое различие заключается в том, что NodeList, как правило, жив, что означает, что изменение документа может привести к появлению или исчезновению узлов. Это может привести к тому, что узлы будут перемещаться немного, и сбросить цикл, который не учитывает его.

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

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 не будет иметь значения в тот момент, поскольку единственные элементы, удаленные из нее, будут теми, которые остались после того, который вы сейчас используете. Узлы, которые появляются перед ним, не будут затронуты.

Ответ 3

Другим подходом может быть использование селектора:

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

Хотя он несовместим со старыми браузерами, он также может сделать трюк, если webcontent предназначен для современных браузеров.

Ответ 4

Вы также можете использовать 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");
    }
}

Ответ 5

Другая возможность, которая также должна быть кросс-браузером, использует ручное taylored getElementsByClassName, которое возвращает фиксированный список node как массив. Это должно поддерживать 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;
}