Puis-je compter sur la création implicite de la balise `tbody`?

<!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script> <script type="text/javascript"> $( document ).ready( function(){ $( "table > tr > td > input[id]" ).each( function( i, element ){ alert( $( element ).attr( 'id' ) ) }); }); </script> </head> <body> <form> <table> <tr><td>City:</td><td><input type="text" id="city" name="city" /></td></tr> <tr><td>state:</td><td><input type="text" id="state" name="state" /></td></tr> </table><br /> <input type="submit" value="OK"/> </form> </body> </html> 

Lorsque je l'écris de cette façon, cela ne fonctionne pas parce que mon navigateur crée automatiquement une étiquette tbody donc je dois écrire

  $( "table tr > td > input[id]" ).each( function( i, element ){ alert( $( element ).attr( 'id' ) ) }); 

ou

  $( "table > tbody > tr > td > input[id]" ).each( function( i, element ){ alert( $( element ).attr( 'id' ) ) }); 

Puis-je compter sur la création implicite de la balise tbody ou ne devrais-je pas compter sur cela?


Ajouté pour expliquer mon commentaire à la réponse de Tim Down:

 <!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js"></script> <script type="text/javascript"> $( document ).ready( function() { var ids = []; var form = document.forms[0]; var formEls = form.elements; var f_len = formEls.length; for ( var i = 0; i < f_len; ++i ) { ids.push( formEls[i].id ); } var data = [ [ 'one', 'two', 'thre' ], [ 'four', 'five', 'six' ] ]; var ids_len = ids.length; for ( i = 0; i < ids_len; i++ ){ $( "#" + ids[i] ).autocomplete({ source: data[i] }); } }); </script> </head> <body> <form> <table> <tr><td>A:</td><td><input type="text" id="a" name="a" /></td></tr> <tr><td>B:</td><td><input type="text" id="b" name="b" /></td></tr> </table><br /> <input type="submit" value="OK"/> </form> </body> </html> 

Lorsque je l'exécute, la Webconsole me montre un avertissement quelque chose comme ceci:
Empty string to getElementById () is passed.
Une chaîne forme les chaînes renvoyées par form.elements est vide.

Il ne s'agit pas de se fier à la création ou à la création automatique.

La question est si c'est obligatoire ou non.

Selon le projet HTML5:

La balise de début d'un élément tbody peut être omise si la première chose à l'intérieur de l'élément tbody est un élément tr et si l'élément n'est pas immédiatement précédé d'un élément tbody ou d'un élément tfoot dont l'étiquette finale a été omise.

La balise d'extrémité d'un élément tbody peut être omise si l'élément tbody est immédiatement suivi d'un élément tbody ou tfoot ou s'il n'y a plus de contenu dans l'élément parent.

Donc, vous pouvez effectivement omettre si votre code répond aux conditions ci-dessus, sinon il est nécessaire.

Comme d'autres personnes ont souligné, même si cela est nécessaire, et l'analyseur html ne le trouvera pas parce que vous ne l'avez pas écrit, il sera inséré dans le DOM pour vous, comme indiqué dans les spécifications html5.

Cela dit, en règle générale, ne comptez jamais que personne ne crée quelque chose automatiquement pour vous! (voir ci-dessous)

Donc, même si le navigateur le crée pour vous, cela ne signifie pas que les navigateurs plus récents ou la nouvelle version du même navigateur suivront de la même manière, et votre code pourrait alors être cassé.


En outre, votre JS pourrait être optimisé.

 $( document ).ready( function(){ $( "td > input[id]" ).each( function( i, element ){ alert( element.id ); }); }); 
  1. Toujours écrire des points-virgules à la fin des déclarations. Ne comptez pas sur le moteur JS pour les écrire! (voir au dessus).

  2. Il n'est pas nécessaire d'appeler la fonction jQuery et de créer une objet jQuery hors de l'élément juste pour appeler la méthode attr() pour obtenir l'identifiant. JavaScript a déjà la méthode id() pour récupérer l'identifiant.

  3. Si votre balisage actuel est comme celui que vous avez posté dans votre réponse, vous pouvez écrire le sélecteur jQuery comme ceci: table input[id] . Ou, si vous avez des tables imbriquées td > input[id] comme suggéré gilly3.

