内部HTML中的Javascript搜索排除html标记

时间:2015-07-06 12:18:21

标签: javascript html

我在 javascript 中编写了一个自定义搜索来突出显示文本。

方案是获取innerHtml并搜索文本并突出显示它们。

问题:如果用户在 中搜索 i 找到<div>标签,一切都搞砸了。

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;

3 个答案:

答案 0 :(得分:2)

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

  • 获取<!DOCTYPE html> <html> <head> <title></title> <style type="text/css"> body { background-color: #222222; } canvas { background-color: #000000; width: 25%; height: 400px; } </style> </head> <body> <canvas id="mainCanvas"></canvas> <script type="text/javascript"> var canvas = document.getElementById("mainCanvas"); var context = canvas.getContext("2d"); var keys = []; var speed = 4; // var width = 25%; var height = 400; window.addEventListener("keydown", function(e) { keys[e.keyCode] = true; }, false); window.addEventListener("keyup", function(e) { delete keys[e.keyCode]; }, false); var player = { x: 10, y: 10, width: 30, height: 30 }; function game() { update(); render(); } function update() { if (keys[40]) player.y++ * speed; if (keys[38]) player.y-- * speed; if (keys[37]) player.x-- * speed; if (keys[39]) player.x++ * speed; } function render() { context.clearRect(0, 0, (canvas.width * 0.25), height); context.fillStyle = "white"; context.fillRect(player.x, player.y, player.width, player.height); } setInterval(function() { game(); }, 1000/30); </script> </body> </html> 子节点(而不是body
  • 遍历节点:
    • 如果它是文本节点(叶子):搜索要替换的字符串。
    • 如果它是一个元素节点:get and traverse the children。

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

innerHTML

这是一个示例演示(也可在此JSFiddle上找到):

&#13;
&#13;
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);
    }
  }
}
&#13;
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");
&#13;
&#13;
&#13;

此解决方案的一个问题是它添加了包含搜索字符串的每个文本节点的其他<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>元素(尽管我不知道可能给您带来多大的不便)。它也是递归的,你可能想要研究一个迭代的替代方案。

UPDATE。我知道你没有要求这个,但我认为这可能很有趣:通过重新排序参数列表,并在第一次调用时添加一些初始化,你可以制作为用户提供的功能清理器,同时添加一些有趣的功能:

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");

你可以看到一个关于这个JSFiddle的演示:http://jsfiddle.net/tkm5696w/2/

答案 1 :(得分:1)

您可以使用innerText代替innerHTML。 您可以使用element.textContent

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

MDN - textContent

Internet Explorer介绍了element.innerText。意图相似,但有以下不同之处:

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

答案 2 :(得分:0)

innerHtml将搜索给定元素中的文本和元素。使用innerText或textContent只搜索文本(我明白这就是你想要的)