I'm looking for ideas to hide a div when it reaches another div and show it again when it passes the same div. There can also be multiple divs to pass. Something like:
var bottom = $('.out-of-grid-images')
$(window).scroll(function(){
if ($(this).scrollTop() > bottom){
$('.share-icons').fadeOut(200); // hide share icons when reached and overlaps
}
else if ($(this).scrollTop() < bottom){ {
$('.share-icons').fadeIn(200); // show icons when passed element
}
});
I can not produce a jsFiddle because I haven't found anything similar to work with. Any ideas?
EDIT:
The share icons are a fixed position element. The elements reached are dynamic and not fixed from top of the page (they are post content images out of the grid)
EDIT: here's an image to illustrate the matter
What you'll want to do is have an Array of divs that you want to trigger the hiding effect, then calculate their bounding rectangle, and then perform collision detection on them.
Here is a very rough example - you'll have to fix the showing and hiding, as this will cause a fadeIn/fadeOut on each scroll event.
const shareIcons = $('.share-icons');
const divs = $('.trigger-div');
const rects = [];
divs.each(function () {
rects.push(this.getBoundingClientRect());
});
$(window).scroll(function () {
let interectsAny = false;
rects.forEach(function (rect) {
if (intersectRect(rect, shareIcons[0].getBoundingClientRect())) {
interectsAny = true;
}
});
if (interectsAny) {
shareIcons.fadeOut(200);
} else {
shareIcons.fadeIn(200);
}
});
// https://stackoverflow.com/questions/2752349/fast-rectangle-to-rectangle-intersection
function intersectRect(r1, r2) {
return !(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top);
}
Related
I am working on a bootstrap based website and I have the following case :
A main container and a floating left navigation menu.
The floating left navigation menu, is set to position fixed, because it is following the user scroll.
What I would like is when the end user resize the window, and when the main content meets the left menu (overlap), the left menu becomes hidden, and when there is enough space the left menu comes back.
Actually, it is not really working, it is blinking. I have written a little bit of jquery binded to the resize function.
Here is the jsfiddle :
https://jsfiddle.net/cuw46rsv/5/
function getDiffLeftMenu(div1, div2) {
var value = ($(div1).offset().left - $(div2).offset().left);
console.log(value - $(div2).width());
if(value - $(div2).width() < 0){
return true;
}
}
$(window).on('resize', function(event) {
var value = ($('.central-content').offset().left - $('#sectionsMenu').offset().left);
if(getDiffLeftMenu('.central-content','#sectionsMenu')){
$('#sectionsMenu').hide();
}
else {
$('#sectionsMenu').show();
}
}).resize();
Is this possible to not have this blinking effet ?
Thanks a lot for any help.
Regards.
Here's the solution with your logic, .hide() method causes it to have offset 0 and that's why it's blinking (it can get stuck as hidden all the time).
https://jsfiddle.net/cuw46rsv/7/
function getDiffLeftMenu(div1, div2) {
var value = ($(div1).offset().left - $(div2).offset().left);
console.log(value - $(div2).width());
if(value - $(div2).width() < 0){
return true;
}
}
By using opacity offset will stay there.
$(window).on('resize', function(event) {
var value = ($('.central-content').offset().left - $('#sectionsMenu').offset().left);
if(getDiffLeftMenu('.central-content','#sectionsMenu')){
$('#sectionsMenu').css('opacity', 0);
}
else {
$('#sectionsMenu').css('opacity', 1);
}
}).resize();
well you are doing it wrong, but you can solve it like this (as a workaround):
$(window).on('resize', function(event) {
var value = ($('.central-content').offset().left - $('#sectionsMenu').offset().left);
if(getDiffLeftMenu('.central-content','#sectionsMenu')){
setTimeout(function(){$('#sectionsMenu').hide();},20);
}
else {
$('#sectionsMenu').show();
}
}).resize();
https://jsfiddle.net/cuw46rsv/6/
I have a div called #menu which I want to display when I scroll past the element #section3, if I scroll up past that element again, I want #menu to disappear
How would I code this?
Maybe something like this?
scrolled = "no"
$(window).scroll(function(){
scr = $("body").scrollTop();
if (scr > 100 && scrolled == "no"){
$("#menu").css({"display:block"})
displayed = "yes"
}
if (displayed == "yes" && scrolled = "yes"){
$("#menu").css({"display:none"})
}
});
The above assumes that #section3 is 100 pixels down the page. If you do not know where its going to be on the page then you could use the method outlined here:
Trigger event when user scroll to specific element - with jQuery
With jQuery you can get the scroll position with $("body").scrollTop();.
Expanding on what #Ned Hulton said, I recommend comparing the scroll position to the top of a "container element" (or 'row') in your page like this:
if ($('body').scrollTop() > $('#someRow').offset().top){
//do something
}
That way you can account for your container appearing at a variable distance down the page (which will come in handy for mobile browsing or cases where your text wraps to additional lines)
I just whipped this up in jsfiddle
https://jsfiddle.net/rb56j0yu/
it uses jQuery, and checks the scroll position against the target div. Css sets the menu as position: fixed, and defaults to hidden.
$(window).scroll(function(){
var yPos = $("body").scrollTop();
var yCheck = $("#c3").position().top;
if (yPos > yCheck && !$("#menu").is(":visible"))
{
$("#menu").show();
}
if (yPos <= yCheck && $("#menu").is(":visible"))
{
$("#menu").hide();
}
});
First, get your #section3 top offset and height. Which will be used as the threshold whether #section3 is actually on the window screen.
var top = $('#section3').offset().top;
var bot = topOffset + $('#section3').height();
Then, detect it on your scroll event.
$(window).on('scroll', function () {
var scrollTop = $(window).scrollTop();
if (scrollTop >= top && scrollTop <= bot) {
// #section3 is within the screen.
$('#menu').show();
}
else {
// #section3 is out of screen.
$('#menu').hide();
}
});
This is a common use case, I wrote following code:
// what does "Auto Header" mean, goto https://www.yahoo.com/
// scroll down and you will see the purple part auto fixed to top,
// while when scroll up, it restores and does not be fixed.
// 1. multiple auto header elements handled
// 2. dynamically create/remove elements issue handled
// 3. no unnecessary dom operation, high performance
// usage: just add 'class="auto-header"' to any element you want to auto header
// suggest set each auto-header element specific width and height
// do not guarantee it works when resize or scroll left/right
$(document).ready(function() {
var rawTops = [],
rawLefts = [],
rawStyles = [],
$locations = [], // record next sibling so that element easily find where to restore
fixed = []; // mark whether this element is fixed
$(".auto-header").each(function() {
var $this = $(this),
offset = $this.offset();
rawTops.push(offset.top);
rawLefts.push(offset.left);
rawStyles.push($this.attr("style"));
$locations.push($this.siblings().eq($this.index()));
fixed.push(false);
});
$(window).on("scroll", function() {
$(".auto-header").each(function(i, e) {
if(!fixed[i] && $(window).scrollTop() > rawTops[i]) {
var $te = $(this).clone(true);
$(this).remove();
$locations[i].before($te);
$te.css({
"position": "fixed",
"top": 0,
"left": rawLefts[i],
"z-index": 100
});
fixed[i] = true;
} else if(fixed[i] && $(window).scrollTop() < rawTops[i]) {
$(this).removeAttr("style").attr("style", rawStyles[i]);
fixed[i] = false;
}
});
});
});
I have a question concerning jQuery's scrollTop functionality, and it's ability to toggle a class based on the amount of vertical scroll.
What I am trying to accomplish is on any page with a "section.banner" class, that after you scroll past the banner a class is applied to the body tag. This will allow me to change the fill colors of several SVGs that are in the site's header, as well as a fixed positioned side nav that is for pagination.
I am terrible at javascript, and have been stuck searching and trying to get this for hours. any help will be greatly appreciated. Here's the code that I'm working with now (CodeKit is telling me it is wrong, which I am not surprised). The value of 200 is just a placeholder and will be calculated by the height of a fluid image. Full disclosure, I have no idea if the brackets and parenthesis are correct.
// Header/Fixed Pagination Banner Scroll Recoloriing (toggle class)
// Check If '.banner' Exists
if( $('section.banner').length > 0) {
$('body').scrollTop(function)()
{
if $(window).scrollTop >= 200 {
$('body').toggleClass('downtown');
return false;
}
}
}
Try something like this :
if( $('section.banner').length > 0) {
$(window).scroll(function() {
{
if ($(window).scrollTop() >= $('section.banner').scrollTop()) {
$('body').toggleClass('downtown');
return false;
}
});
}
UPDATE
There was little mistake in my code : http://jsfiddle.net/t2yp15hq/
var top = $('section.banner').position().top;
if($('section.banner').length > 0) {
$(window).scroll(function() {
if ($(this).scrollTop() >= top) {
$('body').addClass('downtown');
}
else
{
$('body').removeClass('downtown');
}
});
}
It does not work with toogleClass, the background is flashing.
UPDATE
http://codepen.io/anon/pen/wBWzXy
The solution is to recalculate the top when the window is resized :
$(window).resize(function(){
top = $('section.story-intro').offset().top - 90;
});
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.
I have a function that gets called when a user scrolls to check for scrollTop() and after a certain scroll happens it changes the menu's z-index from -1 to 1. However this only occurs on a scroll so if the user refreshes the site the menu is virtually unusable until the next scroll occurs.
Is there a way for me to call this and check if the amount of screen scrolled (after the refresh not a user scroll) meets the criteria change the z-index?
My JS:
function getPosition(){
var y = $(window).scrollTop();
var status = (y > 880) ? true : false;
//console.log(status);
if(status)
$('#actual-menu').css('z-index', 1);
else
$('#actual-menu').css('z-index', -1);
}
z-index property has no effect on non-positioned elements, the element must be either relatively positioned ,absolutely positioned, or fixed.Replace your line with this:
Try adding this first ,
$("#actual-menu").css('position', 'relative');
$('#actual-menu').css('z-index', 1);
Just run getPosition inside of your ready event.
Functioning Example
var limit = 50;
$(function () {
function getPosition() {
var y = $(window).scrollTop();
var status = (y > limit) ? true : false;
if (status) {
$('#actual-menu').css('zIndex', 1);
} else {
$('#actual-menu').css('zIndex', -1);
}
}
$(document).on('scroll', getPosition);
getPosition();
});