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.
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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With