Javascript on scroll event change css then wait and then rechange - javascript

I am trying to change the css on scroll event and it is working.
$(window).scroll(function () {
$(".navcont").css("background-color", "pink")
});
But, when I try to give delay and change it back,
$(window).scroll(function () {
$(".navcont").css("background-color", "pink")
.delay( 5000 )
.css("background-color", "white");
});
It always shows pink color, But I want the white color first then delay and then pink color.
Can some one help me with this!
thanks in advance

Try using only setTimeout, without animate:
$(window).scroll(function () {
$(".navcont").css("background-color", "pink");
setTimeout(function() {$(".navcont").css("background-color", "white")}, 8000);
});
Here on jsFiddle.

First thing I think of is using .animate() to get the callback, then using setTimeout to delay the return to CSS:
$(window).scroll(function(){
$('.navcont').animate({backgroundColor:'pink'},1,function(){
var $this = $(this);
setTimeout(function(){
$this.css({backgroundColor:'white'});
},80000);
});
});
The 1 means the animation is 1 millisecond long, which is invisible to the eye but I've had issue with using zero so I just add a value to satisfy the callback.

The delay() function works only on a jQuery effects queue, not on all functions. The effects are such as fadeIn, slideUp, etc. There is a custom effect generator called animate() and you can use that with delay(). However, you cannot animate non-numeric properties like background-color. So here is a trick -
$(window).scroll(function () {
$(".navcont")
.animate({dummyProperty: "dummyValue"},1,"linear",function(){
$(this).css("background-color","pink")
})
.delay( 80000 )
.animate({dummyProperty: "dummyValue"},1,"linear",function(){
$(this).css("background-color","blue")
});
});
The first argument for animate is a css property you wish to animate. Since background-color cannot be animated, we use a dummy property here (you can use anything here, doesn't make any difference).
The second argument is the time of animation. We just use 1 millisecond here because we set the real delay using the delay() function.
The third argument is the easing (doesn't matter in this case).
The fourth argument is a callback function with 'this' pointing to the selected HTML element. So we change it's background-color here.

Related

Animation not completing transition on SVG hover animation, when hover out occurs fast

I have made a very simple hover animation for a thumbnail by using a SVG icon. See here. The JS code I used is like so:
var elemRemoveAnim = null;
$('.vedio-thumb').hover(
function(){
$(this).find('.youtube-icon > .youtube-red')[0].classList.add('y-animated' , 'fadeInUp');
$(this).find('.youtube-icon > .youtube-white')[0].classList.add('y-animated' , 'fadeInUp');
},
function(){
removeVedioAnim($(this));
});
function removeVedioAnim(elem) {
elemRemoveAnim = elem;
setTimeout(function(){
elemRemoveAnim.find('.youtube-icon > .youtube-red')[0].classList.remove('y-animated' , 'fadeInUp');
elemRemoveAnim.find('.youtube-icon > .youtube-white')[0].classList.remove('y-animated' , 'fadeInUp');
}, 1000);
}
As you can see, I am trying to remove the animation class, after a delay of 1000ms, that's because iif you hover over and immediately hover out (you'll have to do it really fast), you'll notice that the animation gets stuck, i.e. the white arrow will still only be in half transition. Technically this is happening because the animation class has been removed too soon.
If I add the code in the hover out function, this aggravates the situation even more. Is there a more versatile solution to this problem?
One more problem with the with this solution is that once you hover and then if you hover out and you do it 2-3 times really fast, for the 2-3 time you've hovered the animation will take play only once, simply the setTimeout function will wait 1 second to remove the classes. I wonder if there is a more elegant way to do this.
SEE DEMO
Use "animationend" event to capture the end of fadingInUp motion on the arrow, that runs longer (the white one).
$utube_white.one("animationend webkitAnimationEnd oAnimationEnd",function() {
$utube_red.get(0).classList.remove('y-animated' , 'fadeInUp');
$utube_white.get(0).classList.remove('y-animated' , 'fadeInUp');
isLocked = false;
});
In your example there's no need for a mouseleave function in HOVER event, because you don't do anything particular on it - just remove animation classes without any other motion. This could be done in "Animationend" event in the first "HandlerIn" function.
Instead of a mouseleave function put the empty $.noop to prevent jQuery think that your hover function contains only one argument.
.hover(handlerIn, $.noop) and not .hover( handlerInOut ). You can change it, it's up to you, but in the last case the function will fire on both MouseOn and MouseOut.
Use a flag "isLocked" as well to prevent firing HandlerIn on quick hovers.

.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;
}

