I'm need to count specific divs and after each X
divs insert another div with a paragraph in it. All in pure JavaScript.
I am done with counting the specific divs but I don't know how to handle the loop and insert the container and the paragraph.
<div >
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
</div>
<script>
count = document.getElementsByClassName("special-div").length; // Output: X
</script>
CodePudding user response:
A basic for statement would be suitable for this problem.
Use
querySelectorAll
instead ofgetElementsByClassName
as it's easier to manage - QSA returns an array-like static node list whereas gEBCN returns a live HTML collection which may trip you up when you start inserting new elements during its iteration.To find out where you should add the new div element use the remainder operator (also called "modulo"). As you iterate over the node list check to see if dividing the current index 1 (arrays are zero-based) by the specified number results in zero. If it does, add in the new div element
after
the current one.
Note: I've separated out the code to create a new div element into a function to keep things simple.
const divs = document.querySelectorAll('.special-div');
// Loop over the array-like structure that
// qsa returns. Find the remainder of dividing
// the index by the supplied `n` argument. If it's
// zero create a new div element and add it `after`
// the current div
function insertAfter(n, text) {
for (let i = 0; i < divs.length; i ) {
if ((i 1) % n === 0) {
const div = createDiv(text);
divs[i].after(div);
}
}
}
// For convenience a function that creates
// a new paragragh element wrapped in a div.
// It uses the text passed in as an argument
function createDiv(text) {
const div = document.createElement('div');
div.className = 'special-div';
const para = document.createElement('p');
para.textContent = 'new!';
div.appendChild(para);
return div;
}
// Call the main function. The arguments are
// the count where you add a new div, and the
// text you want to appear in the paragraph
insertAfter(2, 'new!');
div.special-div p { color: red; }
<div >
<div >one</div>
<div >two</div>
<div >three</div>
<div >four</div>
<div >five</div>
<div >six</div>
</div>
CodePudding user response:
This iterates the nodes with the special-div
class, keeping track of the index. For non-zero indexes divisible by interval
it creates and inserts a new div.
const interval = 3;
const parent = document.getElementById("parent");
const elements = [...document.getElementsByClassName("special-div")];
const divWithText = text => {
const newNode = document.createElement("div");
newNode.appendChild(document.createTextNode(text));
return newNode
};
elements.forEach((node,i) => {
if (i && i % interval === 0) {
parent.insertBefore(divWithText("new div"), node);
}
});
<div id="parent" >
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
</div>
CodePudding user response:
Sorry, I'm not quite sure what output you are expecting is like.
How about using .insertAdjacentHTML(<position>, <text>)
? It inserts HTML code to a specified element. You don't need to count divs :)
element.insertAdjacentHTML()
- You can choose a target element by changing
element
likemain
in my code.
- You can choose a target element by changing
position:
'beforeend'
- This means "Just inside the element, after its last child."
- In the case of Example 1, right before
</div>
of .main
position:
'afterend'
- This means "After the element. Only valid if the element is in the DOM tree and has a parent element."
- In the case of Example 2, right after
</div>
of .special-div
Example 1
const main = document.querySelector('.main');
let html = `
<div>
<p>new</p>
</div>
`
// Insert html at the end of all children of .main
main.insertAdjacentHTML('beforeend', html);
<div >
<div >div 1</div>
<div >div 1</div>
<div >div 1</div>
</div>
Example 2
const targetDivs = document.querySelectorAll('.special-div');
let html = `
<div>
<p>new</p>
</div>
`
// Insert html after every specific div
targetDivs.forEach(div => div.insertAdjacentHTML('afterend', html));
// you can't do this: targetDivs.insertAdjacent()
// Because targetDivs is a NodeList which is like an array [].
// You have to use .insertAdjacent() on every div one by one,
// not on an array(NodeList)
<div >
<div >div 1</div>
<hr>
<div>Ignore this div</div>
<hr>
<div >div 1</div>
<hr>
<div >div 1</div>
</div>
CodePudding user response:
You can try it like this:
var divs = document.getElementsByClassName('special-divs');
var afterHowMany= 5;
for( var i = 0; i < divs.length; i =afterHowMany )
divs.slice(i,i afterHowMany).wrapAll('<div ></div>');
This recursively adds a new div after every 5 elements. You can take any other number apart from 5 as well.