Add class to viewport Div when scrolling up and scrolling down - javascript

I use Following code to add class when elements comes into viewport and remove when it goes out of viewport
function check_if_in_view() {
var window_height = $window.height();
var window_top_position = $window.scrollTop();
var window_bottom_position = $(window).scrollTop() + $(window).height();
$.each($animation_elements, function () {
var $element = $(this);
var element_height = $element.outerHeight();
var element_top_position = $element.offset().top;
var element_bottom_position = (element_top_position + element_height);
if ((element_bottom_position <= window_bottom_position) && element_top_position >= window_top_position) {
$element.addClass('blue');
} else {
$element.removeClass('blue');
}
});
}
It works fine in scroll up and down , But now I want to add different classes for scroll up and down , I tried below code but it doesnt seem to be working .
if((element_bottom_position <= window_bottom_position)) {
$element.addClass('blue');
}
else if (element_top_position >= window_top_position) {
$element.addClass('red');
} else {
$element.removeClass('blue').removeClass('red');
}

You will have to store the value of the scrollTop outside of your function and compare the scrollTop value inside your function to check if its more of less then the initial value of scrollTop , something like THIS.
you can integrate the same in your code like so:
$(function(){
var $animation_elements = $('.justlolo'),
$window = $(window),
scrollTop = $(window).scrollTop();
function check_if_in_view() {
var window_height = $(window).height();
var window_top_position = $(window).scrollTop();
var window_bottom_position = $(window).scrollTop() + $(window).height();
$.each($animation_elements, function () {
var $element = $(this);
var element_height = $element.outerHeight();
var element_top_position = $element.offset().top;
var element_bottom_position = (element_top_position + element_height);
if ((element_bottom_position > window_top_position) && element_top_position < window_bottom_position && window_top_position > scrollTop) {
$element.removeClass('red').addClass('blue');
} else if((element_bottom_position > window_top_position) && element_top_position < window_bottom_position && window_top_position < scrollTop) {
$element.removeClass('blue').addClass('red');
} else {
$element.removeClass('blue red');
}
});
}
$(window).on('scroll' , () => {
check_if_in_view();
scrollTop = $(window).scrollTop();
})
});
*, *:after, *:before {
box-sizing: border-box;
}
.justlolo {
height: 70vh;
background: #ccc
}
div:nth-of-type(even) {
background: #eee;
opacity: 0.8;
}
.blue {
background: blue !important;
}
.red {
background: red !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="justlolo"></div>
<div class="justlolo"></div>
<div class="justlolo"></div>

Related

Dynamic nav menu boostrap that it is left or right side that related with sreenwidth

I have a nav menu that has got a lot ul in ul tag so I have to change where it is opened that right side or left side.
And if main menu is bigger than screenwidth then they must be hamburger menu that they are not fit on screen.
I created this js code. It is working and stable.
something that requires attention.
1- there is a class that's name is ".has-children" in my design
2- if screen bigger than 1070, it can be shown
#media (max-width: 1070px)
so You may need to change relating to your code this code in my js
if (screenWidth > 1070)
because it will be start after 1070
<script>
$(document).ready(function () {
var menu = $("#nav").find("ul:first");
var navbarSticky = $(".navbar.navbar-sticky");//navbar-sticky
var menubarLeft = $(".site-branding");//logo left
var menubarRight = $(".toolbar");//toolbar right
var right = parseInt(menubarRight.css("right").replace("px", "")); // right space of right toolbar
var oldMenu = menu.html(); //necessary for reset it that configured
var minWidthSiteMenu = 1070;
var screenWidth = $(window).outerWidth();
if (screenWidth > minWidthSiteMenu) {
menu.html(oldMenu);
setMenuPosition();
}
$(window).resize(function () {
var screenWidth = $(window).outerWidth();
if (screenWidth > minWidthSiteMenu) {
menu.html(oldMenu);
setMenuPosition();
}
});
function setMenuPosition() {
var menuFixed = false;
var humburgerMenuArray = new Array();
var counter = 0;
for (var i = 0; i < 1; i++) {
var result = navbarSticky.width() - menubarLeft.width() - menubarRight.width() - menu.width() - right - 70;// 70 for icon of humburger menu
if (result < 0) {
//console.log(menu.find("li").last().html());
humburgerMenuArray[counter] = $("#nav").find("ul:first > li:last").html();
counter++;
$("#nav").find("ul:first > li:last").remove();
result = navbarSticky.width() - menubarLeft.width() - menubarRight.width() - menu.width() - right;
menu.css("margin-left", menubarLeft.width() + result / 2 + 20 + "px");
i = -1;
menuFixed = true;
}
else {
menu.css("margin-left", menubarLeft.width() + result / 2 + 20 + "px");
i = 1;
}
//console.log(menu);
//console.log(result);
}
if (menuFixed) {
var imageHamburger = "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-menu'><line x1='3' y1='12' x2='21' y2='12'></line><line x1='3' y1='6' x2='21' y2='6'></line><line x1='3' y1='18' x2='21' y2='18'></line></svg>";
var humburgerMenu = "<li><a href='javascript:void(0)' style='padding-top: 26px !important;' class='menu-toggle'>" + imageHamburger + "</a>";
humburgerMenu += "<ul class='sub-menu'>";
var counterHumburger = humburgerMenuArray.length;
humburgerMenuArray.forEach(function () {
var hasChildren = humburgerMenuArray[counterHumburger - 1].search("sub-menu");
if (hasChildren === -1) {
humburgerMenu += "<li>";
}
else {
humburgerMenu += "<li class='has-children'>";
}
humburgerMenu += humburgerMenuArray[counterHumburger - 1];
humburgerMenu += "</li>";
//console.log(humburgerMenuArray[counterHumburger - 1]);
counterHumburger--;
});
humburgerMenu += "</ul>";
humburgerMenu += "</li>";
menu.append(humburgerMenu);
//console.log(menu.html());
}
$("#nav").css("visibility", "visible");
//set setSubMenuPositionLeftRightSide
setSubMenuPositionLeftRightSide();
}
/* Menu Position Left or Right Side */
var style = document.createElement('style');
style.innerHTML = "li.left-arrow > a::after {border-left: 0 solid !important;border-right: .32em solid !important;}";
document.head.appendChild(style);
var menuLeftPositionIsOk = false;
var nextMenuPositon = 0;
var zIndex = 10000;
function setSubMenuPositionLeftRightSide() {
var screenWidth = $(window).outerWidth(); //outerWidth is very important because it is not contain to spage of scroll that overflow
//console.log(screenWidth);
//reset all rel attr - its name is rel-menu-position
$("#nav > ul").each(function (i) {
$(this).find("ul").removeAttr('rel-menu-position');
});
$("#nav > ul > li > ul > li").hover(function (e) {
menuLeftPositionIsOk = false;
//nextMenuPositon = 0; // it is not necessary
zIndex = 10000;
}, function (c) { });
var menuId = 0;
if (screenWidth > minWidthSiteMenu) {
$(".has-children").hover(function (e) {
zIndex++;
$(e.currentTarget).css("zIndex", zIndex);
//console.log($(e.currentTarget).css("zIndex"));
menuPositionCalculate(e, screenWidth);
},
function (c) {
menuLeftPositionIsOk = false;//this is very important for other sub menu that you have change it...
$(c.currentTarget).css("zIndex", 'auto');
$(c.currentTarget).removeClass("left-arrow");
//console.log("menu is closed");
});
}
}
function menuPositionCalculate(e, screenWidth) {
var menuPosition = $(e.target).offset().left + $(e.currentTarget).width() + $(e.currentTarget).find('ul').outerWidth();
//console.log("menuPosition " + menuPosition);
// 25px space left side
if (nextMenuPositon - $(e.currentTarget).find('ul').outerWidth() - 25 < 0) {
menuLeftPositionIsOk = false;
//console.log("RESET - left side - if " + menuPosition + " >> " + screenWidth);
}
if ($(e.currentTarget).find('ul').first().attr('rel-menu-position') === 'left') {
menuLeftPositionIsOk = true;
}
if ($(e.currentTarget).find('ul').first().attr('rel-menu-position') === 'right') {
menuLeftPositionIsOk = false;
}
// 25px space right side
if (menuPosition + 25 > screenWidth ||
menuLeftPositionIsOk ||
nextMenuPositon + 25 > screenWidth) {
menuPosition = $(e.target).offset().left + $(e.currentTarget).width() + $(e.currentTarget).find('ul').outerWidth();
menuLeftPositionIsOk = true;
nextMenuPositon = menuLeftSidePosition(e);
//console.log("left side if " + menuPosition + " >> " + screenWidth);
$(e.currentTarget).addClass("left-arrow");
$(e.currentTarget).find('ul').first().attr('rel-menu-position', 'left');
} else {
$(e.currentTarget).removeClass("left-arrow");
$(e.currentTarget).find('ul').first().attr('rel-menu-position', 'right');
}
}
function menuLeftSidePosition(e) {
//20px come over to parent menu
var menuPositionLeft = $(e.target).offset().left - $(e.currentTarget).find('ul').first().outerWidth() + 20;
$(e.currentTarget).find('ul').first().offset({ "left": menuPositionLeft });
return menuPositionLeft;
}
});
</script>

Fixed sidebar on scroll then back to normal when scrolled up

I want to mimic this effect for sidebar:
https://www.matchesfashion.com/us/womens/just-in/just-in-this-month
I think I have everything working expect the scroll up functionality. Here is my codepen: https://codepen.io/anon/pen/vVByvR?editors=0010
var $sideBar = $('.sidebar');
var sideBarOriginalST = $sideBar.position().top;
var placedAchieved = false;
var sideBarPostion = -570;
var lastScrollTop = 0;
var stopPos = ($sideBar.position().top + $sideBar.outerHeight()) - 291;
$(window).on('scroll', function() {
var sT = $(this).scrollTop();
$sideBar = $('.sidebar');
if(sideBarOriginalST <= sT && !placedAchieved) {
$sideBar.css({
position: 'fixed',
top: (sT-sideBarOriginalST) * -1
});
placedAchieved = false;
}
if(stopPos <= sT) {
placedAchieved = true;
$sideBar.css({
position: 'fixed',
top: sideBarPostion
})
}
// having trouble on scroll up event
if (sT < lastScrollTop) {
console.log(sT, sideBarPostion);
placedAchieved = false;
// $sideBar.css({
// position: 'fixed',
// top: sideBarPostion+=1
// });
}
if(sideBarOriginalST >= sT) {
$sideBar.css({
position: 'static',
top: 0
});
placedAchieved = false;
}
lastScrollTop = sT;
})
No need for javascript! Use position: sticky.
More info: https://css-tricks.com/position-sticky-2/
Is that what you are looking for ?
var $sidebar = $('.sidebar');
var sidebar_height = $sidebar.height();
var $last_item = $('.sidebar .row:last-child');
var last_item_offset = $last_item.offset().top;
var last_item_height = $last_item.height();
$(window).on('scroll', function() {
var scroll_top = $(this).scrollTop();
if(scroll_top >= last_item_offset)
{
$sidebar.css({
position: 'fixed',
top: '-' + (sidebar_height - last_item_height) + 'px'
});
}
else
{
$sidebar.css({
position: 'static',
top: 'auto'
});
}
});
https://codepen.io/anon/pen/oavZyg?editors=0010

Fade in on Scroll Plain JavaScript No JQuery

I'm trying to implement a text fade in on scroll similar to this https://codepen.io/hollart13/post/fade-in-on-scroll.
$(function(){ // $(document).ready shorthand
$('.monster').fadeIn('slow');
});
$(document).ready(function() {
/* Every time the window is scrolled ... */
$(window).scroll( function(){
/* Check the location of each desired element */
$('.hideme').each( function(i){
var bottom_of_object = $(this).position().top + $(this).outerHeight();
var bottom_of_window = $(window).scrollTop() + $(window).height();
/* If the object is completely visible in the window, fade it it */
if( bottom_of_window > bottom_of_object ){
$(this).animate({'opacity':'1'},1500);
}
});
});
});
However, I do not want to use JQuery. I want to accomplish this using plain JavaScript. Unfortunately, most of the examples online are JQuery based and there's very little with plain JavaScript.
This is what I've attempted so far to "translate" this JQuery into plain JS. It's not working. Could anyone point at where I went wrong?
window.onscroll = function() {myFunction()};
function myFunction() {
var elements = document.getElementsByClassName("target");
for(var i = 0; i < elements.length; i++){
var bottomOfObject = elements[i].getBoundingClientRect().top +
window.outerHeight;
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset :
(document.documentElement || document.body.parentNode ||
document.body).scrollTop;
var bottomOfWindow = scrollTop + window.innerHeight;
if(bottomOfWindow > bottomOfObject){
$(this).animate({'opacity': '1'}, 1500);
}
}
console.log(bottomOfObject);
}
Thanks in advance!
Try this simple vanilla JavaScript solution
var header = document.querySelector("#header");
window.onscroll = function() {
if (document.body.scrollTop > 50) {
header.className = "active";
} else {
header.className = "";
}
};
#header {
background-color: black;
transition: all 1s;
position: fixed;
height: 40px;
opacity: 0;
right: 0;
left: 0;
top: 0;
}
#header.active {
opacity: 1;
}
#wrapper {
height: 150vh;
}
<html>
<body>
<div id="header"></div>
<div id="wrapper"></div>
</body>
</html>
Essentially there is an element positioned on the top of the screen which is invisible at first (with opacity 0) and using javascript I add an class to it that makes it visible (opacity 1) what makes it slowly visible instead of instantly is the transition: all 1s;
Here's my version with dynamic opacity based on scroll position, I hope it helps
Window Vanilla Scroll
function scrollHandler( event ) {
var margin = 100;
var currentTop = document.body.scrollTop;
var header = document.querySelector(".header");
var headerHeight = header.getBoundingClientRect().height;
var pct = (currentTop - margin) / ( margin + headerHeight );
header.style.opacity = pct;
if( pct > 1) return false;
}
function addListeners() {
window.addEventListener('scroll' , scrollHandler );
document.getElementById("click" , function() {
window.scrollTop = 0;
});
}
addListeners();

