如何在html文档中使用javascript动态地处理单词/字符串然后标记它?

时间:2011-03-23 13:28:16

标签: javascript html dom dom-traversal

我有一个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树,或者是否可以在正文部分中获取整个代码然后搜索该单词?

在这两种情况下,在我找到某个地方之后,你如何识别它并将它的DOM-parent更改为span(我想这是必须要做的)然后添加提到的属性?

这不是我期望的代码,而是什么方法或概念可以完成这项工作。

我并不是一个框架解决方案,而是以纯粹的javascript方式。

3 个答案:

答案 0 :(得分:2)

您需要找到类型为TEXT_NODE(3)的DOM节点并包含您期望的单词。当您需要将该节点拆分为三个节点时。

首先是一个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>

答案 1 :(得分:2)

这是我几年前写的一个函数,用于搜索特定文本,并突出显示它们(将匹配项置于具有特定类名的span中)。

它遍历DOM树,检查文本内容。每当它找到包含所查找文本的文本节点时,它将用三个新节点替换该文本节点:

  1. 一个文本节点,其中包含匹配前的文字,
  2. 包含匹配文本的一个(新创建的)span元素
  3. 以及匹配后文本的一个文本节点。
  4. 这是我的功能。它是更大的脚本文件的一部分,但它也应该独立运行。 (我已经注释了对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;
    }
    

答案 2 :(得分:0)

我发现以下问题: Find text string using jQuery?

这似乎与您尝试做的很接近。您现在试图仅包装文本“七”还是试图包装&lt; li&gt;的整个内容?