ejemplo - Insertar HTML en el nodo de texto con JavaScript
title html (4)
El siguiente artículo le da el código para reemplazar el texto con elementos HTML:
http://blog.alexanderdickson.com/javascript-replacing-text
Del artículo:
var matchText = function(node, regex, callback, excludeElements) {
excludeElements || (excludeElements = [''script'', ''style'', ''iframe'', ''canvas'']);
var child = node.firstChild;
do {
switch (child.nodeType) {
case 1:
if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) {
continue;
}
matchText(child, regex, callback, excludeElements);
break;
case 3:
child.data.replace(regex, function(all) {
var args = [].slice.call(arguments),
offset = args[args.length - 2],
newTextNode = child.splitText(offset);
newTextNode.data = newTextNode.data.substr(all.length);
callback.apply(window, [child].concat(args));
child = newTextNode;
});
break;
}
} while (child = child.nextSibling);
return node;
}
Uso:
matchText(document.getElementsByTagName("article")[0], new RegExp("//b" + searchTerm + "//b", "g"), function(node, match, offset) {
var span = document.createElement("span");
span.className = "search-term";
span.textContent = match;
node.parentNode.insertBefore(span, node.nextSibling);
});
Y la explicación:
Esencialmente, la forma correcta de hacerlo es ...
- Iterar sobre todos los nodos de texto.
- Encuentra la subcadena en los nodos de texto.
- Dividirlo en el offset.
- Inserte un elemento span entre la división.
Tengo un pequeño nodo de texto:
var node
Y quiero envolver un lapso alrededor de cada aparición de "lol".
node.nodeValue = node.nodeValue.replace(/lol/, "<span>lol</span>")
Imprime "<span>lol<span>"
cuando quiero "lol"
como elemento de intervalo.
Es posible que necesite un node
para que sea el nodo principal, de esa manera puede simplemente usar innerHTML:
node.innerHTML=node.childNodes[0].nodeValue.replace(/lol/, "<span>lol</span>");
Aquí node.childNodes[0]
refiere al nodo de texto real, y node
es su elemento contenedor.
La respuesta presentada por Andreas Josas es bastante buena. Sin embargo, el código tenía varios errores cuando el término de búsqueda apareció varias veces en el mismo nodo de texto. Aquí está la solución con esos errores corregidos y, además, el inserto se incluye en matchText para un uso y comprensión más fáciles. Ahora solo la nueva etiqueta se construye en la devolución de llamada y se devuelve a matchText mediante una devolución.
Función actualizada matchText con correcciones de errores:
var matchText = function(node, regex, callback, excludeElements) {
excludeElements || (excludeElements = [''script'', ''style'', ''iframe'', ''canvas'']);
var child = node.firstChild;
while (child) {
switch (child.nodeType) {
case 1:
if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1)
break;
matchText(child, regex, callback, excludeElements);
break;
case 3:
var bk = 0;
child.data.replace(regex, function(all) {
var args = [].slice.call(arguments),
offset = args[args.length - 2],
newTextNode = child.splitText(offset+bk), tag;
bk -= child.data.length + all.length;
newTextNode.data = newTextNode.data.substr(all.length);
tag = callback.apply(window, [child].concat(args));
child.parentNode.insertBefore(tag, newTextNode);
child = newTextNode;
});
regex.lastIndex = 0;
break;
}
child = child.nextSibling;
}
return node;
};
Uso:
matchText(document.getElementsByTagName("article")[0], new RegExp("//b" + searchTerm + "//b", "g"), function(node, match, offset) {
var span = document.createElement("span");
span.className = "search-term";
span.textContent = match;
return span;
});
Si desea insertar etiquetas de anclaje (enlace) en lugar de etiquetas de intervalo, cambie el elemento de creación a "a" en lugar de "intervalo", agregue una línea para agregar el atributo href a la etiqueta y agregue ''a'' a excludeElements Lista para que los enlaces no se creen dentro de los enlaces.
No decir que esta es una mejor respuesta, pero estoy publicando lo que hice para completar. En mi caso, ya he buscado o determinado las desviaciones del texto que necesitaba resaltar en un nodo #text en particular. Esto también aclara los pasos.
//node is a #text node, startIndex is the beginning location of the text to highlight, and endIndex is the index of the character just after the text to highlight
var parentNode = node.parentNode;
// break the node text into 3 parts: part1 - before the selected text, part2- the text to highlight, and part3 - the text after the highlight
var s = node.nodeValue;
// get the text before the highlight
var part1 = s.substring(0, startIndex);
// get the text that will be highlighted
var part2 = s.substring(startIndex, endIndex);
// get the part after the highlight
var part3 = s.substring(endIndex);
// replace the text node with the new nodes
var textNode = document.createTextNode(part1);
parentNode.replaceChild(textNode, node);
// create a span node and add it to the parent immediately after the first text node
var spanNode = document.createElement("span");
spanNode.className = "HighlightedText";
parentNode.insertBefore(spanNode, textNode.nextSibling);
// create a text node for the highlighted text and add it to the span node
textNode = document.createTextNode(part2);
spanNode.appendChild(textNode);
// create a text node for the text after the highlight and add it after the span node
textNode = document.createTextNode(part3);
parentNode.insertBefore(textNode, spanNode.nextSibling);