Stop element from scrolling at the footer - javascript

So I'm trying to get this element to scroll which it does but I'd like it to stop scrolling before the footer.
At the moment I have this but the pages don't have the same length so the >= 17900 is not a good solution for me.
$(window).scroll(function (event) {
var windowTop = $(this).scrollTop();
if (windowTop >= 17900) {
$(".product-form__item--quantity").addClass("non-fixed");
$(".product-form__item--submit").addClass("non-fixed");
$("#ProductPhotoImg").addClass("non-fixed");
$("#option_total").addClass("non-fixed");
$(".product-single__title").addClass("non-fixed");
$(".product-form__item--quantity").removeClass("change");
$(".product-form__item--submit").removeClass("change");
$("#ProductPhotoImg").removeClass("change");
$("#option_total").removeClass("change-option");
$(".product-single__title").removeClass("change");
} else {
//console.log('a');
$(".product-form__item--quantity").removeClass("non-fixed");
$(".product-form__item--submit").removeClass("non-fixed");
$("#ProductPhotoImg").removeClass("non-fixed");
$("#option_total").removeClass("non-fixed");
$(".product-single__title").removeClass("non-fixed");
}
});
Thanks for the help

You have more issues than only finding the footer's position here...
First is to find the position of the footer instead of hardcoding a value.
Okay...
Second is that you constantly add and remove classes on scroll.
This sure isn't the desired effect.
The scroll event fires like a dozen times or more on a single mouse wheel spin.
Third is that you force jQuery to lookup for elements, as #Taplar mentionned in comments, each times the script executes (Which is real bad if the script execute constantly!!). This is bad... And unuseful, since this those elements don't change.
So I modified your script... Almost completely :
;)
// Define an element collection ONCE.
var elementsList = $(".product-form__item--quantity, .product-form__item--submit, #ProductPhotoImg, #option_total, .product-single__title");
// Find the footer's position.
var footerPosition = $("#footer").offset().top;
// Set a flag to prevent the the script action when already done.
var footerVisible = false;
$(window).scroll(function (event) {
// How many pixels scrolled + viewport height = position of the last pixel at the bottom of the viewport relative to the document's top.
var viewportBottom = $(this).scrollTop() + $( window ).height();
if (viewportBottom >= footerPosition) {
if(!footerVisible){
// Will update classes on the element in the elementslist collection on user scroll enought to show the footer in viewport.
elementsList.addClass("non-fixed").removeClass("change change-option");
// Set a flag
footerVisible = true;
}
} else {
if(footerVisible){
// Will update classes on the element in the elementslist collection on user scroll from a "visible footer" to a footer below the viewport.
// In other words, You don't want to do it CONSTANTLY except when the footer is visible and dissapears due to user scroll up.
elementsList.removeClass("non-fixed");
// reset the flag.
footerVisible = false;
}
}
});

Related

How to make a div appear and disappear on scroll

I'm currently trying to get a div container to slide in from one side once the user has scrolled down a certain amount of px and disappear after the user has scrolled down another set amount of px.
This page has what I want to do - http://2014.igem.org/Team:CU-Boulder
If anyone can help me, I'd really appreciate it.
To get user's scroll data you can use scrollTop() jQuery method.
Description: Get the current vertical position of the scroll bar for
the first element in the set of matched elements or set the vertical
position of the scroll bar for every matched element.
For example:
$(window).scroll(function() {
var currentHeight = $(window).scrollTop();
if (currentHeight > 200) {
// some action
}
if (currentHeight > 300) {
// another action
}
});
You might be interested looking at this WOW plugin, or at this scrollrevealjs.

Sidebar move after user scrolls down x amount

