[英]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: 一种可能的解决方案是使用节点:
body
child nodes (instead of the innerHTML
) body
子节点(而不是innerHTML
) 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. innerText
和textContent
之间的差异可以在下面的链接中。
MDN - textContent MDN - textContent
Internet Explorer introduced element.innerText
. Internet Explorer引入了
element.innerText
。 The intention is similar but with the following differences: 意图相似但有以下不同之处:
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.