Это нормально, что JavaScript может создать иначе недействительный DOM?

Несколько случайно я обнаружил, что промежуток, вставленный непосредственно внутри тела, остается на месте, когда выполняется с JavaScript (insertBefore), где такой недопустимый DOM, если он создан с буквальным HTML, приводит к тому, что промежуток помещается перед всей таблицей.

Я ожидал либо то же поведение, что и с буквенным HTML-кодом или некоторыми исключениями DOM.

например. этот HTML

<table>
    <thead><tr><th>Table Header</th></td></thead>
    <tbody>
        <span>from HTML &rarr; goes up</span>
        <tr><td>Table Contents</td></tr>
    </tbody>
</table>

с этим JavaScript:

var span = document.createElement('span'),
    tbody = document.querySelector('tbody');
span.innerHTML = 'Created with JS &rarr; stays in place';
tbody.insertBefore(span, tbody.querySelector('tr'));

отображает "Создано с JS → остается на месте" между заголовком и первой строкой; исходный, буквенный, диапазон перемещается за пределы таблицы.

Является ли это нормальным, и могу ли/я должен рассчитывать на это? (Он ведет себя одинаково в FF, Chrome, Opera, IE >= 9 (не тестируется ниже)).

Кроме того, есть ли способ запросить DOM, будет ли контент определенного типа (при нормальных обстоятельствах) действительным в определенный момент в DOM? Это на самом деле то, что я хотел сделать, когда узнал об этом причуде (что это, imho).

Скрипка здесь: http://jsfiddle.net/xr37g9kw/2/

Ответы

Ответ 1

Что касается "это нормально, и я могу/должен рассчитывать на это?" К сожалению, да. Но в основном вы должны знать о типах node, с которыми вы работаете. NB, в случае table существует несколько не очень известных методов DOM (HTMLTableElement.rows. InsertRow() и т.д.).

Что касается "есть ли способ запросить DOM, будет ли контент определенного типа (при нормальных обстоятельствах) действительным в определенной точке DOM?" ничего не было встроено для этой конкретной цели, но вы можете использовать одну собственную функцию JavaScript → DOM API: вы можете позволить браузеру повторно разделить фрагмент HTML "буквально". Да, я говорю о innerHTML.

В вашей скрипте добавление ** tbody.outerHTML = tbody.outerHTML ** "исправляет" структуру, поэтому вы могли гипотетически взять какой-то DOM node, посмотрите на его дерево DOM, клон, "переубедите" его и сравните с оригиналом.

Ответ 2

Да, это поведение по умолчанию, как вы видели. Конечно, он недействителен HTML, так как вы можете проверить здесь http://www.freeformatter.com/html-validator.html, если вы введете HTML.