Toggle class when object visible in the viewport - javascript

I need a script which toggle a class when another class or section is visible in the viewport (during scrolling).
Here I have an script which works for precised distance from top, but can somebody help me to modify it for my needs?
$(window).scroll(function(){
if ($(this).scrollTop() > 50) {
$('#viewport').addClass('turn_on');
} else {
$('#viewport').removeClass('turn_on');
}
});

A couple of things. First the scroll event (as well as the resize event) fire multiple times. Traditionally, developers have used something called debouncing to limit the number of times a function fires. I've never got it to work correctly, so instead I check if a condition is met before continuing. You are basically doing this already.
var bool = false
$(window).on('scroll', function(){
if(!bool){
bool = true;
//fire the function and then turn bool back to false.
};
});
The next thing you need is to identify the element to add the class to. Let's say it has an id of foo.
var yOffset = $('#foo').offset().top;
From here, you'll need to compare the current vertical scroll position with that of the yOffset. You may also need to add the height of the element for when it scrolls out of frame.
var elHeight = $('#foo').height();
The element should be completely in frame with the $(window).scrollTop() equals the yOffset and out of frame when the $(window).scrollTop() is greater than yOffset + elHeight.
This is all assuming the element isn't in the frame to begin with. If it is, it will be trickier but it's a start.

Working fiddle
Try to add function that detect if element passed in argument is visible :
function isVisisble(elem){
return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}
$(window).scroll(function(){
if (isVisisble( $('your_element') ))
$('#viewport').addClass('turn_on');
} else {
$('#viewport').removeClass('turn_on');
}
});
Hope this helps.

Thx everyone for help.
Here I found the solution: LINK
And here is the modified script:
$(document).ready(function () {
var windowHeight = $(window).height(),
gridTop = windowHeight * 0.1,
gridBottom = windowHeight * 1;
$(window).on('scroll', function () {
$('.inner').each(function () {
var thisTop = $(this).offset().top - $(window).scrollTop();
if (thisTop > gridTop && (thisTop + $(this).height()) < gridBottom) {
$(this).addClass('on');
}
});
});
});

Related

can't change z index with javascript

