Fade in or fade out based on scroll - javascript

$(document).scroll(function () {
var y = $(this).scrollTop();
if (y > 397) {
$('#aboutNav.fixed').fadeIn(500);
} else {
$('#aboutNav.fixed').hide();
}
});
As you can tell, this shows a fixed navigation. The CSS is fine, the positioning is great. However I want the navigation to become visible above 397px which it does fine.
However I want the navigation to fade in when I start scrolling:
.fadeIn(500);
When the user starts stops to look at content or whatever, I want the element to fade out
.delay(3000).fadeOut(350);
I believe this is something that can be done by doing an if statement within the first if statement. However a script to check if the user is scrolling and the working script above seem to collide.
Ideas, anyone?

If I understand you correctly. You want the nav to fade in if its above 397px and only when its scrolling... So this function will do that. If I misunderstood your question please clarify in the comments
$(window).scroll(function() {
clearTimeout($.data(this, 'scrollTimer'));//Lets the timer know were scrolling
//Hide/Show nav based on location
var y = $(this).scrollTop();
if (y > 397) {
$('#aboutNav.fixed').fadeIn(500);
} else {
$('#aboutNav.fixed').hide();
}
//TimeOut function that is only hit if we havent scrolled for 3 Seconds
//In here is where you fade out the nav
$.data(this, 'scrollTimer', setTimeout(function() {
$('#aboutNav.fixed').fadeOut();
console.log("Haven't scrolled in 3s!");
}, 3000));
});
JAN 23 UPDATE based on your comment
You can add this to you $(document).ready() function
$("#elementID").hover(function(){
//show here (mouse over)
$("#elementToShow").show();
},function(){
//Start timeout here, (mouse out)
setTimeout(function() {
$("#elementToHide").hide();
}, 3000);
}

Expanding on what Kierchon's answer a bit:
Since there's no real way to tell when the user is done scrolling (i.e. no event for 'finished scrolling') you'll have to use a event-delaying method called debouncing.
Debouncing is basically setting a timeout to run some code (a function) in the future, and if the event calling the debounced function get called again, you clear and reset the timeout, doing this repeatedly until the event finally stops being called. This method is to prevent events that fire repeatedly (such as scroll and resize) to only execute things after the final event fires and your delayed (debounced) code finally executes.
Here is a nice article on use of debouncing methods in JS.
As long as I understand what you need (which I think I do) - Here's a JSBin with some working code

Related

.delay() a .css() action by multiplying an index number

I am trying to create a script that does the following:
Waits until a point on the page is reached by scrolling (.clients with an offset of 500px
Start fading in img's contained inside the .clients div once this event is triggered
Fade in with a slight delay between each item (so they fade in in sequence)
Due to other parts of my code the fade-in has to be with change of opacity:1 and cannot be .fadeIn()
I'm somewhere there but having a few issues. Here is my code:
var targetOffset = $(".clients").offset().top;
var $w = $(window).scroll(function(){
if ( $w.scrollTop() > targetOffset-500 ) {
$('.home .clients img').each(function(index){
console.log(index);
$(this).delay(500 * index).css('opacity','1');
});
}
});
First problem
The event does fire at the correct scroll-point in the page, but it continues to fire. I would like it to only fire once and then not register again. When 500 above .clients is reached, the event should fire, and never again.
Second problem
My .each() does not seem to work correctly. Everything fades in at once. My method for making a small .delay() between the fade-ins doesn't seem to be working. I tried multiplying the index by 500. So the first index is 0, so it fires immediately. The second index is 1 so it should fire after 500 milliseconds and so on. I'd like to work out why this method isn't working.
Any help appreciated. I'd appreciate trying to make the code above work rather than writing something entirely new, unless that's the only way. I'd appreciate explanation of what I was doing wrong so I can learn, instead of just pure-code answers.
JSFiddle
Sidney has attacked most of the problems except one. The scroll event fires multiple times, so it checks the conditional multiple times and then actually sets the animation multiple times. To keep this from happening, I typically like to add another boolean to check if the process has fired at all. I've simplified the code to make the changes more legible.
var working = false;
$(window).on('scroll', function(){
if($(window).scrollTop() > 1000 && !working){
working = true;
setTimeout(function(){
working = false;
}, 500);
};
});
As Tushar mentioned in the comments below your post, instead of using .delay() you could use a plain setTimeout().
On the jQuery docs for .delay() they mention that using setTimeout is actually better in some use-cases too - this is one of them.
The .delay() method is best for delaying between queued jQuery
effects. Because it is limited—it doesn't, for example, offer a way to
cancel the delay—.delay() is not a replacement for JavaScript's native
setTimeout function, which may be more appropriate for certain use
cases.
Using setTimeout your code would look like this:
var targetOffset = $(".clients").offset().top;
var $w = $(window).scroll(function() {
if ($w.scrollTop() > targetOffset - 500) {
$('.home .clients img').each(function(index) {
setTimeout(function() {
$(this).css('opacity','1');
}, (500 * index));
});
}
});
Also, you can unbind an event using .off()
so in your if ($w.scrollTop() > targetOffset - 500) { ... }
you could add a line that looks like this:
$(window).off('scroll');
Which would unbind the scroll handler from the window object.
You could also use .on() to reattach it again some time later. (with on() you can bind multiple events in one go, allowing you to write the same code for multiple handlers once.)
Please change your jquery code with following it will trigger event one time only and may be as per your reuirements :-
var targetOffset = $(".clients").offset().top;
var $w = $(window).scroll(function () {
if ($w.scrollTop() == 1300) {
console.log('here!');
$('.clients img').each(function (index) {
$(this).delay(5000 * index).css('opacity', '1');
});
}
});
Here i have take scroll hight to 1300 to show your opacity effect you can take it dynamically, if you want it 500 then please change the css as following also.
.scroll {
height:700px;
}

Clearing an interval does not work

I'm working on a rather strange and complex function. The idea is that there is a timer that runs a slider. This timer gets cleared when the slider is hovered (i.e. the slider stopts moving). I would also like the timer to be cleared when the slider (or, rather, its parent container) is out of view. With the plugin inview I can check if an element is in the viewport or not. So when I see that the parent element is not in the viewport anymore, I clear the timer. However, this is not working and I can't figure out why. Clearing the timer on hover does work. Here is a fiddle.
The part that is not working:
$("body > .section").bind('inview', function (event, isInView) {
var $this = $(this);
if (isInView) {
// Päuse Twitter slider if it's not in the viewport
if (!$this.is(".twitter")) {
clearInterval(timer);
console.log("Timer cleared");
$(".twitter .article.focus").addClass("pause");
} else {
$(".twitter .article").removeClass("pause");
startTimer();
console.log("Timer restart");
}
}
});
As you can see, the events are logged in console, so they are triggered, but the slider does not stop (as you can see in console: classes are still assigned and remove to the .articles inside .twitter. This means that the timer isn't cleared. But why not? I can't figure it out. The timer is set globally, so that should not be a problem.
EDIT: oh apparently the clearing of the timer on hover doesn't work either... It is strange, because all the console.logs do work. AND timer is set as a global variable.
The key is not to start the timer more times. The inview jQuery plugin fires the inview event anytime you reach top or bottom of the watched element and in your example you start new timer everytime this happens. And since the new timer replaces the timer you already had set up, you lose track of that old timer and cannot clear it afterwards.
Try abstracting the start & pause code and everytime you start, check if the timer is started. For example like this:
function startSlider() {
if (!timer) {
startTimer();
}
}
function pauseSlider() {
clearInterval(timer);
timer = null;
}
I have updated the jsfiddle where you can see it working in action.

Reposition page on window resize

I'm using scrollTo() for page scrolling. One problem I found is, when I resize browser, page don't scroll again to element I specified, but it stays somewhere in middle, so I have to click 'scroll' button again to align the page. Is there any way to align page when user resize browser.
I tried using this:
window.onresize = function() {
scrollToPosition(section[position]);
}
// position is variable which I declared above this event
But this makes scrolling crazy, the page start to move right/left really fast which is not normal. I believe it binds onresize event every time I resize browser.
Is there any solution for my problem
EDIT:
This is jsFiddle, but it seems I don't know how to use jsFiddle since nothing works here: http://jsfiddle.net/52eRj/1/
You can avoid reruning function everytime the resize event is executed by writing code as below. scrollToPosition function will be executed every 1 second when scrolling.
var last = new Date().getTime();
var interval = 1000; // Set your own time.
window.addEventListener('resize', function() {
var curr = new Date().getTime();
if (curr - last > interval) {
last = curr;
scrollToPosition(section[position]);
}
});
The problem might be that you are calling your scrollToPosition function on every resize event, which can be fired 100 times in a normal manual resize.
To avoid this you can use clearTimeout like this:
$(window).resize(function () {
clearTimeout(resizeId);
resizeId = setTimeout(doneResizing, 500);
});
function doneResizing() {
scrollToPosition(section[position]);
}
This way the doneResizing function would only be called after 500 miliseconds since the window has stopped resizing, avoiding therefore, those tens or hundreds of unnecessary calls.

jQuery continuously scales a div element using hover()

I recently tried to use jQuery's effect('scale') function with the hover() function in jQuery. The idea is to enlarge the div element on mouseenter, and shrink it back to normal on mouseleave. The code is as follows:
$('.boxgrid').hover(function(){
$(this).effect('scale', {percent:125}, 1000);
}, function() {
$(this).effect('scale', {percent:80}, 1000);
});
I tried testing this in a jsfiddle, but instead of upscaling and downscaling once when a mouse enters the element, it keeps enlarging it. You can see the jsfiddle here. My question is how do I fix it? My understanding was that the mouseenter event was fired only once, and reset when the mouseleaves event is fired, but this seems to say otherwise? Am I missing something? Any help is greatly appreciated.
It calls the hover function every time the animation finishes. I modified it as follows and it appears to work:
window.boxScaled = false;
$('.boxgrid').hover(function(){
if(!window.boxScaled) {
window.boxScaled = true;
$(this).effect('scale', {percent:125}, 1000);
}
}, function() {
if(window.boxScaled) {
window.boxScaled = false;
$(this).effect('scale', {percent:80}, 1000)
}
});
I think you need to force the animation to stop if you leave the box before it has finished scaling (or reenter the box before it has shrunk):
$('.boxgrid').hover(function(){
$(this).stop().effect('scale', {percent:125}, 1000);
}, function() {
$(this).stop().effect('scale', {percent:80}, 1000);
});
http://jsfiddle.net/magicaj/9GLEy/10/
Your understanding of hover (mouseenter/mouseleave) is correct, they should only fire once upon entering/leaving.

Javascript: do an action after user is done scrolling

I'm trying to figure out a way to do this. I have a list of boxes, each about 150px high. I am using javascript (and jquery) and want that, after a user scrolls down a page, the page will auto scroll so that the boxes line up with the rest of the page (that is to say, if the user scrolls and the y position of the page is not divisible by 150, it will scroll to that nearest point).
Now, I at the moment, I know I can activate an event using the .scroll() jquery event, and I can make it move to a certain point using .scrollTop(). But every pixel the user moves the scroll bar activates the whole function. So is there a way to delay the function from firing until the user hasn't scrolled, and if they should begin to scroll again, the function will halt?
As you are already using jQuery, have a look at Ben Alman's doTimeout plugin which already handles the debouncing of methods (which is what you are after).
Example shamelessly stolen from his website:
$(window).scroll(function(){
$.doTimeout( 'scroll', 250, function(){
// do something computationally expensive
});
});
This is basically the same as Šime Vidas' answer, but less complex:
var scrollTimeout = null;
$(window).scroll(function(){
if (scrollTimeout) clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(function(){yourFunctionGoesHere()},500);
});
500 is the delay. Should be ok for mouse scroll.
Sure, in the event handler for the scroll event, fire off a setTimeout for 100 or 200 milliseconds later. Have that setTimeout function you set inside of the scroll event handler do the positioning logic you mention above. Also have the scroll event handler clear any timeouts set by itself. This way, the last time the scroll event fires, the setTimeout function will get to complete as the scroll event has not cleared it.
The code:
var scrollTimeout = null;
var scrollendDelay = 500; // ms
$(window).scroll(function() {
if ( scrollTimeout === null ) {
scrollbeginHandler();
} else {
clearTimeout( scrollTimeout );
}
scrollTimeout = setTimeout( scrollendHandler, scrollendDelay );
});
function scrollbeginHandler() {
// this code executes on "scrollbegin"
document.body.style.backgroundColor = "yellow";
}
function scrollendHandler() {
// this code executes on "scrollend"
document.body.style.backgroundColor = "gray";
scrollTimeout = null;
}
This would be a scenario, where vanilla JavaScript would be useful.
var yourFunction = function(){
// do something computationally expensive
}
$(window).scroll(function(){
yfTime=setTimeout("yourFunction()",250);
});

Categories