Comment vérifier si l'élément a des enfants en Javascript?

103

Question simple, j'ai un élément par lequel je saisis .getElementById (). Comment vérifier s'il a des enfants?

David
la source

Réponses:

194

Deux façons:

if (element.firstChild) {
    // It has at least one
}

ou la hasChildNodes()fonction:

if (element.hasChildNodes()) {
    // It has at least one
}

ou la lengthpropriété de childNodes:

if (element.childNodes.length > 0) { // Or just `if (element.childNodes.length)`
    // It has at least one
}

Si vous voulez seulement connaître les éléments enfants (par opposition aux nœuds de texte, aux nœuds d'attribut, etc.) sur tous les navigateurs modernes (et IE8 - en fait, même IE6), vous pouvez le faire: (merci Florian !)

if (element.children.length > 0) { // Or just `if (element.children.length)`
    // It has at least one element as a child
}

Cela repose sur la childrenpropriété, qui n'a pas été défini dans DOM1 , DOM2 , ou DOM3 , mais qui a un support quasi universel. (Cela fonctionne dans IE6 et plus et Chrome, Firefox et Opera au moins aussi loin que novembre 2012, lorsque cela a été écrit à l'origine.) Si vous prenez en charge des appareils mobiles plus anciens, assurez-vous de vérifier le support.

Si vous n'avez pas besoin du support IE8 et antérieur, vous pouvez également le faire:

if (element.firstElementChild) {
    // It has at least one element as a child
}

Cela repose sur firstElementChild. Comme children, il n'a pas non plus été défini dans DOM1-3, mais contrairement à childrence qu'il n'a pas été ajouté à IE avant IE9.

Si vous voulez vous en tenir à quelque chose de défini dans DOM1 (peut-être devez-vous prendre en charge des navigateurs vraiment obscurs), vous devez faire plus de travail:

var hasChildElements, child;
hasChildElements = false;
for (child = element.firstChild; child; child = child.nextSibling) {
    if (child.nodeType == 1) { // 1 == Element
        hasChildElements = true;
        break;
    }
}

Tout cela fait partie de DOM1 et est presque universellement pris en charge.

Il serait facile de résumer cela dans une fonction, par exemple:

function hasChildElement(elm) {
    var child, rv;

    if (elm.children) {
        // Supports `children`
        rv = elm.children.length !== 0;
    } else {
        // The hard way...
        rv = false;
        for (child = element.firstChild; !rv && child; child = child.nextSibling) {
            if (child.nodeType == 1) { // 1 == Element
                rv = true;
            }
        }
    }
    return rv;
}
TJ Crowder
la source
Oh, je ne savais pas que childrenc'était seulement ajouté dans DOM4. Sachant qu'il était pris en charge dans n'importe quel navigateur connu, je pensais que c'était à peu près DOM0 / 1.
Florian Margaine
Comment puis-je vérifier si un divélément a divune classe spécifique xyz?
Pooja Desai
firstChild et hasChildNodes renvoient n'importe quel nœud, pas seulement les enfants (nodeType == 1). Vous devriez corriger cela. ;-)
Adrian Maire
1
Jamais vu une condition de boucle comme for (child = element.firstChild; child; child = child.nextSibling ), voté. Merci TJ
NiCk Newman
2
@Aaron: Il est tout à fait possible de ne element.firstChildpas être nullquand element.children.lengthest 0: firstChildet cela concerne des nœuds comprenant des éléments, des nœuds de texte, des notes de commentaires, etc. childrenest purement une liste d' enfants d' élément . Sur les navigateurs modernes, vous pouvez utiliser à la firstElementChildplace.
TJ Crowder
8

Comme le mentionnent slashnick & bobince, hasChildNodes()retournera true pour les espaces (nœuds de texte). Cependant, je ne voulais pas de ce comportement, et cela a fonctionné pour moi :)

element.getElementsByTagName('*').length > 0

Edit : pour la même fonctionnalité, c'est une meilleure solution:

 element.children.length > 0

