How to prevent div from being scrolled off top on iOS - javascript

I am essentially trying to make this work on iOS: http://jsfiddle.net/xtyus/1/
Scrolling should result in the divs stacking at the top.
$(window).scroll(function(){
/* get the current scroll position */
var st = $(window).scrollTop();
/* change classes based on section positions */
if (st >= d1orgtop) {
d1.addClass('latched');
} else {
d1.removeClass('latched');
}
if (st >= d2orgtop) {
d2.addClass('latched');
} else {
d2.removeClass('latched');
}
if (st >= d3orgtop) {
d3.addClass('latched');
} else {
d3.removeClass('latched');
}
if (st >= d4orgtop) {
d4.addClass('latched');
} else {
d4.removeClass('latched');
}
});
The problem is that on iOS, DOM manipulation is frozen during the scroll event (according to iOS Javascript DOM "Freezing?"). Which means that setting position as fixed (by adding the "latched" class) doesn't occur until after the user stops scrolling. This causes unwanted behavior on iOS. The div basically gets scrolled off the top, and then it jumps back down once the latched class is added.
Is there a good workaround for this problem?

Related

Scroll position not being detected good enough

I have a part of code that looks if a user is scrolling up or down, and inside that check if the user is at the top of the page.
To see my position I log that position in my console but for some reason when I scroll up using my scroll wheel fast, it shows a number like 75, 98, 66 etc. Only when I scroll again (while it's already at the top) it goes to 0. Why?
$(window).bind('mousewheel', function(event) {
if (event.originalEvent.wheelDelta >= 0) {
var height = $(window).scrollTop();
console.log(height);
if(height > 20) {
$('.nav-link').css('color', '#2f323a');
}else{
$('.nav-link').css('color', '#ffffff');
}
}
});
I want to change the text color of my menu to white when a user is at the top but now if I scroll up fast using my mouse scroll it does not work right away.
Wouldn't you want to detect any kind of scroll? Not just mouse wheel.
$(document).ready(function() {
$(window).scroll(function() {
if ($(window).scrollTop() >= 20) {
$('.nav-link').css('color', '#2f323a');
} else {
$('.nav-link').css('color', '#ffffff');
}
});
});

Adding class jQuery else if

I've got a fixed header on scroll adding class 'fixed' this works fine. I scroll down and after 50px class 'fixed' is added to my header container and when i scroll back up the 'fixed' class is removed.
Now on my blog pages i'd like the 'fixed' class to always be there, so on page load and even after scrolling up and down i'd like the class 'fixed' to always be added to my header container.
I'm using if else statements in my js but i can't seem to get it working right:
//Fixed header on scroll
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 50) {
$(".header-wrapper").addClass("fixed");
} else if {
$('.blog .header-wrapper').addClass('fixed');
} else {
$(".header-wrapper").removeClass("fixed");
}
});
Any ideas how to sort this?
This makes more sense: Set the fixed class on the blog and test if we have a blog or not when adding the scroll event handler
$('.blog .header-wrapper').addClass('fixed');
if ($(".blog").length==0) {
$(window).scroll(function() {
$(".header-wrapper").toggleClass("fixed",$(window).scrollTop()>=50);
});
}
Do note that the scroll event is triggered every pixel so you may want to debounce it
You have to use conditions in the if clause like so:
//Fixed header on scroll
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 50) {
$(".header-wrapper").addClass("fixed");
} else if($('.blog .header-wraper').length > 0) {
$('.blog .header-wrapper').addClass('fixed');
} else {
$(".header-wrapper").removeClass("fixed");
}
});

Header is displayed when user scrolls up - misaligns if activated too quickly

