Reputation: 6147
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:
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
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
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
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