Synchronized Scrolling Using Jquery

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



Leave a reply



Submit