The header on my site disappears when a user scrolls down the page. If the user begins to scroll up the header is displayed again, even if they're halfway down the page. If the user starts to scroll downwards, the header disappears again.
The effect works pretty well. Here's a CodePen showing the markup, css and javascript:
http://codepen.io/anon/pen/QpWXpj
From what I can see the only issue it has is if you scroll and and up really quickly. It's almost like the code can't react quick enough and the detached class is added when it's not needed. Which means in the demo you get the (lovely) red background even when you're at the top of the browser.
Can anyone help/suggest how the script could be amended to prevent this?
Thanks in advance!
You have to take out the
if (!currentScroll) {
header.removeClass('detached');
}
out of the else block so that the menu jump fix is applicable at all times and not only when the else condition is satisfied.
Check updated codepen: http://codepen.io/nashcheez/pen/KWKjjq
So your js code becomes:
/* ==========================================================================
#SHOW/HIDE HEADER
========================================================================== */
$(function() {
var previousScroll = 0, // previous scroll position
menuOffset = 70, // height of menu (once scroll passed it, menu is hidden)
detachPoint = 220, // point of detach (after scroll passed it, menu is fixed)
hideShowOffset = 5, // scrolling value after which triggers hide/show menu
header = $('.page-head');
$(window).scroll(function() {
if (header.hasClass('expanded')) return;
var currentScroll = $(this).scrollTop(),
scrollDifference = Math.abs(currentScroll - previousScroll);
// if scrolled past menu
if (currentScroll > menuOffset) {
// if scrolled past detach point add class to fix menu
if (currentScroll > detachPoint) {
var value = parseInt(header.css('transform').split(',')[5]);
console.log(value);
if (!header.hasClass('transitioning') && !header.hasClass('detached') && value != -110) {
header.addClass('transitioning').one('transitionend', function() {
console.log('transitionend');
header.removeClass('transitioning');
if (currentScroll > detachPoint) header.addClass('detached');
});
} else if (!header.hasClass('transitioning') && !header.hasClass('detached')) {
header.addClass('detached');
}
}
// if scrolling faster than hideShowOffset hide/show menu
if (scrollDifference >= hideShowOffset) {
if (currentScroll > previousScroll) {
// scrolling down; hide menu
if (!header.hasClass('invisible'))
header.addClass('invisible');
} else {
// scrolling up; show menu
if (header.hasClass('invisible'))
header.removeClass('invisible');
}
}
}
// only remove “detached” class if user is at the top of document (menu jump fix)
if (!currentScroll) {
header.removeClass('detached');
}
// If user is at the bottom of document show menu.
if ($(window).height() + currentScroll == $(document).height()) {
header.removeClass('invisible');
}
// Replace previous scroll position with new one.
previousScroll = currentScroll;
});
});
/* ==========================================================================
#SHOW/HIDE NAVIGATION
========================================================================== */
/*
* Creates classes to enable responsive navigation.
*/
// Wait for the DOM to be ready (all elements printed on page regardless if
// loaded or not).
$(function() {
// Bind a click event to anything with the class "toggle-nav".
$('.page-head__toggle').click(function() {
if ($('body').hasClass('show-nav')) {
$('body').removeClass('show-nav').addClass('hide-nav');
setTimeout(function() {
$('body').removeClass('hide-nav');
}, 500);
} else {
$('body').removeClass('hide-nav').addClass('show-nav');
}
// Deactivate the default behavior of going to the next page on click.
return false;
});
});

jQuery scroll fade-in crash

This code works well, but when I scroll up and down after 4-5 times it crashes and all the elements disappear. Why does this happen and how do I fix it?
$(window).on("load",function() {
$(window).scroll(function() {
var winheight = $(window).innerHeight();
$(".fade").each(function() {
/* Check the location of each desired element */
var objectBottom = $(this).offset().top + $(this).outerHeight();
var windowBottom = $(window).scrollTop() + $(window).innerHeight();
/* If the element is completely within bounds of the window, fade it in */
if ( windowBottom > (objectBottom - (winheight*0.65))) { //object comes into view (scrolling down)
if ($(this).css("opacity")==0) {$(this).fadeTo(500,1);}
} else { //object goes out of view (scrolling up)
if ($(this).css("opacity")==1) {$(this).fadeTo(500,0);}
}
});
}); $(window).scroll(); //invoke scroll-handler on page-load
});
Ok, I supposed that your html is something like this: https://jsfiddle.net/szdwwdac/
Sometimes, if you are scrolling fast up and down, when the element is fading out, your if doesn't work well.
if ( windowBottom >= (objectBottom - (winheight*0.65))) {
if ($(this).css("opacity")==0) {$(this).fadeTo(300,1);}
} else { //object goes out of view (scrolling up)
if ($(this).css("opacity")==1) {$(this).fadeTo(300,0);}
}
It's because of the 500ms of animation.
One of the solutions can be the eneble/disable for 500ms of the scroll page.
You can check this solution: How to disable scrolling temporarily?
EDIT
Another solution can be: add a class "fading" when you are inside your if. Then, in the if, eval if the element hasClass "fading". If not, you can go inside and make the animation.

Scrolling Two Divs Using JQuery/Javascript