I'm trying to change the Z index of an image according to the scroll position,currently in chrome (but it should be working on all broswers).
anyway, it's not working on chrome, unless I get into inspection mode and I don't understand why it's only working in inspection mode?
this is the script:
$( window ).scroll(function() {
var scrollTop = $(window).scrollTop();
if ($(this).scrollTop()>700) {
document.getElementById("back-ground-image").style.zIndex = "-9";
console.log("-9");
} else {
document.getElementById("back-ground-image").style.zIndex = "-19";
console.log("-19");
}
});
Problem
What you need is $(document) not $(window).
By default, you scroll the $(document), not the $(window).
However, when you open your Chrome DevTools, the $(window) is not being scrolled which is why your code works.
To fix the issue, change $(window).scroll() to $(document).scroll() and $(window).scrollTop() to $(document).scrollTop()
Improvements
1. Use jQuery functions
Also, if you're already using jQuery, why not use jQuery selectors and .css():
$("#back-ground-image").css('zIndex', '-9')
instead of
document.getElementById("back-ground-image").style.zIndex = "-9";
2. Use DRY code
(Don't Repeat Yourself)
If you follow recommendation #1, why not set $("#back-ground-image") to a variable instead of repeating it twice.
$(document).scroll(function() {
var scrollTop = $(document).scrollTop(),
$bkImg = $("#back-ground-image");
if ($(this).scrollTop() > 700) {
$bkImg.css('zIndex', '-9');
console.log("-9");
} else {
$bkImg.css('zIndex', '-19');
console.log("-19");
}
});
Otherwise, you could use:
$(document).scroll(function() {
var scrollTop = $(document).scrollTop(),
background = document.getElementById("back-ground-image");
if ($(this).scrollTop()>700) {
background.style.zIndex = "-9";
console.log("-9");
} else {
background.style.zIndex = "-19";
console.log("-19");
}
});

Add class to element if y-position bigger as another element

I want to add a class to an element as soon as the users' scroll-position has "hit" a special - other - element.
I try to use that code therefore
var hands = $(".sw_3--breit");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
// The next line is the one I am asking for help
if (scroll >= window.innerHeight)
{
hands.addClass("fixed");
} else {
hands.removeClass("fixed");
}
});
Which works nice by adding the class after the scroll is bigger then the users display-height I guess. But I want to add - and afterwards also remove - a class when then user has "hit" another element.
What I am asking for is something - very roughly and stupid I know - like:
var other_elements_position = $(".other_element"().position;
if (scroll >= other_elements_position)
How can I achieve that? And I already do use jquery for other things, so using jquery there would make sense I guess.
Thanks!
For people that got the same problem as I do have, this worked for me:
var hands = $(".sw_3--breit");
var hands_original = $(".sw_8").position();
var hands_off = $("#target_agentur").position();
var hands_corrected = (hands_original.top + 680) // here I add a small delay to the trigger of the "animation"
$(window).scroll(function () {
var scroll = $(window).scrollTop();
if (scroll >= hands_corrected && scroll <= hands_off.top) // I doublecheck against 2 heights
{
hands.addClass("fixed");
} else {
hands.removeClass("fixed");
}
});

Run function() if appear in viewport ? jquery-viewport-checker

I use anime-js for create an animation. But, It is far in the page. I would like to launch my animation function when the section in which the item to be animated appears on the screen.
I tried a plugin that I like to use (jquery viewportchecker) but it does not seem to do that.
Can you help me ?
Thank you
I found a solution. The problem with your method is that the function repeats itself to infinity.
I create a little function for check if element is visible. With that, no plugin needed.
function checkVisible( elm, evale ) {
var evale;
evale = evale || "object visible";
var viewportHeight = $(window).height(), // Viewport Height
scrolltop = $(window).scrollTop(), // Scroll Top
y = $(elm).offset().top,
elementHeight = $(elm).height();
if (evale == "object visible") return ((y < (viewportHeight + scrolltop)) && (y > (scrolltop - elementHeight)));
if (evale == "above") return ((y < (viewportHeight + scrolltop)));
}
I also created a variable var counter = 0;. And as soon as the function is called, I increment by 1.
$(window).on('scroll',function() {
if (counter == 0){
if (checkVisible($('.frontend'))) {
// Your function here
}
}
}
At the first time the function will be called, counter will be 1, and thus, the function will not repeat. Thank you for your help !
jQuery.appear
This plugin implements custom appear/disappear events which are fired when an element became visible/invisible in the browser viewport.
https://github.com/morr/jquery.appear
$('someselector').on('appear', function(event, $all_appeared_elements) {
// this element is now inside browser viewport
});
$('someselector').on('disappear', function(event, $all_disappeared_elements) {
// this element is now outside browser viewport
});
Also this plugin provides custom jQuery filter for manual checking element appearance.
$('someselector').is(':appeared')
Have you tried using JQuery's on load method?
Something like
$(document).on('load', '.exampleClass', function() { //do stuff } )

Pure js add and remove (toggle) class after scrolling x amount?

I don't want to use jQuery for this.
It's really simple, I just want to add a class after scrolling past a certain amount of pixels (lets say 10px) and remove it if we ever go back to the top 10 pixels.
My best attempt was:
var scrollpos = window.pageYOffset;
var header = document.getElementById("header");
function add_class_on_scroll() {
header.classList.add("fade-in");
}
function remove_class_on_scroll() {
header.classList.remove("fade-in");
}
window.addEventListener('scroll', function(){
if(scrollpos > 10){
add_class_on_scroll();
}
else {
remove_class_on_scroll();
}
console.log(scrollpos);
});
But console shows a number that continues to grow regardless of scrolling up or down. And the class fade-in never gets added, though console shows we past 10.
You forgot to change the offset value in the scroll handler.
//use window.scrollY
var scrollpos = window.scrollY;
var header = document.getElementById("header");
function add_class_on_scroll() {
header.classList.add("fade-in");
}
function remove_class_on_scroll() {
header.classList.remove("fade-in");
}
window.addEventListener('scroll', function(){
//Here you forgot to update the value
scrollpos = window.scrollY;
if(scrollpos > 10){
add_class_on_scroll();
}
else {
remove_class_on_scroll();
}
console.log(scrollpos);
});
Now you code works properly
Explanation
There is no documentation for that, like you asked for. This is just an issue in the logic workflow.
When you say that scrollpos = window.scrollY your page is at an top-offset of 0, so your variable stores that value.
When the page scrolls, your scroll listener will fires. When yout listener checks for the scrollpos value, the value is still 0, of course.
But if, at every scroll handler, you update the scrollpos value, now you can have a dynamic value.
Another option is you to create a getter, like
var scrollpos = function(){return window.scrollY};
This way you can dynamically check what that method will return for you at every offset.
if(scrollpos() > 10)
See? Hope that helped. (:
One simple way to achieve what you want (one line of code inside the scroll event):
window.addEventListener('scroll', function(e) {
document.getElementById('header').classList[e.pageY > 10 ? 'add' : 'remove']('fade-in');
});
#header {
height: 600px;
}
.fade-in {
background-color: orange;
}
<div id='header'></div>
just use the method toggle in classList
header.classList.toggle('fade-in')

javascript: detect scroll end

I have a div layer with overflow set to scroll.
When scrolled to the bottom of the div, I wanna run a function.
The accepted answer was fundamentally flawed, it has since been deleted. The correct answer is:
function scrolled(e) {
if (myDiv.offsetHeight + myDiv.scrollTop >= myDiv.scrollHeight) {
scrolledToBottom(e);
}
}
Tested this in Firefox, Chrome and Opera. It works.
I could not get either of the above answers to work so here is a third option that works for me! (This is used with jQuery)
if (($(window).innerHeight() + $(window).scrollTop()) >= $("body").height()) {
//do stuff
}
Hope this helps anyone!
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight)
{
//your code here
}
I too searched it and even after checking all comments here and more,
this is the solution to check if reached the bottom or not.
OK Here is a Good And Proper Solution
You have a Div call with an id="myDiv"
so the function goes.
function GetScrollerEndPoint()
{
var scrollHeight = $("#myDiv").prop('scrollHeight');
var divHeight = $("#myDiv").height();
var scrollerEndPoint = scrollHeight - divHeight;
var divScrollerTop = $("#myDiv").scrollTop();
if(divScrollerTop === scrollerEndPoint)
{
//Your Code
//The Div scroller has reached the bottom
}
}
This worked for me:
$(window).scroll(function() {
buffer = 40 // # of pixels from bottom of scroll to fire your function. Can be 0
if ($(".myDiv").prop('scrollHeight') - $(".myDiv").scrollTop() <= $(".myDiv").height() + buffer ) {
doThing();
}
});
Must use jQuery 1.6 or higher
I found an alternative that works.
None of these answers worked for me (currently testing in FireFox 22.0), and after a lot of research I found, what seems to be, a much cleaner and straight forward solution.
Implemented solution:
function IsScrollbarAtBottom() {
var documentHeight = $(document).height();
var scrollDifference = $(window).height() + $(window).scrollTop();
return (documentHeight == scrollDifference);
}
Resource: http://jquery.10927.n7.nabble.com/How-can-we-find-out-scrollbar-position-has-reached-at-the-bottom-in-js-td145336.html
Regards
I created a event based solution based on Bjorn Tipling's answer:
(function(doc){
'use strict';
window.onscroll = function (event) {
if (isEndOfElement(doc.body)){
sendNewEvent('end-of-page-reached');
}
};
function isEndOfElement(element){
//visible height + pixel scrolled = total height
return element.offsetHeight + element.scrollTop >= element.scrollHeight;
}
function sendNewEvent(eventName){
var event = doc.createEvent('Event');
event.initEvent(eventName, true, true);
doc.dispatchEvent(event);
}
}(document));
And you use the event like this:
document.addEventListener('end-of-page-reached', function(){
console.log('you reached the end of the page');
});
BTW: you need to add this CSS for javascript to know how long the page is
html, body {
height: 100%;
}
Demo: http://plnkr.co/edit/CCokKfB16iWIMddtWjPC?p=preview
This will actually be the correct answer:
function scrolled(event) {
const container = event.target.body
const {clientHeight, scrollHeight, scrollY: scrollTop} = container
if (clientHeight + scrollY >= scrollHeight) {
scrolledToBottom(event);
}
}
The reason for using the event is up-to-date data, if you'll use a direct reference to the div you'll get outdated scrollY and will fail to detect the position correctly.
additional way is to wrap it in a setTimeout and wait till the data updates.
Take a look at this example: MDN Element.scrollHeight
I recommend that check out this example: stackoverflow.com/a/24815216... which implements a cross-browser handling for the scroll action.
You may use the following snippet:
//attaches the "scroll" event
$(window).scroll(function (e) {
var target = e.currentTarget,
scrollTop = target.scrollTop || window.pageYOffset,
scrollHeight = target.scrollHeight || document.body.scrollHeight;
if (scrollHeight - scrollTop === $(target).innerHeight()) {
console.log("► End of scroll");
}
});
Since innerHeight doesn't work in some old IE versions, clientHeight can be used:
$(window).scroll(function (e){
var body = document.body;
//alert (body.clientHeight);
var scrollTop = this.pageYOffset || body.scrollTop;
if (body.scrollHeight - scrollTop === parseFloat(body.clientHeight)) {
loadMoreNews();
}
});
To do the same in React/JSX, here is the snippet.
export const scrolledToEnd = event => {
const container = event.target;
if (container.offsetHeight + container.scrollTop >= container.scrollHeight) {
return true;
}
return false;
};
And in your component add
<Component onScroll={scrolledToEnd}>
There is experimental onscrollend event https://developer.mozilla.org/en-US/docs/Web/API/Document/scrollend_event
For now works only in firefox 109+, if other browsers catch up will be very nice.
Have polyfill for that https://github.com/argyleink/scrollyfills
Use like
import "scrollyfills";
...
scrollContainer.addEventListener(
"scrollend",
(ev) => { console.log('scroll END') }
);
I found this methode to get the end of the scroll :
let TheBody = document.getElementsByTagName("body"); // I choose the "body" element for my exemple
function OnScrolling(){ // put this on a scrolling EVENT
let ScrollEnd = TheBody[0].scrollHeight - window.innerHeight; // this is the scroll end Pixel
if (ScrollEnd.toFixed() == window.scrollY.toFixed()){
//do stuff
}
}
Okay now for your DIV or any other element that have a scrolling I found this method on JavaScript :
let D = document.getElementById("D1"); // I gave "D1" as id to my div
// this one is to calculate the scroll end Pixels
let Calc = D.scrollHeight - D.clientHeight;
function ScrollingInD1() {
//this one is to calculate the scrolling percent while going through the <div> it can help for "Responsivity"
let percent = (D.scrollTop * 100) / Calc;
if (D.scrollTop == Calc) {
// do Stuffs
}
}

Categories