Currently experimenting for the first time with javascript. I'm trying to make a simple nav bar that disappears when the user scrolls down, reappears when they scroll up and does the same for when the mouse is in/out of the nav bar's area. Good news! Got that bit done.
The trouble comes when I then scroll up to make the nav bar appear, I move my mouse to click on it and then obviously a mouse event is triggered with the mouse outside of the hotspot and makes the nav bar disappear while you're on your way to it. It does reappear when I'm at the top with the mouse, but I'd like it to stay there once I've scrolled up to make it appear.
I have two if statements, one for the scroll and one for the mouse position. I'd like to make the site prioritise the effect of the scroll if statement over the mouse if statement.
This is the code I've stuck together after reading a hell of a lot of articles:
// Hide nav when scrolling down, show nav when scrolling up
var scrollCtrl = false;
var navbar = document.getElementById("navbar");
var prevScrollPos = window.pageYOffset;
window.onscroll = function() {
var currentScrollPos = window.pageYOffset;
if (prevScrollPos > currentScrollPos) {
navbar.classList.add('show');
var scrollCtrl = true;
} else {
navbar.classList.remove('show');
var scrollCtrl = false;
}
prevScrollPos = currentScrollPos;
}
// Get the height of the nav bar
var navHeight = getComputedStyle(document.getElementById("navbar")).height;
navHeight = navHeight.substring(0, navHeight.length -2);
navHeight = parseInt(navHeight, 10);
// Show nav when mouse is at the top
window.addEventListener('mousemove', function(e) {
var ypos = e.y;
if (ypos <= navHeight && scrollCtrl == false) {
navbar.classList.add('show')
}
else {
navbar.classList.remove('show')
}
});
What I've tried to do is use a boolean called scrollCtrl (because I want the scroll to be in control over the mouse position) but no matter what tweaks I make, I can't seem to get it to work.
The show/hide classes are just a CSS transform.
I am quite new to javascript, so please excuse any etiquette faux pas's!
Related
it isn't a duplicate as I've read the others question but everyone assume that the scroll is vertical, while i need this for horizontal scroll.
What i'm trying to do is to scroll a div, placed somewhere in a page, when it reach the center of the screen or it is almost visible, then when it end its scroll i need to continue the page scrolll.
Actually i have a "slider" like this: JSFIDDLE
Actually, I can get an advise when the element is visible on the page after scrolling, but I don't know how to disable vertical scroll, scroll my div, and then scroll page again. The important thing is that the div scroll how much i continue the scrolling (intended with mouse, keyboard and maybe touch, it will be awesome)
function testInView($el){
var wTop = $(window).scrollTop();
var wBot = wTop + $(window).height();
var eTop = $el.offset().top;
var eBot = eTop + $el.height()+50;
return ((eBot <= wBot) && (eTop >= wTop));
}
function setInView(){
$(".slider-wrapper").each(function(){
var $zis = $(this);
$zis.removeClass("inview");
if(testInView($zis)){
alert("eccolo");
}
});
}
$(document).scroll(function(){
setInView();
});
$(document).resize(function(){
setInView();
});
$(document).ready(function(){
setInView();
});
If you want to disable vertical scrolling then just set overflow-y: hidden on body element
body {
overflow-y: hidden;
}
so hiding the navbar when scrolling simply by adding a class with "top: -50px" for example is easy. However, it doesn't feel very natural. It would be so much nicer, if the navbar would be hiding through actual scrolling, so that the speed of the scrolling always fits. Instead of animating it away, I want to scroll the navbar away and back onscreen (instantly away and after a certain amount of pixels of scrolling up back onscreen again).
How would you approach this?
By the way, I don't really want to use any JQuery for this, I'm using Vue.
I hope I didn't get things wrong but if you want the bar to hide when you scroll, why not just position: absolute it and leave the normal scrolling make it disappear ? that might sound trivial but if you want a natural disappearance, that might be it, no ?
You can use CSS transitions on top to animate it back and forth. However you are triggering the hide when you scroll, you can add/remove classes to trigger the change.
Set the position of the navbar a fixed (or whatever you have currently) until a scroll event on the window passes a certain point, then make the navbar relative to the scrolling container.
See this example: https://jsfiddle.net/n97tu7nt/
The HTML
<div id="main-container">
<div class="nav" id="nav" style="position:fixed; height: 100px; background-color: blue; color: white; width:100%;">
This is the Nav Bar <span id="pos"></span>
</div>
<div style="position:relative; top:130px;" id="container">
<p>
This is some text
</p>
...
The Javascript
var c = document.getElementById('nav');
var t = document.getElementById('container');
var p = document.getElementById('pos');
p.innerHTML = window.scrollY;
var last_known_scroll_position = 0;
var ticking = false;
function doSomething(scroll_pos) {
p.innerHTML = scroll_pos;
if (scroll_pos > 100) {
c.style.position = 'relative';
t.style.top = 0;
}
}
// From https://developer.mozilla.org/en-US/docs/Web/Events/scroll
window.addEventListener('scroll', function(e) {
last_known_scroll_position = window.scrollY;
if (!ticking) {
window.requestAnimationFrame(function() {
doSomething(last_known_scroll_position);
ticking = false;
});
ticking = true;
}
});
It is very hacky, but shows the principle.
This script makes it so when you scroll down in a browser the navigation bar disappears/hides behind the header. I was wondering if it was possible if instead it hid as soon as you scrolled down, hiding it after a user scrolls down a certain number of pixels (say 50px) to avoid touchy nav hiding on slightest scroll.
Thanks in advance for any direction.
// Nav scroll test
var prev = 0;
var $window = $(window);
var nav = $('#belowhead');
$window.on('scroll', function(){
var scrollTop = $window.scrollTop();
nav.toggleClass('hidden', scrollTop > prev);
prev = scrollTop;
});
You can put this inside your "window.on('scroll')" function:
if(scrollTop > 50) {
nav.addClass('hidden');
} else {
nav.removeClass('hidden');
}
2019 Update / Adjustment
The following could be useful for anyone else wishing to develop a header that disappears when you scroll down. I just finished making the following for a website I'm creating that required the top header to disappear when the user started scrolling, but then reappear when they start scrolling up; continuously applying this logic if you were to constantly keep scrolling up and down on the website.
For starters, a class is added to my header tag called nav-scrolled when the user scrolls past a certain point - 50px in this case. This new class can then be styled to change the background-color, add a box-shadow etc...
$(function() {
var header = $(".nav-container");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 50) {
header.addClass("nav-scrolled");
} else {
header.removeClass("nav-scrolled");
}
})
});
However, this only solved the problem of not being able to edit the headers styles if the user is scrolling from the top of the page - not anywhere on the site - the following fixes this.
var userScroll;
var scrollTop = 0;
var delta = 5;
var navHeight = $('header').outerHeight();
$(window).scroll(function(event){
userScroll = true;
});
setInterval(function() {
if (userScroll) {
hasScrolled();
userScroll = false;
}
}, 250);
The next step for me was to sequentially add and remove classes show-nav and hide-nav that had been styled to display and hide the navigation menu. The following checks whether the user has scrolled (up or down) to a value higher than my delta variable. If the user is beginning to scroll up on the website, the class show-nav is added and the header transitions in from the top of the page. If the user is scrolling down the page the class hide-nav is added, and the header is hidden.
function hasScrolled() {
var st = $(this).scrollTop();
// Ensures a higher scroll than $delta
if(Math.abs(scrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > scrollTop && st > navHeight){
// Scroll Down
$('header').removeClass('show-nav').addClass('hide-nav');
$('.nav-toggle').removeClass('open');
$('.menu-left').removeClass('collapse');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('hide-nav').addClass('show-nav');
}
}
scrollTop = st;
}
I'm building a one page site, and wanting to have multiple divs, that are approximatly 400px (but vary) on top of each other. Instead of a smooth scroll, I would like jump to the next div and have it centred on the screen, at the same time adjust the opacity of the content above and below to draw attention to the centre div.
I have tried playing with a few scrolling plugins but have not had anything do what I'm after, most of them are geared towards a full page div, not one only a 1/3 or so the height of the page.
Can someone point me towards something I can adapt to perform this.
Add an event listener to the document which looks for elements with the class .next
Get the distance from the top of the viewport to the top of the element in question
subtract half the value of the viewport height minus the height of the element.
If the element is bigger than the viewport, scoll to to top of the element
Or scroll the element into the middle.
Set the opacity of the unfocused elements.
(Demo)
(function(){
"use strict";
document.addEventListener('click', function(e) {
if(e.target.className.indexOf('next') >= 0) {
var current = e.target.parentElement
var next = current.nextElementSibling || false;
if(next) {
var nextNext = next.nextElementSibling;
var height = next.offsetHeight;
var top = next.offsetTop;
var viewHeight = window.innerHeight;
if(viewHeight - height > 0) {
var scrollTo = top - ((viewHeight - height) / 2);
} else {
var scrollTo = top;
}
window.scroll(0, scrollTo);
current.style.opacity = '0.5';
next.style.opacity = '1';
if(nextNext) nextNext.style.opacity = '0.5';
}
}
}, false);
})();
I am building a mobile site and I have a slide show of images that allows sliding through images horizontally. The javascript library I'm using is bxslider. However, if one touches the slide show and wants to scroll the page up/down, the slide show blocks vertical scrolling and hence another section of the site must be touched.
Could someone please tell me how I could keep vertical scroll enabled (i.e, not allow the slideshow to block the normal scroll?)
Thanks!
Try this, Change the onTouchMove fn in the bxslider library to this
var onTouchMove = function (e) {
if (slider.settings.mode != 'fade') {
var orig = e.originalEvent;
var value = 0;
// if horizontal, drag along x axis
if (slider.settings.mode == 'horizontal')
{
var hchange = orig.changedTouches[0].pageX - slider.touch.start.x;
var vchange = orig.changedTouches[0].pageY - slider.touch.start.y;
if(Math.abs(hchange)>20 && Math.abs(hchange)>Math.abs(vchange))
{
value = slider.touch.originalPos.left + hchange;
setPositionProperty(value, 'reset', 0);
e.preventDefault();
}
// if vertical, drag along y axis
} else{
e.preventDefault();
var change = orig.changedTouches[0].pageY - slider.touch.start.y;
value = slider.touch.originalPos.top + change;
setPositionProperty(value, 'reset', 0);
}
}
}
If you goto the options page for the bxslider website, search for preventDefaultSwipeX, and preventDefaultSwipeY
Those are what you are looking for.