¿Cómo selecciono nodos de texto con jQuery?

Resuelto Christian Oudard asked hace 15 años • 12 respuestas

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?

Christian Oudard avatar Nov 18 '08 20:11 Christian Oudard
Aceptado

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);
Tim Down avatar Dec 09 '2010 15:12 Tim Down

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
  });
Christian Oudard avatar Nov 18 '2008 13:11 Christian Oudard
$('body').find('*').contents().filter(function () { return this.nodeType === 3; });
He Nrik avatar Oct 19 '2011 16:10 He Nrik