【问题标题】:JQuery/Javascript - Search DOM for text and insert HTMLJQuery/Javascript - 在 DOM 中搜索文本并插入 HTML
【发布时间】:2010-12-20 11:20:07
【问题描述】:

如何在 DOM 中搜索文档文本中的某个字符串(例如“cheese”),然后在该字符串之后立即插入一些 HTML(例如,“is wonderful”)。

我尝试了以下方法:

for (var tag in document.innerHTML) {
    if (tag.matches(/cheese/) != undefined) {
        document.innerHTML.append(<b>is fantastic</b>
    }
}

(以上更多是我尝试过的说明,而不是实际代码。我认为语法非常错误,所以请原谅任何错误,它们不是问题)。

干杯,

皮特

【问题讨论】:

    标签: javascript jquery html dom insert


    【解决方案1】:

    有一些本地方法可以在文档中查找文本:

    MSIE:textRange.findText()
    其他:window.find()

    如果发现某些内容,则操作给定的 textRange。
    这些方法应该比遍历整个文档提供更多的性能。

    例子:

    <html>
    <head>
    
      <script>
      function fx(a,b)
      {
        if(window.find)
        {
          while(window.find(a))
          {
            var node=document.createElement('b');
                node.appendChild(document.createTextNode(b));
            var rng=window.getSelection().getRangeAt(0);
                rng.collapse(false);
                rng.insertNode(node);
          }
        }
        else if(document.body.createTextRange)
        {
          var rng=document.body.createTextRange();
          while(rng.findText(a))
          {
            rng.collapse(false);
            rng.pasteHTML('<b>'+b+'</b>');
          }
        }
      }
      </script>
    </head>
    <body onload="fx('cheese','is wonderful')">
    <p>I've made a wonderful cheesecake with some <i>cheese</i> from my <u>chees</u>e-factory!</p>
    </body>
    </html>
    

    【讨论】:

    • 一旦发现文本在非 IE 浏览器中换行并非易事。
    • 问题是关于附加不环绕,这在非 IE 浏览器中也是微不足道的。
    • 很公平。我不相信这将与 DOM 遍历解决方案一样精确,因为它将这些正在创建的节点放置在何处,需要解决区分大小写的问题,并且它会与用户的选择混淆,但它确实有效并且是一个有效的替代方案。 +1。
    • 这两种方法都有设置区分大小写的参数,这只是一个简单的例子,并不是一个完整的解决方案。
    • 我偶然发现了一个类似的问题,发现您的解决方案非常有帮助。例如,您知道我如何将找到的文本包装在&lt;b&gt; 标记中吗?我在 Firefox 中做到了这一点,但我被 IE8 卡住了。
    【解决方案2】:

    这是粗略的,不是这样做的方法,但是;

    document.body.innerHTML = document.body.innerHTML.replace(/cheese/, 'cheese <b>is fantastic</b>');
    

    【讨论】:

    • 希望“奶酪”不会出现在元素属性、CSS 或 JS 中。
    【解决方案3】:

    您可以将它与 JQuery 一起使用:

    $('*:contains("cheese")').each(function (idx, elem) {
        var changed = $(elem).html().replace('cheese', 'cheese <b>is fantastic</b>');
        $(elem).html(changed);
    });
    

    我还没有对此进行测试,但是这些方面的东西应该可以工作。

    请注意,* 将匹配所有元素,甚至是 html,因此您可能希望使用 body *:contains(...) 来确保只查看文档正文的后代元素。

    【讨论】:

      【解决方案4】:

      示例解决方案:

      <ul>
        <li>cheese</li>
        <li>cheese</li>
        <li>cheese</li>
      </ul>
      

      Jquery 代码:

      $('ul li').each(function(index) {
        if($(this).text()=="cheese")
        {
          $(this).text('cheese is fantastic');
        }
      });
      

      【讨论】:

        【解决方案5】:

        这样做的方法是遍历文档并在每个文本节点中搜索所需的文本。任何涉及innerHTML 的方式都是无可救药的缺陷。

        这是一个适用于所有浏览器的函数,它递归遍历指定节点内的 DOM,并用从提供的模板节点 replacementNodeTemplate 复制的节点替换出现的一段文本:

        function replaceText(node, text, replacementNodeTemplate) {
            if (node.nodeType == 3) {
                while (node) {
                    var textIndex = node.data.indexOf(text), currentNode = node;
                    if (textIndex == -1) {
                        node = null;
                    } else {
                        // Split the text node after the text
                        var splitIndex = textIndex + text.length;
                        var replacementNode = replacementNodeTemplate.cloneNode(true);
                        if (splitIndex < node.length) {
                            node = node.splitText(textIndex + text.length);
                            node.parentNode.insertBefore(replacementNode, node);
                        } else {
                            node.parentNode.appendChild(replacementNode);
                            node = null;
                        }
                        currentNode.deleteData(textIndex, text.length);
                    }
                }
            } else {
                var child = node.firstChild, nextChild;
                while (child) {
                    nextChild = child.nextSibling;
                    replaceText(child, text, replacementNodeTemplate);
                    child = nextChild;
                }
            }
        }
        

        这是一个使用示例:

        replaceText(document.body, "cheese", document.createTextNode("CHEESE IS GREAT"));
        

        如果您愿意,您可以创建一个包装函数,以允许您将替换内容指定为 HTML 字符串:

        function replaceTextWithHtml(node, text, html) {
            var div = document.createElement("div");
            div.innerHTML = html;
            var templateNode = document.createDocumentFragment();
            while (div.firstChild) {
                templateNode.appendChild(div.firstChild);
            }
            replaceText(node, text, templateNode);
        }
        

        例子:

        replaceTextWithHtml(document.body, "cheese", "cheese <b>is fantastic</b>");
        

        我已将其合并到一个 jsfiddle 示例中:http://jsfiddle.net/timdown/azZsa/

        【讨论】:

          【解决方案6】:

          我认为可以在除 IE 之外的所有浏览器中使用,但需要确认。

          这也支持 iframe 中的内容。

          注意,我见过的其他示例,例如上面的示例,是 RECURSIVE ,这在 javascript 中可能是不好的,可能会导致堆栈溢出,尤其是在内存有限的浏览器客户端中。过多的递归会导致 javascript 停止执行。

          如果您不相信我,请尝试here 自己的示例...

          如果有人愿意贡献,代码是here

          function grepNodes(searchText, frameId) {
            var matchedNodes = [];
            var regXSearch;
            if (typeof searchText === "string") {
              regXSearch = new RegExp(searchText, "g");
            }
            else {
              regXSearch = searchText;
            } 
            var currentNode = null, matches = null;
            if (frameId && !window.frames[frameId]) {
              return null;
            }
            var theDoc = (frameId) ? window.frames[frameId].contentDocument : document;
            var allNodes = (theDoc.all) ? theDoc.all : theDoc.getElementsByTagName('*');
            for (var nodeIdx in allNodes) {
              currentNode = allNodes[nodeIdx];
              if (!currentNode.nodeName || currentNode.nodeName === undefined) {
                break;
              }
              if (!(currentNode.nodeName.toLowerCase().match(/html|script|head|meta|link|object/))) {
                matches = currentNode.innerText.match(regXSearch);
                var totalMatches = 0;
                if (matches) {
                  var totalChildElements = 0;
                  for (var i=0;i<currentNode.children.length;i++) {
                    if (!(currentNode.children[i].nodeName.toLowerCase().match(/html|script|head|meta|link|object/))) {
                      totalChildElements++;
                    }
                  }
                  matchedNodes.push({node: currentNode, numMatches: matches.length, childElementsWithMatch: 0, nodesYetTraversed: totalChildElements});
                }
                for (var i = matchedNodes.length - 1; i >= 0; i--) {
                  previousElement = matchedNodes[i - 1];
                  if (!previousElement) {
                    continue;
                  }
                  if (previousElement.nodesYetTraversed !== 0 && previousElement.numMatches !== previousElement.childElementsWithMatch) {
                    previousElement.childElementsWithMatch++;
                    previousElement.nodesYetTraversed--;
                  }      
                  else if (previousElement.nodesYetTraversed !== 0) {
                    previousElement.nodesYetTraversed--;
                  }               
                }
              }
            }
            var processedMatches = [];
            for (var i =0; i <  matchedNodes.length; i++) {
              if (matchedNodes[i].numMatches > matchedNodes[i].childElementsWithMatch) {
                processedMatches.push(matchedNodes[i].node);
              }
            }
            return processedMatches; 
          };
          

          【讨论】:

            猜你喜欢
            • 2012-12-24
            • 2017-07-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-12-27
            • 1970-01-01
            • 2012-08-11
            • 2019-11-21
            相关资源
            最近更新 更多