替换元素中的内容而不替换 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>