Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I rely on the implicit creation of the `<tbody>` tag?

<!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>

When I write it this way, it doesn’t work because my browser automatically creates a <tbody> tag. So I have to write:

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

or:

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

Can I rely on the implicit creation of the <tbody> tag, or should I not count on that?

Edit: added to explain my comment to Tim Down’s answer:

<!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>

When I run this, the web console shows me a warning like this: Empty string to getElementById() is passed. One of the strings returned by form.elements is empty.

like image 600
sid_com Avatar asked Sep 10 '11 14:09

sid_com


1 Answers

It's not a question on relying on it being automatically created or not.

The question is if it's mandatory or not.

According to the HTML5 draft:

A tbody element's start tag may be omitted if the first thing inside the tbody element is a tr element, and if the element is not immediately preceded by a tbody thead, or tfoot element whose end tag has been omitted.

A tbody element’s end tag may be omitted if the tbody element is immediately followed by a tbody or tfoot element, or if there is no more content in the parent element.

So you can actually omit it if your code met the above conditions, otherwise it is needed.

As other people pointed out, even if it is needed, and the html parser won't find it because you didn't write it, it will be inserted into the DOM for you, as stated in the html5 specs.

This said, as a rule of thumb, never rely on anyone creating something automatically for you! (see below)

So even if the browser will create it for you, this doesn't mean newer browsers or new version of the same browser will follow the same way, and your code may become broken then.


Also, your JS could be optimized.

$( document ).ready( function(){
    $( "td > input[id]" ).each( function( i, element ){ 
        alert( element.id );
    });
});
  1. Always write semicolons at the end of statements. Don't rely on the JS engine write them for you!!! (see above).

  2. No need to call the jQuery function and create a jQuery object out of element just to call the attr() method to get the id. JavaScript already has the id() method to retrieve the id.

  3. If your actual markup is like the one you posted in your answer, you could write the jQuery selector like this: table input[id]. Or, if you have nested tables td > input[id] like gilly3 suggested.

like image 88
Jose Faeti Avatar answered Sep 28 '22 06:09

Jose Faeti