Let's get straight to it: When the user scrolls x amount, I want the sidebar to begin to move.. Now, once the sidebar reaches its' end, I want it to stay fixed and scroll to the footer. Here's what I got.
http://jsfiddle.net/Ajp44/
Here's my Javascript:
$(document).ready(function() {
// Cache selectors for faster performance.
var $window = $(window),
$sidebar = $('#anchor'),
$sidebarAnchor = $('#right');
// Run this on scroll events.
$window.scroll(function() {
var window_top = $window.scrollTop();
var div_top = $sidebarAnchor.offset().top;
if (window_top > div_top) {
// Make the div sticky.
$sidebar.addClass('stick');
$sidebarAnchor.height($sidebar.height());
}
else {
// Unstick the div.
$sidebar.removeClass('stick');
$sidebarAnchor.height(0);
}
});
});
For some reason JSfiddle isn't displaying what the Javascript is doing, but if you run it on your PC you can see. Whenever the user scrolls passed the ending of the sidebar, the sidebar doesn't scroll down with them like it is suppose to, instead, it jumps of to the right side of the page...
So my question is this: how do I stop the sidebar from jumping to the side of the page, and keep it within the restraints of the parent DIV?
Cheers!
Don't do right : 0 in your stick class. In fixed elements, the position attributes are relative to the viewport.
https://developer.mozilla.org/en-US/docs/Web/CSS/position#Fixed_positioning

Floating elements on scroll

I was wondering how sites like Facebook, with their timeline feature, float a certain element (usually a menu bar, or sometimes a social plugin, etc) when the user has scrolled past a point such that the top of the element is off the screen, etc.
This could be seen as a more general JavaScript (jQuery?) event firing when the user has scrolled to a certain element, or scrolled down a certain number of pixels.
Obviously it would require toggling the CSS property from:
#foo { position: relative; }
to
#foo { position: fixed; }
Or with jQuery, something like:
$('#foo').css('position', 'fixed');
Another way I have seen this implemented is with blogs, where a popup will be called when you reach the bottom, or near the bottom of a page. My question is, what is firing that code, and could you link or provide some syntax/ semantics/ examples?
Edit: I'm seeing some great JS variants coming up, but as I am using jQuery, I think the plugin mentioned will do just nicely.
Take a look at this jsfiddle: http://jsfiddle.net/remibreton/RWJhM/2/
In this example, I'm using document.onscroll = function(){ //Scroll event } to detect a scroll event on the document.
I'm then calculating the percentage of the page scrolled based on it's height. (document.body.scrollTop * 100 / (document.body.clientHeight - document.documentElement.clientHeight)).
document.body.scrollTop being the number of pixels scrolled from the top, document.body.clientHeight being the height of the entire document and document.documentElement.clientHeight being the visible portion of the document, a.k.a. the viewport.
Then you can compare this value to a target percentage, an execute JavaScript. if(currentPercentage > targetPercentage)...
Here's the whole thing:
document.onscroll = function(){
var targetPercentage = 80;
var currentPercentage = (document.body.scrollTop * 100 / (document.body.clientHeight - document.documentElement.clientHeight));
console.log(currentPercentage);
if(currentPercentage > targetPercentage){
document.getElementById('pop').style.display = 'block';
// Scrolled more than 80%
} else {
document.getElementById('pop').style.display = 'none';
// Scrolled less than 80%
}
}
​If you prefer jQuery, here is the same example translated into everybody's favorite library: http://jsfiddle.net/remibreton/8NVS6/1/
$(document).on('scroll', function(){
var targetPercentage = 80;
var currentPercentage = $(document).scrollTop() * 100 / ($(document).height() - $(window).height());
if(currentPercentage > targetPercentage){
$('#pop').css({display:'block'});
//Scrolled more than 80%
} else {
$('#pop').css({display:'none'});
//Scrolled less than 80%
}
});​
An idea would be to handle the window.scroll event and determine if the user has scrolled to the bottom of the page. Here is an example:
http://chrissilich.com/blog/load-more-content-as-the-user-reaches-the-bottom-of-your-page-with-jquery/
Hope it helps!
There is a jquery plugin that might help you in the right direction.
http://imakewebthings.com/jquery-waypoints/
I just answered basically the same question here. In that case it was a table and its header, and the basic idea is like this:
function placeHeader(){
var $table = $('#table');
var $header = $('#header');
if ($table.offset().top <= $(window).scrollTop()) {
$header.offset({top: $(window).scrollTop()});
} else {
$header.offset({top: $table.offset().top});
}
}
$(window).scroll(placeHeader);
Here's a demo.
Quoting myself:
In other words, if the top of the table is above the scrollTop, then
position the header at scrollTop, otherwise put it back at the top of
the table. Depending on the contents of the rest of the site, you
might also need to check if you have scrolled all the way past the
table, since then you don't want the header to stay visible.
To answer your question directly, it is triggered by checking the scrollTop against either the position of an element, or the height of the document minus the height of the viewport (for the scrolled to bottom use case). This check is done every time the scroll event is fired (bound using $(window).scroll(...)).

