86 votes

getElementsByTagName () équivalent pour textNodes

Est-il possible d'obtenir la collection de tous les textNode objets dans un document?

getElementsByTagName() fonctionne très bien pour les Éléments, mais textNodes ne sont pas des Éléments.

Mise à jour: je me rends compte de ce qui peut être accompli par la marche dans les DOM - comme beaucoup de ci-dessous suggèrent. Je sais comment écrire un DOM-walker fonction qui ressemble à chaque nœud dans le document. J'espérais qu'il y a certains navigateur natif façon de le faire. Après tout, c'est un peu étrange que je peux obtenir tout l' <input>s avec un seul appel intégrée, mais pas tous, textNodes.

126voto

Anurag Points 66470

Mise à jour:

J'ai souligné certains de base des tests de performance pour chacun de ces 6 méthodes de plus de 1000 pistes. getElementsByTagName est le plus rapide, mais il le fait d'une moitié de l'emploi, car il ne permet pas de sélectionner tous les éléments, mais seulement un type particulier de tag ( je pense que p) et aveuglément suppose que sa firstChild est un élément de texte. Il pourrait être un peu imparfait, mais sa il y à des fins de démonstration et de comparer son rendement à l' TreeWalker. Exécuter les tests vous-mêmes sur jsfiddle pour voir les résultats.

  1. À l'aide d'un TreeWalker
  2. Personnalisé Itératif De La Traversée
  3. Personnalisé Récursive De La Traversée
  4. Requête Xpath
  5. querySelectorAll
  6. getElementsByTagName

Supposons un instant qu'il y est une méthode qui vous permet d'obtenir tous Text des nœuds en mode natif. Vous auriez encore à parcourir chaque nœud de texte et appelez - node.nodeValue pour obtenir le texte comme vous le feriez avec n'importe quel Nœud DOM. Donc, la question de la performance n'est pas avec une itération à travers les nœuds de texte, mais une itération à travers tous les nœuds qui ne sont pas du texte et de la vérification de leur type. Je dirais (sur la base des résultats) TreeWalker effectue aussi rapide que l' getElementsByTagName, si pas plus rapide (même avec getElementsByTagName jouer les handicapés).

Couru chaque test 1000 fois.

Méthode Total ms ms Moyenne
--------------------------------------------------
document.TreeWalker 301 0.301
Itératif Traverser 769 0.769
Récursive Traverser 7352 7.352
Requête XPath 1849 1.849
querySelectorAll 1725 1.725
getElementsByTagName 212 0.212

La Source de chaque méthode:

TreeWalker

function nativeTreeWalker() {
    var walker = document.createTreeWalker(
        document.body, 
        NodeFilter.SHOW_TEXT, 
        null, 
        false
    );

    var node;
    var textNodes = [];

    while(node = walker.nextNode()) {
        textNodes.push(node.nodeValue);
    }
}

Récursif De L'Arbre Transversal

function customRecursiveTreeWalker() {
    var result = [];

    (function findTextNodes(current) {
        for(var i = 0; i < current.childNodes.length; i++) {
            var child = current.childNodes[i];
            if(child.nodeType == 3) {
                result.push(child.nodeValue);
            }
            else {
                findTextNodes(child);
            }
        }
    })(document.body);
}

Itérative De L'Arbre Transversal

function customIterativeTreeWalker() {
    var result = [];
    var root = document.body;

    var node = root.childNodes[0];
    while(node != null) {
        if(node.nodeType == 3) { /* Fixed a bug here. Thanks @theazureshadow */
            result.push(node.nodeValue);
        }

        if(node.hasChildNodes()) {
            node = node.firstChild;
        }
        else {
            while(node.nextSibling == null && node != root) {
                node = node.parentNode;
            }
            node = node.nextSibling;
        }
    }
}

querySelectorAll

function nativeSelector() {
    var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */
    var results = [];
    var child;
    for(var i = 0; i < elements.length; i++) {
        child = elements[i].childNodes[0];
        if(elements[i].hasChildNodes() && child.nodeType == 3) {
            results.push(child.nodeValue);
        }
    }
}

getElementsByTagName (handicap)

function getElementsByTagName() {
    var elements = document.getElementsByTagName("p");
    var results = [];
    for(var i = 0; i < elements.length; i++) {
        results.push(elements[i].childNodes[0].nodeValue);
    }
}

XPath

function xpathSelector() {
    var xpathResult = document.evaluate(
        "//*/text()", 
        document, 
        null, 
        XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
        null
    );

    var results = [], res;
    while(res = xpathResult.iterateNext()) {
        results.push(res.nodeValue);  /* Fixed a bug here. Thanks @theazureshadow */
    }
}

Aussi, vous pourriez trouver cette discussion utile - http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node

5voto

Brett Zamir Points 5355

Je sais que vous avez spécifiquement demandé une collection, mais si vous vouliez simplement dire cela de manière informelle et que vous ne vouliez pas qu'ils soient tous unis dans une grande chaîne, vous pouvez utiliser:

 var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
 

... avec le premier élément étant l'approche standard DOM3. Notez cependant que innerText semble exclure le contenu des balises de script ou de style dans les implémentations qui le prennent en charge (au moins IE et Chrome), tandis que textContent inclut (dans Firefox et Chrome).

1voto

Alex Ciminian Points 4648

Regarde ça:
http://refactormycode.com/codes/341-jquery-all-descendent-text-nodes-within-a-node .

Consultez également la propriété nodeType du DOM.

1voto

kennebec Points 33886
  document.deepText= function(hoo, fun){
        var A= [], tem;
        if(hoo){
            hoo= hoo.firstChild;
            while(hoo!= null){
                if(hoo.nodeType== 3){
                    if(typeof fun== 'function'){
                        tem= fun(hoo);
                        if(tem!= undefined) A[A.length]= tem;
                    }
                    else A[A.length]= hoo;
                }
                else A= A.concat(document.deepText(hoo, fun));
                hoo= hoo.nextSibling;
            }
        }
        return A;
    }
 

/ * Vous pouvez renvoyer un tableau de tous les nœuds de texte dépendants d’un élément parent, ou vous pouvez passer une fonction et faire quelque chose (trouver ou remplacer ou autre chose) au texte en place.

Cet exemple renvoie le texte des noeuds textuels autres que des espaces blancs dans le corps:

 var A= document.deepText(document.body, function(t){
    var tem= t.data;
    return /\S/.test(tem)? tem: undefined;
});
alert(A.join('\n'))
 

* / Pratique pour rechercher et remplacer, mettre en surbrillance, etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X