Добавить класс в div, содержащий строку innerHTML

Я пытаюсь добавить класс CSS к каждому div на странице, содержащей строку Subject:

Я пытался

var elList = document.querySelectorAll("div");
elList.forEach(function(el) {
  if (el.innerHTML.indexOf("Subject") !== -1) {
    console.info(el);
    el.setAttribute('class', "newClass");
  }
});

но он не вернул никаких узлов. А также

var headings = document.evaluate("//*[contains(normalize-space(text()), 'Subject:')]", document, null, XPathResult.ANY_TYPE, null );
while(thisHeading = headings.iterateNext()){
  thisHeading.setAttribute('class', "newClass");
  console.info(thisHeading);
}

который вернул XPathResult, у которого, похоже, не было никаких узлов как части объекта.

Так выглядит HTML, хотя он глубоко вложен в тело документа.

<div class = "note-stream-header">Subject: Please Reply to This</div>

Как я могу выбрать все узлы, содержащие строку, и добавить к ним класс с помощью JS?

Ваш исходный код выглядит так, как будто он находится на правильном пути. Можете ли вы опубликовать полный фрагмент кода с образцом HTML-документа?

T Nguyen 18.12.2018 22:38

Я только что залил блок HTML.

Matthew 18.12.2018 22:41

Просто попробовал ваш код, отлично работает. jsfiddle.net/c12ya4nq/1

T Nguyen 18.12.2018 22:42

Хм. Интересно, выполняется ли он до того, как узлы завершат загрузку на странице. Я пытаюсь использовать его как часть расширения Chrome.

Matthew 18.12.2018 22:43
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
430
1

Ответы 1

Ваш подход хорош, но поскольку вас интересует содержимое элемента, используйте .textContent вместо innerHTML.

Смотрите дополнительные комментарии в строке.

// .forEach is not supported in all browsers on node lists
// Convert them to arrays first to be safe:
var elList = Array.prototype.slice.call(
    document.querySelectorAll("div"));
    
elList.forEach(function(el) {
  // Use .textContent when you aren't interested in HTML
  if (el.textContent.indexOf("Subject") > -1) {
    console.info(el);
    el.classList.add("newClass");  // Use the .classList API (easier)
  }
});
.newClass { background-color:#ff0; }
<div>The subject of this discussion is JavaScript</div>
<div>The topic of this discussion is JavaScript</div>
<div>The queen's royal subjects weren't amused.</div>
<div>Subject: textContent DOM property</div>

Также неплохо использовать classList вместо setAttribute. :-) Но я думаю, что Array.from было бы лучше, чем использовать кусочек. Какова вероятность того, что NodeList не имеет для каждого? Если это проблема, почему бы не Array.prototype.forEach.call(NodeList, ...).

RobG 19.12.2018 00:26

@RobG Array.from - это ECMA 6 и не поддерживается браузерами, которые не поддерживают .forEach в списках узлов (включая любую версию IE). Вы можете использовать .call(), но тогда вам придется иметь дело с привязкой this, в то время как .slice возвращает массив, который вы можете кэшировать и продолжать использовать после этого одного оператора.

Scott Marcus 19.12.2018 03:41

Я не думаю, что это является проблемой, он не определен, если он не передан в обратный вызов. Но если есть необходимость повторно использовать NodeList как массив, кусочек имеет смысл.

RobG 19.12.2018 05:51

Другие вопросы по теме