简体   繁体   English

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

[英]Javascript search in innerHtml Exclude html tags

I have written a custom search in javascript for highlighting texts. 我在javascript中编写了一个自定义搜索来突出显示文本。

the scenario is to get innerHtml and search for the text and highlight them. 方案是获取innerHtml并搜索文本并突出显示它们。

the problem : if the user search for i the i in the <div> tag were found and everything messed up. 问题 :如果用户搜索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;

what can i do to skip founded index in tags? 我该怎么做才能在标签中跳过已建立的索引?

something like this: 这样的事情:

if(isTag(searchIndex))
    //do nothing

UPDATE: 更新:

if i use innerText instead of innerHtml then all of my text format and style will be ruind. 如果我使用innerText而不是innerHtml那么我的所有文本格式和样式都将是ruind。

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

One possible solution would be to work with nodes: 一种可能的解决方案是使用节点:

  • Get the body child nodes (instead of the innerHTML ) 获取body子节点(而不是innerHTML
  • Traverse the nodes: 遍历节点:
    • If it's a text node (leaf): search for the string to replace. 如果它是文本节点(叶子):搜索要替换的字符串。
    • If it's an element node: get and traverse the children. 如果它是一个元素节点:获取并遍历子节点。

Here is a sample function that will highlight the text that you specify: 这是一个示例函数,它将突出显示您指定的文本:

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

And here is a sample demo (also available on this JSFiddle ): 这是一个示例演示(也可在此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> 

One issue with this solution is that it adds additional span elements wrapping each text node that contained the searched string (although I don't know how big of an inconvenience that may be for you). 此解决方案的一个问题是它添加了包含搜索字符串的每个文本节点的附加span元素(尽管我不知道可能给您带来多大的不便)。 It is also recursive, you may want to look into an iterative alternative. 它也是递归的,你可能想要研究一个迭代的替代方案。


UPDATE. UPDATE。 I know you didn't ask for this, but I thought it could be interesting: by reordering the parameters list, and adding some initialization on the first call, you can make the function cleaner for the user, and at the same time, add some interesting functionality: 我知道你没有要求这个,但我认为它可能很有趣:通过重新排序参数列表,并在第一次调用时添加一些初始化,你可以使用户更清洁功能,同时添加一些有趣的功能:

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]);
        }
    }
}

Now, to search a string within the page, you can simply do: 现在,要搜索页面中的字符串,您只需执行以下操作:

highlightText("ar");

(No second parameter needed as before) (不像以前那样需要第二个参数)

But if you pass an element as a second parameter to the function, then the search will be performed exclusively within the specified element and not in the whole page: 但是,如果将元素作为第二个参数传递给函数,则搜索将仅在指定元素内执行,而不是在整个页面中执行:

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

You can see a demo working on this JSFiddle: http://jsfiddle.net/tkm5696w/2/ 你可以看到一个关于这个JSFiddle的演示: http//jsfiddle.net/tkm5696w/2/

Probably you can use innerText instead of innerHTML . 可能你可以使用innerText而不是innerHTML You can use element.textContent . 您可以使用element.textContent

Differences between innerText and textContent can be in the below link. innerTexttextContent之间的差异可以在下面的链接中。

MDN - textContent MDN - textContent

Internet Explorer introduced element.innerText . Internet Explorer引入了element.innerText The intention is similar but with the following differences: 意图相似但有以下不同之处:

  1. While textContent gets the content of all elements, including and elements, the IE-specific property innerText does not. 虽然textContent获取所有元素(包括元素和元素)的内容,但特定于IE的属性innerText却没有。
  2. innerText is aware of style and will not return the text of hidden elements, whereas textContent will. innerText知道样式,不会返回隐藏元素的文本,而textContent会。
  3. As innerText is aware of CSS styling, it will trigger a reflow, whereas textContent will not. 由于innerText知道CSS样式,它将触发重排,而textContent不会。

innerHtml will search for both text and elements inside given element. innerHtml将搜索给定元素内的文本和元素。 Use innerText or textContent to only search for text (I understand that is what you want) 使用innerText或textContent只搜索文本(我明白这就是你想要的)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM