Skip to content

Issue #220: Fix large scroll steps when content is long #221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 37 additions & 20 deletions jquery.slimscroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,47 +337,64 @@
if (!releaseScroll) { e.returnValue = false; }
}

function barTop2scrollTop(barTop, maxBarTop, maxScrollTop) {
return maxScrollTop * barTop / maxBarTop;
}

function scrollTop2barTop(scrollTop, maxScrollTop, maxBarTop) {
return maxBarTop * scrollTop / maxScrollTop;
}


function scrollContent(y, isWheel, isJump)
{
releaseScroll = false;
var delta = y;
var maxTop = me.outerHeight() - bar.outerHeight();
var maxBarTop = me.outerHeight() - bar.outerHeight();
var maxScrollTop = me[0].scrollHeight - me.outerHeight();
var barTop, scrollTop = y;

if (isWheel)
{
// bar.outerHeight() is lower-bound for usability, so when calculating the scrollTop,
// to avoid the scroll step growing with the height of the content, we need to use
// the un-bound height of the scroll bar
var barHeight = me.outerHeight() * me.outerHeight() / me[0].scrollHeight;
// move bar with mouse wheel
delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
barTop = parseFloat(bar.css('top')) + y * barHeight * parseInt(o.wheelStep) / 100;

// move bar, make sure it doesn't go out
delta = Math.min(Math.max(delta, 0), maxTop);
barTop = Math.min(Math.max(barTop, 0), maxBarTop);

// if scrolling down, make sure a fractional change to the
// scroll position isn't rounded away when the scrollbar's CSS is set
// this flooring of delta would happened automatically when
// this flooring of barTop would happened automatically when
// bar.css is set below, but we floor here for clarity
delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
// For long content and small view port, rounding to unit causes the scroll step
// to be very large so we round to a 1000th of a unit.
barTop = (y > 0) ? Math.ceil(barTop*1000.0)/1000.0 : Math.floor(barTop*1000.0)/1000.0;

// scroll the scrollbar
bar.css({ top: delta + 'px' });
// scroll the content & scrollbar
scrollTop = barTop2scrollTop(barTop, maxBarTop, maxScrollTop);
bar.css({ top: barTop + 'px' });
}

// calculate actual scroll amount
percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight());
delta = percentScroll * (me[0].scrollHeight - me.outerHeight());

if (isJump)
else if (isJump)
{
scrollTop = y;
barTop = scrollTop2barTop(scrollTop, maxScrollTop, maxBarTop);
barTop = Math.min(Math.max(barTop, 0), maxBarTop);
bar.css({ top: barTop + 'px' });
}
else // this case is for when dragging the bar
{
delta = y;
var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
bar.css({ top: offsetTop + 'px' });
// calculate actual scroll amount (bar is already done by caller)
scrollTop = barTop2scrollTop(parseFloat(bar.css('top')), maxBarTop, maxScrollTop);
}

// scroll content
me.scrollTop(delta);
me.scrollTop(scrollTop);

// fire scrolling event
me.trigger('slimscrolling', ~~delta);
me.trigger('slimscrolling', ~~scrollTop);

// ensure bar is visible
showBar();
Expand Down