JokerMartini
JokerMartini

Reputation: 6147

Scroll to next div on click, from current location

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/

Upvotes: 3

Views: 1600

Answers (3)

Serge Seredenko
Serge Seredenko

Reputation: 3541

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.

Upvotes: 1

Alexander Kludt
Alexander Kludt

Reputation: 863

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;
}

Upvotes: 1

indubitablee
indubitablee

Reputation: 8206

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.

Upvotes: 0

Related Questions