Wrapper - Overflow Hidden
Div One: Sidebar
Div Two: Main Content
Div Two will have a normal scroll. Div One I wish to have no visible scroll however when you scroll Div One it scrolls Div Two.
Upon Div One's height hitting the bottom, it will no longer scroll and visa-versa for scrolling back up.
This will result in the sidebar always being visible at the side. Before you ask, I've tried all positioning types to get this to work resulting in many failed attempts.
My live demo can be seen here: http://rafflebananza.com/admin/newadmin.html#
Note I've tried to make a JSFiddle simplified but my maths does not seem to work in there the same. Please suggest whether I should fork all my page to there or whatnot for future visitors needing the same help.
Overview
Scrolling in the wrapper will scroll sidebar to point x only (x being the sidebars height) then stopping but will continue to allow the content to be scrolled. Visa-versa for scrolling back up.
Somewhat half way there...
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop,
position = document.body.scrollTop;
function scrollD() {
var scroll = document.body.scrollTop;
if (scroll > position) {
// Scrolling Down Functions
} else {
// Scrolling Up Functions
}
position = scroll;
}
Updated the answer to match OPs requirements.
I downloaded your website in its current state and made the following changes to your code:
var scrollY = 0;
$(window).scroll(function() {
var sideNav = $('.SideNav'); // The side navigation
var wScrollY = $(this).scrollTop(); // Current scroll position of Window
var navHeight = sideNav.height(); // Height of the Navigation
var StageHeight = $(window).height() - 46; // The display space
if(sideNav.height() > StageHeight) { // Do the following if the side navigation is higher than the display space
var spaceLeft = sideNav.height() - StageHeight; // spaceLeft -> how many pixel left before fixing navigation when scrolling
if(scrollY < wScrollY) { // Scroll direction is down
if (wScrollY >= spaceLeft) // If scroll top > space left -> fixate navigation at the bottom, otherwise scroll with the content
sideNav.css({top:46-spaceLeft+wScrollY});
if (wScrollY <= 46) // Set top strict to 46. Sometimes there is white space left, caused by the scroll event.
sideNav.css({top:46});
} else { // Scroll direction is up
var sideNavTop;
if (sideNav.offset().top < 0) {
sideNavTop = Math.pow(sideNav.offset().top); // if top is negative, make it positive for comparison
} else {
sideNavTop = sideNav.offset().top;
}
if (sideNavTop > (46+wScrollY)) // Fixate the header if top of navigation appears
sideNav.css({top:46+wScrollY});
}
} else {
sideNav.css({top:46+wScrollY}); // Fixate always
}
scrollY = wScrollY;
});
This will let you scroll your side navigation up until its end. Then fixate. If you scroll up, it will still be fixated until your reach the point, where the navigation must scrolled back to its original position.
You can check the edited version here: http://pastebin.com/Zkx4pSKe
Just copy the raw code into a blank html page and try it out.
It's a bit messy and maybe not the best solution, but it works.
Ok, here you go:
var $sidebar = $('.sidebar'),
$window = $(window),
previousScroll = 0;
$window.on('scroll', function (e) {
if ($window.scrollTop() - previousScroll > 0) {
$sidebar.css({
'top': Math.max($window.scrollTop() + $window.height() - $sidebar.outerHeight(true), parseInt($sidebar.css('top'))) + 'px'
});
} else {
$sidebar.css({
'top': Math.min($window.scrollTop(), parseInt($sidebar.css('top'))) + 'px'
});
}
previousScroll = $window.scrollTop();
});
http://jsfiddle.net/7nwzcpqk/1/
i might have misunderstood your desired result incorrectly but you can see if this works for you :
.SideNav {
position: fixed; // you currently have this as position:absolute;
}
You don't need nor a wrapper element nor jQuery. I assume that you are using a wrapper because you want to have the top bar placed there. I think there is a better way to do it by using simply three divs.
The top bar has to be fixed (to be always visible) and of full width.
The side bar also has to be fixed (to be always visible) with a top margin of the height of the top bar.
The content needs just a left padding (width of side bar) and top padding (height of top bar).
Here is the example code (http://jsfiddle.net/zckfwL4p/):
HTML
<div id="top_bar"></div>
<div id="side_bar">links here</div>
<div id="content"></div>
CSS
body {
margin:0px;
padding:0px;
}
#side_bar {
width:50px;
position: fixed;
left:0px;
top:20px;
background-color:blue;
}
#top_bar {
position:fixed;
height:20px;
left:0px;
right:0px;
background-color:red;
}
#content {
position:relative;
padding-left:55px;
padding-top:25px;
}

Categories

Resources