innerHtml中的Javascript搜索排除html标记

Javascript search in innerHtml Exclude html tags

本文关键字:html 标记 排除 搜索 中的 Javascript innerHtml      更新时间:2023-09-26

我用javascript编写了一个自定义搜索,用于突出显示文本。

场景是获取CCD_ 1并搜索文本并突出显示它们。

问题:如果用户搜索i,则会发现<div>标签中的i,并且一切都一团糟。

var textBlock=document.body.innerHTML;
searchIndex = textBlock.toLowerCase().indexOf(what.toLowerCase(), 0);
while(searchIndex >= 0)
{
    ++counter;
    ID = "result" + counter;
    replacement = '<span id='+ID+' style="background-color:#f0da1e">'+what+'</span>';
    textBlock = textBlock.substring(0, searchIndex) + replacement + textBlock.substring(searchIndex + what.length, textBlock.length);
    searchIndex = textBlock.toLowerCase().indexOf(what.toLowerCase(), (searchIndex + replacement.length));
}
document.body.innerHTML=textBlock;

如何跳过标签中的已建立索引?

像这样的东西:

if(isTag(searchIndex))
    //do nothing

更新:

如果我使用innerText而不是innerHtml,那么我所有的文本格式和样式都将被破坏。

var textBlock=document.body.innerText;
document.body.innerHTML=textBlock;

