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

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

Related

How to make an array.length counter update on user scroll using ReactJS

I'm trying to add a simple counter in the bottom of my app like this one:
And it is very simple atm, 80 is my array.length that is being populated through my axios request.
<div>{people.length.toLocaleString()}</div>
And as I scroll down the page, using react-infinite-scroll, the number goes up and up and this is just fine. What I'm trying to do is subtract the number as the user goes back up the page.
Is this something harder than I'm thinking? If so, don't give me the full answer, just give me the path to follow. Thanks.
This is what I'm trying to accomplish: https://mkorostoff.github.io/hundred-thousand-faces/
you can do by using scroll event with window.innerHeight and the element bottom height to check whether its available inside the display window.
You can try like this using onscroll event which is available in library itself.
let counter = 0;
[listofElement].find(ele => {
var conditionHeight = window.innerHeight;
var cordinat = ele.getBoundingClientRect().top;
counter++;
return conditionHeight < cordinat;
});
You can check here with sample working part.
Looking at the source of the page you've linked, the code uses this function to get the size of the page:
function getScrollPercent() {
var face_width = document.getElementById('first').clientWidth;
var face_height = document.getElementById('first').clientHeight;
var body = document.documentElement || document.body;
var faces_per_row = Math.floor(main.clientWidth / face_width);
var total_height = total / faces_per_row * face_height;
var scroll_percent = (body.scrollTop - main.offsetTop + body.clientHeight) / total_height;
var count = Math.floor(scroll_percent * total);
var chunked_count = count - (count % faces_per_row);
if (chunked_count > 0) {
counter.classList = "fixed";
}
else {
counter.classList = "";
}
return (chunked_count > 0) ? chunked_count : 0;
}
The essential bit is var scroll_percent = (body.scrollTop - main.offsetTop + body.clientHeight) / total_height;. Basically, if you can calculate your total height (assuming that isn't infinite), then you can use body.clientHeight, +/- offsets, divided by totalHeight to figure out how far down the page you are. Call this from an event listener on scroll, and you should be good to go.
Incidentally, if this is the infinite scroll library you're talking about using, it's no longer maintained in favor of react-infinite-scroller.
using react-infinite-scroll, you can't back axios request results or remove generated doms.
The solution is calculating width and height of every doms and calculate offset.
Check how many doms are above the scrollReact and so so.

Toggle class when object visible in the viewport

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

Variable two options

Had a look around and couldn't find anything that solved this very simple problem.
I'm still learning jQuery so prior apologies for my stupidity on this one, I know it's a very simple fix but things like using || and trying to using if and else inside a var don't see to work for me.
Essentially this is what I have currently. All I want is to add/remove the class "whitebg" depending on the scroll position and height of the element, which works well.
The problem is trying to query two different elements that each need a different height buffer as you can see (-167 and -90) so cannot be grouped, but need to be 'either / or' so both are accounted for.
Many thanks
Rb
jQuery(window).scroll(function() {
Menuresize();
});
function Menuresize() {
var myheight = jQuery(".section-image-slider, .section-video-slider").height() - 90;
var myheightalt = jQuery(".area-tag").height() - 167;
var scroll = jQuery(window).scrollTop();
if (scroll > myheight) {
jQuery(".bt-menu").addClass("whitebg");
}
elseif (scroll > myheightalt){
jQuery(".bt-menu").addClass("whitebg");
}
else {jQuery(".bt-menu").removeClass("whitebg");}
};
jQuery(window).resize(function() {
Menuresize();
});
If I understand your problem correctly, toggleClass can take a boolean parameter to toggle on/off the class specified. You can then work out a compound boolean expression that results in true or false:
e.g.
jQuery(".bt-menu").toggleClass("whitebg", scroll > myheight || scroll > myheightAlt);
I found the question a little hard to follow so, if it is something else you wanted, please clarify :)
Have your Menuresize function take parameters for the selectors and height, and then just call it for each:
function Menuresize(selector, height) {
var myheight = jQuery(selector).height() - height;
var scroll = jQuery(window).scrollTop();
if (scroll > myheight) {
jQuery(".bt-menu").addClass("whitebg");
}
else {
jQuery(".bt-menu").removeClass("whitebg");
}
};
jQuery(window).resize(function() {
Menuresize(".section-image-slider, .section-video-slider", 90);
Menuresize(".area-tag", 167);
});

How can I set my browser window's scrollbar or a div scrollbar to scroll in increments using animate and scrollTop?

