I have a fixed navbar that hides when a user scroll down; and appears when they scroll up. This works fine.
It is a single page scroller site.
The problem occurs when a user clicks a nav item, and they are subsequently scrolled down the page, the fixed nav disappears. I would like this to stay put when the nav item is clicked, until the user scrolls down themselves with the mouse wheel or scrollbar.
My approach this far has been to set a variable to determine if it is programmatic scrolling or not. I use that variable to determine if the nav should hide or not as a conditional statement.
window.programScrolling = false;
The nav item click function is as below, which sets the var to true.
$('a[href^="#"]:not([href="#"])').on('click',function (e) {
e.preventDefault();
var target = this.hash;
var $target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top
}, 500, 'easeInOutCubic', function () {
window.programScrolling = true;
});
});
This code does indeed work. But only once as now the variable is always true.
I need a way to reset that variable back to false when the user does the scrolling.
I have tried setting on the scroll event
$(window).scroll(function(e) {
window.programScrolling = false;
});
But this seems to take precedence over the click event and hence that variable is now always false.
Any suggestions? Or alternative approaches?
If by $(window).scroll is taking precedence you mean it is called second, you can use this code:
$(window).scroll(function() {
if (programScrolling)
window.programScrolling = false;
else{
//User initiated scroll!
}
});
Related
I've searched hours and finally found a light jQuery code which allows me to animate the click of an anchor link, but when I click on one link it animates down and then jump 100px to the top without animation because the hash is given to the url after the animation which leads to the default anchor link behavior when you click it.
I have a code sample for you with a little comment from me for a fix, or well I thought It'll be a fix...
// Scroll.js (https://css-tricks.com/snippets/jquery/smooth-
scrolling/#comment-1635851)
/*
* Scroll.js:
* 1. added -100 after the .top property which reflects the navigation height.
*/
$(document).ready(function(){
// Add smooth scrolling to all links
$('a').on('click', function(e) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
e.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$('html, body').animate({
scrollTop: $(hash).offset().top-100 // /* [1] */
}, 800, function(){
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
});
Just write on the anchor href attribute javascript::void(0) as in
Though if you want it to act as an anchor and have a url... this will not work :(
What's happening: Scrolling works no matter which position i have the mouse while i scroll.
What i want to achieve: When the user scrolls with the mouse pointer positioned inside a particular container, I would like to disable the plugin from changing pages. When the user scrolls with the mouse pointer outside that same container, the normal functionality of the plugin should be restored; i.e. the pages should be scrollable again.
What have i tried: I listened for the scroll event on the document and found out whether the mouse is inside the container while executing the scroll and store the possibilities as a boolean.
$(document).bind("mousewheel", function(event) {
// preventScroll = true;
console.log(event);
if($(event.target).closest(".no-scroll").length) {
preventScroll = true;
}
else {
preventScroll = false;
}
});
Then onLeave i try to find out the value of preventScroll and try to stop event propagation (since in want to stop an actual event) by returning false
setTimeout(function() {
console.log(preventScroll);
if(preventScroll) {
console.log("no-scroll")
return false;
}
}, 10);
I an using setTimeout to capture the desired value of preventScroll although I guess the plugin executes a scroll within that 10 ms and that's why return false doesn't seem to have an effect. I can't seem to figure out how else to proceed to achieve the desired functionality.
Codepen: https://codepen.io/binarytrance/pen/YxBqPj
In this implementation, the container i want to disable scroll is in the second page/section. Please be aware of the values spit out in the console.
Use the fullpage.js option normalScrollElements. Check the fullpage.js docs for more info:
normalScrollElements: (default null) If you want to avoid the auto scroll when scrolling over some elements, this is the option you need to use. (useful for maps, scrolling divs etc.) It requires a string with the jQuery selectors for those elements. (For example: normalScrollElements: '#element1, .element2'). This option should not be applied to any section/slide element itself.
I am writing code for when a button is clicked it will animate going to a certain spot on the page. The problem is the first time I execute the code it is very laggy on the scrollTop animation. I am using w3schools code so I was surprised it was not working.
Here is the code I am using to animate the scrolling:
// Add smooth scrolling to all links
$("a").on('click', function (event) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (400) specifies the number of milliseconds it takes to scroll to the specified area
$('html, body').animate({
scrollTop: $(hash).offset().top
}, 500, function () {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
I'm trying to scroll to the next section on the page based on the viewport. I do not want to keep track of each element and if they have been visited, because if the user decides to scroll up again, it should just scroll to the next section anyway. Hence why I came up with this solution:
https://jsfiddle.net/w28tfnm9/
$("#scroll-down").on("click", function() {
$(".section").each(function() {
var isInViewPort = $(this).isInViewport();
if (isInViewPort) {
$("html, body").animate({
scrollTop: $(this).next().offset().top
}, 500);
return false;
}
});
});
However, I have a slight issue: It will not scroll to the first element. That makes sense, since I check if the current element is in the viewport, then I scroll to the .next() element, but I can't figure out how to solve this, without messing up what I already have. Is there a better way?
Instead of saying .next(), I essentially want it to go to the next .section element. Since it's not guaranteed the .next() element is a section, this is not a "good" solution.
So I ended up with a hack:
https://jsfiddle.net/w28tfnm9/3/
$(window).on("scroll", function() {
if($("body").scrollTop() < $(".section").offset().top) {
hasScrolled = false;
} else {
hasScrolled = true;
}
});
I basically iterate through each element, if i === 0 it means I am at the top, but since I am trying to grab the next using .get(), I need to set the current iteration to -1. Works like a charm and "resets" when I scroll above the first element.
I'm at a complete loss here. I'll provide what I currently have below, but for some reason, every iteration I try, something goes wrong...either the animation of scroll doesn't work but the other functions work, the animation of scroll does work but other functions do not work, all doesn't work, or all does work but animation flickers...
I tried to comment everything the best I could and have gotten to a point where if I use return false; either in 1 location or another, part of the entire function works, as mentioned above.
In a nut-shell, I'm trying to create an if/else statement that allows for scrolling animation as well as other functions to run all by clicking (1) single div. This div, aside from scrolling back to top with scroll animation, changes it's text AND should focus on a form element.
Any suggestions?
$('.sign_in').click(function () {
// IMPORTANT - This scrolls the page back to top if user clicks on '.sign_in' div - May need fixed as it flickers for some reason...
$('html, body').animate({
scrollTop: 0
}, 350); // NOTE: Set second number to '0' to eliminate flicker - however, doing this also eliminates scroll animation speed...
// return false; // NOTE: Having 'return false;' stated here allows for smooth scrolling without flicker but disables the rest of the functions...
// IMPORTANT - If/Else statement changes text on '.sign_in' div
if ($(this).text() == 'REGISTER') {
$(this).text('LOGIN');
// IMPORTANT - This autofocuses on form element for 'Register' form
$('.fname').focus();
} else {
$(this).text('REGISTER');
// IMPORTANT - This autofocuses on form element for 'Login' form
$('.uname').focus();
}
// IMPORTANT - This flips the form if user clicks on '.sign_in' div
$('#formContainer').toggleClass('flipped');
// return false; // NOTE: Having 'return false;' stated here allows all functions to run but causes flicker on scroll animation...
});
The problem seems to be in setting focus to the input element, set it after the animation and it should be fine
$('.sign_in').click(function () {
var $this = $(this), counter = 0;
// IMPORTANT - This scrolls the page back to top if user clicks on '.sign_in' div - May need fixed as it flickers for some reason...
$('html, body').animate({
scrollTop: 0
}, 350, function(){
if(++counter>1){return;}
// IMPORTANT - If/Else statement changes text on '.sign_in' div
if ($this.text().toUpperCase().trim() == 'REGISTER') {
$this.text('LOGIN');
// IMPORTANT - This autofocuses on form element for 'Register' form
$('.fname').focus();
} else {
$this.text('REGISTER');
// IMPORTANT - This autofocuses on form element for 'Login' form
$('.uname').focus();
}
}); // NOTE: Set second number to '0' to eliminate flicker - however, doing this also eliminates scroll animation speed...
// IMPORTANT - This flips the form if user clicks on '.sign_in' div
$('#formContainer').toggleClass('flipped');
// return false; // NOTE: Having 'return false;' stated here allows for smooth scrolling without flicker but disables the rest of the functions...
// return false; // NOTE: Having 'return false;' stated here allows all functions to run but causes flicker on scroll animation...
});
Demo: Fiddle