Scroll position not being detected good enough - javascript

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

Related

change div height when scrolling down

I have div element that contain google map. The div is on the half of the page, and it's start from the middle (more or less).
Is it possible that the height of it will be expand when user scroll down ( and shrink when scroll up) ?
I have some script that do it, but it's not so friendly.
and the current script is:
// change map size when scroll down
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 450) {
$("#map-warp").addClass("change-map-canvas"); // removed the . from class
$("#map-warp").css("margin-top", "40px"); ; // change margin from top for close infoWindow button
} else {
$("#map-warp").removeClass("change-map-canvas"); // removed the . from class
$("#map-warp").css("margin-top", "10px"); ;
}
});
Try this here:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
var topMargin = 10 - $(window).scrollTop();
if (scroll >= 570) {
$("#map-warp").addClass("change-map-canvas");
$("#map-warp").css("margin-top", "40px");
} else {
$("#map-warp").removeClass("change-map-canvas");
$("#map-warp").css("margin-top", topMargin+"px");
}
});
Until the scroll reaches 570, the map will always stay like in the beginning. After that it will smoothly follow the scroll.

mouse over event within certain window y range

I am working on a project that requires the full length logo shrink to short initial in 2 situations:
A) when page scroll down past 300px.
and
B) if page hasn't scroll past 300px (meaning full length logo still showing), shrink the full length logo to initial to accommodate pulldown menu when mouse over the top menu items.
Here is the code I tried:
it is working but when page scroll past 300px the mouse out should not happen. It should keep the logo as the smaller initial format. Right now the mouse out will happen no matter the page is scroll past 300px or not.
/* shrink logo when page scroll past 300px by adding .smaller class to #logo. */
window.onscroll = function() {myFunction()};
function myFunction() {
if (document.body.scrollTop > 300 || document.documentElement.scrollTop > 300) {
document.getElementById("logo").className = "smaller";
} else {
document.getElementById("logo").className = "";
}
}
/* shrink logo when mouse over top menu items (.showlp) only if page has NOT scroll past 300px */
$(document).ready(function(){
$(".showlp").mouseover(function(){
if (document.body.scrollTop < 300 || document.documentElement.scrollTop < 300) {
document.getElementById("logo").className = "smaller";
}
})
$(".showlp").mouseout(function(){
if (document.body.scrollTop < 300 || document.documentElement.scrollTop < 300) {
document.getElementById("logo").className = "";
}
})
});
Any help is appreciated.
Pass parameters via data attribute in the body tag and access that value via you javascript code.
Eg.
then on your javascript
var ctrl=
$("body").attr("
data-var");
then on your window scroll function set the attribute value to 1, aand listen to it on your mouse over function to know when to
add the functionality.
Eg.
Function
myfunction(){
if(document.bo
dy.scrollTop>3
00){
// swap urclass
// then do
$("body").attr("
data-var", 1);
}
then on your mouse over function do:
$(document).re
ady(function(){
$(".showIp").mo
usover(functio
n(){
var ctrl=
$("body").attr("
data-var");
if(ctrl==1){
//swap class
}
else{
//keep swap
}
});
});

Preventing Fixed Div from covering other Div

need some help.
My setup:
I have a fixed Div ("myFixedDiv") that remains in place when scrolling till
"myFixedDiv" reaches another div ("footer"). Then it moves with scrolling.
The Div "myFixedDiv" is placed next to a div ("text") using: display:inline-block.
Now for my problem:
When the window is horizontally made smaller, "myFixedDiv" is vertically placed after "textDiv" as intended. Only thing is, the upper-half of "myFixedDiv" visibly overlaps "textDiv", covering part of the text. I want "myFixedDiv" to be vertically placed after "textDiv" by pushing "footer" down to allow for this.
See an example here:
JSFIDDLE
You may need to give a little scroll to make "myFixedDiv visible again after making the window smaller.
$(document).scroll(function() { var $self = $("#myFixedDiv"); $self.css('margin-top', 0); var myFixedDivOffset = $self.offset().top + $self.outerHeight(true); if (myFixedDivOffset > ($("#footer").offset().top - 30)) { $self.css('margin-top', -(myFixedDivOffset - $("#footer").offset().top)); } else { $self.css('margin-top', '30px'); } });
Change fixed position to relative position of the div when you resize the window and it should be good
See this fiddle
$(window).resize(function() {
$("#myFixedDiv").css('position','relative');
});
You can also add a condition based on the width of the body to change the CSS of the div to relative or fixed position.
Solved it:
$(document).scroll(function() {
var $self = $("#myFixedDiv");
$self.css('margin-top', 0);
var myFixedDivOffset = $self.offset().top + $self.outerHeight(true);
if (myFixedDivOffset > ($("#footer").offset().top - 30)) {
$self.css('margin-top', -(myFixedDivOffset - $("#footer").offset().top));
} else {
$self.css('margin-top', '30px');
}
});
$(window).resize(function() {
if ($(window).width() < 601) $("#text").css('padding-bottom', '70px'); {
$(window).scrollTop($(window).scrollTop() + 1);
$(window).scrollTop($(window).scrollTop() - 1);
}
});
$(window).resize(function() {
if ($(window).width() > 600) $("#text").css('padding-bottom', '0'); {
$(window).scrollTop($(window).scrollTop() + 1);
$(window).scrollTop($(window).scrollTop() - 1);
}
});

Alerting user when div has been scrolled into view

I am trying to perform a function/alert the user when they have scrolled down to a specific div, and then whey they have scrolled to the bottom of the page. I am able to alert when the user has scrolled to the bottom and back to the top, but not sure how to specify when the user scrolls below the fold(to the middle section). I have the following so far:
HTML
<div class="container top">TOP</div>
<div class="container middle">Middle</div>
<div class="container bottom">Bottom</div>
jQuery
$(function () {
var $win = $(window);
$win.scroll(function () {
if ($win.scrollTop() == 0) {
alert("USER SCROLLED TO TOP");
} else if ($win.height() + $win.scrollTop() == $(document).height()) {
alert("USER SCROLLED TO BOTTOM");
}
});
});
JSFIDDLE: LINK
https://jsfiddle.net/xsLx9ojs/1/
I add ids to the html divs:
<div id="top" class="container top">TOP</div>
<div id="bottom" class="container bottom">BOTTOM</div>
Then I add a condition to detect when bottom div appears in user's screen when he scrolls:
$(function () {
var $win = $(window);
$win.scroll(function () {
if ($win.scrollTop() == 0) {
console.log("USER SCROLLED TO TOP");
} else if ($win.height() + $win.scrollTop() >= $('#top').height() - 50
&& $win.height() + $win.scrollTop() <= $('#top').height() + 50) {
console.log("TRANSITION BETWEEN THE TWO DIVS");
} else if ($win.height() + $win.scrollTop() == $(document).height()) {
console.log("USER SCROLLED TO BOTTOM");
}
});
});
Scroll detection is not so precise cause of the little "jumps" that the mousewheel does. So I added a 100px tolerance. If I were you I would improve this stuff with a boolean that detects if the alert for bottom div has already been given or not so the function doesn't trigger at every scroll like this:
[...]
if ($win.scrollTop() == 0) {
//top reached
} else if ($win.height() + $win.scrollTop() >= $('#top').height()) {
//alert! bottom div appeared while scrolling bottom!
//deal with this with a boolean
} else if ($win.scrollTop() <= $('#top').height()) {
//alert! bottom div disappeared while scrolling top!
//deal with this with a boolean
} else if ($win.height() + $win.scrollTop() == $(document).height()) {
//bottom reached
}
[...]
Part of the issue is that the value of $(document).height() may never be obtained via scrolling, as elements within the page can affect the actual document height versus what the user is able to scroll through.
You could find the position of the bottom container like so
$('.bottom').position();
But that would only give you the element's position within its parent. You would then need to calculate the offset relative to each parent and grandparent, where applicable.
Likewise, you could look into the getBoundingClientRect function:
$('.bottom')[0].getBoundingClientRect();
Take a look at the library Waypoints to see a "ready-made" version.
Update 1:
For your JSFiddle sample, keep in mind that Waypoints needs to have an element hit the top of the window to trigger (this is by default - you can adjust this behavior with an offset).
See my JSFiddle here where I've made each div larger to allow the window to scroll passed, based on your JSFiddle.

Full page slider with native scrollbar

I am building a full page slider that keeps the native scrollbar and allows the user to either free scroll, use the mouse wheel or navigation dots (on the left) to switch to a slide.
Once the user is on the last slide and tries to scroll down further, the whole slider moves up to reveal a simple scrollable section. If the user scrolls down and then tries to go back up, then this new section moves out of the way again and returns the slider back into view.
Fiddle: http://jsfiddle.net/3odc8zmx/
The parts I'm struggling with:
Only the first two navigation dots work. The third one DOES WORK if you area looking at the first slide. But doesn't do anything, if you are on slide 2. Note: the purple one is a short-cut to the second section of the page and not related to the slider.
When moving to the last slide (via the dots, if you're on the first slide) it causes the code to make the whole slider move upwards as it sees this as the user has slid past the last slide as per the description above. I have tried to combat this using a variable called listen to stop the scroll event listening when using the showSlide method... but it seems to be true even though I set it to false, and only reset it to true again after the animation...
When scrolling down using the mouse wheel, I can get to the second section and back up, but not to the first third section. I'm wondering if I could use the showSlide method to better handle this instead of the current dirty next and prev functions I have implemented.
Note: If the user has free-scrolled, when they use the mouse-wheel, I want the slider to snap to the nearest slide to correct itself... Any suggestions for how I could do this?
Can anyone offer some help?
Here's the JS:
var listen = true;
function nextSlide()
{
$('#section1').stop(true,false).animate({
scrollTop: $('#section1').scrollTop() + $(window).height()
});
}
function prevSlide()
{
$('#section1').stop(true,false).animate({
scrollTop: -$('#section1').scrollTop() + $(window).height()
});
}
function showSlide(index)
{
var offset = $('#section1 div').eq(index).offset();
offset = offset.top;
if(offset){
listen = false;
$('.slide-dot').removeClass('active');
$('.slide-dot').eq(index).addClass('active');
$('#section1').stop(true,false).animate({
scrollTop: offset
}, 500, function(){
listen = true;
});
} else {
alert('error');
}
}
$(document).ready(function(){
var fullHeight = 0;
$('#section1 div').each(function(){
fullHeight = fullHeight + $(this).height();
});
var lastScrollTop1 = 0;
$('#section1').on('scroll', function(e){
var st = $(this).scrollTop();
if (st > lastScrollTop1){
if( $('#section1').scrollTop() + $(window).height() == fullHeight) {
if(listen){
$('body').addClass('shifted');
}
}
}
lastScrollTop1 = st;
});
$('#section1').on('mousewheel', function(e){
e.preventDefault();
var st = $(this).scrollTop();
if (st > lastScrollTop1){
nextSlide();
} else {
prevSlide();
}
});
var lastScrollTop2 = 0;
$('#section2').on('scroll', function(e){
var st = $(this).scrollTop();
if (st > lastScrollTop1){
} else {
if( st == 0 ){
$('body').removeClass('shifted');
}
}
lastScrollTop1 = st;
});
$('.slide-dots').css({'margin-top':-$('.slide-dots').height() / 2});
$('.slide-dot').first().addClass('active');
$(document).on('click', '.slide-dot', function(e){
e.preventDefault();
showSlide( $(this).index() );
});
$(document).on('click', '.slide-dot-fake', function(e){
e.preventDefault();
$('body').addClass('shifted');
});
});
And for those wondering why I'm not using something like fullPage.js, it's because it can't handle the way I want to transition between the two areas and have two scrollbars (one for each area).
You can use:
e.originalEvent.wheelDelta
instead of:
st > lastScrollTop1
in the mousewheel event for your third problem to check if the user has scrolled up or down. And also change the +/- in prevSlide. I used dm4web's fiddle for your first problem. And I used:
scrollTop: offset - 1
instead of:
scrollTop: offset
for your second problem, because when the scroll reaches to the last pixel of the third element, it automatically goes to the next section, so 1 pixel is enough for it not to.
Here's the fiddle: http://jsfiddle.net/3odc8zmx/3/
As suggested by #chdltest, you could do it by using fullPage.js.
Here's an example. Go to the last section.
Code used for the example:
Javascript
$('#fullpage').fullpage({
sectionsColor: ['yellow', 'orange', '#C0C0C0', '#ADD8E6'],
scrollOverflow: true,
scrollBar: true,
afterLoad: function (anchor, index) {
//hiding the main scroll bar
if (index == 4) {
$('body, html').css('overflow', 'hidden');
}
//showing the main scroll bar
if (index == 3) {
$('body, html').css('overflow', 'visible');
}
}
});
CSS (in case you prefer to use the normal style for it)
/* Normal style scroll bar
* --------------------------------------- */
.slimScrollBar {
display: none !important;
}
.fp-scrollable {
overflow: auto !important;
}
Advantages of using fullPage.js instead to your own code:
Strongly tested in different devices and browsers. (IE, Opera, Safari, Chrome, Firefox..)
Prevent problems with trackpads, Apple laptops trackpads or Apple Magic Mouse.
Old browser's compatibility, such as IE 8, Opera 12...
Touch devices compatibility (IE Windows Phone, Android, Apple iOS, touch desktops...)
It provides many other useful options and callbacks.

Categories

Resources