Jquery mobile sticky header - javascript

I have a jquery mobile header div (data-role="header" data-position="fixed") with two toolbars inside in a layout like this:
_____________________
|XXXXXXXXXXXXXXXXXXX|
|YYYYYYYYYYYYYYYYYYY|
and I want to reproduce the effect of WhatsApp, where scroll down hides toolbar XXXXXXXX and scroll up shows toolbar XXXXXXXXXX. Toolbar YYYYYY always visible.
By using window.onscroll this can be achieved by adding/removing a class with top:-50px; upon scroll down/scroll up.
It works, however, it works only when the page is loaded for the first time or it is reached with a link having rel=external. In all other cases, it is impossible to see the effect of the added class. I have also tried .addClass("sticky").enhanceWithin() with no effect.
Any suggestion to make this to work every time?
Here the code:
var didScroll = false;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = 20;
$(document).on("scroll", function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var currentScroll = $(this).scrollTop();
if(currentScroll >= 200) {
$("#scrollToTop").show();
} else {
$("#scrollToTop").hide();
}
if(Math.abs(lastScrollTop - currentScroll) <= delta)
return;
if (currentScroll > lastScrollTop && currentScroll > navbarHeight){
$('#PageHeader').removeClass('nav-down').addClass('sticky');
} else {
if(currentScroll + $(window).height() < $(document).height()) {
$('#PageHeader').removeClass('sticky').addClass('nav-down');
}
}
lastScrollTop = currentScroll;
}

