Scroll to next section/class issue - javascript

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.

Related

fullpage.js: disable page scroll when scrolled with the mouse pointer inside a container

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.

Determining user scrolling vs click animate function

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!
}
});

scrollTop(); animation issues

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

jQuery - auto input focus when scroll hit certain element

I am using jQuery plugin called Waypoints
to work with scroll action.
What I want to achieve is setting focus on the first input element of a section that is in the viewport and move the focus to the input of next respective sections when scrolled down. And, when scroll back to the first section up above, it should set the focus back to the input of the first section.
The following is what I have on my actual working setup that is using the aforementioned plugin.
Unfortunately, I can't really get the plugin up and running in my JS Fiddle.
This code block works in terms of setting focus on page load and changing focus to the targeted input when scrolled down
but scrolling back to the top section does not set the focus back.
(function($) {
var firstInput = $('section').find('input[type=text]').filter(':visible:first');
if (firstInput != null) {
firstInput.focus();
}
$('section').waypoint(function () {
var getFocus = $(this).find('input[type=text]').filter(':visible:first');
getFocus.focus();
});
$('section').waypoint(function () {
var getFocus = $(this).find('input[type=text]').filter(':visible:first');
getFocus.focus();
}, {
offset: function () {
return -$(this).height();
}
});
});
Here is my JS Fiddle
that doesn't have the plugin part.
As long as somebody can explain how they should be done in normal jQuery
if not familiar with this plugin.
jQuery Waypoints is very straightforward to use. I haven't tried with your code but I got it done with this:
$('input:first').focus();
$('section').waypoint(function() {
$(this).find('input:first').focus();
});
Please see this fiddle.
However, using mousewheel on scrolling down, the scroll sometimes jumps back at the mid part. It might be how the browser reacts on input focus. I haven't gone through the whole documentation but there is no example for input focus.
If you're only looking to do just this simple task I suggest you drop the plugin. I can show you how to get this done with jQuery.
You can handle the scrolling with jQuery's scroll() function. You need to get the scrollTop() on scrolling event then compare it with the <input>'s top offset().
$(window).scroll(function(){
var st = $(this).scrollTop();
$('input[type=text]').each(function(){
var offset = $(this).offset();
if(st >= offset.top -20 && st < offset.top + $(this).height()){
$(this).focus();
}
});
});
Here is the fiddle.

Remove/avoid adding target link to URL

This one may be simple for the jQuery/JavaScript gurus here, but I just can't find a solution for it around the web.
Case
I have a link at the bottom of a page that says Back to Top, the link is simply a target link like this:
Back to Top
So when you click it, it jumps to the top of page. Simple.
Problem
When the target link is clicked, the id #top is added to the URL of the page, ie:
http://website.com/about-us/#top
Question
Is there a way to remove or avoid getting that id #top added to the URL of the page but retain the functionality of the page jumping to the top?
Any help with this is greatly appreciated.
In either case (jQuery or vanilla JavaScript), you'll want to do the following:
Select all anchor tags where href is set to #top
Create a "jump" function which sets the page position to the top and returns false to prevent the default link behavior
Bind the "jump" function to the click event of all of the nodes found
To jump you have several options. I've provided them (jQuery and JS specific) in the first example below.
Using jQuery
jQuery makes selecting and binding to a click event easy. Then you can jump to the top of the page using jQuery or straight JavaScript.
$('a[href="#top"]').click(function() {
//
// To jump, pick one...
//
// Vanilla JS Jump
window.scroll(0,0)
// Another Vanilla JS Jump
window.scrollTo(0,0)
// jQuery Jump
$('html,body').scrollTop(0);
// Fancy jQuery Animated Scrolling
$('html,body').animate({ scrollTop: 0 }, 'slow');
//
// ...then prevent the default behavior by returning false.
//
return false;
});
jQuery's animate provides options for animation duration and easing along with the ability to set a callback.
Vanilla JavaScript
You can also use Vanilla JS the whole way through... Querying and binding, however, become a bit more painful.
Modern browsers support document.querySelectorAll() which will allow you to grab all of the link elements just as you would with jQuery:
var links = document.querySelectorAll('a[href="#top"]');
Then loop over the elements and bind the "jump":
for (var i = links.length - 1; i >= 0; i--) {
links[i].onclick = function() { window.scroll(); return false; };
};
If your target browser doesn't gift you with querySelectorAll you just loop through all of the anchor tags to find the ones linked to #top:
var links = document.body.getElementsByTagName('a');
for (var i = links.length - 1; i >= 0; i--) {
var l = links[i];
if(l.getAttribute('href') === '#top') {
l.onclick = function() { window.scroll(); return false; }
}
}
$('a[href=#top]').click(function(){
$(window).scrollTop(0);
return false;
});
You need to stop the tag a's default event to trigger.
When handling anchor click events, always use e.preventDefault(); On Click of Anchor element. When you don't need anchor element.
e.preventDefault();
$('html, body').animate({ scrollTop: 0 }, 'slow');
This will work
$('a.standard').click(function() {
$('body,html').animate({
scrollTop: 0
});
});

Categories

Resources