jquery - texto - Reemplazar contenido en elementos sin reemplazar HTML
reemplazar html jquery (3)
Supongamos que tengo la siguiente estructura HTML:
<test>
<div>
This is a test
</div>
<div>
This is another test
<button>
Button test
</button>
</div>
</test>
Ahora uso el siguiente código jQuery para reemplazar, por ejemplo, ''T'':
$("test *").each(function(index, value) {
$(this).html($(this).html().replace(new RegExp(''t'', "ig"), "<b>t</b>"));
});
Sin embargo, esto da como resultado la siguiente estructura HTML (que es inesperada, vea la etiqueta <button>
, que rompe mi 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>
Lo que quiero lograr es:
<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>
Básicamente, quiero reemplazar dentro de todo el elemento pero conservar las etiquetas HTML y todos los atributos HTML.
Con jQuery esto podría lograrse de forma bastante simple. Cree una función que tome el elemento del que desea actualizar el texto, el texto que desea reemplazar y con qué desea reemplazarlo. Luego, en la función, desea eliminar el código HTML hijo y actualizar el texto restante en el elemento con el texto de reemplazo. Luego puede ejecutar de forma recursiva esta misma función para cada uno de los elementos secundarios antes de volver a agregarlos al elemento principal.
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>
Parece que quieres poner en negrita todos los caracteres T, pero tu expresión regular también está capturando tu html.
Realice la operación en innerText en lugar de innerHTML. No he usado jQuery en un par de años, así que podría haber una manera más óptima de hacerlo, pero esto debería hacerlo.
$("test *").each(function(index, value) {
$(this)[0].innerText = $(this)[0].innerText.replace(new RegExp(''t'', "ig"), "<b>t</b>");
});
Puede evitar jQuery, y no preocuparse por el button
en particular (ya que eso no ayudará si toca una etiqueta de input
, etc.), si reemplaza solo en nodos de texto.
Buscamos nodos de texto, en cada caso detectamos la primera "t" (o "T") que vemos, lo envolvemos en <b>
y seguimos adelante. Se encontrarán otras coincidencias en la misma área en los nodos de texto posteriores.
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>