I'm using the following javascript for the top of page logo/section before the footer here:
<div id="townEnd">InsideTown</div>
<script>
$(document).ready(function(){
// hide #townEnd first
$("#townEnd").hide();
// fade in #townEnd
$(function () {
$(window).scroll(function () {
if ($(this).scrollTop() > 1000) {
$('#townEnd').fadeIn();
} else {
$('#townEnd').fadeOut();
}
});
// scroll body to 0px on click
$('#townEnd a').click(function () {
$('body,html').animate({
scrollTop: 0
}, 800);
return false;
});
});
});
</script>
How would I calculate when the logo should fadein at the end of the page? I just used 1000 as an example. It only seems to work when I scroll really fast too.
First, you should just use this.scrollTop instead of $(this).scrollTop() - it might not look like much to you, but it is a HUGE thing.
On the same path, you can use this.scrollHeight to get the height of the scrollable area. Subtract this.innerHeight to get the maximum scroll position, then subtract about 30 pixels to give yourself some padding.
if( this.scrollTop < this.scrollHeight - this.innerHeight - 30)
You should also have a boolean to keep track of the state of the element, maybe isfadedin, which you update. Then, only call fadeIn and fadeOut if the state changes. This will save a LOT of processing time!
Vanilla JS is awesome :p
Related
I am trying to build a simple vertical timeline. You can click up or down to scroll it little by little but I also wanted to have it jump, smooth scroll, to anchors. This somewhat works but the behavior is unpredictable.
This isn't usually difficult but something new for me is that the scrolling behavior is inside a div so the whole page shouldn't be moving.
You can try it in the fiddle. Clicking random buttons will sometimes bring you to the right spot, other times it will just scroll to a random place.
JSFiddle
Here is the basic Jquery.
var step = 280;
var scrolling = false;
$(".scrollUp").bind("click", function (event) {
event.preventDefault();
$("#timeline").animate({
scrollTop: "-=" + step + "px"
});
})
$(".scrollDown").bind("click", function (event) {
event.preventDefault();
$("#timeline").animate({
scrollTop: "+=" + step + "px"
});
})
$('.timelineButton').click(function () {
$('#timeline').animate({
scrollTop: $($(this).attr('href')).offset().top
}, 2000);
return false;
});
A few things need fixing :
Use .position().top (relative to offset parent) instead of .offset().top (relative to document)
Specify the offset parent by styling the #timeline container with position: relative
Because .position() returns dynamically calculated values, .position().top will be the value-you-want minus the current-scrollTop. Therefore you need to add the current-scrollTop back on.
CSS
#timeline {
...
position: relative;
}
Javascript
$('.timelineButton').click(function (event) {
event.preventDefault();
$('#timeline').animate({
scrollTop: $($(this).attr('href')).position().top + $('#timeline').scrollTop()
}, 2000);
});
Demo
Add Ids to each div & use that ID like href="#ID". This will scroll window to that particular section ID given in href
Check this
$('.timelineButton').click(function () {
if($('#timeline').is(':animated')){}else{
$('#timeline').animate({
scrollTop: $($(this).attr('href')).offset().top
}, 2000);
return false;
}
});
.is(':animated') will be tell you if the element is animating, if not, animate it.
It prevent the unpredictable jumps.
EDIT
Best way to prevent this is: .stop().animate
$('.timelineButton').click(function () {
$('#timeline').stop().animate({
scrollTop: $($(this).attr('href')).offset().top
}, 2000);
return false;
});
EDIT V2
Check this Fiddle: https://jsfiddle.net/a489mweh/3/
I have to put the position offset of each elements in an array, becouse every animate in timeline change the offset.top of each element.Check the data-arr="0" over each button, to tell the array what position of the element have to retrieve.Tell me if works.
Cheers
i'am trying to make the airbnb.nl effect where a 'how it works' div appears from the top on button click. Then when you scroll down (or click the close button) it disappears again.
When the div is hide after scrolling to 630px the scrollbar shoots up so i've set the scrollbar to 0 at the same time. Problem is that it keeps repeating this 'scrollTop to 0' script when you scroll down further, making it a unwanted loop.
Any suggestions on how to only use this script (scrollTop -> 0) once, while the div is shown? Or maybe even prettier solutions? ;)
This is where it's live: www.energyguards.nl (and i disabled the scrollTop function there for now)
jQuery(document).on('click', '.flip', function(e){
e.preventDefault();
jQuery(".panel").slideToggle("slow");
});
$(window).scroll(function(){
if($(this).scrollTop() > 630) $('.panel').hide();
if($(this).scrollTop() > 630) $(window).scrollTop( 0 );
});
Hope to hear from you guys,
cheers Joeri
Check this DEMO out http://jsfiddle.net/yeyene/46o7chfu/1/
Hope you means like this.
JQUERY
$(document).ready(function () {
// scroll to top and show top content
$('#show_top_bar').on('click',function(){
$('html, body').stop().animate({
scrollTop: 0
}, 300, function() {
$('#top_bar').slideDown(300);
});
});
// hide top content on click close icon
$('#close_top_bar').on('click',function(){
$('#top_bar').slideUp(100);
});
});
$(window).scroll(function() {
// hide top content when scroll position is top of content
if($(this).scrollTop() > $('#content').position().top){
if($('#top_bar').css('display') !== 'none') {
$('#top_bar').slideUp(0);
$('html, body').stop().animate({
scrollTop: 0
}, 0 );
}
}
});
I am building a full page slider that keeps the native scrollbar and allows the user to either free scroll, use the mouse wheel or navigation dots (on the left) to switch to a slide.
Once the user is on the last slide and tries to scroll down further, the whole slider moves up to reveal a simple scrollable section. If the user scrolls down and then tries to go back up, then this new section moves out of the way again and returns the slider back into view.
Fiddle: http://jsfiddle.net/3odc8zmx/
The parts I'm struggling with:
Only the first two navigation dots work. The third one DOES WORK if you area looking at the first slide. But doesn't do anything, if you are on slide 2. Note: the purple one is a short-cut to the second section of the page and not related to the slider.
When moving to the last slide (via the dots, if you're on the first slide) it causes the code to make the whole slider move upwards as it sees this as the user has slid past the last slide as per the description above. I have tried to combat this using a variable called listen to stop the scroll event listening when using the showSlide method... but it seems to be true even though I set it to false, and only reset it to true again after the animation...
When scrolling down using the mouse wheel, I can get to the second section and back up, but not to the first third section. I'm wondering if I could use the showSlide method to better handle this instead of the current dirty next and prev functions I have implemented.
Note: If the user has free-scrolled, when they use the mouse-wheel, I want the slider to snap to the nearest slide to correct itself... Any suggestions for how I could do this?
Can anyone offer some help?
Here's the JS:
var listen = true;
function nextSlide()
{
$('#section1').stop(true,false).animate({
scrollTop: $('#section1').scrollTop() + $(window).height()
});
}
function prevSlide()
{
$('#section1').stop(true,false).animate({
scrollTop: -$('#section1').scrollTop() + $(window).height()
});
}
function showSlide(index)
{
var offset = $('#section1 div').eq(index).offset();
offset = offset.top;
if(offset){
listen = false;
$('.slide-dot').removeClass('active');
$('.slide-dot').eq(index).addClass('active');
$('#section1').stop(true,false).animate({
scrollTop: offset
}, 500, function(){
listen = true;
});
} else {
alert('error');
}
}
$(document).ready(function(){
var fullHeight = 0;
$('#section1 div').each(function(){
fullHeight = fullHeight + $(this).height();
});
var lastScrollTop1 = 0;
$('#section1').on('scroll', function(e){
var st = $(this).scrollTop();
if (st > lastScrollTop1){
if( $('#section1').scrollTop() + $(window).height() == fullHeight) {
if(listen){
$('body').addClass('shifted');
}
}
}
lastScrollTop1 = st;
});
$('#section1').on('mousewheel', function(e){
e.preventDefault();
var st = $(this).scrollTop();
if (st > lastScrollTop1){
nextSlide();
} else {
prevSlide();
}
});
var lastScrollTop2 = 0;
$('#section2').on('scroll', function(e){
var st = $(this).scrollTop();
if (st > lastScrollTop1){
} else {
if( st == 0 ){
$('body').removeClass('shifted');
}
}
lastScrollTop1 = st;
});
$('.slide-dots').css({'margin-top':-$('.slide-dots').height() / 2});
$('.slide-dot').first().addClass('active');
$(document).on('click', '.slide-dot', function(e){
e.preventDefault();
showSlide( $(this).index() );
});
$(document).on('click', '.slide-dot-fake', function(e){
e.preventDefault();
$('body').addClass('shifted');
});
});
And for those wondering why I'm not using something like fullPage.js, it's because it can't handle the way I want to transition between the two areas and have two scrollbars (one for each area).
You can use:
e.originalEvent.wheelDelta
instead of:
st > lastScrollTop1
in the mousewheel event for your third problem to check if the user has scrolled up or down. And also change the +/- in prevSlide. I used dm4web's fiddle for your first problem. And I used:
scrollTop: offset - 1
instead of:
scrollTop: offset
for your second problem, because when the scroll reaches to the last pixel of the third element, it automatically goes to the next section, so 1 pixel is enough for it not to.
Here's the fiddle: http://jsfiddle.net/3odc8zmx/3/
As suggested by #chdltest, you could do it by using fullPage.js.
Here's an example. Go to the last section.
Code used for the example:
Javascript
$('#fullpage').fullpage({
sectionsColor: ['yellow', 'orange', '#C0C0C0', '#ADD8E6'],
scrollOverflow: true,
scrollBar: true,
afterLoad: function (anchor, index) {
//hiding the main scroll bar
if (index == 4) {
$('body, html').css('overflow', 'hidden');
}
//showing the main scroll bar
if (index == 3) {
$('body, html').css('overflow', 'visible');
}
}
});
CSS (in case you prefer to use the normal style for it)
/* Normal style scroll bar
* --------------------------------------- */
.slimScrollBar {
display: none !important;
}
.fp-scrollable {
overflow: auto !important;
}
Advantages of using fullPage.js instead to your own code:
Strongly tested in different devices and browsers. (IE, Opera, Safari, Chrome, Firefox..)
Prevent problems with trackpads, Apple laptops trackpads or Apple Magic Mouse.
Old browser's compatibility, such as IE 8, Opera 12...
Touch devices compatibility (IE Windows Phone, Android, Apple iOS, touch desktops...)
It provides many other useful options and callbacks.
I've been trying to fade out a splash when scrolling down, and fading it in when scrolling back to the top of the page. It seems to work ok when scrolling down, but when I go back, it doesn't fades in. I tryed using fadeIn and FadeOut instead of fadeTo but didn't get a proper behavior
The code is actually pretty simple:
var splashTop = $('.splash-container').offset().top;
$(window).scroll(function () {
if ((splashTop - $(window).scrollTop()) < 50) {
$('.splash-container').stop().fadeTo("slow", 0);
} else {
$('.splash-container').stop().fadeTo("fast", 1);
}
});
And here is the jsFiddle example:
jsFiddle
If you just need to check if the scroll is at the top or not then you don't need to check the position of the Splash, Try:
$(window).scroll(function () {
if ($(window).scrollTop() > 0) {
$('.splash-container').stop().fadeTo("slow", 0);
console.log('p')
} else {
$('.splash-container').stop().fadeTo("fast", 1);
console.log(box1Top)
}
});
Check the Demo Fiddle
Edit
Now why your code doesn't work? ... Because you are always getting a value less than 50:
splashTop = 8 always
-
$(window).scrollTop() = more than 0
Then the result is always negative or 8 as max, you can never have a number more than 8 and your else condition is useless.
I have the following script:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$("#reas").fadeIn(2000);
$(".footer").fadeIn(2000);
$(".master_footer").css("position", "relative");
}
});
The script above changes the position of .master_footer if the user scrolls below #reas. But when i go up the position for .master_footer remains at relative. What can I do to reset it to position:absolute when the user scrolls back up?
by changing only the js code:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$("#reas").fadeIn(2000);
$(".footer").fadeIn(2000);
$(".master_footer").css("position", "relative");
}else{
$(".master_footer").css("position", "absolute");
}
});
But i would rather use something like:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$("#reas").fadeIn(2000);
$(".footer").fadeIn(2000);
$(".master_footer").addClass('relative');
}else{
$(".master_footer").removeClass('relative');
}
});
and then you can just custom your css
.relative{ position:relative; }
Assuming you've set the css for the .master_footer element previous to setting it with the javascript: in your javascript, when you want to reset the element back to its default style, just remove the style attribute from the element:
$(".master_footer").removeAttr("style");
for example:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$("#reas").fadeIn(2000);
$(".footer").fadeIn(2000);
$(".master_footer").css("position", "relative");
} else if ($(window).scrollTop() < 500){ // <-- set your reset point here
$(".master_footer").removeAttr("style");
}
});
where you would set the else if statement to whatever point you wanted to reset your element at.
First of all, I would recommend a polling solution rather than attaching an event handler to the scroll event, particularly if you intend to support older versions of IE, some of which seem to trigger the event for each pixel scrolled! E.g., you can check the scroll position as you are once per second.
Secondly, since you are using 2000ms fades, you should hold in a variable the state of the elements being faded so you don't fire a fadeOut event while the element is still being faded in (or at the very least you can stop() the existing animation).
And as far as your original question is concerned, it looks like maybe you should be able to set $('.master_footer').css('position', 'absolute') when (t < y) if you are setting position to relative when t == y. (You also might want to check t >= y in case the browser being used supports overscroll).