fadeOut and then change image

I have a question about the .attr jQuery method.
I want to create 4 event on click: fade Out, delay, change src attribute and the fade in.
I have this code:
$( "#button" ).click(function() {
$('img').fadeOut().delay(800).attr('src','1-big.jpg').fadeIn();
});
But when I click the button the image changes immediately and then it fades out, delay and fadein. Why the .attr method run first?
Use callbacks to help enforce the order that the functions run -
$( "#button" ).click(function() {
$('img').fadeOut(800, function() {
$(this).attr('src','1-big.jpg').fadeIn();
})
});
You could use animation callbacks:
$('#button').click(function() {
$('img').fadeOut(function() {
$(this).attr('src', '1-big.jpg');
$(this).fadeIn();
});
});
Maybe worth considering DeSandro's imagesLoaded plugin: https://github.com/desandro/imagesloaded
The delay function can only be used to delay jQuery effects, or perhaps more accurately, functions that use an effects queue. Changing of the src attribute will therefore happen immediately.
In this case, you can run a function after the fadeOut has finished with a callback, change the src attribute, and then delay before fading in:
// default fadeOut time is 400ms, which now needs to be included
$('img').fadeOut(400, function() {
$(this).attr('src','1-big.jpg').delay(800).fadeIn();
});
It may also be a good idea to pre-load the image, just in case it cannot be downloaded within 800 milliseconds.

how to fire a jquery child function at the start of parent animation

I'm coding a button that has a CSS arrow which flips up and down every time it's container is clicked.
It looks fine, but i can't figure out how to fire the toggleClass function as soon as slideToggle has been clicked.
The arrow looks like it is lagging a little because it waits a fraction of a second until the end of the slideToggle animation.
Is it possible to make the toggleClass fire at the start of the animation rather than the end?
$("#content_link").click(function(){
$("#content").slideToggle("fast",function(){
$("div#arrow_container").toggleClass('arrow_down');
$("div#arrow_container").toggleClass('arrow_up');
});
});
not sure if this is what you are asking for but yes call it before the slideToggle() function and not inside its callback function
$("#content_link").click(function(){
$("div#arrow_container").toggleClass('arrow_down')
.toggleClass('arrow_up');
$("#content").slideToggle("fast");
});
Remove that code from the call back and add it after the slideToggle function call like this
$("#content_link").click(function(){
$("#content").slideToggle("fast");
$("div#arrow_container").toggleClass('arrow_down');
$("div#arrow_container").toggleClass('arrow_up');
});
You can set a start callback as well:
$("header#tag_cat1 div#cat1_content_link").click(function(){
$("#tag_cat1_content").slideToggle({
duration: "fast",
complete: function(){
$("section.category header > div#cat1_content_link > div").toggleClass('gt_arrow_down_5px');
$("section.category header > div#cat1_content_link > div").toggleClass('bt_arrow_up_5px');
},
start: function() {...}
});
});
Take a look at the second form of .slideToggle()

Need Sequence .css() For multi div

I have 5 divs #BS1,#BS2,#BS3,#BS4,#BS5 ..
i need to make every one when hover on the container div ( left-section ) i need to hidden each one and delay maybe from 5000 to 2000 and back it visible again !! that`s my code
$("#left-section-5").hover(function () {
$("#BS1").css("display", "none").delay(500).css("display", "block");
$("#BS2").css("display", "none").delay(50).css("display", "block");
});
The .delay() method only delays subsequent animations on the element(s) in question, and the .css() method is not an animation method. Use .hide() and .show() instead, which are (if you provide a duration) animation methods:
$("#BS1").hide(1).delay(2000).show(1);
// etc.
Or if you want a fancier effect try some other effects methods, e.g.:
$("#BS1").fadeOut("slow").delay(2000).fadeIn("slow");
If by "sequence .css()" you mean that you want the elements to be animated one after the other you can do something like this:
var $divs = $('div[id^="BS"]'),
i = 0;
function next() {
if (i < $divs.length)
$divs.eq(i++).animate({"opacity":0}, 300)
.delay(100)
.animate({"opacity":1}, 300, next);
}
next();
Demo: http://jsfiddle.net/r4byV/

Categories