I'd like to normalize table rows. This works like a charm, except in IE (tested with IE 11).
I've created a demo snippet to demonstrate the issue:
$(function() {
$("table tbody tr span").each(function() {
var $this = $(this);
var $parent = $this.parent();
$this.replaceWith($this.html());
$parent[0].normalize();
});
});
<link href="https://cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>President</th>
<th>Birthplace</th>
</tr>
</thead>
<tbody>
<tr>
<td><span>Zach</span>ary Taylor</td>
<td>Barboursville, Virginia</td>
</tr>
</tbody>
</table>
This replaces the <span>
element with its content. After this step the node will look like:
Then, normalize()
is called to merge the splitted text nodes. However, in IE11 the text nodes are still splitted.
I can't see any issue from my side. What's the cause of this problem and what could be the solution?
As it turned out that this is a IE11 bug, I've filled in a bug report!
It seems like IE-11 can't normalize elements that are already part of your document If your developers toolbar is open.
This is also relevant for IE9 & 10 (emulated by using
meta http-equiv="X-UA-Compatible"
tag)
When you only create new nodes and you don't attach them to the document - everything works great (for both situations - developers toolbar is open and close):
d = document.createElement('div');
d.appendChild(document.createTextNode('text 1'));
d.appendChild(document.createTextNode('text 2'));
console.log(d.childNodes.length + ' - Should be 2')
d.normalize();
console.log(d.childNodes.length + ' - Should be 1')
If, however, you are working with nodes that are already part of your document, the normalize
function doesn't work if your developer toolbar is open:
d = document.getElementsByTagName('div')[0];
d.appendChild(document.createTextNode('text 1'));
d.appendChild(document.createTextNode('text 2'));
console.log(d.childNodes.length + ' - should be 2 on every browser')
d.normalize();
console.log(d.childNodes.length + ' - should be 1, however it\'s 2 on IE')
<div></div>
If you really want, what you can do is extract the nodes from the document and add them after you normalize them:
d = document.getElementsByTagName('div')[0];
d.appendChild(document.createTextNode('text 1'));
d.appendChild(document.createTextNode('text 2'));
console.log(d.childNodes.length + ' - should be 2 on every browser')
dNew = d.cloneNode(true)
dNew.normalize()
d.parentElement.replaceChild(dNew, d)
d = document.getElementsByTagName('div')[0];
console.log(d.childNodes.length + ' - should be 1 on every browser')
<div></div>
Update - 28/8
Answer was updated after the comment from @dude. It took some time to investigate the cause here, but I think that now I covered everything.
Note that for IE8 (forced by using
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8">
in IE-11) thenormalize()
function works for both elements that are in the DOM tree and elements that are not, even with the developers toolbar was open.