Можно ли положиться на неявное создание тега <tbody>? - PullRequest
13 голосов
/ 10 сентября 2011
<!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>

Когда я пишу это таким образом, это не работает, потому что мой браузер автоматически создает тег <tbody>.Поэтому я должен написать:

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

или:

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

Могу ли я положиться на неявное создание тега <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 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>

Когда я запускаю это, веб-консоль показывает мне предупреждение, подобное этому: Empty string to getElementById() is passed. Одна из строк, возвращаемых form.elements пусто.

Ответы [ 6 ]

7 голосов
/ 10 сентября 2011

Вопрос не в том, полагаться на то, что он создается автоматически или нет.

Вопрос в том, является ли он обязательным или нет.

Согласно проекту HTML5:

Начальный тег элемента tbody может быть опущен, если первым элементом внутри элемента tbody является элемент tr, и если этому элементу непосредственно не предшествует thead thebody или элемент tfoot, конечный тег которого был опущен.

Конечный тег элемента tbody может быть опущен, если за элементом tbody сразу следует элемент tbody или tfoot, или если в родительском элементе больше нет содержимого.

Таким образом, вы можете на самом делеопустите его, если ваш код удовлетворяет вышеуказанным условиям, в противном случае он необходим.

Как указали другие люди, даже если он необходим, и анализатор html не найдет его, потому что вы его не написали,он будет вставлен в DOM для вас, как указано в спецификации html5.

При этом, как правило, никогда не полагается на то, что кто-то создаст что-то автоматическое.для вас! (см. ниже)

Таким образом, даже если браузер создаст его для вас, это не означает, что новые браузеры или новая версия того же браузера будут следовать тем же путем, и вашитогда код может быть поврежден.


Кроме того, ваш JS может быть оптимизирован.

$( document ).ready( function(){
    $( "td > input[id]" ).each( function( i, element ){ 
        alert( element.id );
    });
});
  1. Всегда пишите точки с запятой в конце операторов. Не полагайтесь на движок JS, пишите их для вас !!! (см. Выше).

  2. Нет необходимости вызывать функцию jQuery и создавать объект jQueryвне элемента просто вызвать метод attr(), чтобы получить идентификатор.В JavaScript уже есть метод id() для получения идентификатора.

  3. Если ваша фактическая разметка похожа на ту, которую вы опубликовали в своем ответе, вы можете написать селектор jQuery следующим образом: table input[id].Или, если у вас есть вложенные таблицы td > input[id], как предложено в gilly3.

4 голосов
/ 10 сентября 2011

Я не согласен с ответом @ spike, по крайней мере, если мы говорим об обычном разборе HTML (без использования innerHTML).Каждый tr становится потомком неявно созданного tbody, если только он не является потомком другого thead, tbody или tfoot.jQuery.support.tbody для таблиц, созданных с использованием innerHTML или, возможно, других методов DOM или около того.Если вы опустите <tbody> в разметке, он всегда вставляется.

Элемент tbody не является обязательным, он просто имеет необязательный как открывающий, так и закрывающий тег.Сомневаться в неявном создании tbody является такой же ошибкой, как и сомнение в неявном создании элемента html или body.

Чтобы доказать то, что я сказал, спецификация HTML4 запрещает любые элементы <tr> какпрямые потомки <table> s:

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

Спецификация HTML5 гласит, что <tr> может при определенных обстоятельствах быть потомком <table>, однако это относится только к DOM, а не к разбору разметки:

8.2.5.4.9 Режим вставки "в таблицу"

...

Начальный тег, имя тега которого одно из: "td","th", "tr"

Действуйте так, как если бы был замечен маркер начального тега с именем тега "tbody" , затем повторно обработайте текущий токен.

3 голосов
/ 10 сентября 2011

Чтобы защитить от необязательного характера тега tbody (и, соответственно, независимо от того, что браузер решит сделать со своим механизмом выбора), вы можете записать оба переключателя:

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

Но это, честно говоря, немного хак. Вам лучше явно добавить элемент <tbody> и покончить с ним.

В качестве альтернативы подумайте, почему вы вообще используете детский комбинатор.

В вашем примере, я не знаю, почему вам нужно использовать такой сложный селектор. Вы не вложенные таблицы (поэтому не нужно использовать дочерний комбинатор), и у вас есть только два ввода текста. Если вам нужны только два поля ввода текста, просто используйте $('input[type="text"]').

3 голосов
/ 10 сентября 2011

Вы не можете полагаться на браузер, автоматически создающий его. Спецификация HTML говорит, что она должна быть необязательной, хотя я считаю, что Firefox и IE создают ее, как вы видели. Вы можете использовать это свойство, чтобы узнать, как ведет себя браузер (true означает, что он не будет добавлен)

jQuery.support.tbody

Посмотрите на этот пример в нескольких браузерах: http://jsfiddle.net/CuBX9/1/

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

1 голос
/ 11 сентября 2011

Если вы пытаетесь заполучить все входные данные в элементе <form>, который содержит таблицу, это неправильный подход, поскольку существует простой подход DOM, который существовал с момента появления JavaScript и работает во всехосновные скриптовые браузеры когда-либо выпускались.Элемент формы имеет свойство elements, которое представляет собой совокупность всех элементов управления формы внутри формы.Все, что вам нужно, это получить форму, которую вы можете сделать любым подходящим для вас способом:

var form = document.forms[0];
var formEls = form.elements;
for (var i = 0, len = formEls.length; i < len; ++i) {
    alert(formEls[i].id);
}
1 голос
/ 10 сентября 2011

Вы можете просто использовать селектор-потомок вместо родительского селектора или какую-либо комбинацию, если важно, чтобы вход был дочерним по отношению к td. Таким образом, это не имеет значения. И наоборот, вы также можете просто вставить элементы tbody и использовать полную цепочку родитель / потомок, не беспокоясь.

$('table td > input[id]') 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...