Je ne suis pas d'accord avec la réponse @ spike, au moins si on parle d'analyse HTML ordinaire (n'utilisant pas innerHTML ). Chaque tr devient un enfant de tbody implicitement créé à tbody que ce ne soit déjà un enfant d'un autre thead , tbody ou tfoot . jQuery.support.tbody est destiné aux tables créées à l'aide de innerHTML ou probablement d'autres méthodes DOM. Si vous omettez <tbody> dans le balisage, il est toujours inséré.

L'élément tbody n'est pas facultatif, il a simplement la tbody ouverture et de fermeture optionnelle. Le doute sur la création implicite de tbody est une erreur similaire quant au doute sur la création implicite d' html ou d'élément body .

Pour prouver ce que j'ai dit, la spécification HTML4 interdit tous les éléments <tr> comme enfants directs de <table> s:

 <!ELEMENT TABLE - - (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)> 

La spécification HTML5 indique que <tr> peut être, dans certaines circonstances, un enfant de <table> , mais cela ne s'applique qu'aux DOM, et non à l'analyse de balisage:

8.2.5.4.9 Le mode d'insertion "en table"

Une étiquette de départ dont le nom de tag est l'un de: "td", "th", "tr"

Agis comme si un jeton de tag de départ avec le nom de la balise "tbody" avait été vu , puis retrait le jeton actuel.

Vous ne pouvez pas compter sur le navigateur qui le crée automatiquement. La spécification HTML indique qu'il devrait être facultatif, mais je crois que Firefox et IE le créent comme vous l'avez vu. Vous pouvez utiliser cette propriété pour savoir comment le navigateur se comporte (en fait, il ne sera pas ajouté)

 jQuery.support.tbody 

Découvrez cet exemple dans un tas de navigateurs: http://jsfiddle.net/CuBX9/1/

http://api.jquery.com/jQuery.support/

Pour se défendre contre la nature facultative de l'étiquette tbody (et par extension, quel que soit le navigateur décide de faire avec son moteur sélecteur), vous pouvez écrire les deux sélecteurs:

 $('table > tbody > tr > td, table > tr > td').find('input[type="text"]') 

Mais c'est honnêtement un peu un hack. Vous feriez mieux d'ajouter explicitement l'élément <tbody> et de l'avoir terminé.

Sinon, considérez pourquoi vous utilisez même le combinateur enfant.

Dans votre exemple, je ne sais pas pourquoi vous devriez utiliser un sélecteur aussi compliqué. Vous n'êtes pas des tables de nidification (donc pas besoin d'utiliser le combinateur enfant), et vous n'avez que deux entrées de texte. Si tout ce que vous voulez, ce sont les deux champs de saisie de texte, utilisez simplement $('input[type="text"]') .

Vous pouvez simplement utiliser le sélecteur descendant au lieu du sélecteur parent ou une combinaison s'il est important que l'entrée soit un enfant d'un td . De cette façon, cela n'aurait pas d'importance. À l'inverse, vous pouvez également mettre les éléments tbody dans la chaîne mère / enfant intégrale sans vous inquiéter.

 $('table td > input[id]') 

Si vous essayez de saisir toutes les entrées dans l'élément <form> qui contient le tableau, il s'agit d'une mauvaise approche, car il existe une approche DOM simple qui existe depuis l'aube de JavaScript et fonctionne dans tous les principaux navigateurs scriptables Jamais sorti. Un élément de formulaire a une propriété elements qui est une collection de tous les contrôles de formulaire sous la forme. Tout ce dont vous avez besoin, c'est de saisir le formulaire, que vous pouvez faire de la manière qui vous convient le mieux:

 var form = document.forms[0]; var formEls = form.elements; for (var i = 0, len = formEls.length; i < len; ++i) { alert(formEls[i].id); }