jQuery Fadeout on Click or after delay - javascript

I am displaying a message box on a website. I would like to be able to have it either fadeout on click or after X seconds. The problem is that the delay() function takes the place over the click() function making it so even if you click close you still have to wait the time.
Here is the jQuery
$(document).ready(function() {
$(".close-green").click(function () {
$("#message-green").fadeOut("slow");
});
//fade out in 5 seconds if not closed
$("#message-green").delay(5000).fadeOut("slow");
})
I also set up a simple jsfiddle. To see the problem comment out the delay line http://jsfiddle.net/BandonRandon/VRYBk/1/

You should change it to a setTimeout:
http://jsfiddle.net/VRYBk/3/
(in the jsfiddle link)
I removed your delay line and replaced it with a standard setTimeout like:
setTimeout(function(){
$("#message-green").fadeOut("slow");
},5000)
As a note of WHY, is because JS is read top to bottom and it'll read your delay before you click and trigger the event. Therefore, even when you click the delay is being run causing all animation to pause.

This would be an ideal use for jQuery 1.5's new Deferred objects:
// a deferred object for later processing
var def = $.Deferred();
// resolve the deferred object on click or timeout
$(".close-green").click(def.resolve);
setTimeout(def.resolve, 5000);
// however the deferred object is resolved, start the fade
def.done(function() {
$(".message-green").fadeOut("slow");
});
Working demo at http://jsfiddle.net/Nyg4y/3/
Note that it doesn't matter that if you press the button the timer still fires - the second call to def.resolve() is ignored.

I fount it the best workaround suggested by Oscar Godson, I somehow added this to it:
if (! $clicked.hasClass("search"))
{
setTimeout(function()
{
jQuery("#result").delay('1500').fadeOut('2800');
},7000);
}
});
His original suggestion is very useful:
You should change it to a setTimeout: http://jsfiddle.net/VRYBk/3/
(in the jsfiddle link)
I removed your delay line and replaced it with a standard setTimeout like:
setTimeout(function(){
$("#message-green").fadeOut("slow");
},5000)
By Oscar Godson,

Related

fadeOut() callback completes before fading is done

I am working on a font-test page that should switch the font of the header and paragraph tags on click. Which works fine but the experience is really jarring so I want to smooth it out with the following path:
fadeout -> do the font swap -> fade in
But the code runs the font swap first, then the animation.
I have the following code snippet, I am only including the jQuery because it's the root cause of my problem.
// Anytime a card is clicked
$('.card').click(function(){
// Call card by id and switch the fonts
var id = "#" + this.parentElement.id;
$(this).fadeOut(900,swapFont(id));
$(this).fadeIn(500);
// attach the above to some sort of transition callback
});
// Function to swap the font around so that the header is now the body font and the body font is now the header font
function swapFont(id) {
// font-swap logic in here which works fine
}
The issue is because the fadeOut() animation is (effectively) asynchronous. This means the next statement will be evaluated while the animation is in progress - hence the behaviour you're seeing. To fix this you need to use the callback pattern that the fadeX() methods provide.
Also, you're passing the result of the immediate execution of swapFont() to the callback, instead of a function reference to run when the event occurs. Try this:
$('.card').click(function(){
var id = "#" + this.parentElement.id;
$(this).fadeOut(900, function() {
swapFont(id);
$(this).fadeIn(500);
});
});
You are currently passing the result of the swapFont() call, instead you need to point to the function itself.
So this:
$(this).fadeOut(900,swapFont(id));
is the same as:
var x = swapFont(id);
$(this).fadeOut(900, x);
Easiest way is to wrap it in an anonymous function:
$(this).fadeOut(900, function() { swapFont(id) });
Edit:
The fadeIn will also execute before the fadeOut has completed. You can add a .delay or, better, call the fadeIn in the callback as per Rory's answer (so I won't repeat here).

Javascript running tasks chronologically [duplicate]

