So I currently I have this:
$('#message_notice').click(function(){
$(this).fadeOut('slow');
});
$('#message_notice').delay(8000).fadeOut('slow');
What I'm ultimately trying to do is if a message is clicked, then go ahead and fade it out. Otherwise, in X seconds, fade it out automatically.
I can do one or the other, but if I have both (as in my example) then the on-click doesn't work (just the delayed fade).
I'm using jQuery 1.4.4.
You need to call .stop(true) in the click handler to cancel the delay() that you put in the queue.
New code should look like
$('#message_notice').click(function(){
$(this).stop(true).fadeOut('slow');
});
$('#message_notice').delay(8000).fadeOut('slow');
That's because when you run
$('#message_notice').delay(8000).fadeOut('slow');
you are creating an animation queue to which your
$('#message_notice').fadeOut('slow');
gets appended if someone clicks.
For a solution see the answer by SLaks who posted it faster than I could finish writing...
Related
I need to stop my code in a for loop, a sleep() function that stalls time does not work because my HTML does not render in that time and a setTimeout function will continue the loop before doing the set code.
For example, this will display alerts with 1,2,3 before 3 alerts with Stop.
function test(){
for (var i = 1;i<4;i++) {
alert(i);
setTimeout(function(){alert("Stop");},1000);
}
}
How could I wait until continuing with my loop while letting the HTML render ?
Use the DOMContentLoaded event to check once your HTML is fully rendered:
<script>
document.addEventListener('DOMContentLoaded', function(event) {
alert('html loaded');
});
</script>
In your example you could instead just use confirm instead to show a message, and when the user clicks then you use the next setTimeout to show the next message.
But, I think this is not what you are actually looking for.
There are many ways to do asynchronous javascript that doesn't impact html rendering, such as using Web Workers, or pass functions inside of setTimeout and those can use closures to help track where you are, but, have the next setTimeout be called after some processing, and after some event, as these will allow the rendering to continue until certain events or time happens.
I have a problem with queuing up events in jQuery. I have an elevator project that allows the user to click on buttons, and then lights go on and then numbers change. That works fine, except when they punch a number again before it reaches the floor picked the first time. I want it to get to the floor first picked before it goes to the second clicked floor (or third, or fourth, etc.). I've done some stuff with .promise, when done, etc. and none of it seems to work.
I am using .click which appears to be the issue, because it fires the function regardless of where it is currently. Trouble is that I can't seem to find any alternative and it needs to finish current operation first before moving on to any other floors.
I hope I explained this well. If not please let me know. Perhaps there is another way entirely of doing it. Still learning this front end/jQuery stuff.
$( ".button" ).click(function(event) {
// doing stuff here....
$( runMainscript() ).promise().done(function() {
runMainscript(buttonclicked, floorQ);
});
});
function runMainscript(buttonclicked,floorQ) {
//doing stuff here
}
BTW, here is a timer for 2 seconds on each floor.
JSfiddle: http://jsfiddle.net/ak25Lxab/1/
See how if you click on two buttons quickly, it jumps around?
The deferred object works slightly differently. You should explicitly declare a deferred variable like this:
var dfd = new $.Deferred();
And when you want to fire done callback, you should call:
dfd.resolve();
So your queueing part of the script now looks like this:
$.when(dfd.promise()).done(function() {
dfd = new $.Deferred();
var onfloor = $("#onfloor").text();
runMainscript(buttonclicked, floorQ, onfloor);
});
And inside runMainscript you resolve this dfd deferred when elevator arrived to the floor.
See demo. Now, all floors are in the queue using deferred object.
I'm not an expert in deferreds, so maybe you can optimise this script further.
I don't really understand your problem and your jsfiddle is not working for me but as far as I can see you want to stop listen for the click event when the elevator is moving.
To do this you can stop listening for the click event and then restore the listener.
http://api.jquery.com/off/
So ideally, listen for the click event, as soon as it's fired stop listening for the click event, do your operations and then restore the listener on the click event for the .button
Or you can try to do something like this, put a state and do nothing if the state is not cleared:
jQuery - How can I temporarily disable the onclick event listener after the event has been fired?
I want to give the same animation to a set of elements, but each incrementally delayed so that the animations make a sort of a 'wave'.
I made a fiddle about it; http://jsfiddle.net/ttLJ3/
Basically each element be delayed by increments of 50ms, do a thing, wait 300ms and undo it.
It just simply doesn't seem to work. It does nothing. If I remove the .delay(300).show(), all elements disappear immediately.
How can I make this work? Thanks in advance! :)
I was able to fix your problem here.
http://jsfiddle.net/ttLJ3/1/
Since delay works with the fx queue, you have to pass in an integer of sorts for delay to work otherwise the hide and show methods will execute immediately. Making it seem as if nothing is happening at all. I passed in 0 to each of the hide and show calls to fix the issue.
$(this).delay(50 * index).hide(0).delay(300).show(0);
According to the .hide() doco, "When a duration is provided, .hide() becomes an animation method." Apparently this means that if you don't provide a duration the hiding isn't done in the animation queue and so doesn't work with .delay().
So try adding a short duration to .hide() and .show():
$(this).delay(50 * index).hide(1).delay(300).show(1);
Updated demo: http://jsfiddle.net/ttLJ3/2/
Let's say I've called $element.fadeIn(200). 100 ms later, something happens on that page and I want to interrupt that fade and immediately fadeOut(). How can I do this?
If you call calling $element.fadeIn(200).fadeOut(0), the fadeOut() only happens after the fadeIn() has finished.
Also, is there a way I can examine $element to determine if a fadeIn() or fadeOut() is running? Does $element have any .data() member that changes?
stop() will only remove animations that are not executed yet.
use stop(true, true) to interrupt and remove the current animation too!
You will get smooth fadeIn/Out effect by clearing queue but not jumping to the end, using .stop(true,false), but please notice that as FadeIn can be interrupted this way, FadeOut can not. I reported it as a bug like years ago, but noone cared. FadeIn only works if the object is hidden. But there is workaround... use FadeTo instead - it works on hidden as well as partially faded objects:
$('.a').hover(function(){
$('.b').stop(true,false).fadeTo(3000,1); // <- fadeTo(), not FadeIn() (!!!)
},function(){
$('.b').stop(true,false).fadeOut(3000);
});
Here's how it works: http://jsfiddle.net/dJEmB/
AFAIK fadeIn and fadeOut run synchronously, so no, I do not think you can interrupt them while they are running. You would have to wait until it is done executing.
If you call the stop method on the element it will stop all animations. The reason the fadeOut call in your example isn't called until after fadeIn is because animations are executed in a queue-like fashion.
You can use the stop() function to interrupt any animation that takes place during that particular moment. Let me know if this works.
Its always a good practice to keep functions that deal with an animation etc inside the function's callback. You can tell if the fadeIn() has finished by doing your function from within its callback, like:
$element.fadeIn(200, function(){
//do callback
});
If that is not possible then you can declare a variable outside the function. Say, var elmFadeInRunning = false. Change it to true right before you call fadeIn and change it back to false in the callback of the fadeIn. That way you can know if its still running if elmFadeInRunning == true.
Another working example
<div id="fadediv">Yay, I like to fade</div>
<button id="stopdatfade" >Stop that fade!</button>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script>
(function($){
currentfade = $("#fadediv").fadeOut(5000).fadeIn(5000).fadeOut(5000).fadeIn(5000);
$('#stopdatfade').on('click', function () {
if (typeof currentfade !== 'undefined') {
currentfade.stop(true, true);
}
});
})(jQuery);
</script>
Adding .stop(true,true) prior to the fadeIn will interrupt any current animations and execute the fadeIn immediately.
$('.saved').stop(true, true).fadeIn().delay(400).fadeOut(4000);
Try taking animation out from queue.
$('...').fadeIn(200).dequeue().fadeOut(0);
http://api.jquery.com/queue/
http://api.jquery.com/dequeue/
I have a problem involving setinterval. It's probably best to show an example so here's a link here:
http://boudaki.com/testing/carouselTest
Basically I'm having problems making this work like I need it to. When the page loads the content rotates every three seconds and the numbered buttons on the right do so also. when you click on a button the buttons extend and the animation is stopped - all good. Then when you click the little close button at the bottom of the buttons the animation resumes - all good....but then when you come to click on the numbered buttons again the animation keeps on going. Why?
There's rather a lot of code but the setIntervals and clear intervals are:
line 69: on document.ready start the animation off -assign timerId to a global var
line 87: When the user clicks on the numbered button clearinterval in that animation
line 102: when the user clicks on the close button start the animation again
That's it....I just don't get why it doesn't stop the animation the second time around??? Can anyone see why?
Any ideas?
This is a guess, but try bringing all your functions and variables into the $(document).ready(function() {...}) call.
Then change your setInterval() so that you're passing in a reference to the function instead of a string for eval:
timerId = setInterval( rotateForward, 3000 );
Be sure to change all of them.
To be honest I don't know why this would work, but making the variable local may help to ensure that we're dealing with only one version of timerId.
$closeButton.click(function() { ... }); is inside of your loop. That handler is getting added 4 times, so when you click close, 4 timers are added and only 1 is cleared when you open the menu again.
I think the problem is the scoping of timerId. Try changing alert('should stop now'); to alert('should stop now' + timerId);
I'll bet you'll find that timerId is always the same value.
The only thing I can think of is... I'm pretty sure you can't put the () inside the setInterval call. It does seem to work at first, but maybe that's part of the issue? Hard to say... but I'd at least start there.
setInterval("rotateForward", 3000);
Also, maybe try calling the clearInterval every time before you start it.