Найти все экземпляры строки, НЕ входящие в теги ?

#javascript #jquery

#javascript #jquery

Вопрос:

Я пишу JavaScript, который просматривает HTML-документ и находит все экземпляры ключевого слова, которые НЕ являются ссылками — не внутри <a> тега. Например, давайте возьмем следующий HTML, и я ищу ключевое слово «ноутбуки».

 <p>I love laptops so much and these are <a href="mylink">some of my <i>favorite laptops</i></a>. Don't you love laptops also?</p>
  

Итак, мне нужен способ вернуть экземпляры 1 и 3 здесь, но не номер 2, потому что он находится внутри ссылки. Я не уверен, что правильный способ сделать это — использовать регулярное выражение (я не могу подобрать подходящее для этого) или выполнить итерацию через DOM или что-то в этом роде. Я могу использовать либо jQuery, либо прямой JS.

Комментарии:

1. вы уже пробовали что-нибудь? Если да, пожалуйста, покажите это, возможно, мы сможем исправить это для вас

2. Что именно вы хотите? Я полагаю, что такой массив, как ['laptop', 'laptop'] , был бы не слишком полезен.

3. instances 1 and 3 here, Какие экземпляры вы вызываете, потому что, как показывает DOM, у вас есть p элемент, который содержит a элемент, который содержит i элемент. IOW: ваш p элемент содержит все 3 ноутбука, так что мы должны вернуть?.

4. Поскольку вы тестируете иерархию DOM, я бы избегал разбора строк, потому что это будет чрезвычайно сложно и хрупко. Может подойти настоящий синтаксический анализатор HTML. Возможно, анализатор DOM?

5. «проблема» тривиальна. но отсутствие каких-либо усилий с вашей стороны действительно мешает людям помогать вам.

Ответ №1:

Предполагая, что вам нужен список элементов, содержащих ‘laptop’, это может помочь вам начать:

 let elements = [...document.querySelectorAll('*')]
    .filter(e =>
        !e.closest('A') amp;amp;
        [...e.childNodes].some(c =>
            c.nodeType === 3 amp;amp; c.textContent.match(/blaptops?b/i)));

elements.forEach(e => e.style.border = '1px solid black');  
 * {padding: 5px;}  
 <div>child text is not considered so this div will not be returned.
  <div>laptop, this div will be returned.</div>
  <div>this div will not.</div>
  <a>laptop in anchor tags are ignored. <span> nested laptop inside anchor tags are also not returned.</span></a>
</div>
<div>plural and capital LapTops will also work, this div will be returned.
  <div>this laptop div will also be returned.</div>
  <div>but parent text is not considered so this div won't be returned.</div>
</div>  

Комментарии:

1. @canon, нет, это не сработает. На самом деле мой фрагмент содержит такой пример, взгляните на 1-й div «дочерний текст не учитывается, поэтому этот div не будет возвращен»

2. Я понимаю, что вы имеете в виду. Неясно, какое ожидаемое поведение для вашего описанного сценария, и я предпочитаю предполагать, что требуется самое простое решение. Спасибо за объяснение.

3. Вы снова правы. 🙂 Я прибегну к аргументу «это тривиально для обхода .parentElement и проверки на этот случай, и OP выиграет от выполнения этого самостоятельно».

4. Обновлено, даже не знал, что этот метод существует, спасибо!

5. Большое спасибо за это. Это отлично работает, но есть одно предостережение. Если в элементе имеется более одного экземпляра ключевого слова, это не указывает на смещение для каждого или на то, что существует более одного. И если в элементе есть несколько экземпляров, и один связан, а другой нет, я не знаю, как определить, какой из них какой.