On scroll load data on demand

I am implementing on demand loading of data through scrolling.
I have register the function in document.ready for a div.
The data should only be populated once the scroll is reached to the last. so to identify whether the scroll has reached till the last i am using the below function.
$("#tree").scroll(function () {
if (isScrolledToBottom(this)) {
}
});
But the function is not returning the correct value. What I mean is it should return the a true value when scroll has reached to its last.
function isScrolledToBottom(object) {
return ($(object).attr('scrollHeight') - $(object).scrollTop() - 1) <= $(object).height();
};
Try this instead :
return ($(object).attr('offsetHeight') + $(object).attr('scrollTop') >= $(object).attr('scrollHeight'));
If you want to do infinite scrolling, check out my answer here:
How to load the web page content based on user scrolling
This demo is triggered at a certain Y scroll position. If you are looking to accomplish this specifically when a user reaches a certain item, you might want to look at the Waypoints plugin.
http://imakewebthings.com/jquery-waypoints/
Infinite scroll Demo: http://imakewebthings.com/jquery-waypoints/infinite-scroll/
$('.theItems:last').waypoint(function(event, direction) {
//Ajax fetch here
});
var scrollHeight = $(object).prop("scrollHeight"); // total scrollable height of the element
var scrollTop = $(object).scrollTop(); // how far you have come from the top while scrolling vertically
var height = $(object).height(); // the constant height of the portion in display at all times
if (scrollHeight === (scrollTop + height)) {
//console.log("fetching page");
fetchNextPage();
}

Efficient way to select elements touching top edge of viewport

What would be computationally-efficient ways to select elements touching the top edge of browser window viewport as the page is scrolled?
See attached image. Green elements are selected because they are touching the top edge.
UPDATE
An example of how I'll use this is to fade elements that are going off-screen. There may be hundreds of them on the page. Imagine a page like Pinterest. Computing offset and scrollTop for hundreds of them at the rate of scroll event, even if throttled still feels really inefficient.
This is what I came up with. I think that it could be improved upon by caching the scrollTop values, but this is pretty good. I have included the framework for caching the boxtops, but not the implementation code. I have also only implemented scrolling down to hide divs. I have left reshowing them on upscroll as an exercise for you.
When the window is scrolled we get the last hidden div. We know that everything before this div is already hidden. Then use a 'while next element is off the screen' hide it. As soon as a div isn't off the screen we abort. Thus saving time from iterating through the entire list.
http://jsfiddle.net/kkv3h/2/
//track whether user has scrolled up or down
var prevScrollTop = $(document).scrollTop();
$(document).scroll(function() {
var currentScrollTop = $(this).scrollTop();
if (currentScrollTop > prevScrollTop) {
//down
var lasthiddenbox = $('.fadeboxhidden:last');
var nextbox = (lasthiddenbox.length > 0) ? lasthiddenbox.next('.fadebox') : $('.fadebox:first');
while (nextbox.length) {
console.log('box: ' + nextbox.offset().top + ' scroll: ' + currentScrollTop);
if (nextbox.offset().top < currentScrollTop) {
nextbox.animate({ opacity: 0 }, 3000).addClass('fadeboxhidden');
}
else { return; }
nextbox = nextbox.next('.fadebox:first');
}
} else {
//up
}
prevScrollTop = currentScrollTop ;
});
//create an object to hold a list of box top locations
var boxtops = new Object;
//gather all boxes and store their top location
$('.fadebox').each( function(index) {
//you may want to dynamically generate div ids here based on index. I didn't do this
//because i was already using the id for positioning.
var divid = $(this).prop('id');
boxtops[divid] = $(this).offset().top;
//console.log(boxtops[divid]);
});
I'm thinking the best way would be that you could mark elements you want to determine hit testing with by some class, say "hit-test-visible" or something. Then, for those elements, on the scroll event, you should be able to find their offset compared to the document - see jQuery offset, and then based on the scroll value, if the offset is less than the scroll, and the offset + element height is greater than the scroll offset, then the element should be "touching" the top edge.

Categories