Applying a third condition to function

I have the following function which appliess css to #screen-nav when the user scrolls up and different css when user scrolls down
jQuery(document).ready(function($){
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight(true);
$(window).scroll(function(event) { didScroll = true; });
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 0);
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop) {
// Scroll Down
$('#screen-nav').removeClass('nav-down').addClass('nav-up');
} else {
$('#screen-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
});
css
#screen-nav {
position: fixed;
top: 0; left: 0; right: 0;
}
#screen-nav.nav-up { top: -100px; }
#screen-nav.nav-down { top: 0; }
I want to add a third class. I want #screen-nav { top: 50px; } when the user is 300px from the top. (so I figure apply a third class .nav-top when the user is in that position) But not sure how to integrate it into my code.
Basically, I want the nav (navigation) to appear lower on the page when the user is at the top, and when it comes down when the user scrolls up, I want it to be right at the top.
add condition of javascript
if(st == 300){ $("#screen-nav").css({ top: '50px' }); }
<script type="text/javascript">
jQuery(document).ready(function($){
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight(true);
$(window).scroll(function(event) { didScroll = true; });
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 0);
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if(st == 300)
{
$("#screen-nav").css({ top: '50px' });
}
else if (st > lastScrollTop) {
// Scroll Down
$('#screen-nav').removeClass('nav-down').addClass('nav-up');
}
else {
$('#screen-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
});
</script>

How to disable a jQuery function after screen resize

I'm trying to disable this navigation code after the screen is less than 1000px
$(document).ready(function(){
var scroll_start = 0;
var startchange = $('body');
var offset = startchange.offset();
if (startchange.length){
$(document).scroll(function() {
scroll_start = $(this).scrollTop() > 50;
if(scroll_start > offset.top) {
$("#nav").css('background-color', 'rgba(35,46,63,1)');
$("#nav").css('box-shadow', '4px 0px 10px rgba(0,0,0,0.5)');
} else {
$('#nav').css('background-color', 'rgba(35,46,63,0)');
$("#nav").css('box-shadow', '0px 0px 0px rgba(0,0,0,0)');
}
});
}
});
Any help would be appreciated!
Based on your code with slight modification I would do this as follows:
$(document).ready(function(){
var scroll_start = 0;
var startchange = $('body');
var offset = startchange.offset();
var doScrollStuff;
$(window).resize(function(){
doScrollStuff = $(window).width() >= 1000;
}).resize();
if (startchange.length){
$(document).scroll(function() {
if (doScrollStuff) {
scroll_start = $(this).scrollTop() > 50;
if(scroll_start > offset.top) {
$("#nav").css('background-color', 'rgba(35,46,63,1)');
$("#nav").css('box-shadow', '4px 0px 10px rgba(0,0,0,0.5)');
} else {
$('#nav').css('background-color', 'rgba(35,46,63,0)');
$("#nav").css('box-shadow', '0px 0px 0px rgba(0,0,0,0)');
}
}
});
}
});
Use onjQuery API to bind the event and use a specific name to easily unbind it later.
$(document).on("scroll.Nav", function () {
And then later, if some condition is met either in the callback of that function(){ code segment, or in another code segment, simply use
$(document).off("scroll.Nav");
You can try this:
var windowWidth = $(window);
windowWidth.on('resize', function(){
if(window.innerWidth < 1000){
//do something
}
})
In the //do something section, you can write your disable function in there. This code above will execute the inner function whenever the screen resizes and is less than 1000px.

Categories

Resources