JQuery/Javascript - 在 DOM 中搜索文本并插入 HTML
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4489119/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JQuery/Javascript - Search DOM for text and insert HTML
提问by Dr.Molle
How do I search the DOM for a certain string in the document's text (say, "cheese") then insert some HTML immediately after that string (say, "< b >is fantastic< /b >").
我如何在 DOM 中搜索文档文本中的某个字符串(比如“cheese”),然后在该字符串之后立即插入一些 HTML(比如“< b > is nice</b >”)。
I have tried the following:
我尝试了以下方法:
for (var tag in document.innerHTML) {
if (tag.matches(/cheese/) != undefined) {
document.innerHTML.append(<b>is fantastic</b>
}
}
(The above is more of an illustration of what I have tried, not the actual code. I expect the syntax is horribly wrong so please excuse any errors, they are not the problem).
(以上更多是对我尝试过的内容的说明,而不是实际代码。我认为语法是非常错误的,所以请原谅任何错误,它们不是问题)。
Cheers,
干杯,
Pete
皮特
回答by Dr.Molle
There are native methods for finding text inside a document:
有用于在文档中查找文本的本机方法:
MSIE:textRange.findText()
Others: window.find()
MSIE:textRange.findText()
其他:window.find()
Manipulate the given textRange if something was found.
Those methods should provide much more performance than the traversing of the whole document.
如果找到某些内容,则操作给定的 textRange。
这些方法应该比遍历整个文档提供更多的性能。
Example:
例子:
<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>
回答by Eivind
This is crude and not the way to do it, but;
这是粗略的,而不是这样做的方法,但是;
document.body.innerHTML = document.body.innerHTML.replace(/cheese/, 'cheese <b>is fantastic</b>');
回答by Deniz Dogan
You can use this with JQuery:
你可以在 JQuery 中使用它:
$('*:contains("cheese")').each(function (idx, elem) {
var changed = $(elem).html().replace('cheese', 'cheese <b>is fantastic</b>');
$(elem).html(changed);
});
I haven't tested this, but something along these lines should work.
我还没有测试过这个,但是沿着这些方向的东西应该可以工作。
Note that *will match all elements, even html, so you may want to use body *:contains(...)instead to make sure only elements that are descendants of the document body are looked at.
请注意,*将匹配所有元素,甚至html,因此您可能希望使用它body *:contains(...)来确保仅查看文档正文的后代元素。
回答by Mohan Ram
Sample Solution:
示例解决方案:
<ul>
<li>cheese</li>
<li>cheese</li>
<li>cheese</li>
</ul>
Jquery codes:
jQuery 代码:
$('ul li').each(function(index) {
if($(this).text()=="cheese")
{
$(this).text('cheese is fantastic');
}
});
回答by Tim Down
The way to do this is to traverse the document and search each text node for the desired text. Any way involving innerHTMLis hopelessly flawed.
这样做的方法是遍历文档并在每个文本节点中搜索所需的文本。任何涉及的方式innerHTML都是无可救药的缺陷。
Here's a function that works in all browsers and recursively traverses the DOM within the specified node and replaces occurrences of a piece of text with nodes copied from the supplied template node replacementNodeTemplate:
这是一个适用于所有浏览器的函数,它递归地遍历指定节点内的 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;
}
}
}
Here's an example use:
这是一个使用示例:
replaceText(document.body, "cheese", document.createTextNode("CHEESE IS GREAT"));
If you prefer, you can create a wrapper function to allow you to specify the replacement content as a string of HTML instead:
如果您愿意,您可以创建一个包装函数,以允许您将替换内容指定为 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);
}
Example:
例子:
replaceTextWithHtml(document.body, "cheese", "cheese <b>is fantastic</b>");
I've incorporated this into a jsfiddle example: http://jsfiddle.net/timdown/azZsa/
我已将其合并到一个 jsfiddle 示例中:http: //jsfiddle.net/timdown/azZsa/
回答by brandon
Works in all browsers except IE I think, need confirmation though.
我认为适用于除 IE 之外的所有浏览器,但需要确认。
This supports content in iframes as well.
这也支持 iframe 中的内容。
Note, other examples I have seen, like the one above, are RECURSIVE which is potentially bad in javascript which can end in stack overflows, especially in a browser client which has limited memory for such things. Too much recursion can cause javascript to stop executing.
请注意,我见过的其他示例(如上面的示例)是 RECURSIVE,这在 javascript 中可能很糟糕,可能会导致堆栈溢出,尤其是在内存有限的浏览器客户端中。太多的递归会导致 javascript 停止执行。
If you don't believe me, try the examples hereyourself...
如果您不相信我,请自己尝试此处的示例...
If anyone would like to contribute, the code is 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;
};

