I am having some trouble with this one. I have the following javascript...
$(window).on('scroll', function() {
scrollPosition = $(this).scrollTop();
if (scrollPosition >= 130) {
header.animate({height: '51px'}, 500);
mainNav.css("display", "none");
logo.fadeOut("fast");
scrollLogo.delay(300).slideDown("fast");
$(this).off('scroll');
}
else {
header.animate({height: '130px'}, 500);
}
});
I am trying to do a series of changes to my header when scrolled past 130 px and then return it to its original state if scrolled back up. Everything works fine if I comment out the else statement, but as soon as I start to add to it, everything breaks. I cannot figure out why. Any help is much appreciated.
My guess would be that you're repeatedly calling either the if or the else condition, whereas you just want to call them just once.
Try something like this:
var compactHeader = false;
$(window).on('scroll', function() {
scrollPosition = $(this).scrollTop();
if (scrollPosition >= 130 && !compactHeader) {
compactHeader = true;
// Code to collapse header...
} else if (scrollPosition < 130 && compactHeader) {
compactHeader = false;
// Code to expand header...
}
});
As well as checking the scroll position we check whether the header is collapsed or expanded, to ensure the animation is only performed once.
Related
I'm trying to trigger a smooth scroll to an element at the end of the page and another one to the top of the page everytime I move the mousewheel respectively down or up. The two parts have both height:100vh.
The thing is that once it goes down it starts to behave randomly.
I feel like I need to interrupt the animation completely after the scroll is completed because it "fights with itself" struggling to go back up and vice versa. Of course I could be easiy wrong, I'm trying to learn the way.
Is there some performance issue? Maybe it is unable to get the inputs in time? Something is overlapping? It seems like there's some sort of cooldown before I can scroll again. This is what I'm trying to understand. Thanks
jQuery(window).bind('mousewheel DOMMouseScroll', function(event){
if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
// scroll up
console.log("scroll up");
jQuery('html,body').animate({scrollTop: jQuery("#top").offset().top}, 1200, 'linear');
}
else {
// scroll down
console.log("scroll down");
jQuery('html,body').animate({scrollTop: jQuery("#bottom").offset().top}, 1200, 'linear');
}
});
Same thing with this, here I'm using the Jquery.scrollTo library
jQuery(window).bind('mousewheel DOMMouseScroll', function(event){
if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
// scroll up
console.log("scroll up");
jQuery('body').scrollTo('#top', {duration:1200});
}
else {
// scroll down
console.log("scroll down");
jQuery('body').scrollTo('#bottom', {duration:1200});
}
});
Here's the html for completeness:
<div id="top" style="height:100vh;background-color: #2196f3;"></div>
<div id="bottom" style="height:100vh;background-color: #009688;"></div>
EDIT:
If I move the mousewheel just the bare minimum it works perfectly both ways so the problem is input overlapping, in other words I need a way to send just the first scroll input and not the entire scroll otherwise too many inputs make the script "crash".
here's a working example, try to scroll up and down:
https://jsfiddle.net/mr8hnxbd/
Calling .stop(true) works, but I believe it might cause issues mid animation if you keep scrolling in the direction of the animation, extending the duration of the animation. Alternatively you can do the following to ensure the animation completes before doing another animation.
(function(jQuery) {
let position = '';
let scrolling = false;
let animationDuration = 1200;
jQuery(window).bind('mousewheel', function(event){
if (event.originalEvent.wheelDelta > 0) {
// scroll up
if (scrolling || position === 'top')
return;
//console.log("scroll up");
scrolling = true; //Prevents any scrolling when scrolling is active
position = 'top'; //Prevents scrolling up when already at the top
jQuery('html,body').animate(
{
scrollTop: jQuery("#top").offset().top
},
animationDuration,
'linear',
function () {
scrolling = false; //After the animation is complete, set scroling to false
},
);
}
else {
// scroll down
if (scrolling || position === 'bottom')
return;
//console.log("scroll down");
scrolling = true;
position = 'bottom';
jQuery('html,body').animate(
{
scrollTop: jQuery("#bottom").offset().top
},
animationDuration,
'linear',
function () {
scrolling = false;
},
);
}
});
})($);
<div id="top" style="height:100vh;background-color: #2196f3;"></div>
<div id="bottom" style="height:100vh;background-color: #009688;"></div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
I need to change the style of my header, but this if condition doesn't work and log only (false) in my console and do not change anything, so i was wondering if there is a problem in my syntax or my logic.
note there no error in my console.
$(document).ready(function() {
var header = $(".hotel-header");
var scroll = $(window).scrollTop();
if (scroll >= 200) {
header.addClass("hotel-header-scroll");
console.log("true");
} else {
header.removeClass("hotel-header-scroll");
console.log("false");
}
});
As you are running this method when the document is ready , there is an error beacuse when page loads the header scroll is less than 200 therefore else condition run. I have changed $(document).ready(function() to $(window).scroll(function() this function is called when user scrolls the page. Then the method is called it will check the scroll and return the true or false based upon your condition.Below is working example
$(window).scroll(function() {
var header = $(".hotel-header");
var scroll = $(window).scrollTop();
if (scroll >= 200) {
header.addClass("hotel-header-scroll");
console.log("true");
} else {
header.removeClass("hotel-header-scroll");
console.log("false");
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="hotel-header"></div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<h1>hi</h1>
Added the <br> for some content to scroll.
I have a website with two scroll options. When you scroll down, it scrolls to the anchor Point 1.
I also have a Button which jumps to the same anchor point.
My problem: When I click the Button, the site jumps to the Anchor, but because there are two ways to the anchor, it triggers the first scroll option as well.
jQuery(document).ready(function($) {
var flag = true;
$(window).scroll(function () {
if (flag == true) {
scroll = $(window).scrollTop();
if (scroll > 50) $('#scroll-down')[0].click();
flag = false;
}
});
$(window).scroll(function () {
if (flag == false) {
scroll = $(window).scrollTop();
if (scroll < 50 )
flag = true;
}
});
});
Any solutions for this ?
From the screencast you sent, this code should scroll to the bottom of the banner when the button is clicked (provided you correctly place the anchor div):
jQuery(document).ready(function ($) {
// The button is assumed to have an id of 'scroll-down' - triggered when clicked
$('#scroll-down').on('click', function () {
// Move to the pre-defined anchor point
// Insert <div id="scroll-down-anchor"></div> to where you want to scroll to
$('html, body').animate({
scrollTop: $('[id=scroll-down-anchor]').position().top
// Set the speed of the scroll here (currently set to 1000 ms)
}, 1000);
});
});
I'm still not sure from the screencast what you want to do with the behaviour based on the window position when the window is scrolled.
UPDATE: In light of the screencast and further information.
The code has been updated, BUT, although this is, I think, what your code was trying to achieve, I don't think the effect is very nice at all because you're intercepting a user's intention, hijacking it, and making something different happen. It's also very choppy, and to improve that would probably take many more lines of code (eg to determine speed of existing scroll, intercept that and make it accelerate organically - way beyond the scope of this kind of answer). Maybe there's a plugin out there to do this nicely.
Anyway, I think this code completes what you were trying to achieve, but the end effect, although subjective, is not very nice in my opinion. I've put in explanatory comments:
jQuery(document).ready(function ($) {
// Variable to store scrolling state
var scrolling = false;
// Variable to store position to determine whether scrolling up or scrolling down
var previousScroll = 0;
$(window).scroll(function () {
// Only is state is not 'scrolling' (ie not to run if button has been clicked)
if (scrolling === false) {
// Get position
var currentScroll = $(this).scrollTop();
// Compare position to stored variable: scrolling up or scrolling down
if (currentScroll > previousScroll) {
// Determine if position is 'within the zone' - set here to 50px
if (currentScroll < 50 && currentScroll !== 0) {
console.log('IN ZONE');
// Trigger button click
$('#scroll-down').trigger('click');
} else {
// Normal scrolling down code, outside zone
console.log('SCROLLING DOWN ');
}
}
else {
// Scrolling up code
console.log('SCROLLING UP ');
}
// Set variable for comparison of next scroll event
previousScroll = currentScroll;
}
});
// The button is assumed to have an id of 'scroll-down' - triggered when clicked
$('#scroll-down').on('click', function () {
// Set the scrolling state
scrolling = true;
// Animate with callback to set scrolling back to 'true' when complete
$('html, body').animate({ scrollTop: $('[id=scroll-down-anchor]').position().top }, 1000, function () {
// Callback code - set scrolling state to be false when animation has finished
scrolling = false;
});
});
});
I have a sapui5 table and I am trying to log in the console if the table is being scrolled up or down. I can get it to working if I use a regular div.
Example here.
But I can't seem to get it to work for a sapui5 table. I have tried the following:
var lastScroll = 0;
$("#__xmlview0--players-vsb-sb").scroll(function () {
var st = $(this).scrollTop();
if (st > lastScroll) {
console.log("scrolling down");
} else {
console.log("scrolling up");
}
lastScroll = st;
});
I'm getting the id #__xmlview0--players-vsb-sb when I inspect element on the scrollbar. This seems like the id I should use. Any ideas of how to get this to work?
Here is my JSBin.
If you put the scroll event inside a setTimout, it starts working.
setTimeout(function(){
var lastScroll = 0;
$("#__xmlview0--players-vsb-sb").scroll(function () {
var st = $(this).scrollTop();
if (st > lastScroll) {
console.log("scrolling down");
} else {
console.log("scrolling up");
}
lastScroll = st;
});
}, 700);
This is an indication that the UI library is clearing out events on the elements it uses when it initializes its own events on them. This is probably to remove the risk of memory leaks. I would suggest not using the timeout, and seeing this stack for more info: SAPUI5-Which method to call once a view is displayed everytime?
I have a problem with the scrolling animation. Jumpy scroll occurs when the page is scrolled after scroll-animation. I suspected the scroll-event repeats itself, but I'm not sure. Can you help me with it?
$(document).ready(function(){
var offset;
var anchor = $("#navigation").offset().top;
$(window).bind('mousewheel', function (e) {
offset = $(window).scrollTop();
if (e.originalEvent.wheelDelta < 0) {
//mouse scroll down
console.log('Down: ' + offset + " " + anchor);
if (offset >= anchor) {
// if anchor has been scrolled, user can scroll further
// the problem ocuurs in this block
return true;
} else {
// animate to anchor( nav menu)
$("body, html").animate({
scrollTop: anchor + 1
}, 200);
$("#navigation").addClass("nav-fixed");
return false;
}
} else {
//mouse scroll up
if (offset < anchor) {
$("#navigation").removeClass("nav-fixed");
return true;
}
}});
});
JSFiddle: http://jsfiddle.net/0noms3cs/
Thank you a lot!
Your issue is simple. The scroll event fires over and over again. Your line of thinking behind the cause of this issue is correct, you have a large number of animate events that get stacked up which causes this weird behavior.
You can resolve this issue by adding a boolean variable (such as scrollInitialized) that starts out as false and gets flipped to true once the scroll event has fired once.
Here's the altered JS code. Note: I only added the scrollInitialized variable and a check for it in the if statement.
Edit: I also removed the inner if-else case since it was not necessary using this design.
EDIT 2: I originally misunderstood what you wanted to do. What you need to do was add a scrollLock variable that would only be set to true for the duration of your animation. After thinking about this, I implemented it for you. Here is the Jsfiddle:
https://jsfiddle.net/04gaaapo/1/
Here is the new JS code:
$(document).ready(function () {
var scrollLock = false;
var offset;
var anchor = $("#navigation").offset().top;
$(window).bind('mousewheel', function (e) {
offset = $(window).scrollTop();
// if scroll is NOT locked and we are above the anchor
if (scrollLock === false && offset < anchor) {
if (e.originalEvent.wheelDelta < 0) {
// scrolling down
scrollLock = true;
// animate to anchor( nav menu)
$("body, html").animate({
scrollTop: anchor + 1
}, 200);
// unlock in 250ms
setTimeout(toggleLock, 250);
// add nav class
$("#navigation").addClass("nav-fixed");
} else if (e.originalEvent.wheelDelta > 0) {
// scrolling up
scrollLock = true;
// animate to top of page
$("body, html").animate({
scrollTop: 0
}, 200);
// unlock in 250ms
setTimeout(toggleLock, 250);
// remove nav class
$("#navigation").removeClass("nav-fixed");
}
}
});
function toggleLock() {
scrollLock = !scrollLock;
};
});