Why this hide menu / navigation on scroll works? - javascript

I've been looking on the internet for vanilla Javascript implementation of hiding menu when scrolled—and found this solution:
var previousScroll = window.pageYOffset;
window.addEventListener( 'scroll', hideMenu );
function hideMenu() {
var menubar = document.querySelector('.navigation');
var currentScroll = window.pageYOffset;
if ( currentScroll > previousScroll) {
menubar.style.transform = "translateY(-60px)";
}
else {
menubar.style.transform = "";
}
previousScroll = currentScroll;
}
What I don't understand is, why this works? Why the variable "previousScroll" value could be different with "currentScroll" value?
I've tried to put previousScroll inside the function hideMenu, and it doesn't work.

Your function hideMenu()is called after the execution of the scroll.
So, windows.pageYOffsetwill return the Y position after scrolling, while the previousScrollis the Y before scrolling.
That's why it whorks ;)
Here how does it work step by step :
Step 1 (page loaded)
previousScroll => 0 (top of the page)
pageYOffset=> 0 (instant Y
window scroll position)
currentScroll => ??
Step 2 (scroll)
previousScroll => 0 (no changes)
page is doing scroll ('scroll' event is fired)
pageYOffset => 100 (instant Y window scroll position)
'scroll' callback function is called (hideMenu() here)
update of currentPosition (= pageYOffset = 100)
update of previousPosition (now is equals to currentPosition)
....
Have a look to this jsFiddle

The hideMenu function is called when the user scrolls. Therefore, we have access to the current pageYOffset in the page.
We have no way to know where we were before the scroll. That is, unless we kept a reference to it before the 'scroll' event happened.
If you put your variable in the function, previous and current will return the same value and we won't be able to compare them.

currentScroll is updated when the user scrolls. It represents the current scroll offset.
If the user scrolls down (currentScroll > previousScroll) then we decide to hide the menu bar. Otherwise we reset its position.
At the end, we update previousScroll to keep the last scroll position for the next hideMenu function call (steps 1 to 3)

Related

jquery detect direction of scroll event up/down and bottom and store it to use outside of scroll function

