Detect when Browser Scrolls Below a Certain Point - javascript

I have a webpage filled with divs, and when the page reaches 300px from the bottom, it loads more divs.
I'm having trouble finding a detection that works everywhere.
I need some JavaScript (i.e. not JQuery) if statement to put into the body's onscroll function that will detect the browser scrolling below 300px from the bottom, which works with IE, FF, Chrome, Opera, Safari, Android browsers, iBrowsers, etc.

You could use a library like
http://code.google.com/p/jquery-appear/
And bind to the last element you dynamically display in each batch, so that when it comes into view, the next batch is shown.

I'm pretty sure you can use jQuery's "scrollTop" method on the document object or possibly the body tag.
i.e.
if ($(document).scrollTop() > whatever) {
doWhatever();
}

You have to know the position of the point, then checks the window scrollTop
if ($(window).scrollTop() > point) {
//Carry On
}

Related

Keeping scroll position when adding elements on top works in Firefox but not Chrome

I have a Meteor app (source code) which has a stream of entries and new entries are being constantly added on top. I am trying to make it so that if an user scrolls down to a particular entry, that entry should stay visible and not move even when more entries are added on top. Adding and removing entries is animated using Velocity.
I have made code which does that, but it works only in Firefox, while in Chrome it quickly starts jumping around as more entries are coming. Why is that and how could I fix it?
I'm going to post this since it took me a while to figure out. For me it had to do with the Scroll Anchoring feature which was introduced as default in Chrome 56.
The overflow-anchor property enables us to opt out of Scroll Anchoring, which is a browser feature intended to allow content to load above the user's current DOM location without changing the user's location once that content has been fully loaded. Source
You might want to try setting overflow-anchor to none, to opt out of the Scroll Anchoring functionality:
body {
overflow-anchor: none;
}
You can find a demo here, showcasing the difference with and without scroll anchoring.
After you insert the elements at the top, you need to manually re-scroll to the correct position:
function insertNewElementAtTop(parent, elem) {
var scrollTopBeforeInsert = parent.scrollTop;
parent.insertBefore(elem, eParent.firstChild);
parent.scrollTop = scrollTopBeforeInsert + elem.offsetHeight;
}

Disable Chrome's scroll preserving feature

I have a page containing a list of items:
Load more button should load some more items via ajax and append it to the items container preserving current scroll position. So after I click it the feed I expect it to look like this (green items are new):
But in fact Chrome 56 executes some computations to make the page stay in the same state, and what I see looks like this:
Is there any way to prevent this smart scrolling position setting in Chrome?
Update: I can reproduce the behavior only if parent container ('body' in my case) has 'display: flex' property (I use it to achieve 'sticky footer' feature).
I solved a similar problem by adding overflow-anchor: none; to the scroll container.
https://wicg.github.io/ScrollAnchoring/
Today it seems that this property was excluded? When adding 'overflow-anchor: none;' as style on a div element I get the message: Validation (CSS 3.0): "overflow-anchor" is not a known css property name.
This is simple. Before performing your AJAX call, save the scroll position of the page to a variable, then, after the call, scroll to the position indicated by that variable. Here is what you should write before your AJAX call:
var scrollpos = window.scrollY;
and here is the code after your AJAX call
window.scrollTo(0,scrollpos)
Hope this works
Why chrome makes calculations to preserve the scroll position? Usually the page will only be longer, so the scroll position stay fixed anyway.
I assume you remove the button, so the position cannot be kept, while content was not reloaded. You should reserve the button space in the dom and remove the reserved space when inserting the reloaded items.

IE, and iframe.elementFromPoint not passing event

Update: Fiddle Demonstration -- http://jsfiddle.net/7tfbtso6/2/ -- Most of the settings work in chrome and firefox, but the only one that works in IE is Left-align: 105px. I do have overflow set to hidden on html and body, but this makes no difference. IE will not work if the element is not visible on screen. And overflow: visible on html and body give the effect of auto and no effect on the problem here.
My site uses two contentEditable divs.
#rInput is part of the document.
#rSyntax is part of an iframe under (z-index) #rInput.
In every browser I've tried so far, except IE (I'll get to that in a moment.), I'm able to determine what element is contained within the iframe using elementFromPoint().
In IE's case, this is only possible if they're not overlapping which isn't possible because a secondary purpose, as the name implies, is to provide syntax-highlighting.
The IE IFrame has to be visible, on screen, not obstructed by any objects. I've tried display: none;, visibility: hidden, and pushing it down in a div with overflow: hidden, but all of these attempts cause it not to work. I've also tried setting the height and width to small proportions.
If any of these could work, I could use two copies of rSyntax, one on top (z-index), hidden somehow, for mouse events and one for syntax highlighting.
Most of these solutions work in every browser but IE. The IE box simply demands that it be on top.
"Flickering" it with css (display, visibility, pointer-events) seems awfully hacky (and just plain awful). I haven't really tried to implement it because it seems like a last resort.
The problem is further complicated because I'm trying to capture clicks and mouseovers, for different purposes (clicks for finding content, mouseovers for tooltips--created with a div mimicking attr("title").
I've briefly tried placing the iframe on top (z-index) of the div, but there's no way to intercept the clicks and pass to the lower object because it runs in to the same problem.
Here's the script I'm using to get the objects, partly in case it's useful to anyone.
$(document).on("mousemove", "#rInput", function (e) {
$element = $(document.getElementById('frSyntax').contentDocument.elementFromPoint(e.pageX+$("#rInputContainer").scrollLeft()-10,e.pageY+$("#rInputContainer").scrollTop()-12));
if ($element.is("span") && $element.attr("title") && $element.attr("title").length) {
$("#syntip").text($element.attr("title"));
$("#syntip").css({"top": e.pageY+10, "left": e.pageX, "display": "inline-block"});
} else {
$("#syntip").hide();
}
});
I have considered transparency, and that works for this element, because it's small, but I use a similar setup with a large element that takes up more than 50% of the screen, there would be problems.
After many frustrating efforts, I concluded that pushing the top (z-index-wise) element offscreen was the only solution for IE/Edge. Flickering it with display: none causes some properties I needed, like width, to not be accurate.
Just make sure you push it farther than the element will ever be. My application is sidescrolling so I merely needed to place the css top to something like 2000.

