Reputation: 5271
const len = document.getElementById('parent').children.length
for (let i = 0; i < len; i++) {
const div = document.createElement("div");
document.getElementById('parent').insertBefore(div, document.getElementById('parent').children[i])
}
<div id="parent">
<div class="asfd"></div>
<div class="xcbs"></div>
<div class="msfd"></div>
<div class="powg"></div>
<div class="ksle"></div>
</div>
This code returns
<div id="parent">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div class="asfd"></div>
<div class="xcbs"></div>
<div class="msfd"></div>
<div class="powg"></div>
<div class="ksle"></div>
</div>
What I am trying to achieve is to get an empty div before each current class
<div id="parent">
<div></div>
<div class="asfd"></div>
<div></div>
<div class="xcbs"></div>
<div></div>
<div class="msfd"></div>
<div></div>
<div class="powg"></div>
<div></div>
<div class="ksle"></div>
</div>
I can understand after inserting the first empty div, then the first empty div becomes the first child [0]
. Is there a solution to achieve the goal? Thanks
Upvotes: 3
Views: 80
Reputation: 12954
This happens because document.getElementById('parent').children
return a live collection of children and document.getElementById('parent').children[i]
will always be <div class="asfd"></div>
, so you must make a copy of document.getElementById('parent').children
outside of the for
loop:
const children = [...document.getElementById('parent').children];
for (let i = 0; i < children.length; i++) {
const div = document.createElement("div");
div.innerHTML = i;
document.getElementById('parent').insertBefore(div, children[i])
}
<div id="parent">
<div class="asfd">asfd</div>
<div class="xcbs">xcbs</div>
<div class="msfd">msfd</div>
<div class="powg">powg</div>
<div class="ksle">ksle</div>
</div>
Upvotes: 1
Reputation: 56770
To solve the problem with the changing indexes, use a querySelectorAll('#parent div')
and iterate over it using for..of
instead of an index-based loop:
for (const child of document.querySelectorAll('#parent div')) {
document.getElementById('parent').insertBefore(document.createElement("div"), child);
}
#parent div[class] {
background-color: red;
height: 4px;
}
#parent div:not([class]) {
background-color: yellow;
height: 4px;
}
<div id="parent">
<div class="asfd"></div>
<div class="xcbs"></div>
<div class="msfd"></div>
<div class="powg"></div>
<div class="ksle"></div>
</div>
Upvotes: 1
Reputation: 15821
This is because while you are iterating on elements you are adding it and length changes:
1 - first loop you add a div at 0
2 - second loop element that was at 0 now it's at 1 and you add a div before it
3 - and so on...
Solution: foreach loop (used hr instead of div because is easier to view without styles)
Array.from(document.getElementById('parent').children).forEach( (item, index) => {
const div = document.createElement("hr");
document.getElementById('parent').insertBefore(div, item)
})
<div id="parent">
<div class="asfd">asfd</div>
<div class="xcbs">xcbs</div>
<div class="msfd">msfd</div>
<div class="powg">powg</div>
<div class="ksle">ksle</div>
</div>
Upvotes: 1