替换元素中的内容而不替换 HTML
Replace content in elements without replacing HTML
假设我有以下 HTML 结构:
<test>
<div>
This is a test
</div>
<div>
This is another test
<button>
Button test
</button>
</div>
</test>
现在我用下面的jQuery代码来替换,例如'T':
$("test *").each(function(index, value) {
$(this).html($(this).html().replace(new RegExp('t', "ig"), "<b>t</b>"));
});
但是,这会导致以下 HTML 结构(这出乎意料,请参阅 <button>
标记,它破坏了我的 HTML):
<test>
<div>
<b>T</b>his is a <b>t</b>es<b>t</b>
</div>
<div>
<b>T</b>his is ano<b>t</b>her <b>t</b>es<b>t</b>
<bu<b>t</b><b>t</b>on>
Bu<b>t</b><b>t</b>on <b>t</b>es<b>t</b>
</bu<b>t</b><b>t</b>on>
</div>
</test>
我要实现的是:
<test>
<div>
<b>T</b>his is a <b>t</b>es<b>t</b>
</div>
<div>
<b>T</b>his is ano<b>t</b>her <b>t</b>es<b>t</b>
<button>
Bu<b>t</b><b>t</b>on <b>t</b>es<b>t</b>
</button>
</div>
</test>
基本上,我想在整个元素内进行替换,但保留 HTML 标签和所有 HTML 属性。
您似乎想将所有 T 字符加粗,但您的正则表达式也符合您的 html。
对innerText而不是innerHTML执行操作。我已经有几年没有使用 jQuery 了,所以可能有更好的方法来做这件事,但应该这样做。
$("test *").each(function(index, value) {
$(this)[0].innerText = $(this)[0].innerText.replace(new RegExp('t', "ig"), "<b>t</b>");
});
您可以避免 jQuery,而不必特别担心 button
(因为如果您点击 input
标签等,那将无济于事),如果您更换仅在文本节点中。
我们寻找文本节点,在每种情况下都会发现我们看到的第一个 "t"(或 "T"),将其包装在 <b>
中,然后继续。同一区域的其他匹配项将在后面的文本节点中找到。
var wrapText = "t";
var el = document.getElementsByTagName('test')[0];
replaceIn(el);
function replaceIn(el) {
var i = 0;
while (i < el.childNodes.length) {
var cn = el.childNodes[i];
if (cn.nodeType == 3) { // text node
var p = cn.textContent.toLowerCase().indexOf(wrapText);
if (p >= 0) {
var range = new Range();
range.setStart(cn, p);
range.setEnd(cn, p + 1);
range.surroundContents(document.createElement('b'));
++i; // don't check the <b> we just created
}
}
else {
replaceIn(cn);
}
++i;
}
}
<test>
<div>
This is a test
</div>
<div>
This is another test
<button>
Button test
</button>
<input value="input test" />
</div>
</test>
使用 jQuery 这可以很简单地实现。创建一个函数,该函数采用您希望更新其文本的元素、您希望替换的文本以及您希望将其替换为的内容。然后在您要删除子 HTML 的函数中,并使用替换文本更新元素中剩余的任何文本。然后,您可以递归地 运行 为每个子元素执行相同的函数,然后再将它们追加回父元素。
function replaceTextInHtmlBlock($element, replaceText, replaceWith)
{
var $children = $element.children().detach();
//Now that there should only be text nodes left do your replacement
$element.html($element.text().replace(replaceText, replaceWith));
//Run this function for each child element
$children.each(function(index, me){
replaceTextInHtmlBlock($(me), replaceText, replaceWith);
});
$element.append($children);
}
$(document).ready(function(){
$("#doReplace").click(function(){
replaceTextInHtmlBlock($("#top"), $("#replace").val(), $("#with").val());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top">
<div>
This is a test
</div>
<div>
This is another test
<button>
Button test
</button>
</div>
</div>
<br />
<br />
<div>
<label>Replace</label>
<input id="replace" value="t" />
<label>with</label>
<input id="with" value="<strong>t</strong>" />
<button id="doReplace">Do Replace</button>
</div>
假设我有以下 HTML 结构:
<test>
<div>
This is a test
</div>
<div>
This is another test
<button>
Button test
</button>
</div>
</test>
现在我用下面的jQuery代码来替换,例如'T':
$("test *").each(function(index, value) {
$(this).html($(this).html().replace(new RegExp('t', "ig"), "<b>t</b>"));
});
但是,这会导致以下 HTML 结构(这出乎意料,请参阅 <button>
标记,它破坏了我的 HTML):
<test>
<div>
<b>T</b>his is a <b>t</b>es<b>t</b>
</div>
<div>
<b>T</b>his is ano<b>t</b>her <b>t</b>es<b>t</b>
<bu<b>t</b><b>t</b>on>
Bu<b>t</b><b>t</b>on <b>t</b>es<b>t</b>
</bu<b>t</b><b>t</b>on>
</div>
</test>
我要实现的是:
<test>
<div>
<b>T</b>his is a <b>t</b>es<b>t</b>
</div>
<div>
<b>T</b>his is ano<b>t</b>her <b>t</b>es<b>t</b>
<button>
Bu<b>t</b><b>t</b>on <b>t</b>es<b>t</b>
</button>
</div>
</test>
基本上,我想在整个元素内进行替换,但保留 HTML 标签和所有 HTML 属性。
您似乎想将所有 T 字符加粗,但您的正则表达式也符合您的 html。
对innerText而不是innerHTML执行操作。我已经有几年没有使用 jQuery 了,所以可能有更好的方法来做这件事,但应该这样做。
$("test *").each(function(index, value) {
$(this)[0].innerText = $(this)[0].innerText.replace(new RegExp('t', "ig"), "<b>t</b>");
});
您可以避免 jQuery,而不必特别担心 button
(因为如果您点击 input
标签等,那将无济于事),如果您更换仅在文本节点中。
我们寻找文本节点,在每种情况下都会发现我们看到的第一个 "t"(或 "T"),将其包装在 <b>
中,然后继续。同一区域的其他匹配项将在后面的文本节点中找到。
var wrapText = "t";
var el = document.getElementsByTagName('test')[0];
replaceIn(el);
function replaceIn(el) {
var i = 0;
while (i < el.childNodes.length) {
var cn = el.childNodes[i];
if (cn.nodeType == 3) { // text node
var p = cn.textContent.toLowerCase().indexOf(wrapText);
if (p >= 0) {
var range = new Range();
range.setStart(cn, p);
range.setEnd(cn, p + 1);
range.surroundContents(document.createElement('b'));
++i; // don't check the <b> we just created
}
}
else {
replaceIn(cn);
}
++i;
}
}
<test>
<div>
This is a test
</div>
<div>
This is another test
<button>
Button test
</button>
<input value="input test" />
</div>
</test>
使用 jQuery 这可以很简单地实现。创建一个函数,该函数采用您希望更新其文本的元素、您希望替换的文本以及您希望将其替换为的内容。然后在您要删除子 HTML 的函数中,并使用替换文本更新元素中剩余的任何文本。然后,您可以递归地 运行 为每个子元素执行相同的函数,然后再将它们追加回父元素。
function replaceTextInHtmlBlock($element, replaceText, replaceWith)
{
var $children = $element.children().detach();
//Now that there should only be text nodes left do your replacement
$element.html($element.text().replace(replaceText, replaceWith));
//Run this function for each child element
$children.each(function(index, me){
replaceTextInHtmlBlock($(me), replaceText, replaceWith);
});
$element.append($children);
}
$(document).ready(function(){
$("#doReplace").click(function(){
replaceTextInHtmlBlock($("#top"), $("#replace").val(), $("#with").val());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top">
<div>
This is a test
</div>
<div>
This is another test
<button>
Button test
</button>
</div>
</div>
<br />
<br />
<div>
<label>Replace</label>
<input id="replace" value="t" />
<label>with</label>
<input id="with" value="<strong>t</strong>" />
<button id="doReplace">Do Replace</button>
</div>