一种可能的解决方案是使用节点:

  • 获取body子节点(而不是innerHTML(
  • 遍历节点:
    • 如果是文本节点(叶子(:搜索要替换的字符串
    • 如果它是一个元素节点:获取并遍历子节点

下面是一个示例函数,它将突出显示您指定的文本:

function highlightText(nodeList, what) {
  // traverse all the children nodes
  for (var x = 0; x < nodeList.length; x++) {
    // text node, search directly
    if (nodeList[x].nodeType == 3) {
      // if it contains the text that you are looking for, proceed with the replacement
      if (nodeList[x].textContent.indexOf(what) >= 0) {
        // your code (mostly :P)
        var ID = "result" + counter;
        var replacement = '<span id="'+ID+'" style="background-color:#f0da1e">'+what+'</span>';
        var textBlock = nodeList[x].textContent;
        var searchIndex = nodeList[x].textContent.indexOf(what);
        while(searchIndex >= 0)
        {
          ++counter;
          ID = "result" + counter;
          replacement = '<span id="'+ID+'" style="background-color:#f0da1e">'+what+'</span>';           
          textBlock = textBlock.substring(0, searchIndex) + replacement + textBlock.substring(searchIndex + what.length, textBlock.length);
          searchIndex = textBlock.toLowerCase().indexOf(what.toLowerCase(), (searchIndex + replacement.length));
        }
        // create a new element with the replacement text
        var replacementNode = document.createElement("span");
        replacementNode.innerHTML = textBlock;
        // replace the old node with the new one
        var parentN = nodeList[x].parentNode;
        parentN.replaceChild(replacementNode, parentN.childNodes[x]);
      }
    } else {
      // element node --> search in its children nodes
      highlightText(nodeList[x].childNodes, what);
    }
  }
}

这里有一个示例演示(也可以在这个JSFiddle上获得(:

var counter = 0;
function highlightText(nodeList, what) {
  // traverse all the children nodes
  for (var x = 0; x < nodeList.length; x++) {
    // text node, search directly
    if (nodeList[x].nodeType == 3) {
      // if it contains the text that you are looking for, proceed with the replacement
      if (nodeList[x].textContent.indexOf(what) >= 0) {
        // your code (mostly :P)
        var ID = "result" + counter;
        var replacement = '<span id="'+ID+'" style="background-color:#f0da1e">'+what+'</span>';
        var textBlock = nodeList[x].textContent;
        var searchIndex = nodeList[x].textContent.indexOf(what);
        while(searchIndex >= 0)
        {
          ++counter;
          ID = "result" + counter;
          replacement = '<span id="'+ID+'" style="background-color:#f0da1e">'+what+'</span>';			
          textBlock = textBlock.substring(0, searchIndex) + replacement + textBlock.substring(searchIndex + what.length, textBlock.length);
          searchIndex = textBlock.toLowerCase().indexOf(what.toLowerCase(), (searchIndex + replacement.length));
        }
        // create a new element with the replacement text
        var replacementNode = document.createElement("span");
        replacementNode.innerHTML = textBlock;
        // replace the old node with the new one
        var parentN = nodeList[x].parentNode;
        parentN.replaceChild(replacementNode, parentN.childNodes[x]);
      }
    } else {
      // element node --> search in its children nodes
      highlightText(nodeList[x].childNodes, what);
    }
  }
}
var nodes = document.body.childNodes;
console.log(nodes);
highlightText(nodes, "ar");
<p>Men at some time are masters of their fates: The fault, dear Brutus, is not in our stars, but in ourselves, that we are underlings.</p>
<p><b>William Shakespeare</b>, <em>Julius Caesar</em> (Act I, Scene II)</p>

这个解决方案的一个问题是,它添加了额外的span元素来包装包含搜索字符串的每个文本节点(尽管我不知道这会给您带来多大的不便(。它也是递归的,您可能想研究一个迭代的替代方案。


更新我知道你没有要求这样做,但我认为这可能很有趣:通过重新排序参数列表,并在第一次调用时添加一些初始化,你可以让用户的函数更干净,同时添加一些有趣的功能:

function highlightText(what, node) {
    // initialize values if first call
    node = node || document.body;
    var nodeList = node.childNodes;
    // traverse all the children nodes
    for (var x = 0; x < nodeList.length; x++) {
        // text node, search directly
        if (nodeList[x].nodeType == 3) {
            // if it contains the text that you are looking for, proceed with the replacement
            if (nodeList[x].textContent.indexOf(what) >= 0) {
                // your code (mostly :P)
                var ID = "result" + counter;
                var replacement = '<span id="'+ID+'" style="background-color:#f0da1e">'+what+'</span>';
                var textBlock = nodeList[x].textContent;
                var searchIndex = nodeList[x].textContent.indexOf(what);
                while(searchIndex >= 0)
                {
                    ++counter;
                    ID = "result" + counter;
                    replacement = '<span id="'+ID+'" style="background-color:#f0da1e">'+what+'</span>';         
                    textBlock = textBlock.substring(0, searchIndex) + replacement + textBlock.substring(searchIndex + what.length, textBlock.length);
                    searchIndex = textBlock.toLowerCase().indexOf(what.toLowerCase(), (searchIndex + replacement.length));
                }
                // create a new element with the replacement text
                var replacementNode = document.createElement("span");
                replacementNode.innerHTML = textBlock;
                // replace the old node with the new one
                var parentN = nodeList[x].parentNode;
                parentN.replaceChild(replacementNode, parentN.childNodes[x]);
            }
        } else {
            // element node --> search in its children nodes
            highlightText(what, nodeList[x]);
        }
    }
}

现在,要在页面中搜索字符串,您只需执行以下操作:

highlightText("ar");

(不需要像以前那样的第二个参数(

但是,如果您将一个元素作为第二个参数传递给函数,那么搜索将只在指定的元素中执行,而不是在整个页面中执行:

highlightText("ar", document.getElementById("highlight_only_this"));

您可以在这个JSFiddle上看到一个演示:http://jsfiddle.net/tkm5696w/2/

也许您可以使用innerText而不是innerHTML。您可以使用innerHtml0。

innerTexttextContent之间的差异可以在以下链接中。

MDN-text内容

Internet Explorer推出了element.innerText。意图相似,但有以下区别:

  1. 而textContent获取所有元素的内容,包括和元素,IE特定属性innerText没有
  2. innerText知道样式,不会返回隐藏的文本元素,而textContent会
  3. 由于innerText知道CSS样式,它将触发回流,而textContent不会

innerHtml将搜索给定元素内的文本和元素。使用innerText或textContent只搜索文本(我知道这就是你想要的(