Список цитат ищется в тексте и выделяется цветом по клику, но поиск идет от начала и до последнего найденного элемента, а не по всем тексту, помогите

Найдена первая цитата

Вторая цитата которая идет дальше по тексту

Поиск осуществляется по тексту до первой найденной цитаты, то есть переменная root содержит текст, меньший начального. Я не могу это исправить. Хотелось бы что бы поиск осуществлялся по всему тексту, на кнопки "Показать в тексте" можно было нажимать неограниченное количество раз.

function domRangeHighlight(text) {
      $('div span').replaceWith(function(){
        return $(this).text();
   });
      
      var root = document.getElementById('text').firstChild;
      console.log(root);
      var content = root.nodeValue;
      console.log(content);
      // Проверим есть ли совпадения с переданным текстом
      if (content.indexOf(text) !== -1) {
        if (document.createRange) {
          var rng = document.createRange();
          // Ставим верхнюю границу по индексу совпадения,
          rng.setStart(root, content.indexOf(text));
          // а нижнюю по индексу + длина текста
          rng.setEnd(root, content.indexOf(text) + text.length);
          // Создаём спан с синим фоном
          var highlightDiv = document.createElement('span');
          highlightDiv.style.backgroundColor = 'blue';
          // Обернём наш Range в спан
          rng.surroundContents(highlightDiv);       
              
         }
         } 
        }

Форма HTML

<form action="/" method="post">
        {% if text %}
            <div id="text">{{text}}</div>
            <a href="/">проверить другой текст</a>

        {% else %}
        <form action="/" method="post">
            <textarea id = 'text' name="some_text"></textarea>
            <input type="submit" value="Проверить" />
        </form>
        {% endif %}
        
    </form>

Ответы (1 шт):

Автор решения: Ivan Shatsky

После того, как вы "обернули" фрагмент текста в теги <span>...</span>, первым потомком элемента root, который вы получите после вызова document.getElementById('text').firstChild, как раз и будет элемент типа Text, содержащий текст с его начала и до появления элемента <span>. Это конечно если предыдущее совпадение не случилось с самого начала текста, тогда первым потомком будет этот самый <span>. Насколько я понимаю, вы пытаетесь обойти это, превращая каждый элемент <span> в текст с помощью следующего фрагмента кода:

$('div span').replaceWith(function(){
    return $(this).text();
});

Но вы не учитываете того, что в этом случае вы всё равно получаете в качестве "детей" элемента <div id="text"> три отдельных элемента типа Text - то, что было до элемента <span>, то, что было внутри элемента <span>, и то, что было после элемента <span>. Поэтому первым потомком всё равно остаётся только один из них. Так что советую вам выкинуть ваш jQuery подальше, и делать проще:

var txt = document.getElementById('text');
txt.textContent = txt.textContent;
→ Ссылка