I hope my fiddle will help you out:
[http://jsfiddle.net/Lfve19u0/]
Ramon.

Related

Scrolling up to the topmost in iOS's Safari causes problems with scrolling-up/down detection

I have the following Javascript code:
$(window).scroll(function() {
if (window.innerWidth <= 768) {
let scrollStatus = $(this).scrollTop();
if (scrollStatus > lastScrollTop) {
//do some stuffs
else
//do some other stuffs
lastScrollTop = scrollStatus;
}
});
So it worked well with non-mobile devices and Android devices. However, when I ran that on iOS's Safari and scroll to the topmost, it drags down the viewport by a little bit before bouncing up back when I release my finger hold. That bounce back up is detected by the above Javascript code as scrolling up and causes the trigger on the else section, which is undesirable. How do I fix this?
Before bouncing back Safari overscrolls the Y-Position into negative land. You can use this to ignore position changes from the bounce animation.
The window scroll event fires very rapidly. For performance reasons you don't want to handle these events directly.
The example below shows how to check in 250ms intervals whether the user has scrolled, which is easy on performance.
var didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
// interval scroll handler
setInterval(function() {
if ( didScroll ) {
didScroll = false;
scrolled();
}
}, 250);
var lastScrollTop = 0;
function scrolled() {
var scrollStatus = window.pageYOffset;
if (scrollStatus < lastScrollTop) {
//user scrolled up
} else if ( lastScrollTop >= 0) {
//user scrolled down
}
lastScrollTop = scrollStatus;
}
Alternatively you can alleviate performance issues by resetting a timeout that only calls the scrolled() function after scrolling has finished.
var timer;
$(window).scroll(function() {
if ( timer ) clearTimeout(timer);
timer = setTimeout(function(){
scrolled();
}, 100);
});
var lastScrollTop = 0;
function scrolled() {
var scrollStatus = window.pageYOffset;
if (scrollStatus < lastScrollTop) {
//user scrolled up
} else if ( lastScrollTop >= 0) {
//user scrolled down
}
lastScrollTop = scrollStatus;
}

Detect if user scrolls more than 20px no matter where it's on the page

Is it possible to detect if the user scrolls more than 20px wherever it's on the page??
I mean, in a one page design, I need to remove a class when the user scrolls more than 20px but not only from the top of the document.
Each time he opens a popup, a class is added to the popup in question, once the user scrolls, I would like to remove this class.
Repeat this function no matter where it's on the page.
My current code :
$(window , 'body').on('scroll', function() {
$('.navbar-collapse').collapse('hide');
$("#wrapper").removeClass('newsletter-opened');
$("#newsletter").removeClass('opened');
});
Thank you!
You can use jQuery for that.
With my solution, if user has scroll 200px when he come on your page if he scroll to top or bottom with minumum 20px of scroll your changes was called.
var userScroll = $(document).scrollTop();
$(window).on('scroll', function() {
var newScroll = $(document).scrollTop();
if(userScroll - newScroll > 20 || newScroll - userScroll > 20){
$('.navbar-collapse').collapse('hide');
$("#wrapper").removeClass('newsletter-opened');
$("#newsletter").removeClass('opened');
}
}
EDIT:
After look your jsFiddle, i know what you want, just check that :
Just define the scroll at the moment when popin is enable and make your job only when the popin has class opened
$(document).ready(function(){
$("a.open-newsletter").on( "click", function() {
$("#newsletter").toggleClass('opened');
userScroll = $(document).scrollTop();
return false;
});
$(window , 'body').on('scroll', function() {
if ( $("#newsletter").hasClass('opened') ) {
var newScroll = $(document).scrollTop();
if (userScroll - newScroll > 100 || newScroll - userScroll > 100) {
$("#newsletter").removeClass('opened');
}
}
});
});
Actually, the Scroll function will take effect on every pixel the page is scrolled, which is too heavy in terms of performance.
As a result, if you just take the difference between newScroll & userScroll, the result may be wrong sometimes (because the new and old scroll positions will be updated shortly as the page is moving along)
Therefore, we can just set a time interval which checks the scroll position every 250 milliseconds (this will both increase performance and give time for users to scroll more than 20px as your requirement):
var didScroll;
var lastScrollTop = 0;
var delta = 20;
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Return if they scroll less than 20px (delta)
if(Math.abs(lastScrollTop - st) <= delta)
return;
// Do what you want here
console.log("lastScrollTop: ",lastScrollTop, " - newScroll: ", st);
$('.navbar-collapse').collapse('hide');
$("#wrapper").removeClass('newsletter-opened');
$("#newsletter").removeClass('opened');
lastScrollTop = st;
}
EDITED VERSION BELOW:
(according to your fiddle, I deleted "use strict" and commented out the $('.navbar-collapse') & $('#wrapper'))
Would you mind trying this again (seems that some previous errors just prevented my code from executing)
$(document).ready(function(){
$("a.open-newsletter").on( "click", function() {
$("#newsletter").toggleClass('opened');
return false;
});
var didScroll;
var lastScrollTop = 0;
var delta = 20;
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Return if they scroll less than 20px (delta)
if(Math.abs(lastScrollTop - st) <= delta)
return;
// Do what you want here
console.log("lastScrollTop: ",lastScrollTop, " - newScroll: ", st);
//$('.navbar-collapse').collapse('hide');
//$("#wrapper").removeClass('newsletter-opened');
$("#newsletter").removeClass('opened');
lastScrollTop = st;
}
});

How to show and hide menu based on start and scroll

I have two menus on a page, I am trying to show the one when the page is loaded and the other when there is a scroll.
This is my page Link
I would like to show the white part when position is at the top
and the blue part when there is a scroll past the top position
This is what am trying presently
<script type="text/javascript" src="//code.jquery.com/jquery-git.js"></script>
<script type='text/javascript'>//<![CDATA[
$(function(){
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - 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 > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-bar-below op-page-header cf').addClass('banner include-nav');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('banner include-nav').addClass('nav-bar-below op-page-header cf');
}
}
lastScrollTop = st;
}
});//]]>
</script>
can some one please help its not working for me
You can just detect if the scroll is at the top of the page or not whenever scroll event fired. if yes, show white header, and vice versa
$(window).scroll( function() {
var scrollPosition = $(window).scrollTop();
if(scrollPosition === 0) {
//show white header
}
else {
//show blue header
}
}
Of course you have to make sure when page first load, it show the white one first (use css). since the code above won't run Until user do scroll (fire this event)
*EDIT
for this :
"and the blue part when there is a scroll past the top position"
you can try this plugin
http://stickyjs.com/
sample code for fix the menu at top position.
$(document).scroll(function() {
var y = $(document).scrollTop()
var header = $('.include-nav');
var blue-menu = $('.cf');
var screenHeight = header.height();
if (y >= screenHeight) {
blue-menu.css({
position : "fixed",
"top" : "0",
"left" : "0"
});
header.css("position", "relative");
} else {
blue-menu.css("position", "relative");
}
});

Event scroll up and fixed header jquery

I have a function
$(document).ready(function () {
var lastScroll = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if ((lastScroll - st) == 5) {
$("header").css("position", "fixed");
}
else {
$("header").css("position", "absolute");
}
lastScroll = st;
});
});
But I want, when I scroll up on 5px, header again shows.
How I can follow event scroll up 5px?
You're updating your lastScroll too often, to make sure it has scrolled past a certain delta (in your case 5px) you should include that clause before checking if the user has scroll up or down.
This tutorial may help you, but I also created a fiddle with an updated version of your code.
But it would go like this:
$(document).ready(function () {
var lastScroll = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScroll - st) <= 5)
return;
if (st < lastScroll) {
$("header").css("position", "fixed");
} else {
$("header").css("position", "absolute");
}
lastScroll = st;
});
});

Stop a function when I click on a div

I am trying to stop a function when I click on a div "ego". The function displays or hides the header depending on the position of the scroll and should only work by default.
Here's my code:
$("#ego").click(function(e){
var $this = $(this);
if($this.data('clicked', false)){
hasScrolled();
}
e.stopPropagation();
});
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - 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 > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').animate({top:"-178px"}, 200, 'easeOutCubic');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').animate({top:"0px"}, 200, 'easeOutCubic');
}
}
lastScrollTop = st;
}
Here's the fiddle:
https://jsfiddle.net/antoniobarcos/wL2vuv4h/2/
Any idea?
so if i get you right you want to stop hiding the navigation bar on top when you click a certain div:
you can achieve this by adding a class on click on the button to your #ego like stopNavigation. further you have to adjust your if clause where you set the top position of the header:
$("#ego").click(function(e){
var $this = $(this);
$this.toggleClass('stopNavigation');
});
and
if (st > lastScrollTop && st > navbarHeight && !$('#ego').hasClass('stopNavigation')){
// Scroll Down
$('header').animate({top:"-178px"}, 200);
}
i updated your fiddle for further information! i hope this is what you want to achieve: https://jsfiddle.net/wL2vuv4h/3/

Categories