Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sync Scrolling of Divs Without Sluggish Scrollwheel

Tags:

jquery

I've successfully got two divs on a page, each with a scrollbar, and using jQuery, when one div is scrolled, the other scrolls accordingly.

$('#left').scroll(function () {
    $('#right').scrollTop($(this).scrollTop());
});

$('#right').scroll(function () {
    $('#left').scrollTop($(this).scrollTop());
});

This works fine as along as you use the keyboard or click on the scroll bar and drag to do the scrolling, but if you use the mouse scrollwheel it's incredibly slow, due, I think, to the fact that there's a 'feedback loop'.

Is there a way I can prevent this loop so that scrolling with the mouse scrollwheel works smoothly?

Here's a fiddle showing the problem.

like image 814
Philip Stratford Avatar asked Aug 03 '16 11:08

Philip Stratford


People also ask

How can I scroll through a page without scrolling the contents?

Where the browser interprets input for its own use (as it does with shortcut keys and the mouse wheel) those commands never reach the web page for JavaScript to see them. Generally if you click on a scrollable div, you can use the mouse wheel to scroll through its contents, without scrolling the entire page.

How to synchronize scroll positions in jQuery?

And no.... jQuery is not dead. To synchronize the scroll positions we can use .scrollTop () to know the position of the content with respect to the top of the page. First, we place the page div with the main content and then the block div with the secondary content that will scroll with respect to the main one according to its position.

How to scroll two divs at the same time using jQuery?

In case you have two divs of different sizes you may sometimes want to scroll both at the same time but at different speeds depending on their size. For example, you could have text in one and images in the other and want to scroll both at the same time. To achieve this, we will do it with the jQuery JavaScript library.

Why won't my Div scroll when I move the mouse wheel?

Where the browser interprets input for its own use (as it does with shortcut keys and the mouse wheel) those commands never reach the web page for JavaScript to see them. Since moving the wheel scrolls the whole web page your div will not be under the mouse cursor for long.


1 Answers

The problem is, that you have a scroll event listener on both divs. The event is bouncing then. One workaroung would be to unbind the other listener with off and reassign it afterwards.

But there should be a short delay, because the browser takes some time for setting the scrollTop to the new value. One way would be using setTimeout for this task.

// a helper variable
var timeout;

$('#left, #right').on("scroll", function callback() {
    // clear the 'timeout' every 'scroll' event call
    // to prevent re-assign 'scroll' event to other element
    // before finished scrolling
    clearTimeout(timeout);

    // get the used elements
    var source = $(this),
        target = $(source.is("#left") ? '#right' : '#left');

    // remove the callback from the other 'div' and set the 'scrollTop'
    target.off("scroll").scrollTop(source.scrollTop());

    // create a new 'timeout' and reassign 'scroll' event
    // to other 'div' on 100ms after the last event call
    timeout = setTimeout(function() {
        target.on("scroll", callback);
    }, 100);
});

Working example:

// a helper variable
var timeout;

$('#left, #right').on("scroll", function callback() {
    // clear the 'timeout' every 'scroll' event call
    // to prevent re-assign 'scroll' event to other element
    // before finished scrolling
    clearTimeout(timeout);

    // get the used elements
    var source = $(this),
        target = $(source.is("#left") ? '#right' : '#left');

    // remove the callback from the other 'div' and set the 'scrollTop'
    target.off("scroll").scrollTop(source.scrollTop());

    // create a new 'timeout' and reassign 'scroll' event
    // to other 'div' on 100ms after the last event call
    timeout = setTimeout(function() {
        target.on("scroll", callback);
    }, 100);
});
div {
  width: 50%;
  height: 200px;
  overflow-y: scroll;
}

#left {
  float: left;
}

#right {
  float: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="left">
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>10th P Tag</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>20th P Tag</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>30th P Tag</p>
</div>
<div id="right">
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>10th P Tag</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>20th P Tag</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>Content Here</p>
  <p>30th P Tag</p>
</div>

jsfiddle

like image 134
eisbehr Avatar answered Oct 01 '22 23:10

eisbehr