children[]est un sous-ensemble de childNodes[], contenant uniquement des éléments.

Compatibilité

c24w
la source
2

Vous pouvez vérifier si l'élément a des nœuds enfants element.hasChildNodes(). Méfiez-vous dans Mozilla, cela retournera vrai si le est un espace après la balise, vous devrez donc vérifier le type de balise.

https://developer.mozilla.org/En/DOM/Node.hasChildNodes

slashnick
la source
7
Pas seulement dans Mozilla. C'est un comportement correct; c'est IE qui se trompe.
bobince
2

Vous pouvez également effectuer les opérations suivantes:

if (element.innerHTML.trim() !== '') {
    // It has at least one
} 

Cela utilise la méthode trim () pour traiter les éléments vides qui n'ont que des espaces (auquel cas hasChildNodesrenvoie true) comme étant vides.

Démo JSBin

Danield
la source
Comment cela se comporte avec les commentaires HTML?
Victor Zamanian
1

En retard mais le fragment de document pourrait être un nœud:

function hasChild(el){
    var child = el && el.firstChild;
    while (child) {
        if (child.nodeType === 1 || child.nodeType === 11) {
            return true;
        }
        child = child.nextSibling;
    }
    return false;
}
// or
function hasChild(el){
    for (var i = 0; el && el.childNodes[i]; i++) {
        if (el.childNodes[i].nodeType === 1 || el.childNodes[i].nodeType === 11) {
            return true;
        }
    }
    return false;
}

Voir:
https://github.com/k-gun/so/blob/master/so.dom.js#L42
https://github.com/k-gun/so/blob/master/so.dom.js # L741

K-Gun
la source
1

Essayez la propriété childElementCount :

if ( element.childElementCount !== 0 ){
      alert('i have children');
} else {
      alert('no kids here');
}
Stirling
la source
0

Une isEmpty( <selector> )fonction réutilisable .
Vous pouvez également l'exécuter vers une collection d'éléments (voir exemple)

const isEmpty = sel =>
    ![... document.querySelectorAll(sel)].some(el => el.innerHTML.trim() !== "");

console.log(
  isEmpty("#one"), // false
  isEmpty("#two"), // true
  isEmpty(".foo"), // false
  isEmpty(".bar")  // true
);
<div id="one">
 foo
</div>

<div id="two">
 
</div>

<div class="foo"></div>
<div class="foo"><p>foo</p></div>
<div class="foo"></div>

<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>

renvoie true(et quitte la boucle) dès qu'un élément a un contenu quelconque à côté d'espaces ou de retours à la ligne.

Roko C. Buljan
la source
-9
<script type="text/javascript">

function uwtPBSTree_NodeChecked(treeId, nodeId, bChecked) 
{
    //debugger;
    var selectedNode = igtree_getNodeById(nodeId);
    var ParentNodes = selectedNode.getChildNodes();

    var length = ParentNodes.length;

    if (bChecked) 
    {
/*                if (length != 0) {
                    for (i = 0; i < length; i++) {
                        ParentNodes[i].setChecked(true);
                    }
    }*/
    }
    else 
    {
        if (length != 0) 
        {
            for (i = 0; i < length; i++) 
            {
                ParentNodes[i].setChecked(false);
            }
        }
    }
}
</script>

<ignav:UltraWebTree ID="uwtPBSTree" runat="server"..........>
<ClientSideEvents NodeChecked="uwtPBSTree_NodeChecked"></ClientSideEvents>
</ignav:UltraWebTree>
Govind Kumar Sahu
la source
Veuillez ne pas fournir uniquement des solutions basées sur le code. Aussi, pourquoi avez-vous commenté du code là-dedans?
Lee Taylor
Downvote: Ce code est obscur, une partie du code est inutile, il n'y a pas de commentaires ou d'explications et cela ressemble à un copier / coller. De plus, la partie XML n'a rien à voir ici.
Adrian Maire
2
Quelle est cette folie?
NiCk Newman