The general idea to the site i am designing is to scroll through a set of menu items horizontally and incrementally underneath a static div that will magnify(increase dimensions and pt size) the contents of a menu items. I don't really need help with the magnify portion because i think it's as simple as adding a mag class to any of the menuItem divs that go underneath the static div. I have been messing with this for a few weeks and the code I have for incrementally scrolling, so far, is this:
$(document).ready(function () {
currentScrollPos = $('#scrollableDiv').scrollTop(120); //sets default scroll pos
/*The incrementScroll function is passed arguments currentScrollPos and UserScroll which are variables that i have initiated earlier in the program, and then initiates a for loop.
-The first statement sets up the variables: nextScrollPos as equal to the currentScrollPos(which by default is 120px) plus 240px(the distance to next menuItem), prevScrollPos as equal to the currentScrollPos(which by default is 120px) minus 240px(the distance to next menuItem).
-The second Statement checks to see if the user has scrolled using var userScroll
-The third statement sets: var CurrentScroll equal to the new scroll position and var userScroll to false*/
function incrementScroll(currentScrollPos, userScroll) {
for (var nextScrollPos = parseInt(currentScrollPos + 240, 10),
prevScrollPos = parseInt(currentScrollPos - 240, 10); //end first statement
userScroll == 'true'; console.log('dude'), //end second statement and begining of third
currentScrollPos = scrollTop(), userScroll = 'false') {
if (scrollTop() < currentScrollPos) {
$('#scrollableDiv').animate({
scrollTop: (parseInt(prevScrollPos, 10))
}, 200);
console.log('scrolln up')
} else if (scrollTop() > currentScrollPos) {
$('#scrollableDiv').animate({
scrollTop: (parseInt(nextScrollPos, 10))
}, 200);
console.log('scrolln down')//fire when
}
}
}
$('#scrollableDiv').scroll(function () {
userScroll = 'true';
_.debounce(incrementScroll, 200); //controls the amount of times the incrementScroll function is called
console.log('straight scrolln')
});
});
I have found a variety of solutions that are nigh close: such as a plugin that snaps to the next or previous div horizontally demo, another solution that also snaps and is based on setTimeout demo, but nothing that nails incrementally scrolling through divs. I also found a way to control the rate at which a user may scroll through the menuItems using debounce which is included in the above code.
The console.logs inside the loop do not fire when I demo the code in jsfiddle which leads me to believe the problem lies within the loop. I'm a noob though so it could be in syntax or anywhere else in the code for that matter. Also in the second demo, i have provided the css for the horizontal static div, but the moment I put it in my html it keeps the js from working.
I would like to write the code instead of using a plugin and any help would be appreciated! Also, thank you ahead of time!
Try this fiddle. Menu container height is 960px to show 4 menu items. "Zoom" div is positioned absolutely at top. When you scroll mouse over this div, menu items shifts to top/bottom. I had to add additional div to bottom to be able to scroll to last 3 menu items. JS code:
jQuery(document).ready(function($){
var current = 0;
var menu = $('.menu-container').scrollTop(0);
var items = menu.find('.menu-item');
var zoom = $('.zoom');
function isVerticalScroll(event){
var e = event.originalEvent;
if (e.axis && e.axis === e.HORIZONTAL_AXIS)
return false;
if (e.wheelDeltaX)
return false;
return true;
}
function handleMouseScroll(event){
if(isVerticalScroll(event)){
var delta = event.originalEvent.wheelDelta * -1 || event.originalEvent.detail;
current += (delta > 0 ? 1 : -1);
if(current < 0)
current = 0;
if(current >= items.length){
current = items.length - 1;
}
menu.stop().animate({
"scrollTop": current * 240
}, 300);
items.removeClass('current').eq(current).addClass('current');
event && event.preventDefault();
return false;
}
}
zoom.on({
"MozMousePixelScroll": handleMouseScroll,
"mousewheel": handleMouseScroll
});
});
Hope it will help.

Menu that fit to the buttom/top of the screen

I saw a cool style/js function (I can tell what it is) that implemented on a side menu.
You know the situation when you have a long center page and one of / both of you sides ends and that leave a blank space? Well this site implemented this thing that just when the user scrool to the place where the side menu end - the menu get absolute postion and doesnt move.
How can I do this?
If you want to see an example you can look here (just scroll and look on the sides)
I believe you can achieve similar effect using this: http://www.wduffy.co.uk/blog/keep-element-in-view-while-scrolling-using-jquery/comment-page-1/ (just making it move with 0 as speed parameter instead of slow, as in the example) and adding conditions about whether the current position fits within the box it is displayed (you can take height of the box - menu being moved on page or box that contains the menu - by using .height() jQuery function).
EDIT:
The page you referenced uses the following JavaScript code to support what you try to accomplish:
<script type="text/javascript">
$(function(){
var seoHeight = $$('dvIndexSeoMaster').height();
seoHeight = (seoHeight > 0) ? seoHeight : 0;
var documentHeight = $(document.body).height() - 120 - seoHeight;
var fixedMode = false;
var hasFixedClass = false;
var leftColElm = $sc('dvFixed');
var leftColPos = leftColElm.offset().top;
var leftColHeight = leftColElm.height();
var rightColElm = $$('dvIndexMasterRightCol');
var rightColPos = rightColElm.offset().top;
var rightColHeight = rightColElm.height();
function scrollElm(elmPos,elmHeight,objElm, cssClass){
var fixedMode = false;
var hasFixedClass = false;
var windowTop = $(window).scrollTop();
(windowTop >= elmPos && (windowTop + elmHeight) < documentHeight) ? fixedMode = true : fixedMode = false;
if( fixedMode){
$(objElm).addClass(cssClass);
hasFixedClass = true;
}else if( (fixedMode == false)){
$(objElm).removeClass(cssClass);
hasFixedClass = false;
}
};
$(window).scroll(function(){
scrollElm(leftColPos,leftColHeight,leftColElm,'make-fixed');
scrollElm(rightColPos,rightColHeight,rightColElm, 'make-fixed');
});
});
</script>
And the make-fixed CSS class has the following definition:
.make-fixed {
position: fixed;
top: 0;
z-index: 200;
}
You can make an element stay in the same place, even as the user scrolls, with the CSS position:fixed property: http://www.w3.org/TR/CSS2/visuren.html#fixed-positioning

Categories