3

In my current solution to scroll from a div to another div I support both previous and next.

This works by saving the index of the div last scrolled to in order to determine where to scroll to next. However this breaks when users scroll with their wheel. I was wondering if there is a way to calculate which div is the closest to the top of the window, to then determine which index to scroll to next.

This in return would remove the issues that I'm having.

Test error using my current solution:


  1. Go to the jsfiddle link
  2. Click the down arrow twice. It should scroll from one div to the next.
  3. Next, using the wheel on your mouse scroll down 3/4 of the page.
  4. Now hit the down arrow again. You'll see it takes you back to the top where you last left off stepping down.

http://jsfiddle.net/JokerMartini/yj9pvz2a/1/

var curr_el_index = 0;
var els_length = $(".section").length;

    $('.btnNext').click(function () {
        curr_el_index++;
        if (curr_el_index >= els_length) curr_el_index = 0;
        $("html, body").animate({
            scrollTop: $(".section").eq(curr_el_index).offset().top - 20
        }, 700);
    });

    $('.btnPrev').click(function () {
        curr_el_index--;
        if (curr_el_index < 0) curr_el_index = els_length - 1;
        $("html, body").animate({
            scrollTop: $(".section").eq(curr_el_index).offset().top - 20
        }, 700);
    });

Solution Updated: http://jsfiddle.net/JokerMartini/82wo9e3c/1/

JokerMartini
  • 5,674
  • 9
  • 83
  • 193

3 Answers3

1

You can retrieve current offset of an element relative to the document using jquery offset (http://api.jquery.com/offset/). So you could use something like this:

function getTopElement(elements){
  var topEl;
  $.each(elements, function(index,el){
    if(!topEl || topEl.offset().top < el.offset().top){
      topEl = el;
    }
 });

  return topEl;
}
indubitablee
  • 8,136
  • 2
  • 25
  • 49
Alexander Kludt
  • 854
  • 6
  • 17
1

According to this answer, there is a way to calculate distance of div from top of viewport, to be specific like this:

($element.offset().top - $(window).scrollTop())

So, you just have to find the one with minimal positive value:

var closest_to_top = $('.section').toArray().reduce(function(curr, section) {
    var bottom = $(section).offset().top + $(section).height()
    var distance = (bottom - $(window).scrollTop())
    if (distance < 0) return curr
    return distance > curr.distance ? curr : {
        distance : distance,
        section : section
    }
}, {section:null, distance:+Infinity}).section

This is the highest section whose bottom is below the top of viewport. Remove +$(section).height() if section's top is required.

Community
  • 1
  • 1
Serge Seredenko
  • 3,541
  • 7
  • 21
  • 38
0

try adding this to deal with the page scrolling. demo: http://jsfiddle.net/yj9pvz2a/2/

var section_height = $(".section").height() + 80; //80 margins

$(window).on('scroll', function() {
    curr_el_index = Math.floor($(window).scrollTop() / section_height);
});

explanation: so what you're experiencing in your code is that when a user doesnt use your navigation to scroll to different sections, the curr_el_index remains the same. this $(window).scroll() function takes into account the scroll not from your navigation buttons.

function: on scroll of the button, it takes the the scroll height of the window and divides it by the scroll height of the section and rounds it down to the nearest whole number and sets the current index section to that number.

indubitablee
  • 8,136
  • 2
  • 25
  • 49
  • This could possibly fail if you scroll several div elements at once. – Aditya Sep 24 '15 at 15:08
  • Just scrolled directly from A to J and then clicked the up arrow. Skipped I and went directly to H. But this solution will work in almost all cases here. – Aditya Sep 24 '15 at 15:12