I am trying to figure it out whole day already and nothing seems to work, so I would really appreciate help. Here is simplified example of what I have in HTML:
<div id="big-div"> <div class="middle-div"> <div>Child:</div> <div class="small-div">1</div> </div> <div class="middle-div"> <div>Child:</div> <div class="small-div">2</div> </div> <div class="middle-div"> <div>Child:</div> <div class="small-div"></div> </div> </div>
Result is:
Child: 1 Child: 2 Child:
What I would like to achieve is to show middle-div
only if small-div
has any content, so the result would be:
Child: 1 Child: 2
I have tried this approach:
const element = document.getElementById("big-div"); let middle = element.getElementsByClassName("middle-div"); let small = element.getElementsByClassName("small-div"); for (let m = 0; m < middle.length; m++) { for (let s = 0; s < small.length; s++) { if (small[s].innerHTML = "") { middle[m].style.display = "none"; } } }
and the result looks like this:
Child: Child: Child:
I have also tried this:
var small = [...document.getElementsByClassName("small-div")]; var disappear = function () { if (small.innerHTML == "") { parent.small.display = "none"; } } small.forEach(disappear);
But that didn’t do anything and console.log(small.innerHTML);
showed undefined
.
Can someone help me figure out how to do this correctly?
Advertisement
Answer
I’d find all the .small-div
elements inside .middle-div
elements inside #big-div
and if the don’t have any child nodes, add a class to the .middle-div
that hides it:
const smalls = document.querySelectorAll("#big-div .middle-div .small-div"); for (const small of smalls) { if (!small.firstChild) { small.closest(".middle-div").classList.add("hide"); } }
Live Example (hides the elements after 800ms):
setTimeout(() => { const smalls = document.querySelectorAll("#big-div .middle-div .small-div"); for (const small of smalls) { if (!small.firstChild) { small.closest(".middle-div").classList.add("hide"); } } }, 800);
.hide { display: none; }
<div id="big-div"> <div class="middle-div"> <div>Child:</div> <div class="small-div">1</div> </div> <div class="middle-div"> <div>Child:</div> <div class="small-div">2</div> </div> <div class="middle-div"> <div>Child:</div> <div class="small-div"></div> </div> </div>
If you want to allow for a single node that has whitespace and still consider that div “empty”, you could use:
const smalls = document.querySelectorAll("#big-div .middle-div .small-div"); for (const small of smalls) { if ( !small.firstChild || (small.childNodes.length === 1 && !small.firstChild.nodeValue.trim()) ) { small.closest(".middle-div").classList.add("hide"); } }
setTimeout(() => { const smalls = document.querySelectorAll("#big-div .middle-div .small-div"); for (const small of smalls) { if ( !small.firstChild || (small.childNodes.length === 1 && !small.firstChild.nodeValue.trim()) ) { small.closest(".middle-div").classList.add("hide"); } } }, 800);
.hide { display: none; }
<div id="big-div"> <div class="middle-div"> <div>Child:</div> <div class="small-div">1</div> </div> <div class="middle-div"> <div>Child:</div> <div class="small-div">2</div> </div> <div class="middle-div"> <div>Child:</div> <!-- Note that now it has a text node with whitespace --> <div class="small-div"> </div> </div> </div>