Not sure if this is a bug or a feature. When parsing html with table elements outside a table, jQuery ignores non-table elements.
<tr><td>table data</td></tr>
<div>div after will be ignored</div>
passed into $(html)
becomes
<tr><td>table data</td></tr>
When passing the same html into plain javascript element.innerHTML = html
becomes
table data
<div>div after will be ignored</div>
Here it is in action https://codepen.io/addbrick/pen/mprBgP
EDIT: Right after posting this I realized jQuery is removing the table elements because of the opposite behavior in the dom.
To start with, that’s not a valid HTML.
Yes. The Jquery parser cleanup that.
If you have a close look at source code jquery, html function uses parseHTML before it actually sets the innerHTML
.
And the parseHTML is calling a buildFragment and removing all the spurious elements inside the string.
Below is a part of source code of buildFragment function
// Add nodes directly
if ( jQuery.type( elem ) === "object" ) {
jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
// Convert non-html into a text node
} else if ( !rhtml.test( elem ) ) {
nodes.push( context.createTextNode( elem ) );
// Convert html into DOM nodes
} else {
tmp = tmp || safe.appendChild( context.createElement( "div" ) );
// Deserialize a standard representation
tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
wrap = wrapMap[ tag ] || wrapMap._default;
tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
// Descend through wrappers to the right content
j = wrap[ 0 ];
while ( j-- ) {
tmp = tmp.lastChild;
}
// Manually add leading whitespace removed by IE
if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[ 0 ] ) );
}
// Remove IE's autoinserted <tbody> from table fragments
if ( !support.tbody ) {
// String was a <table>, *may* have spurious <tbody>
elem = tag === "table" && !rtbody.test( elem ) ?
tmp.firstChild :
// String was a bare <thead> or <tfoot>
wrap[ 1 ] === "<table>" && !rtbody.test( elem ) ?
tmp :
0;
Yes, that is where you actual passed string gets evaluated and creating DOM nodes.
And finally, div should not be used a a element inside a table directly. Can be wrapped inside a td
and tr
.
So why exactly jquery ignored it ? because that is not real and valid html. If you look close at html specification of Table, you can only have the given tags. In a table tag,
<!ELEMENT TABLE - -
(CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)>
<!ATTLIST TABLE -- table element --
%attrs; -- %coreattrs, %i18n, %events --
summary %Text; #IMPLIED -- purpose/structure for speech output--
width %Length; #IMPLIED -- table width --
border %Pixels; #IMPLIED -- controls frame width around table --
frame %TFrame; #IMPLIED -- which parts of frame to render --
rules %TRules; #IMPLIED -- rulings between rows and cols --
cellspacing %Length; #IMPLIED -- spacing between cells --
cellpadding %Length; #IMPLIED -- spacing within cells --
>
And inside a each tag
<!ELEMENT THEAD - O (TR)+ -- table header -->
<!ELEMENT TFOOT - O (TR)+ -- table footer -->
As you can see, there is no div tag directly allowed.
However in case of vanilla javascript innerHTML
, no such parsing happens and browser directly interprets the string provided to dom nodes and add's them to the document.
Removes all of element's children, parses the content string and assigns the resulting nodes as children of the element.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With