Rana Depto
Rana Depto

Reputation: 721

jQuery Scrolling to Next Section Not Working Properly

I am trying to develop a site where if user press n or N key on the keyboard, the page will auto scroll to the next section. Same applies to the previous section. But I am facing a problem, to scroll next section, sometimes I have to press n twice. On the contrary, it's skipping two sections instead of one while I am pressing p key to go back the previous section. How can I solve this? I am including my code here:

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
         pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

    <script type="text/javascript">
        function ScrollTo(address) {
            $('html, body').animate({
                scrollTop : ($('#' + address).offset().top)
            }, 700);
        }

    </script>

</head>

<body>


<section id="section1">
    <h1>section1</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section2">
    <h1>section2</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section3">
    <h1>section3</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section4">
    <h1>section4</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section5">
    <h1>section5</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section6">
    <h1>section6</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section7">
    <h1>section7</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section8">
    <h1>section8</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section9">
    <h1>section9</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>


<section id="section10">
    <h1>section10</h1>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</section>



<script type="text/javascript">

    var sections = [];
    $(document).find("section").each(function() {
        sections.push(this.id);
    });

    var sectionIndex = 0;

    $(document).keyup(
        function(evt) {
            var elid = $(document.activeElement).is("input, textarea");
            if (elid) {
                return;
            }

            if ((evt.keyCode == 80 | evt.keyCode == 112)
                & sectionIndex > 0) {
                sectionIndex=sectionIndex-1;
                ScrollTo(sections[sectionIndex]);
            } else if ((evt.keyCode == 78 | evt.keyCode == 110)
                & sectionIndex < sections.length - 1) {
                sectionIndex=sectionIndex+1;
                ScrollTo(sections[sectionIndex]);
            }
        });


    $(document).scroll(
        function() {
            $('section').each(
                function() {
                    if ($(this).position().top <= $(document).scrollTop() && ($(this).position().top + $(this).outerHeight()) > $(document).scrollTop()) {
                        sectionIndex = sections.indexOf(($(this).attr('id')));
                    }
                });
        });
</script>

</body>
</html>

Upvotes: 1

Views: 315

Answers (1)

Kos
Kos

Reputation: 72299

Hint: Change your code a little bit...

$('section').each(
  function () {
    this.style.background = '';
    if ($(this).position().top <= $(document).scrollTop() && ($(this).position().top + $(this).outerHeight()) > $(document).scrollTop()) {
      this.style.background = 'lightseagreen';
      sectionIndex = sections.indexOf(($(this).attr('id')));
    }
  });

now during scrolling you'll see which section is "current". This demonstrates the problem: after pressing "N" the previous section is still "current".

You can easily fix it:

  • currently the highlighted section is the one that intersects the upper bound of the screen,
  • instead, you can imagine a line a bit below top of the screen, like 50px lower, and consider that as the "focus point" that determines which section is current.

The code could look like this:

    $('section').each(
      function () {
        const focus = $(document).scrollTop() + 50;
        this.style.background = '';
        if ($(this).position().top <= focus && ($(this).position().top + $(this).outerHeight()) > focus) {
          this.style.background = 'lightseagreen';
          sectionIndex = sections.indexOf(($(this).attr('id')));
        }
      });

Only change here is comparing against $(document).scrollTop() + 50 instead of $(document).scrollTop(). Notice that now the section becomes highlighted quicker, before it touches the top edge of the screen.

Upvotes: 1

Related Questions