1

I have a container that have multiple a4 page (number is random) and I want to detect what page I'm currently viewing.

This is my code:

<div class="mycont">

    <div id="page1" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
        <h1>page1</h1>
    </div>

    <div id="page2" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
        <h1>page2</h1>
    </div>

    <div id="page3" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
        <h1>page3</h1>
    </div>

</div>

<div style="position: fixed; bottom: 0; left: 50%; padding: 10px 50px; background-color: #ccc;" id="curpage">cur page 1</div>

And with this script I can detect only 1 page

<script>
$(document).ready(function() {
  var target = $("#page2").offset().top;
  var interval = setInterval(function() {
    if ($(window).scrollTop() >= target) {
      $("#curpage").text("cur page 2");
    }
  }, 250);
});
</script>

How to detect page 3,4... 50,51 etc ?

FluffyKitten
  • 12,639
  • 10
  • 31
  • 45
FireFoxII
  • 764
  • 3
  • 16
  • 28

4 Answers4

1

Here is vanilla JS solution...

Ad class .page to pages elements on your page, then select child elements (needs to be child cose to check if element is in view port it has to have content visible):

 document.querySelectorAll('.page *');

Add scroll event on window, $(document).ready wont help you here.

And check with element is in is In Viewport with isInViewport function. If element is in view port get its page parent id:

page.parentElement.id

References Read the link on how the isInViewport function work.

var isInViewport = function(elem) {
  var distance = elem.getBoundingClientRect();
  return (
    distance.top >= 0 &&
    distance.left >= 0 &&
    distance.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
    distance.right <= (window.innerWidth || document.documentElement.clientWidth)
  );
};
// read the link on how above code works

var findMe = document.querySelectorAll('.page *');

window.addEventListener('scroll', function(event) {
// add event on scroll
findMe.forEach(page => {
    //for each .page
    if (isInViewport(page)) {
      //if in Viewport
      document.querySelector('#curpage').innerHTML="cur "+page.parentElement.id;
    }
});
}, false);

EXAMPLE:

jsfiddle.net

ikiK
  • 5,467
  • 3
  • 11
  • 27
1

What you are attempting to do is called ScrollSpy. With jQuery, the .scroll() method will be useful:

https://api.jquery.com/scroll/

Here are some How To references that will get you all the way there:

References:

https://www.w3schools.com/bootstrap/bootstrap_scrollspy.asp

https://www.w3schools.com/bootstrap/bootstrap_ref_js_scrollspy.asp

how to use scrollspy without using bootstrap

cssyphus
  • 31,599
  • 16
  • 79
  • 97
1

You can use Intersection Observer:

let observer = new IntersectionObserver(function(entries) {
    var ele = entries.filter(entry => entry.isIntersecting);
    if (ele.length > 0) {
        ele = ele[0].target;
        console.log('Visible element is now: ' + ele.id);
    }
});

document.querySelectorAll('.mycont [id^=page]')
                             .forEach(ele => observer.observe(ele));
<div class="mycont">

    <div id="page1" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
        <h1>page1</h1>
    </div>

    <div id="page2" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
        <h1>page2</h1>
    </div>

    <div id="page3" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
        <h1>page3</h1>
    </div>

</div>

<div style="position: fixed; bottom: 0; left: 50%; padding: 10px 50px; background-color: #ccc;" id="curpage">cur page 1</div>
gaetanoM
  • 39,803
  • 6
  • 34
  • 52
  • Is there a possibility to add a vertical offset? When I reach start of next page, console show that "element is now page X" but I'm currently viewing 90% of old page... – FireFoxII Sep 10 '20 at 16:21
1

We can do this dynamically in jQuery so it finds all page divs, works out their position and checks which page is showing on scroll.

  1. Get all of your page elements dynamically and stop the top of each and its id (and any other information you might want to use) in an array:
    var mypages = [];
    $(".mycont > div").each(function( el ) {
        mypages.push({
            pageid : $(this).attr("id"),
            pagetop : $(this).offset().top
        });
    });
  1. In the $( window ).scroll event, you can check the current window position against the position of each of your pages like this:
    $( window ).scroll(function() {
        $.each(mypages, function(i, page) {
          if ($(window).scrollTop() >= page.pagetop) {
              $("#curpage").text(page.pageid );
              console.log('Page: ' + page.pageid + " at " + page.pagetop);
          }
        });
    });

Working Example:

var mypages = [];
// get all your page elements 
$(".mycont > div").each(function( el ) {
    //...add the id and top position into our array
    mypages.push({
        pagename : $(this).attr("id"),
        pagetop : $(this).offset().top
    });
});

$( window ).scroll(function() {
    // loop through each page... 
    $.each(mypages, function(i, page) {
      //...and compare its `top` to the window position
      if ($(window).scrollTop() >= page.pagetop) {
          $("#curpage").text(page.pagename);
      }
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mycont">

  <div id="page1" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
    <h1>page1</h1>
  </div>

  <div id="page2" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
    <h1>page2</h1>
  </div>

  <div id="page3" style="width: 21cm; height:29.7cm; border: 1px solid; margin: 10px 0">
    <h1>page3</h1>
  </div>

</div>

<div style="position: fixed; bottom: 0; left: 50%; padding: 10px 50px; background-color: #ccc;" id="curpage">cur page 1</div>

Note, this assumes all child divs of your .mycont are pages - if this is not the case in your project, you can easily change the selector to suit.

FluffyKitten
  • 12,639
  • 10
  • 31
  • 45