What I'm looking to do is add a class to a specific element with a specific class when an element with a different or no class is below it.
For instance, let's use this code as an example.
< p >This is a sentence.</p>
< p >This is a sentence.</p>
< p >This is a sentence.</p>
<button >Click Here</button>
< p >This is a sentence.</p>
< p >This is a sentence.</p>
< p >This is a sentence.</p>
<image src="URL" />
Taking that example, I want to look at everything with the class name "my-paragraph", and when an element without the class of "my-paragraph" is below it, add another class to it which would be "nomargin" in this example.
This is what the final output might look like.
< p >This is a sentence.</p>
< p >This is a sentence.</p>
< p >This is a sentence.</p>
<button >Click Here</button>
< p >This is a sentence.</p>
< p >This is a sentence.</p>
< p >This is a sentence.</p>
<image src="URL" />
For the life of me, I can't work out how to code that up, and it's a problem that has absolutely been busting my brain for a few days and the imposter syndrome is real.
I feel like I want to start with a for loop, but I just can't get there on the logic side of it.
It would be great to be Vanilla JS if possible.
CodePudding user response:
It might be easier to put the groupings of <p>
tags in a containing div and then use css to style the container and take advantage of the css :last-of-type()
selector to apply different styles to the last my-paragraph tag before a button or an image.
<div >
<p >This is a sentence.</p>
<p >This is a sentence.</p>
<p >This is a sentence.</p>
</div>
<button >Click Here</button>
<div >
<p >This is a sentence.</p>
<p >This is a sentence.</p>
<p >This is a sentence.</p>
</div>
<image src="URL" />
and then css something like this
.paragraph-container .my-paragraph:last-of-type() {
margin: 0;
}
You may not even need the container, I always have to play around with the -of-type
css selcectors a bit to get what I want
CodePudding user response:
I think JDawwgy's answer is the best practice for this, but in case wrapping groups of paragraph tags into divs is not an option (like, maybe you're making a wysiwyg), here's a direct answer.
In vanilla JS, you can (a) get all paragraph tags, (b) loop through those paragraph tags, then (c) detect whether their next sibling is another <p>
, then (d) apply a class if the next sibling is not a <p>
.
const allParagraphs = document.querySelectorAll('p');
allParagraphs?.forEach((paragraphNode) => {
const nextSibling = paragraphNode.nextSibling;
if(nextSibling?.tagName.toLowerCase() !== 'p')
paragraphNode.className = ' nomargin';
});
CodePudding user response:
You can try this.
const children = [...document.getElementsByClassName("my-paragraph")];
children.forEach((child) => {
if (!child.nextElementSibling.classList.contains("my-paragraph")) {
child.classList.add('nomargin')
}
});