I've the following JavaScript snippet:
$("#dashboard").addClass("standby").delay(3000).removeClass("standby");
$(".active").removeClass("active");
$("." + target).addClass("active");
$(".showDiv").removeClass("showDiv").addClass("hide");
$("#" + target).removeClass("hide").addClass("showDiv");
While #dashboard is in standby, it should handle all this CSS-Class changes. After this changes, it should display the #dashboard again. So I set delay() between the add and remove of the standby-class. To see if it works I added the too long duration of 3sek.
But it doesn't delay! Why it don't? I don't see it...
delay will only work on actions that go through the animation pipeline, and won't have an influence on the timing of instant atomic operations like that. In order to delay things such as adding or removing classes, then you can use setTimeout.
the .delay() method allows us to delay the execution of functions that follow it in the queue. It can be used with the standard effects queue or with a custom queue.
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.
.delay() will only delay animations in jQuery.
To set an actual delay, you might want to use setTimeout().
let cancelId;
// ...
cancelId = window.setTimeout(function() {
// ... do stuff ...
}, 3000);
// If you want to cancel prematurely, use `window.clearTimeout`
if (cancelId) {
window.clearTimeout(cancelId);
}
This will execute the code in ... do stuff ... in 3 seconds (3000 miliseconds)
As stated ... delay won't work the way you expect ...
Here is how it works:
$(document).ready(function(){
var audio = new Audio('sang3.mp3');
audio.play();
$("#image1")
.hide()
.attr("src", "https://placeholdit.imgix.net/~text?txtsize=63&bg=FF6347&txtclr=ffffff&txt=Image-1&w=350&h=250")
.fadeIn(1000)
.delay(3000)
.fadeOut(1000)
.queue(function(next) {
$(this).attr("src", "https://placeholdit.imgix.net/~text?txtsize=63&bg=FF6347&txtclr=ffffff&txt=Image-2&w=350&h=250")
next();
})
.fadeIn(1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<img src="" id="image1">
Delay won't work the way you expect it to on these line:
$("#image1").delay(9000).attr("src", "image/image1.jpg");
$("#image1").delay(9000).attr("src", "image/image2.jpg");
It will run the attribute change immediately. Why? Because the attribute change isn't part of the "animation". Delay can only be used with with animating functions.
If you only need two images, it might be easiest for you to have two images stacked together, and fade them in and out as needed.
If you want to expand this to many images, try using the more robust ".animate" function to fade in and out. "Animate" can be given a callback function that will be called when complete.
Try utilizing .queue()
$("#image1").delay(5000).fadeIn(3000, function() {
$(this).delay(9000, "task" ).queue("task", function() {
$(this).attr("src", "image/image1.jpg")
.delay(5000).fadeOut(3000, function() {
$(this).delay(9000, "task")
.queue("task", function() {
$(this).attr("src", "image/image2.jpg")
.delay(5000).fadeIn(3000, function() {
$(this).delay(5000).fadeOut(3000)
})
}).dequeue("task")
});
}).dequeue("task")
});
All your delays start on $(document).ready();
$("#image1").delay(5000).fadeIn(3000);
$("#image1").delay(9000).attr("src", "image/image1.jpg");
$("#image1").delay(5000).fadeOut(3000);
$("#image1").delay(9000).attr("src", "image/image2.jpg");
$("#image1").delay(5000).fadeIn(3000);
$("#image1").delay(5000).fadeOut(3000);
Think of it this way. When doc is ready, JS start executing whatever is inside that function, first delay it executes is this: $("#image1").delay(5000).fadeIn(3000);
That will START a delay of 5000 ms and then a fadeOut() with a duration of 3000 ms. That fadeOut is synchronus to the delay, but the next line of code is completely asynchronous to this one.
Then it procceeds to the next line. And so on. It won't wait to your delay to finish, it simply starts counting on the background.
.delay() DOES stack when applied to the same element: JSFiddle
I leave this just in case someone is confused as I was
Seems like for what you are trying to do, you might want to take a look at CSS transitions:
http://css-tricks.com/almanac/properties/t/transition/
You can still have .addClass(), except now your class will utilize these transition properties, and you won't need .delay().
Usually we need to do things before removing the standby state, so we remove the class in an ajax callback :
$("#dashboard").addClass("standby");
$.get('urltoget',function(data){
if(data)
$("#dashboard").removeClass("standby");
else
$("#dashboard").removeClass("standby").addClass('error');
})

Jquery Fade in Text for Certain Time

In my application I have a script that tells when somebody comes online or goes offline. I put the text of if somebody goes online/offline via content = name+' went offline' or vice versa. I then put that text in a div at the end of my function call: $('#new').text(content);
The problem comes with the fade out, all in all it's not really working. I've been trying to play around with it. Here's what I have so far:
$('#new').text(content);
$('#new').fadeIn('slow', function() {
setTimeout($('#new').fadeOut('slow', function() {
$('#new').css('display', 'none');
}));
});
display:none inside the callback is unnecessary, fadeOut() automatically sets the display to none after concluding.
$('#new').text(content);
$('#new').fadeIn('slow', function() {
setTimeout("$('#new').fadeOut('slow');", 2000);
});
2000 is the number of miliseconds you'd like to delay it, change it to whatever value suits you better.
As #Pst commented, the function-object may be more consistent even though I personally have more issues with function-objects than code strings.
You may also use the function-object:
$('#new').text(content);
$('#new').fadeIn('slow', function() {
setTimeout(function(){ $('#new').fadeOut('slow'); }, 2000);
});
You need to remember to provide duration for which the setTimeout should wait before acting.
$("#hello")
.text(content)
.fadeIn("slow", function(){
setTimeout(function(){
$("#hello").fadeOut();
}, 2000);
});
2000 indicates 2 seconds. If you would like it to stay visible longer, increase this.
Functional Demo: http://jsbin.com/aciwon/edit#javascript,html
Are you using this inside a $(document).ready()? If not, place it like:
$(document).ready(function() {
$('#new')
.text(content)
.fadeIn('slow', function() {
setTimeout(function() { $('#new').fadeOut('slow'); }, 2000);
});
});
Also, be sure to initialize your element with a display: none and note I've removed part of the unecessary code.
Your setTimeout() code is wrong, you have to pass a function to it.
Why not just use delay?
$("#new").text(content).fadeIn("slow").delay(1000).fadeOut("slow");

jQuery: prevent animation and timeout queuing?

I have probably a simple problem to solve but I don't know what's the right approach on that.
I have a div.notification bar on top of my website that is hidden by default. The bar does get an additional class of either success or warning that sets it to display:block; if needed.
So, there are two cases. Either an output message is rendered directly to the .notification bar on page-load (and it gets a class of success or warning right with it) OR the .notifcation bar is sliding down from top and is fed with json data.
Any way, the notification bar should always be visible for 10 seconds and than slide back up.
Therefore I wrote two functions that handle this bar.
var timing = 10000;
function notificationOutput(type, message) {
var note = $('.notification');
note.hide();
note.find('.message').html(message);
note.stop(true,true).slideDown().delay(timing).slideUp();
}
function notificationSlideUp(slideUp) {
var note = $('.notification');
if ( slideUp ) note.delay(timing).slideUp();
else note.stop(true,true).slideUp();
}
So the notificationOutput() function is triggered from various other functions that return json data and render that into the box.
And the notificationSlideUp() function is right now called on every page load because in my header I have this …
<script type="text/javascript">
$(document).ready(function(){
notificationSlideUp(true);
});
</script>
And there is a reason for that! Remember the case where the .notification is directly set to visible on page-load … e.g. when a user logs-in on my platform the .notification bar is immediately visibile and says "Welcome Username, you've successfully logged in".
I call the notifictaionSlideUp() function in my header to make sure the currently visible .notification bar will slideUp() again after 10 seconds.
And here occurs the problem … 
Somehow this causes the entire notifcation timing and sliding up and down to be "confused". So there must happen some queuing of the slide-functions and or of the delay() function, because without the note.stop(true,true) in the notificationOutput() function the notification wouldn't slideDown() immediately if it's triggered within the first 10 seconds after the page load. That is because the notificationSlideUp() function has already triggered the slideUp() and the delay() of the object.
And the same happens to the delay. If a .notification is put out within the first 10 seconds the delay timing isn't right because the delay counter already started on page-load.
Any idea how to solve that so that it always works?
Update:
var notificationTimer;
function notificationOutput(type, message) {
var note = $('.notification');
note.hide();
note.find('.message').html(message);
note.stop(true,true).slideDown();
clearTimeout(notificationTimer);
notificationTimer = setTimeout(function() {
note.stop(true,true).slideUp();
}, 10000);
}
function notificationSlideUp(slideUp) {
var note = $('.notification');
if ( slideUp ) {
clearTimeout(notificationTimer);
notificationTimer = setTimeout(function() {
note.stop(true,true).slideUp();
}, 10000);
} else {
note.stop(true,true).slideUp();
}
}
Unfortunately, jQuery's delay() function doesn't offer any method for canceling a delay the way setTimeout() does with clearTimeout(). I'd suggest replacing your delay()s with named setTimeout()s, and writing a condition to clearTimeout() for cases in which you need to cancel/trigger a queued animation right away.
http://api.jquery.com/delay/
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.
But you can use the following 'hint' - replace delay with some animation which does not change anything. For example with .animate({opacity:1},timing)

A sticky situation for jQuery slideshow

I'm required to develop a slideshow (not an existing one) with jQuery. I was able to change picture with a function that I created named changePic (takes an image link). It incorporates the fading animation from the jQuery library.
For the slideshow I'm trying to use a while loop. It kind of works, except that it doesn't wait for the animation to finish.
How do I, a) wait for the animation to finish, b) delay the changing picture so it display the picture for a couple of seconds?
Also tried Settimeout, and it doesn't work.
Edit:
Basically changing image is like this:
function changePic(imglink){
var imgnode = document.getElementById("galleryimg");
$(imgnode).fadeTo(500, 0, function(){
$(imgnode).attr("src", imglink);
$(imgnode).fadeTo(1000, 1);
})
}
and the slideshow code is like this, but obviously it shouldn't.
function slideshow(gallerylinks){
var i=0;
while (i<gallerylinks.length){
changePic(gallerylinks[i]);
i++;
}
}
You could always try ditching the while loop, and going with a perpetually recursive function...
on the .animate, you could add a timeout function (at whatever interval) that calls the changePic function. As I have no idea what your code looks like, I will provide a fantastically generic outline.
/* array of imgUrls */
var imgUrls = new Array(); //populate it however
changePic(slideToShowIndex, fadeOutSpeed, fadeInSpeed, slideDelay)
{
$('#slideHolder').animate({ opacity: 0}, fadeOutSpeed , function(){
$('#slideHolder').attr('src', imgUrls[slideToShowIndex]);
$('#slideHolder').animate({ opacity: 1 }, fadeInSpeed, function() {
setTimeout(function() { changePic(slideToShowIndex+1, fadeOutSpeed, fadeInSpeed, slideDelay);}, slideDelay});
});
}});
}
$(document).ready(function() {
changePic(0, 5000, 5000, 10000);
});
This should (in theory) fade the image out, swap it with the new one, and fade it in (both taking 5 seconds) and then adding a delay to call itself with the next slide index in 10 seconds.
This is in no way perfect, but does outline the general idea. Since we have no idea what your code looks like, I can only assume your setTimeout was in the wrong spot. Doing it like this will make sure that the animation has finished before the timeout is set. This guarantees that the slide wont change until after the animation has changed.
of course you could always use a combination of the ':not(:animated)' selector and a setInterval to achieve much the same effect.
EDIT: made a slight change to stack the animations properly. The thoery behind this still works even with the OPs addition of code.
You could have provided more details or example code but have a look at stop() and delay() functions.

Categories

Resources