Animate behaves wierdly in Chrome and Firefox (ok in IE)

I use this code:
$("img.cloudcarousel").each(function(i, e){
coords[i] = $(e).offset();
});
to save the position of the images (and it works).
Then I animate them and move them.
Then I use this code:
$("img.cloudcarousel").each(function(i, e){
$(e).animate({top:coords[i].top, left:coords[i].left}, 1000);
});
to animate them back to where they belong.
in IE (at least 8) it works fine but in Chrome and Firefox it animates 40-50 pixels too much to the left and down (like its over-animating).
dont ask me how I discovered this: when i use mousewheel over them they go to where they belong!
I guess it's somehow related to the buildup of the animation queue, however I only use four images and it doesn't fix on its own after x time, only on the mousewheel stuff.
edit : added to jsfiddle.net
I'm not really sure how that site works but I added my HTML and JS into it:
http://jsfiddle.net/3wqYg/
The $(e).offset() is not returning the values that is currently defined in your fiddle. I have not looked up the definition of offset but if you output the coords, you will see it is not the same as in the code
Edit: I see the problem see offset() http://api.jquery.com/offset/ it returns the x, y relative to document BUT when you animated it back it is relative to the parent element (default behavior). So in the doc it mentions using position(). that is relative to the parent element, I have not tried it but if you use that it should work.
Final Edit: yep works fine with position see http://jsfiddle.net/3wqYg/1/ you must copy it into a test page because it does not animate on fiddle

Using window.onscroll event to detect page/frame scrolling

I want to postion a DIV inside a page such that it is visible to the user even if the user vertically scrolls the page.
The page has a heading at the top of the page which is 75 px tall. Now when the user is at the top of the page and has not scrolled vertically, the DIV must be postioned below the heading. However, once the user scrolls the page causing the heading to go out of sight, the same DIV must now be position at the top of the page (i.e. near the top edge of the browser viewport)
My big concern is the support for window.onscroll event on browsers. I checked QuirksMode for compatibility (http://www.quirksmode.org/dom/events/scroll.html). It seems to have decent compatibility on IE and Firefox. However the Safari and Chrome support seems a bit quirky. And both these browsers are part of my target browsers' list.
Can anybody tell me if the window.onscroll event is an effective way of detecting page/frame scrolls? Any other suggestions?
P.S. I have considered using the CSS position: fixed rule. It is close to the solution but the DIV is just stuck to one position and I cannot have it adaptively move based on the visiblity of the heading.
Thanks!
Here's another alternative method you could try. I use it to position a toolbar div on top of the page (works for ipad too).
Instead of using the onScroll event, I am using a timer to fire every 500ms to detect where the windows is scrolled to via scrollTop . You could adjust the timer to about 200ms if you like.
Here's a stripped down sample of my code:
This jquery code checks when and if my dom element div named "floatlayer" (which is a div that contains my buttons toolbar) is ready and then calls the function setRepeater
$(#floatlayer").ready(function () {
return setRepeater();
});
Then, this is the function that creates a timer to keep executing the function "keepIncrease" every 500ms
function setRepeater() {
aTimer = window.setInterval("keepIncrease()", 500);
return false;
}
This is the function keepIncrease() which is repeated every 500ms and is responsible to position the toolbar div based on the current window scrolled position :
function keepIncrease() {
var divToolbar = $("#floatlayer")[0];
var currentPos = $(window).scrollTop();
divToolbar.style.top = currentPos + "px";
return false;
}
Something else out of topic:
If your content is inside an iframe, you could also use $(window.parent).scrollTop() instead of $(window).scrollTop()
If you read about the clunkiness in WebKit on Quirksmode, you'll notice the following:
Safari (but not on iPhone) and Chrome seem to monitor scrollTop acces in order to determine whether the user has scrolled an element. The log function of my test script changes scrollTop regularly, and Safari responds by firing a scroll event. Since the logging of this event changes the log element's scrollTop once more, scroll events will be fired continuously.
All this happens when the log element at the bottom of the page doesn't have a scrollbar yet, when it has a normal overflow: visible, and even when I set scrollTop to 0 each time a new event is logged. The buggy behaviour stops only when I remove the scrollTop line entirely.
This issue shouldn't affect what you're trying to achieve since you're not setting the scrollTop of any element. You're attaching onscroll to the window, which appears to have no issues between any browser anyway.
Why not just use "fixed"?
Oh, I see, I missed the part about the header.
You could still utilize the position:fixed option, though. You would just set the position against "body" initially (accounting for the 75px gap), and once the header leaves viewability, you can realign the div against the top of the viewport. But without using onscroll in some way or another you probably won't be able to do what you want to do. Sometimes you just have to make the decision: Do I want the feature more, or the people more?

Categories

Resources