Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My script is not showing whats truly visible element wise

Tags:

javascript

I found posts and online articles on how to do something like this but most examples are not in plain JavaScript. So this script works almost perfectly if all the sections are the same height for example 220px. So I thought I was getting closer in having this script working how I want it to work like overtime but then I realize

it had flaws when I decided to change the sections height and play around with the code more to see if it had any flaws that I was unaware of so basically this script is designed to output the name

of the sections that are visible but it is not showing the correct output for example if section 1 is the only one that is visible in the div it will say section-1 if multiple sections are visible it will say for example section-1,section-2 etc. Basically it should work like this regardless of the sections height

Example 1

Example 2

I know I have to change the code or altered it but I'm getting more confused the more I play around with it so how can I pull this off so I can always have the correct output? If I have to change my code completely to be able to do this then I don't mind.

This is my code

document.addEventListener('DOMContentLoaded',function(){

document.querySelector('#building').addEventListener('scroll',whichSectionsAreInSight);

function whichSectionsAreInSight(){
  var building= document.querySelector('#building');
  var top = building.scrollTop;
  var bottom = top+building.offsetHeight;
  var arr = [];
  
  Array.prototype.forEach.call(
  building.querySelectorAll('#building .sections'),
  
 function(sections){
    if ((sections.offsetTop < top && top <sections.offsetTop+sections.offsetHeight) || (sections.offsetTop < bottom && bottom < sections.offsetTop+sections.offsetHeight)){
      arr.push(sections.id);
    }
   
   }
   
  );
	
  document.querySelector('#status').innerHTML = arr.join(',')
}

  whichSectionsAreInSight();
  
});
h1{
  margin: 0;
  text-align: center;
}
#building{
  background-color: gray;
  height: 200px;
  width: 200px;
  overflow: auto;
}
.sections{
  height: 80px;
  width: 100%;
}
#section-1{
    background-color: dodgerblue;
}
#section-2{
    background-color: gold;
}
#section-3{
    background-color: red;
}
#section-4{
    background-color: gray;
    height: 220px;
}
<p id='status'></p>
<div id='building'>
  <div id='section-1' class='sections'><h1>Section 1</h1></div>
  <div id='section-2' class='sections'><h1>Section 2</h1></div> 
<div id='section-3' class='sections'><h1>Section 3</h1></div>
  <div id='section-4' class='sections'><h1>Section 4</h1></div>
</div>

1 Answers

You were pretty close!

First off, you need to set the parent element to position:relative otherwise the parent that is being measured against is the document.

Also, the algorithm is simpler than what you had. Just make sure that the top of the element is less than the bottom of the parent, and the bottom of the element is greater than the top of the parent.

In your case this is offsetTop < bottom and offsetTop + offsetHeight > top

document.addEventListener('DOMContentLoaded', function() {

  document.querySelector('#building').addEventListener('scroll', whichSectionsAreInSight);

  function whichSectionsAreInSight() {
    var building = document.querySelector('#building');
    var top = building.scrollTop;
    var bottom = top + building.offsetHeight;
    var arr = [];

    Array.prototype.forEach.call(
      building.querySelectorAll('#building .sections'),

      function(section) {
        if (section.offsetTop < bottom && section.offsetTop + section.offsetHeight > top) {
          arr.push(section.id);
        }
      }

    );

    document.querySelector('#status').innerHTML = arr.join(',')
  }

  whichSectionsAreInSight();

});
h1 {
  margin: 0;
  text-align: center;
}

#building {
  background-color: gray;
  height: 200px;
  width: 200px;
  overflow: auto;
  position: relative;
}

.sections {
  height: 80px;
  width: 100%;
}

#section-1 {
  background-color: dodgerblue;
}

#section-2 {
  background-color: gold;
}

#section-3 {
  background-color: red;
}

#section-4 {
  background-color: gray;
  height: 220px;
}
<p id='status'></p>
<div id='building'>
  <div id='section-1' class='sections'>
    <h1>Section 1</h1>
  </div>
  <div id='section-2' class='sections'>
    <h1>Section 2</h1>
  </div>
  <div id='section-3' class='sections'>
    <h1>Section 3</h1>
  </div>
  <div id='section-4' class='sections'>
    <h1>Section 4</h1>
  </div>
</div>
like image 58
JasonB Avatar answered Jan 03 '26 02:01

JasonB



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!