I have the following function which I tried to make for detecting if the scroll event is up or down. It works fine but I also wanted to check if the user has reached the bottom to perform some actions. Or even better, I wanted to replace the down event with the bottom check. In simple words, it should always detect scroll up but should only detect bottom once the scrollbar reaches the bottom and not when scrolling down. Lastly, I want to store this in the variable scroll and use it later outside of the $().scroll() event. However, when I do console.log(scroll) outside of the scroll event it updates only once during the page load and never returns updated value on scroll. If I place this inside of the scroll event then it updates properly. But I need to use it outside of the scroll event and therefore it is mandatory that I can get the updated value of scroll variable.
var lastScrollTop = 0,
delta = 5,
scroll = '';
$('.chat-box').scroll(function(event) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta) {
return;
}
if (st > lastScrollTop) {
scroll = 'down';
} else {
scroll = 'up';
}
lastScrollTop = st;
console.log(scroll); // RETURNS UPDATED VALUE PROPERLY AS SCROLL EVENT TRIGGERS IT
});
console.log(scroll); // DOESN'T RETURN UPDATED VALUE
Expectations: How can I get the following?
Detect when the scrollbar hits the bottom and update the scroll variable with value bottom.
Store the updated value in the scroll variable to use it outside of the scope of $('.chat-box').scroll(function (event) event.
The console statement in the last line is executed after the script is loaded. At this time the var scroll is an empty string. After that the last line will not be executed again.
If you call the console statement after scrolling again, maybe in a function or another event handler, the updated value is loged. You could for example call that statement in a click event handler:
$('.chat-box').on('click', function() {
console.log('click: ' + scroll); // DOES NOW RETURN THE UPDATED VALUE
});
Working example:
(i changed the selected element for the scroll event to $(window) for demonstration)
var lastScrollTop = 0,
delta = 5,
scroll = '';
$(window).scroll(function(event) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta) {
return;
}
if (st > lastScrollTop) {
scroll = 'down';
} else {
scroll = 'up';
}
lastScrollTop = st;
console.log('scroll: ' + scroll); // RETURNS UPDATED VALUE PROPERLY AS SCROLL EVENT TRIGGERS IT
});
$('.chat-box').on('click', function() {
console.log('click: ' + scroll); // DOES NOW RETURN THE UPDATED VALUE
});
.chat-box {
width: 300px;
height: 1000px;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat-box"></div>

Get scroll value on element with position:fixed

I have a page with a header section. In it, two blocks that move sideways after scrolling or dragging on the mobile.
I am trying to set the scrolling for the header, but I want too that the rest of the page stays in place until the side blocks reach left: -50% and right:-50%.
I have an event scroll set to header, with pageYoffset values.
I tried to set the rest of the content the page gives to the section with the position:fixed, but then the scroll does not work anymore, and do not count pageYoffset.
Do you have any ideas how to get around it, so that the rest of the page would scroll only after the full unveiling of the header?
(in short, the pink section should be on top and wait until the header disappears)
let current = $(window).scrollTop();
let windowHeight = $(window).height();
let eleLeft = $(".cd-half-left");
let eleRight = $(".cd-half-right");
let currPositionLeft = eleLeft.position().left;
let currPositionRight = eleRight.position().right;
let headerHeaight = $(".cd-section").height();
let halfBlockWidth = $(".cd-half-block").width();
let windowWidth = $(window).width();
$(window).scroll(function (event) {
current = $(window).scrollTop();
console.log({total:total,current:current});
var newPosition = ((current / headerHeaight)*100) / 2;
console.log(newPosition);
eleLeft.css({left:"-"+newPosition+'%'});
eleRight.css({right:"-"+newPosition+'%'});
});
FIDDLE
A solution would be not to use window scroll but instead handle scroll gesture (from mousewheel and touchmove) to control left and right panel, and prevent actual scroll when the panels are not fully opened.
so instead of $(window].scroll(handler), try with $('.cd-block').bind('mousewheel', handler) and $('.cd-block').bind('mousewheel', handler)
The handler being:
function updateCurrent(event) {
if (current >= 50) {
current = 50;
} else {
if (current <= 0) {
current = 0;
}
// if below 50 we cancel the event to prevent the scroll
event.originalEvent.preventDefault();
}
eleLeft.css({left:"-"+current+'%'});
eleRight.css({right:"-"+current+'%'});
}
Here is a buggy but working solution (keyboard space, up and down should be handled too):
fiddle

Check 'mousewheel' event direction with scroll locked

I currently have a slick slider on top of my page that should change slides on scroll, and after a certain point it should go back to normal scroll behaviour.
What I want to do is to initially lock the scroll (yeah, I know that changing scroll behaviour is a terrible thing for UX, but this was a mandatory request that came directly from the client), check the amount of times the scroll event was fired, check if it was up or down, and then switch slides accordingly.
My code currently looks like this:
$('body').on('DOMMouseScroll mousewheel', function(e) {
var viewportHeight = $(window).height(),
firstWaypoint = viewportHeight / 2,
secondWaypoint = viewportHeight,
thirdWaypoint = 3/2 * viewportHeight,
unlockPoint = viewportHeight * 2,
$slider = $('.home-hero__inner__text');
if (/* Y scroll position < thirdWaypoint lock scroll */) {
e.preventDefault();
} else if (/* If Y scroll position < secondWaypoint show first slide */) {
$slider.slick('slickGoTo', 0);
} else if (/* If Y scroll position > secondWaypoint show second slide */) {
$slider.slick('slickGoTo', 1);
} else if (/* If Y scroll position > thirdWaypoint show third slide */) {
$slider.slick('slickGoTo', 2);
} else {
// Unlock scroll
}
});
The thing is that as I currently lock scroll capabilities using preventDefault(), I can no longer check my page scrollTop() position since it is always at the top, returning a 0 value.
Is there a way to check how many pixels should've been scrolled on normal behaviour, and whether it was up or down? 'cause I need to keep a track of the assumed scroll position to trigger each step of the if statement.
You could just check if the wheelDelta is positive or negative
$(document).on('DOMMouseScroll mousewheel', function(e) {
var moved = e.originalEvent.wheelDelta || e.originalEvent.detail * -1 || 0;
if (moved > 0) {
// scrolled up
} else if (moved < 0) {
// scrolled down
}
});
FIDDLE

Stop scrolling page, scroll div

I'm creating this landing page: http://tag4share.com/landing/#
Where is located the two galaxy s3 (one white with "Organizador" label on it and a black with "Participante" label), I want to stop scrolling the page and automatically start scrolling the content inside the mobile (an iFrame, div, anything).
Is it possible?
Basically I want to "focus" the scrolling inside a div (and make it work even if the cursor isn't hovering it). Or animate while scrolling without scrolling the body.
Example: http://www.google.com/nexus/5/
On the "Everything you need to capture the moments that matter." part.
My attempt:
var lastScroll;
var currentScroll = $(window).scrollTop();
$(window).scroll(function() {
lastScroll = currentScroll;
currentScroll = $(window).scrollTop();
if($(window).scrollTop() >= 2024 && $(window).scrollTop() < 2500)
{
var difference = currentScroll - lastScroll;
$(".main").css({"margin-top":"-="+currentScroll});
}
});
I've tried to move the main div along with scrolling. It works but it looks really strange (keeps shaking).
Thanks!
I've just tidied up your code a tad, fixed indentation etc.
As for actually scrolling your div when you hit the position, use animate to actually mimic the scrolling effect, once you know you have reached the bottom, you can put another if statement within the scroll function to stop resetting the scroll position.
var lastScroll;
var scrollPosition = $(window).scrollTop();
var reachedBottom = false;
var phonePositionTop = $('#phoneContainerID').position().top;
var phonePositionBottom = phonePositionTop + $('#phoneContainerID').height();
$(window).scroll(function() {
if(scrollPosition >= phonePositionTop && scrollPosition < phonePositionBottom && reachedBottom == false){
var difference = currentScroll - lastScroll;
// Keep resetting scroll to the phoneContainerTop position
$(".main").css({"margin-top": phonePositionTop});
var scrollLimit = -100;
if ($('#phoneContainerID').position().top < scrollLimit) {
//Once the scroll limit is less than -100 (scrolled up 100 pixels)
// Disable our 'pause' effect, and continue
reachedBottom = true;
}
}
});
I haven't tested this, however I was just giving you an idea of where to go from here.
I hope I have helped a little!

Jquery when the user hits bottom of the page

I've been working on a scroll to top function for my website, and that part of it works fine. My problem is however that I have a fixed div that is overlapping my footer when it hits the bottom of the page.
Here is the function that I have working.
$(document).scroll(function (e) {
if (document.body.scrollTop >= 800) {
$('#beamUp').show(1000);
} else {
$('#beamUp').hide(1000);
return false;
}
});
Is there somehow I could detect when I hit that part of the page and stop the div from moving past that.Help is much appreciated!
jsFiddle: http://jsfiddle.net/zazvorniki/RTDpw/
Just get the height of the page, minus the height of the div in question, as well as the footer... make sure the top is never greater than that value... you'll also need an onresize event handler re-evaluate that value.
looking at your jsfiddle... here are my edits
In your scroll listener, I am checking for the position of the page, and adjusting the bottom position of the floater appropriately. I also set the initial display:none, so you don't need to call .hide() in your initial script. In addition, resizing the window has the effect of scrolling for your use, so I changed the listener for both events.
$(document).on('scroll resize', function (e) {
var viewHeight = $(window).height();
var viewTop = $(window).scrollTop();
var footerTop = $("footer").offset().top;
var baseline = (viewHeight + viewTop) - footerTop;
var bu = $("#beamUp").css({bottom: (baseline < 0 ? 0 : baseline) + 'px'});
if (viewTop >= 50) {
bu.show(1000);
} else {
bu.hide(1000);
}
});

Categories

Resources