Synchronized scrolling using jQuery?
You can use element.scrollTop / (element.scrollHeight - element.offsetHeight)
to get the percentage (it'll be a value between 0
and 1
). So you can multiply the other element's (.scrollHeight - .offsetHeight)
by this value for proportional scrolling.
To avoid triggering the listeners in a loop you could temporarily unbind the listener, set the scrollTop
and rebind again.
var $divs = $('#div1, #div2');
var sync = function(e){
var $other = $divs.not(this).off('scroll'), other = $other.get(0);
var percentage = this.scrollTop / (this.scrollHeight - this.offsetHeight);
other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight);
// Firefox workaround. Rebinding without delay isn't enough.
setTimeout( function(){ $other.on('scroll', sync ); },10);
}
$divs.on( 'scroll', sync);
http://jsfiddle.net/b75KZ/5/
synchronise scrolling between 2 divs in native javascript (2020)
Here's the simple way to keep two divs aligned. Javascript doesn't dispatch event on actions from scripts by default, so there's no need to keep track of which div is being scrolled.
const divs = document.querySelectorAll( 'div' );
divs.forEach(div => div.addEventListener( 'scroll', e => {
divs.forEach(d => {
d.scrollTop = div.scrollTop;
d.scrollLeft = div.scrollLeft;
});
}) );
html, body {
height: 100%;
}
body {
display: flex;
padding: 0;
margin: 0;
}
div {
width: 50%;
height: 100%;
overflow: scroll;
}
span {
width: 200vw;
height: 300vh;
display: block;
background: linear-gradient(90deg, transparent, yellow), linear-gradient( 0deg, red, blue, green );
}
#div2 {
margin-top: 30px;
}
<div id="div1"><span></span></div>
<div id="div2"><span></span></div>
Sync Scrolling of Divs Without Sluggish Scrollwheel
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>
Synchronize scrollbars between two elements - jQuery
Found out a good solution. Debouncing does the trick.
You can use a combination of timers and bools to make sure the element is being scrolled by the user. Thus, when the scroll event is rapidly and consecutively fired (like when a user scrolls down), it prevents the handlers from recursively calling eachother. The following code does the trick:
var userScroll1 = true;
var userScroll2 = true;
var timer;
$div1.scroll(function() {
if(userScroll2) {
userScroll1 = false;
clearTimeout(timer);
$div2.scrollTop($div1.scrollTop());
timer = setTimeout(function() {
userScroll1 = true;
}, 100);
}
});
$div2.scroll(function(){
if(userScroll1) {
userScroll2 = false;
clearTimeout(timer);
$div1.scrollTop($div2.scrollTop());
timer = setTimeout(function() {
userScroll2 = true;
}, 100);
}
});
Check out the properly functioning jsbin: https://jsfiddle.net/axtn/a91fsar3
synchronizing scrolling between 2 divs
Always check the console - that will cause errors because you are attempting to use jQuery methods on native elements (since you retrieved them via [0]
). If you were doing this purely for the sake of the if
condition, there's no need - to check the selectors found elements, you can just query the length
property.
$(function() {
var bmrDetailDiv = $("div[id$='_bmrDetailDataDiv']");
var residentDetailDiv = $("div[id$='_residentDetailDataDiv']");
if (bmrDetailDiv.length && residentDetailDiv.length) {
bmrDetailDiv.on('scroll', function () {
residentDetailDiv.scrollTop($(this).scrollTop());
});
residentDetailDiv.on('scroll', function () {
bmrDetailDiv.scrollTop($(this).scrollTop());
});
}
});
Other changes:
1) Document ready handler instead of window.onload
2) Use of $(this)
inside event callback
JQuery: How to sync scrollbars
This worked for me in Firefox but not in IE.
<SCRIPT language="javascript" type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></SCRIPT>
<SCRIPT language="javascript" type="text/javascript" src="jquery.frameready.js"></SCRIPT>
$(document).ready(function()
{
// Sync Header Frame with Detail Frame`
$.frameReady( function() {
var ifr2 = $(window.parent.document.getElementsByName('UserQueue_Detail')).contents();
$(document).scroll( function(){
ifr2.scrollLeft($(document).scrollLeft());
});
},
"UserQueue_Header"
);
// Sync Detail Frame with Header Frame
$.frameReady( function() {
var ifr1 = $(window.parent.document.getElementsByName('UserQueue_Header')).contents();
$(document).scroll( function(){
ifr1.scrollLeft($(document).scrollLeft());
});
},
"UserQueue_Detail"
);
});
Related Topics
Can You Have a JavaScript Hook Trigger After a Dom Element's Style Object Changes
Copy to Clipboard Using JavaScript in iOS
Inject a JavaScript Code in Webview iOS
Vuejs: Why Is "This" Undefined
Jqgrid Server Side Error Message/Validation Handling
I Keep Getting "Uncaught Syntaxerror: Unexpected Token O"
Include a JavaScript File in Shiny App
JavaScript Es6 Promise for Loop
Limit Labels Number on Chart.Js Line Chart
Mobile Safari on iOS Crashes on Big Pages
Call JavaScript Function from Native Code in Wkwebview
Objective-C/Swift Regex Matching Across Multliple Lines
Data-Toggle Tab Does Not Download Leaflet Map
Why Does ++[[]][+[]]+[+[]] Return the String "10"