¿Cómo selecciono nodos de texto con jQuery?
Me gustaría obtener todos los nodos de texto descendientes de un elemento, como una colección jQuery. ¿Cuál es la mejor manera de hacer eso?
jQuery no tiene una función conveniente para esto. Debe combinar contents()
, que proporcionará solo nodos secundarios pero incluirá nodos de texto, con find()
, que proporcionará todos los elementos descendientes pero ningún nodo de texto. Esto es lo que se me ocurrió:
var getTextNodesIn = function(el) {
return $(el).find(":not(iframe)").addBack().contents().filter(function() {
return this.nodeType == 3;
});
};
getTextNodesIn(el);
Nota: si está utilizando jQuery 1.7 o una versión anterior, el código anterior no funcionará. Para solucionar este problema, reemplácelo addBack()
con andSelf()
. andSelf()
está en desuso a partir de addBack()
1.8 en adelante.
Esto es algo ineficiente en comparación con los métodos DOM puros y tiene que incluir una solución fea para la sobrecarga de su función por parte de jQuerycontents()
(gracias a @rabidsnail en los comentarios por señalarlo), por lo que aquí hay una solución que no es de jQuery y que utiliza una función recursiva simple. ElincludeWhitespaceNodes
parámetro controla si los nodos de texto de espacios en blanco se incluyen o no en la salida (en jQuery se filtran automáticamente).
Actualización: se corrigió el error cuando includeWhitespaceNodes es falso.
function getTextNodesIn(node, includeWhitespaceNodes) {
var textNodes = [], nonWhitespaceMatcher = /\S/;
function getTextNodes(node) {
if (node.nodeType == 3) {
if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
textNodes.push(node);
}
} else {
for (var i = 0, len = node.childNodes.length; i < len; ++i) {
getTextNodes(node.childNodes[i]);
}
}
}
getTextNodes(node);
return textNodes;
}
getTextNodesIn(el);
Jauco publicó una buena solución en un comentario, así que la copio aquí:
$(elem)
.contents()
.filter(function() {
return this.nodeType === 3; //Node.TEXT_NODE
});
$('body').find('*').contents().filter(function () { return this.nodeType === 3; });