Как динамически адресовать слово / строку с помощью JavaScript в html-документе, а затем пометить его? - PullRequest
0 голосов
/ 23 марта 2011

У меня есть HTML-документ:

<html>
  <body>
    <p>
      A funny joke:
      <ul>
        <li>do you know why six is afraid of seven?
        <li>because seven ate nine.
      </ul>
      Oh, so funny!
    </p>
  </body>
</html>

Теперь я хочу идентифицировать первый случай появления «семерки» и пометить его

<span id="link1" class="link">

Как это можно сделать?

Вам нужно проанализировать DOM-дерево или можно получить весь код в разделе body и затем найти слово?

В обоих случаях после того, как я где-то нашел слово, как вы его определили и изменили его родительский DOM на span (я думаю, это то, что нужно сделать), а затем добавили упомянутые атрибуты?

Я ожидаю не столько кода, сколько того, какие методы или концепции будут работать.

И я не столько интересуюсь фреймворком-решением, сколько чисто javascript.

Ответы [ 3 ]

2 голосов
/ 25 марта 2011

Вам нужно найти узел DOM с типом TEXT_NODE (3) и содержать ожидаемое слово.Когда вам нужно разделить этот узел на три.

Первый - это TEXT_NODE, который содержит текст перед искомым словом, второй - это узел SPAN, содержащий искомое слово, а третий - еще один TEXT_NODE, содержащий хвост исходного узла (все после искомого слова).

Вот исходный код ...

<html>
   <head>
      <style type="text/css">
         .link {
            color: red;
         }
      </style>
   </head>
  <body>
    <p>
      A funny joke:
      <ul>
        <li>do you know why six is afraid of seven?
        <li>because seven ate nine.
      </ul>
      Oh, so funny!
    </p>
    <script type="text/javascript">
       function search(where, what) {
         var children = where.childNodes;
         for(var i = 0, l = children.length; i < l; i++) {
            var child = children[i], pos;
            if(child.nodeType == 3 && (pos = child.nodeValue.indexOf(what)) != -1) { // a TEXT_NODE
               var value = child.nodeValue;
               var parent = child.parentNode;
               var start = value.substring(0, pos);
               var end = value.substring(pos + what.length);
               var span = document.createElement('span');

               child.nodeValue = start;
               span.className = 'link';
               span.id = 'link1';
               span.innerHTML = what;
               parent.appendChild(span);
               parent.appendChild(document.createTextNode(end));
               return true;
            } else
               if(search(child, what))
                  break;
         }
         return false;
       }
       search(document.getElementsByTagName('body')[0], 'seven');
    </script>
  </body>
</html>
2 голосов
/ 25 марта 2011

Это функция, которую я написал несколько лет назад, которая ищет определенный текст и выделяет его (помещает совпадения в span с определенным именем класса).

Проходит по DOM-дереву, изучая текстовое содержимое. Всякий раз, когда он находит текстовый узел, содержащий искомый текст, он заменяет этот текстовый узел тремя новыми узлами:

  1. один текстовый узел с текстом, предшествующим совпадению,
  2. один (недавно созданный) span элемент, содержащий соответствующий текст,
  3. и один текстовый узел с текстом после совпадения.

Это та функция, которая у меня есть. Это часть большого файла сценария, но он также должен работать независимо. (Я прокомментировал вызов ensureElementVisible, который сделал элемент видимым, поскольку сценарий также имел возможности свертывания и расширения).

Он делает одну (другую) вещь, которая вам, вероятно, не понадобится: он превращает текст поиска в регулярное выражение, соответствующее любому из нескольких слов.

function findText(a_text, a_top) {
    // Go through *all* elements below a_top (if a_top is undefined, then use the body)
    //  and check the textContent or innerText (only if it has textual content!)
    var rexPhrase = new RegExp(a_text.replace(/([\\\/\*\?\+\.\[\]\{\}\(\)\|\^\$])/g, '\\$1').replace(/\W+/g, '\\W*')
                                    , 'gi');
    var terms = [];
    var rexSearchTokens = /[\w]+/g;
    var match;
    while(match = rexSearchTokens.exec(a_text)) {
        terms.push(match[0]);
    }
    var rexTerm = new RegExp('\\b(' + terms.join('|') + ')', 'gi');

    var hits = [];
    walkDOMTree(a_top || document.body,
                function search(a_element) {
                    if (a_element.nodeName === '#text') {
                        if(rexPhrase.test(a_element.nodeValue)) {
//                          ensureElementVisible(a_element, true);
                            hits.push(a_element);
                        }
                    }
                });

    // highlight the search terms in the found elements
    for(var i = 0; i < hits.length; i++) {
        var hit = hits[i];
        var parent = hit.parentNode;

        if (parent.childNodes.length === 1) {
            // Remove the element from the hit list
            hits.splice(i, 1);

            var text = hit.nodeValue;
            parent.removeChild(hit);
            var match, prevLastIndex = 0;
            while(match = rexTerm.exec(text)) {
                parent.appendChild(document.createTextNode(text.substr(prevLastIndex, match.index - prevLastIndex)));
                var highlightedTerm = parent.appendChild(document.createElement('SPAN'));
                highlightedTerm.className = 'search-hit';
                highlightedTerm.appendChild(document.createTextNode(match[0]));
                prevLastIndex = match.index + match[0].length;

                // Insert the newly added element into the hit list
                hits.splice(i, 0, highlightedTerm);
                i++;
            }
            parent.appendChild(document.createTextNode(text.substr(prevLastIndex)));

            // Account for the removal of the original hit node
            i--;
        }
    }

    return hits;
}
0 голосов
/ 23 марта 2011

Я нашел следующий вопрос: Найти текстовую строку, используя jQuery?

Это похоже на то, что вы пытаетесь сделать. Теперь вы пытаетесь обернуть только текст «семь» или вы пытаетесь обернуть все содержимое

?
...