When I click my button, I append a new div. I would like that, if any part of the div is not visible to the window, scroll untill it shows.
So if it is upwards from the center of the window, scroll up JUST until you see it's top, and if it is downwards from the center, scroll down just until you see its bottom.
In my searchings I found https://api.jquery.com/scrollTop/ , but that doesn't seem to be what I'm describing
I only want to scroll enough to display it entirely on screen, not always on top
Check this working fiddle for the solution.
You can use scrollTop() to scroll to any div. First we need to find the direction of the scroll to correctly provide the value for scrollTop() function. This can be found using position().
$('#button4').click(function() {
// check if the div lies below the button
if ($('#div3').position().top - $('#button4').position().top > 0) {
// in this case we need to add shift
var shift = $(window).height() - $('#div3').height();
} else {
var shift = 0;
}
$(window).scrollTop($('#div3').offset().top - shift);
});
Alternatively if you wish to check the position of the div relative to the current viewport (or the center of the current window view) you can use getBoundingClientRect() like:
$('#button4').click(function() {
// check if the div lies below the viewport
if ($('#div3')[0].getBoundingClientRect().top > 0) {
// in this case we need to add shift
var shift = $(window).height() - $('#div3').height();
} else {
var shift = 0;
}
$(window).scrollTop($('#div3').offset().top - shift);
});
Here is the alternate fiddle.
So if you are using jQuery.
//scroll top of element
var $myNewElement = $(".new-element-class");
$('html, body').scrollTop($myNewElement.offset().top)
I think this should work. Make sure your div is appended before calling the scrollTop function.
If I understand correctly, this jsfiddle is what you are looking for.
I also added a simple animation so the document doesn't awkwardly jump around the viewport.
Features
If a new element is created, and part of that new element is below the current viewport, the document will be scrolled until the bottom of the viewport is shown. Vice versa if part of the new element is above the current viewport.
If the new element is completely visible within the current viewport, no scrolling will occur.
All scrolling effects are animated.
A configurable offset (Leave some padding instead of scrolling to the very edge of the new element)
How it works
When the button is clicked, a new div element is appended.
$('section').append('<div>');
Next, we figure out if this div is above the current viewport using the below function:
function isElementAboveViewport(element) {
return $(element).offset().top < $(window).scrollTop();
}
in an if statement:
if (isElementAboveViewport($('section > div:last-child'))) {
...
}
If the condition is truthy, we scroll! (offset is configurable - In the JS fiddle, I used 40 which is the height of the button covering the top 40px of the viewport)
$('html, body').animate({
scrollTop: $('section > div:last-child').offset().top - offset
}, 1000);
Now, we check if the new element is below the current viewport with a similar function:
function isElementBelowViewport(element) {
return $(element).offset().top + $(element).height() > $(window).scrollTop() + $(window).height();
}
If the element is too far down in the document, we scroll! (Again, offset is configurable)
$('html, body').animate({
scrollTop: $('section > div:last-child').offset().top + $('section > div:last-child').height() - $(window).height() + offset
}, 1000);
Please let me know if this is what you were looking for and/or if you have any questions about how it works.
Related
I have a div called cop which has a fixed position.
That div should behave same as the questions tab (which is similar) but it is changing its position when page is scrolled .
My Script
$(window).scroll(function()
{
var top = 100 * $(window).scrollTop() / ($(document).height() - $(window).height());
if (top > 40)
{
$(".cart, .top").fadeOut();
}
else
{
$(".cart, .top").fadeIn();
}
});
I have created a working example on CODEPEN. It is easier to understand it in action. First you need to read the scroll event where you can take action on your desired element:
$(window).scroll(function() {
currentTop = $("body").scrollTop();
if (currentTop > 300) {
$(".cop").addClass("copChange");
} else {
$(".cop").removeClass("copChange");
}
});
When you scroll more than 300px in this example, your .cop div will acquire relative position instead of fixed. It will return to original setting when you scroll up. I attempted by different CSS class since it will be easy for you to change styling in any way you want.
How do I apply a fadeIn and fadeOut jquery effect to an element once a div element reaches or hits the topmost part of the screen?
if ($("#divId").scrollTop() == 0) {
$("#element").fadeIn();
}
This should do it:
//bind to the window scroll event, so we check the position every time the user scrolls
$(window).on('scroll', function () {
// scrollTop() will give you the current window scrolling position,
// while position().top will give you the vertical position of your element.
// when the scroll position is >= to the vertical pos of the element...
// it means that ht element is now at the top of the screen.
if( $('body').scrollTop() >== $('#divId').position().top) {
$('#divId').fadeOut();
}else{
$('#divId').fadeIn();
}
});
You should check for top value in the offset(). offset gives you the coordinates w.r.t. the document.
Call the function every time your div changes its position and check for -
if($("#yourDiv").offset().top == 0){
//fadeOut
}
Hope this helps!
I'm trying to fix a elements position based on the scroll position within the window.
I thought it would be as easy as getting the offset of the element where the fixed element should become fixed and then when the window.scrollTop is equal to it add CSS but it is weird.
It seems as though the offset of the element is larger than the scrollTop largest numeral.
Is there any other way of getting this to work?
I want it to have the same functionality as this with regards to the footer on scroll;
http://be.blackberry.com/
But I don't want to clone the element, I want to detect when it gets to near the bottom of the page and then change the position on the bottom of the element.
Thanks in advance.
B
This should help get you in the right direction:
var footer = $("#footer");
// min amount to show when not scrolled to the bottom of the page.
var minVisable = 25;
$(parent.document).scroll(function() {
// check position
if (window.scrollY + window.innerHeight + minVisable > $("html").height()) {
// if at the bottom of the page, stick the footer to it
footer.css("position","absolute").css("top", $("html").height() - footer.height());
} else {
// else keep top part of footer on the screen
footer.css("position","fixed").css("top", window.innerHeight - minVisable );
}
});
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(...)).
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.