I have a popup window in my site that show additional information about the elements been show in the main screen. I need to syncronize the scrolling between the two windows, in a way that when the user scroll one of the window , the other window is automatticaly scrolled in the same ammount.
I was able to do that using jquery scroll event, and using the scrollTop function to set the scroll position. something like this:
$("#localDiv").scroll(function() {
var scrollPos = $("#localDiv").scrollTop();
$("targetElement").scrollTop( scrollPos );
});
I've simplified the actual code, because I have to do some work to reach the elements in another window, but this is not the question.
The problem is, this code works fine in Chrome and IE, but in FireFox the scrolling gets really slow.
I've created an example here : http://jsfiddle.net/Lv2dw787/4/. The problem seems to ocurr with DIV's in the same page as well. You can note that when the scrolling syncing is disabled, the speed turn back to normal.
Does anyone have a clue on how to fix this on FireFox?
Edit after Dave Chen answer:
The accepted answer solved my problem, but it has a catch. I first tried to do this:
lock = true;
try {
var scrollPos = $("#contentDivA").scrollTop();
$("#contentDivB").scrollTop( scrollPos );
}
finally
{
lock = false;
}
But the $("#contentDivB").scrollTop( scrollPos ); line seems to generate a scroll event on divB only after the current function finishes executing, so the finally part of try..finally was executing before that. So I had to this:
lock = true;
var scrollPos = $("#contentDivA").scrollTop();
$("#contentDivB").scrollTop( scrollPos );
and on DivB scroll event:
if (lock)
lock = false;
else {
(Do the scroll on DivA)
}
The reason is because of two reasons:
Firefox does smoothing on its scrolling
jQuery's scrollTop will trigger events
Let's look at some pseudo-code:
When divA is scrolled -> scroll divB to the same spot
When divB is scrolled -> scroll divA to the same spot
The problem is that when you scroll divA or divB to the same spot, it will also cause the when to happen again.
So for example, when you scroll divA, this is what happens:
scroll divA -> scroll divB to the same spot -> scroll divA to the same spot
This causes divA to stick to the same spot after scrolling a little, and thus what causes the sluggish effect in firefox.
A solution is to ignore scrolling events when you scroll:
$(document).ready(function() {
var ignore = false;
$("#contentDivA").scroll(function() {
var tmpIgnore = ignore;
ignore = false;
if (!tmpIgnore && $("#chkSyncEnabled")[0].checked)
{
var scrollPos = $("#contentDivA").scrollTop();
scrollTop($("#contentDivB"), scrollPos);
}
});
$("#contentDivB").scroll(function() {
var tmpIgnore = ignore;
ignore = false;
if (!tmpIgnore && $("#chkSyncEnabled")[0].checked)
{
console.log("here");
var scrollPos = $("#contentDivB").scrollTop();
scrollTop($("#contentDivA"), scrollPos);
}
});
function scrollTop(el, position) {
ignore = true;
el.scrollTop(position);
}
});
Example
Related
so i want to detect scrolling to the top(or bottom) when i'm already at the top(or bottom) of the page. I've seen a couple questions with similar problems here, but the only answer was to detect mousewheel event.
but considering the fact that i want to detect it when it's triggered by any similar action (like pressing the up/down key, or mousewheel and touchpad scrolling, or pageUp/Down, or home/end ...) should I create eventlisteners for each and every one of them? does anyone know a better way of doing it??
This is what I have for you so far. I can detect when you hit the top or bottom regardless of how you scrolled. The issue is detecting when you are trying to keep scrolling after you reached it because the scroll event does not fire unless you actually scroll. The only thing I can think of is to programmatically scroll the screen up slightly so that you can scroll again, but I don't recommend doing that. Other than this I don't see any other way other than creating custom events for each possible way the user can scroll.
$(function(){
var lastScrollBarPos = 0;
$(window).scroll(function(event){
var browserViewportHeight = $(window).height();
var hmtlDocHeight = $(document).height();
var scrollBarPos = $(window).scrollTop();
if (scrollBarPos > lastScrollBarPos){
// downscroll code
console.log('scroll down');
if(hmtlDocHeight == browserViewportHeight + scrollBarPos){
console.log('reached bottom');
}
} else {
// upscroll code
console.log('scroll up');
if(scrollBarPos == 0){
//we are at the top and someone is scrolling
console.log('reached top');
}
}
lastScrollBarPos = scrollBarPos;
});
});
I've been dealing with this problem since days now and I hope somebody here can help me.
I'm trying to make a sticky navigation and a 100% height header (body and html are set to 100% height too). Basically the problem I have is that the sticky navigation only works well after the page is (re)loaded. However scrolling after having resized the browser's window makes the navigation either jump to early or to late to the fixed position at the very top.
I'd need to implement a resize event I guess, so that the calculation of the variable "navOffset" fires everytime the window is resized, right?
I tried many ways of inserting this into my code which are also explained in the link below, but I falied everytime.
I hope somebody can disclose this secret to me as I'm getting insane about this.
Thanks a lot and have a great week!
Sascha
Example of the effect I want to achieve:
http://html5-webdesign.berlin/
Tutorials, which didn't help me:
https://stackoverflow.com/…/jquery-combine-document-ready-an…
jQuery(document).ready(function() {
var navOffset = jQuery("nav").offset().top;
jQuery("nav").wrap('<div class="nav-placeholder"></div>');
jQuery(".nav-placeholder").height(jQuery("nav").outerHeight());
jQuery(window).scroll(function() {
var scrollPos = jQuery(window).scrollTop();
if (scrollPos >= navOffset) {
jQuery("nav").addClass("fixed");
} else {
jQuery("nav").removeClass("fixed");
}
});
});
Just copy your second function (which you should probably name) and add it to the window resize event:
jQuery(document).ready(function() {
var navOffset = jQuery("nav").offset().top;
jQuery("nav").wrap('<div class="nav-placeholder"></div>');
jQuery(".nav-placeholder").height(jQuery("nav").outerHeight());
function setPosition() {
var scrollPos = jQuery(window).scrollTop();
if (scrollPos >= navOffset) {
jQuery("nav").addClass("fixed");
} else {
jQuery("nav").removeClass("fixed");
}
}
jQuery(window).scroll(setPosition);
jQuery(window).resize(setPosition);
});
I would like to know if it is possible to disable all scrolling on a webpage.
I am currently using
html, body { overflow:hidden; }
The issue is that this does not work on iOS devices and if you hold in the mouse wheel and drag it down you can also scroll, so it seems like a very poor solution to the problem
Is there a way to disable all methods of scrolling on all devices and then re-enable it?
I have had this exact same issue, i fixed it with the following;
var disableScroll = false;
var scrollPos = 0;
function stopScroll() {
disableScroll = true;
scrollPos = $(window).scrollTop();
}
function enableScroll() {
disableScroll = false;
}
$(function(){
$(window).bind('scroll', function(){
if(disableScroll) $(window).scrollTop(scrollPos);
});
$(window).bind('touchmove', function(){
$(window).trigger('scroll');
});
});
the touch move is bound to the window as the window scroll event is not fired until touch move is completed, so this allows a much smoother experience on iOS!
This isn't a perfect solution as you can 'throw' the page, but it will return to desired position when the throw has complete (as the window scroll event will then be fired). This is because iOS browsers strip out a lot of events for performance. also setTimeout and setInterval functions do not fire whilst the page is being thrown, having a loop isn't an option either!
see here http://jsfiddle.net/8T26k/
I have a dialog box appearing when user clicks on any of the flat.
What I want to do is to lock scrollbar if viewport height is bigger than 550px. Now I apply overflow:hidden to body, but this causes site jumping when scrollbar is hiding. I want to disable scrolling, but still show a scrollbar. Is it possible?
Thanks in advance!
You can simulate a scrollbar lock by detecting the scroll, and scrolling back to the previous position.. (this might appear jerky on some browsers especially if you drag the scroll bar itself)
function lockScroll() {
var lockX = window.scrollX;
var lockY = window.scrollY;
function lockIt() {
window.scrollTo(lockX,lockY);
return false;
}
window.addEventListener("scroll",lockIt,false)
return {
stop: function(){
window.removeEventListener("scroll",lockIt,false)
}
}
}
Usage:
var locker = lockScroll(); // locks scrolling
And when you're done you can re-enable scrolling
locker.stop(); // unlocks scrolling
If I have a div with overflow:auto so that it is a scrollable div and I load it with information that makes a significant scroll area, is there a way that when I load the information, the div shows the bottom results? Or essentially scrolls to the bottom?
I've seen jQuery solutions but this is for use in an HTA so I cannot use jQuery. Is there a purely javascript way to accomplish this?
var myDiv = document.getElementById('myDiv');
myDiv.scrollTop = myDiv.scrollHeight;
Works in Firefox, Safari, Opera, Chrome and even Internet Explorer, which is more than I can say for the SSE test case I Set up... lol
I will spare you the rant about the obtuse solutions offered by others, and here is an example of code that could be used for an instant messaging type client.
document.body.onload = function()
{
var myDiv = document.getElementById('myDiv');
// Pick your poison below, server sent events, websockets, AJAX, etc.
var messageSource = new EventSource('somepage');
messageSource.onmessage = function(event)
{
// You must add border widths, padding and margins to the right.
var isScrolled = myDiv.scrollTop == myDiv.scrollHeight - myDiv.offsetHeight;
myDiv.innerHTML += event.data;
if(isScrolled)
myDiv.scrollTop = myDiv.scrollHeight;
};
};
The part of that example that is relevant checks to see if the div is already scrolled to the bottom, and if it is, scrolls it to the bottom after adding data to it. If it is not already scrolled to the bottom, the div's scroll position will stay such that the visible content of the div is unaffected by adding the data.
document.getElementById('mydiv').scrollTop = 9999999;
The scrollTop property specifies the scrolling offset in pixels from the top of the region. Setting it to a very large value will force it to the bottom.
How about this?
function scroll_to_max(elm) { // {{{
if(!scroll_to_max_el) {
scroll_to_max_el = elm;
setTimeout(scroll_to_max, 10); // Allow for the element to be updated
} else {
var el = scroll_to_max_el;
var t = el.scrollTop;
el.scrollTop = t+100;
if(el.scrollTop != t) {
setTimeout(scroll_to_max, 10); // Keep scrolling till we hit max value
} else {
scroll_to_max_el = null;
}
}
}
var scroll_to_max_el = null; // Global var!
// }}}
(NOTE: Only tested it in Chrome...)
Late answer but this is much more helpful
$('#mydiv').scrollTop(($('#mydiv').height()*2));
I think you need to set the scrollTop after the element is updated.
setTimeout(function (){
el.scrollTop = 999999999
}, 10)
also, in chrome at least, 99999999999 will scroll to the bottom. but 999999999999 (an extra 9) will scroll to the top. it's probably converted to an int in the C side of webkit.