I want to slid a div on window scroll to bottom. When document reach 800 (bottom) Div should scroll right 0 and less then 800 it should slid and hide.
Problem is when scrolling to bottom div is sliding and showing but again when scrolling to top it doesn't slid and hide.
This is my code
$(document).scroll(function () { // remove "$"
var s = $("#slidebox");
var y = $(this).scrollTop();
if (y > 800) {
s.animate({"right":"-450px"}, "slow");
} else if (y < 800) {
s.animate({"right":"0px"}, "slow");
}
});
Basically i want is to hide and show (with a slid effect) div on document scroll to bottom.
Check scrolling below jsfiddle.
jsfiddle
On one hand, user390....'s response is correct in that the height is calculated incorrectly.
On the other hand, the way animations work is that they queue up one after another, so sometimes the div doesn't slide in/away until everything else before it is done. Using .stop() fixes the issue.
var s = $("#slidebox");
$(document).scroll(function () { // remove "$"
var y = $(this).scrollTop() + $(window).height();
console.log(y);
if (y > 800) {
s.stop().animate({"right":"-450px"}, "slow");
} else {
s.stop().animate({"right":"0px"}, "slow");
}
});
Your problem is that the value you are using for your "Did I reach the bottom" if statement is wrong.
Here is the calculated value you should be using:
$(document).scroll(function () { // remove "$"
var s = $("#slidebox");
var y = $(this).scrollTop();
var bottom = jQuery(document).height() - jQuery(window).height();
if (y >= bottom) {
s.animate({"right":"-450px"}, "slow");
} else {
s.animate({"right":"0px"}, "slow");
}
});
Plus, I'd also recommand you to use a .stop(true, true) on your animated element before triggering the "animate" function if you don't want people to mess around with it.
Related
I'm currently making an overlay that covers a sticky top bar when the user has scrolled beyond a certain point (down) and disappears when scrolling back up. However, I'd like to be able to scroll for at least 50px before the code is executed (something like a gap before the overlay is triggered).
$(function() {
var prevScroll = $(document).scrollTop(); //initial position
$(window).scroll(function() {
var newScroll = $(document).scrollTop(); //position from top after scrolling
if(newScroll > prevScroll) { // checks if the user has scrolled up or down
var fromNew = $(document).scrollTop(); // holds value to compare with the position + gap amount
if (fromNew > newScroll + 50) { //checks to see if scrolled for 50px
$("#stick-start").fadeIn("fast");
prevScroll = newScroll + 50; //initial position + scrolled amount
};
} else {
var fromNew = $(document).scrollTop();
if (fromNew > newScroll - 50) {
if ($("#stick-start").hasClass("is-stuck")) {
$("#stick-start").fadeOut("fast");
prevScroll = newScroll - 50;
};
};
};
});
});
The condition that checks whether you're scrolling up or down works. But as it is now, the overlay just keeps fading in and out repeatedly. How do I make it so that you have to scroll at least 50px before anything happens ?
I think this should get you where you're going.
var $document = $(document);
$(window).scroll(function() {
if ($document.scrollTop() >= 50) {
$("#stick-start").fadeIn("fast");
} else {
$("#stick-start").fadeOut("fast");
}
});
EDIT: had an error, should be good now.
$(window).scroll(function() {
if ($(this).scrollTop() >= 50) {
$("#stick-start").fadeIn();
} else {
$("#stick-start").fadeOut();
}
});
I'm trying to get the div to snap to the center of the viewport, right now it just snaps to the top. I was trying to put an offset of 50% but can only get it in px's.
EDIT
I added a new fiddle where I tried to include $(window).scrollTop() / 2)
http://jsfiddle.net/kZY9R/84/
$("#item").offset().top - 100
var body = $("html, body");
var items = $(".item");
var animating = false;
$(window).scroll(function() {
clearTimeout($.data(this, 'scrollTimer'));
if (!animating) {
$.data(this, 'scrollTimer', setTimeout(function() {
items.each(function(key, value) {
if ($(value).offset().top > $(window).scrollTop()) {
animating = true;
$(body).stop().animate( { scrollTop: $(value).offset().top }, 1000,'swing');
setTimeout(function() { animating = false; }, 2000);
return false;
}
});
}, 50));
}
});
I found this:
$('html, body').animate({scrollTop: $('#your-id').offset().top -100 }, 'slow');
Source: Run ScrollTop with offset of element by ID
Here's the trick to keep your viewport centralized on a particular div.
Prerequisites
You need to take into account the following three criteria to be able to centralize the viewport on a given item:
height of the last item that appeared on the viewport.
The distance of the last item from the top of the page, i.e. the offset().top of the item.
The height value of the viewport (i.e the window object).
Calculating Vertical Position of the Item
The required scrollTop value for the window can be calculated as in the following:
var scrollValue = itemOffset // offset of the item from the top of the page
- .5 * windowHeight // half the height of the window
+ .5 * itemHeight; // half the height of the item
You are basically, moving the top of your viewport to the item under view's top offset initially. This, as you've already experienced, snaps the item to the top of the window.
The real magic part comes when you subtract half of the window's height to go halfway along it vertically, and then shifting your view back down by adding half the item's height. This makes the item appear vertically centralized with regards to the viewport.
Note:
To be able to query the last item that appeared on the viewport, you have to iterate over all of the elements that have a top offset value (i.e. offset().top) less than or equal to that of the window's scrollTop value:
$.each($('.item'), function(i, value) {
if ($(viewport).scrollTop() >= $(this).offset().top) {
lastItemInView = $(this);
}
});
With the above, the lastItemInView variable will always end up with the last element visible in the window.
Demo
Not sure if you figured this out yet or not but I took some code from this answer (How to tell if a DOM element is visible in the current viewport?) that shows how to tell if an element is visible in the view port.
Using that I modified your code to loop through each item and find the first visible one in the viewport and then center that one also factoring in the margin-top you have. Let me know if this helps!
Fiddle: http://jsfiddle.net/kZY9R/86/
var body = $("html, body");
var items = $(".item");
var animating = false;
$(window).scroll(function() {
clearTimeout($.data(this, 'scrollTimer'));
if (!animating) {
$.data(this, 'scrollTimer', setTimeout(function() {
items.each(function(key, value) {
if (elementInViewport(value)) {
animating = true;
var margin = parseInt($(value).css('margin-top'));
$('html,body').animate({
scrollTop: $(value).offset().top - ($(window).height() + margin - $(value).outerHeight(true)) / 2
}, 200);
setTimeout(function() {
animating = false;
}, 2000);
return false;
}
});
}, 50));
}
});
function elementInViewport(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while (el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
}
I'm in a One Page project, and I need a DIV to increase the height while scrolling down, but when scrolling up, keep the height, and does not decrease.
I'm using JQuery with the following code:
$(function(){
$(window).scroll(function() {
var $broca = $('#corpo');
var st = $(this).scrollTop();
$broca.height( st - 600 );
if( st == 0 ) {
$broca.hide();
} else {
$broca.show();
}
}).scroll();
To detect if the scrolling is going down, or up, you can always store the last value of the scroll, and then compare it to the scrollTop() at the event handler:
var lastVal = 0;
$(window).scroll(function() {
var st = $(this).scrollTop();
if (st > lastVal){
// Is scrolling down... Increase height of div
} else {
// Is scrolling up, do nothing...
}
lastVal = st;
});
I have a series of divs that are 100% height with a scroll to function that takes you to the next div out of the viewport on background click. However, if the next div is already slightly in the viewport the whole thing is counted as being visible and the scroll to bypasses it. Can anyone offer direction on how to get the script to scroll to the div even if it's partially in the viewport already?
Codepen here.
If you begin scrolling slightly in the codepen and then click on the background you'll see that it doesnt scroll you to the div that's already in the viewport but the div after that.
$(document).ready(function() {
// get initial nav height
var $window = $(window);
var wst = $window.scrollTop();
var th = $('div.top').height();
var currentSlide = $('#wrapper').data( 'current-slide', $('div.slide').eq(0) );
$('div.scroll_images').css({ height: 'auto', overflow: 'visible', top: 0 });
$('div.scroll_images div.inner').css({ position: 'absolute', top: 0 });
$('div.slide').each(function() {
$(this).css('padding',function() {
return (($(window).height()-$(this).height())/2)+'px 0'
});
});
// scrollto for click on slide
jQuery.fn.scrollTo = function(hash) {
$this = $(this);
st = $this.offset().top - th; // subtract nav height
$('html, body').animate({ scrollTop: st }, 550
);
}
$('#wrapper').click(function(e){
//get the current slide index from the body tag.
$this = currentSlide.data( 'current-slide' );
$next = $(".slide:below-the-fold");
if($next.length) {
$next.scrollTo($next.attr('id'));
//Save the next slide as the current.
$('#wrapper').data( 'current-slide', $next );
} else {
//Throw us back to the top.
$('div.slide:first').scrollTo($('div.slide:first').attr('id'));
//Save the first slide as the first slide, which
//Cycles us back to the top.
$('#wrapper').data( 'current-slide', $('div.slide:first'));
}
})
//Images fade in
$('img').hide();
$('img').each(function(i) {
if (this.complete) {
$(this).fadeIn();
} else {
$(this).load(function() {
$(this).fadeIn();
});
}
});
//Stop links affecting scroll function
$("a").click(function(e) {
e.stopPropagation();
});
});
(function($) {
$.belowthefold = function(element, settings) {
var fold = $(window).height() + $(window).scrollTop();
return fold <= $(element).offset().top - settings.threshold;
};
$.extend($.expr[':'], {
"below-the-fold": function(a, i, m) {
return $.belowthefold(a, {threshold : 0});
}
});
})(jQuery);
Here's what I might try to do: go through each div in the series. Find the div who's offset() is closest to $(window).scrollTop(). Now, find the next() div after the "current" one and scroll to it.
For comparing the offset() of each div, try something like this:
var closest = $('[selector]:first');
$('[selector]').each(function() {
var oldDistance = Math.abs(closest.offset() - $(window).scrollTop());
var newDistance = Math.abs($(this).offset() - $(window).scrollTop());
if(newDistance < oldDistance) {
closest = $(this);
}
}
I have a webpage that has a floating div in it which follows the user as the page scrolls.
the page is made up of other divs that can be expanded and hidden using jquery slideToggle functionality.
the problem is when i hide a div, the scroll bar moves down the page as the div is hidden instead of staying at the top of the page. any idea why this is happening?
Code for the Scroll:
var scrollPos;
$().ready(function () {
var $scrollingDiv = $("#FloatingClaimToolBar");
$(window).scroll(function () {
var top = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;
// global var
scrollPos = top;
$scrollingDiv
.stop()
.animate({ "marginTop": (top - 15) + "px" }, 0);
});
});
After the div is hidden i call this method with the intention of positioning the floating div back to the top of the page but it doesn't work:
function AdjustToolBar(divID) {
var $scrollingDiv = $("#FloatingClaimToolBar");
$scrollingDiv
.stop()
.animate({ "marginTop": (window.scrollPos-15) + "px" }, 0);
}