Welcome to WebmasterWorld Guest from 54.145.39.186

Forum Moderators: open

Message Too Old, No Replies

stopping "chained" functions before they end

     

sssweb

3:08 pm on Jan 20, 2013 (gmt 0)

5+ Year Member



I have a jQuery slideshow in which I sometimes chain various functions together (jQuery runs in one function, ending in a call to the next function) to create a series of page effects. These extended effects can take a minute or so to run.

When the user navigates to another slide, I need to stop & reset the animation so that: a) it doesn't continue during the next slide, and b) so that if the user navigates back to the original slide, the animation starts from scratch.

Usually, some combination of stop(), clearTimeout(), or script-specific command works. Sometimes though, it doesn't. Questions:

1) Is there a way to stop animations on different elements all at once? I've tried:

.stop(true) & .stop(true, true) - doesn't always work
.clearQueue() - only works on one object
.finish() - promising, but stops my jquery slideshow too
event.stopPropagation() - stops slideshow but not animations (opposite of what I want)

I've even tried globally turning fx off, then back on:
fx.off = true; $.fx.off = false;
Also promising, but unfinished animations pick up where left off while finished ones revert to initial state.

2) Is there a better way to chain the animations together than described in my opening sentence that allows for a simple stop/reset?

sssweb

10:50 pm on Jan 21, 2013 (gmt 0)

5+ Year Member



I found one solution that works in some cases, but still not all:

var timer = null;

function myFunc(){
// code
timer = setTimeout("myFunc()", 1);
}

// run this on reset to stop the above function:
function stop(){
clearTimout(timer);
}

Any better ideas?

daveVk

11:48 pm on Jan 21, 2013 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



if .stop(true, true) is used ( 2nd true = jumpToEnd ) the callback function is called and may start a chained animation.

sssweb

1:20 pm on Jan 22, 2013 (gmt 0)

5+ Year Member



Yes, that's what I discovered. I only use it on statements that don't have a callback; otherwise, I use .stop(true);

I've been searching the web for this; other than my second post above, I didn't come up with much -- so maybe there's no solution. Unless somebody knows a way to set up .queue() to sequence through a series of animations working on different objects. Then I could just clear the queue.

sssweb

2:40 pm on Jan 24, 2013 (gmt 0)

5+ Year Member



I guess there's no clear answer to this, so I'll continue to minimize it as best I can using the above methods.

I've got email notification on for this topic and welcome further reply; otherwise, I'll consider it closed.

sssweb

10:06 pm on Jan 28, 2013 (gmt 0)

5+ Year Member



Update - for anyone looking for a solution to this, I found the following:

First, the culprit: jQuery .delay() does not respond to .stop(); from the jQuery docs:

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.

I'm not the only one who's brought this up; the following bug tickets suggest fixes, but I couldn't get them to work (I include them in case better skilled coders can figure them out):

[bugs.jquery.com...] - implies that the 'bug' was fixed as of jquery 1.7, but I upgraded to the latest version and still had the problem

[bugs.jquery.com...] - suggests clearQueue(), but as another poster pointed out here ( [bugs.jquery.com...] ), it doesn't always work

*********

SOLUTIONS: I found two plug-ins that do the trick:

.doTimeout() [benalman.com...] works so far for me

.delayed() [theloveofcode.com...] - this one is chainable and has more functionality; the problem though is that it only works on specific events (i.e. click, onload, etc.); I need it to work directly from a selector: $("id").delay(5000).animate(...);

If anyone can get it to work that way, I'd like to know.

daveVk

12:23 am on Jan 29, 2013 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Good find

.animate() would also be worth a try, animating nothing ( or nothing visible )

sssweb

1:33 pm on Jan 29, 2013 (gmt 0)

5+ Year Member



Yes - I saw that hack posted by someone in the jquery forum. I couldn't get it to work animating nothing, so I think you have to include a dummy CSS call that doesn't really change anything (like "z-index": 1, or opacity: 1 for already visible elements). You also have to include a time to sub for the delay. So:

$("id").animate({"z-index": 1}, 5000).animate(...);

is the same as:

$("id").delay(5000).animate(...);

except that you can stop it with:

$("id").stop(true);

sssweb

2:08 pm on Jan 29, 2013 (gmt 0)

5+ Year Member



BTW, minor correction: the doTimeout() plug-in mentioned above is chainable too.

daveVk

9:47 pm on Jan 29, 2013 (gmt 0)

WebmasterWorld Senior Member 5+ Year Member



Or invent your own property seems to be OK

$("id").animate({x:1}, 5000).animate(...);

sssweb

3:53 pm on Jul 24, 2013 (gmt 0)

5+ Year Member



For anyone still following this topic (or who lands here via search), below is an update and a decent solution.

First, some clarification about jQuery stop() -- most here probably know this, but if not it'll confuse you as it did me. I thought stop() applies to the entire chained command; it does not. It applies to the SPECIFIC animation in the chain running at the moment stop() is called.

So in the chain:

$("#ID").fadeIn(1000).delay(1000).fadeOut(1000, do_next_func);

stop() acts on either of the three items attached to the object "#ID". That completely changes how it acts with and without the various 'true' flags. Each apply only to the specific animation being run, not the chain. (Example: stop(true,true) does NOT execute do_next_func() if called during fadeIn(1000), but stop() DOES.)

This may have resulted in my misunderstanding my own tests on this, because I now find that stop() DOES work on delay(). My earlier post was incorrect.

Last, I hit on a simple solution for stopping a line of animations tied together by successive function calls. Example:

function do_1() { $("#ID1").fadeIn(1000, do_2); }
function do_2() { $("#ID2").fadeIn(1000, do_3); }
function do_3() { $("#ID3").fadeIn(1000); }

If you have a long list of animations on various #IDs, it's a hassle managing the stop()'s. But it's easy if you add a single class to each object (e.g. <div class="ID" id="ID1"></div>, <div class="ID" id="ID2"></div>, etc). Then you can stop everything with a single command: $(".ID").stop()

sssweb

6:03 pm on Jul 24, 2013 (gmt 0)

5+ Year Member



Also found a few more methods:

$('[id]').stop(true); // stops any element with an id
$('[id^="ID"]').stop(true); // stops any element with id that starts with "ID"
$(".ID [id]").stop(true); // stops any element that's a descendant of class="ID" and has an id

Other similar commands work as well.

Question: which uses more resources, stopping via a class selector that applies to say, 10 elements, or via $('[id]'), where 10 elements have id's?

httpwebwitch

8:13 pm on Jul 25, 2013 (gmt 0)

WebmasterWorld Administrator httpwebwitch is a WebmasterWorld Top Contributor of All Time 10+ Year Member



id selection is almost always faster, but you could test that to know for certain

sssweb

1:36 pm on Jul 26, 2013 (gmt 0)

5+ Year Member



yes, I tested and that seems to be true, with one caveat: limit the number of ID's beings checked as much as possible. General ID checks, if your page has many (besides the ones you want to stop), are slowest:

$('[id]').stop(true);

The fastest one I found was:
$('[id^="testID"]').stop(true);
which zeroes in on ID's w/specific name strings

Next best is:
$(".ID").stop(true);
assuming class "ID" is only assigned to the animations you want to stop.

That method works just as fast as the fastest one if you tweak it like so:
$(".ID [id]").stop(true);
(not sure why, since in my test it didn't reduce the number of elements checked; maybe just because it's more specific -- doesn't have to LOOK for more)
 

Featured Threads

Hot Threads This Week

Hot Threads This Month