I am trying to wrap each span in a container. To achieve this I used a for loop to create multiple containers and then append the span to the container of the same index.
Why isnt my logic working?
Html: Two span tags (Sorry html code wont show)
Javascript:
var spans = document.getElementsByTagName('span'),
body = document.getElementsByTagName('body')[0];
for(var i = 0; i < spans.length; i++)
{
var container = document.createElement('figure');
container.setAttribute('class', 'container');
body.appendChild(container);
container.appendChild(spans[i]);
}
Edit: https://jsfiddle.net/tsrLutpg/1/
Part of the reason for the oddity is because the HTMLCollection set to spans is "live." This means, as you modify a <span>, the collection changes to reflect that change.
In this case, the collection changes the order the <span>s are listed in. As you're iterating, some may be wrapped twice moving from one <figure> to another, while others may remain unaltered when they move to an index that's already been visited.
<span>Foo</span>
<span>Bar</span>
<span>Baz</span>
for (var i = 0; i < spans.length; i++)
{
// ...
console.log(Array.from(spans).map(s => s.outerHTML));
container.appendChild(spans[i]);
}
// ["<span>Foo</span>", "<span>Bar</span>", "<span>Baz</span>"] (1 2 3)
// ["<span>Bar</span>", "<span>Baz</span>", "<span>Foo</span>"] (2 3 1)
// ["<span>Bar</span>", "<span>Foo</span>", "<span>Baz</span>"] (2 1 3)
You can avoid this by creating a static collection of the <span>s to iterate over, that doesn't change as the <span>s change.
In modern browsers, you can use Array.from() for this (similar to the above snippet).
var spans = Array.from(document.getElementsByTagName('span'));
https://jsfiddle.net/394La14t/
For compatibility, MDN offers a polyfill you can use. Or, you can call .slice() instead.
var spans = Array.prototype.slice.call(document.getElementsByTagName('span'), 0);
Here is the solution that properly wraps span tags:
var spans = document.getElementsByTagName("span");
for (var i = 0; i < spans.length; i++) {
var container = document.createElement("figure");
container.className = "container";
var span = spans[i];
span = span.parentNode.replaceChild(container, span);
container.appendChild(span);
}
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