I have made a (rather complicated) solution where I have 4 menu items pop in/out from the side and I make that happen by toggling a class.
$('.menuitem').toggleClass('show');
It works great but the client now wants it to "slide out". I figured that I can make him happy if I can create a delay between each toggle, but I cant find a good way to do it. In practice I want each menu item to toggleClass but with a delay of maybe 250ms before next toggleClass.
Edited - Apparently the delay function wont work with toggle, only with animations.
Consider this following code:
$('.menuitem').each(function(i) {
var elm=$(this);
setTimeout(function() {
elm.toggleClass('show');
}, i * 250);
});
See it in action, in this demo i have hiding diving one by one and delay is 1000 ms.
What about:
$('.menuitem').toggleClass('show').delay(1000).toggleClass('hide');
See jQuery's delay() function for further reference.
I would do the $('.menuitem').toggleClass('show') in a separate event.
For instance <button onmousedown="$('.menuitem').toggleClass('show');" onclick="myfunc();">Fast Toggle</button>
If you toggle onmousedown the page will render with the toggle before the click event fires.
Related
According to jQuery document on .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.
Could someone please expand on this? When is it more appropriate to use .delay(), and when is it better to use .setTimeout()?
I think what you posted explains itself really.
Use .delay() for jQuery effects including animations.
setTimeout() is best used for everything else. For example when you need to trigger an event at a certain elapsed time.
As far as I understand, .delay() is meant specifically for adding a delay between methods in a given jQuery queue. For example, if you wanted to fade an image into view during the span of 1 second, have it visible for 5 seconds, and then spend another second to fade it out of view again, you could do the following:
$('#image').fadeIn(1000).delay(5000).fadeOut(1000);
In this instance, .delay() is more intuitive to use since it is specifically meant for delaying events in a given jQuery queue. setImeout(), on the other hand, is a native JavaScript method that isn't intended explicitly for a queue line. If you wanted an alert box to pop up 1 second after clicking on a button, you could do the following:
function delayAlert() {
var x = setTimeout("alert('5 seconds later!')", 5000);
}
<input type="submit" value="Delay!" onclick="delayAlert();" />
You can use delay with animations, for example:
$('.message').delay(5000).fadeOut();
You can also use timeOut to delay the start of animations, for example:
window.setTimeout(function(){
$('.message').fadeOut();
}, 5000);
As you see, it's easier to use delay than setTimeout with animations.
You can delay pretty much anything with setTimeout, but you can only delay animations with delay. Methods that aren't animations are not affected by delay, so this would not wait a while before hiding the element, it would hide it immediately:
$('.message').delay(5000).hide();
.delay() is mostly used for chaining together animation effects with pauses in between.
As the docs mention, there is no way to cancel the delay. In the case where you may want to cancel the delay, a setTimeout() should be used instead so you can cancel it with clearTimeout()
Another side effect of delay(): it seems to disable the ability to hide (or fadeOut, etc) the objecting being delayed, until the delay is over.
For example, I set up the following code (perhaps a stackoverflow developer will recognize the css names....) to hide a 'div':
$j(document).ready(function(){
var $messageDiv = $j("<div>").addClass('fading_message')
.text("my alert message here").hide();
var $closeSpan = $j("<span>").addClass('notify_close').text("x");
$closeSpan.click(function() {$j(this).parent().slideUp(400);});
$messageDiv.append($closeSpan);
$j('.content_wrapper_div').prepend($messageDiv);
$messageDiv.fadeTo(500, .9).delay(5000).fadeTo(800,0);
});
Clicking the "x" that's in the span (that's in the 'div') did fire off the click function (I tested with an alert in there), but the div didn't slideUp as directed. However, If I replace the last line with this:
$messageDiv.fadeTo(500, .9);
..then it did work - when I clicked the "x", the surrounding div slideUp and and away. It seems as if the background running of the "delay()" function on the $messageDiv "locked" that object, so that a separate mechanism trying to close it couldn't do so until the delay was done.
The Situation
I am using the effect() function of JQuery UI. The type of effect doesn't really matter but for the purpose of this question lets use "bounce". This effect is called when a link is clicked, so my complete example code is as follows:
$('#button').click(function (e) {
e.preventDefault();
$('#box').effect('bounce');
});
Here is a demo
The Problem
The problem I have, or more the behavior I want to get rid of, is that when you click the link multiple times in quick succession then it queues up the animations. (See the demo, click the link 10 times fast, then release and watch it continue to animate)
The Requirement
I just want to prevent effects/animations from being queued. In other words, I am looking for clicks to be ignored if the box is already bouncing. Is there anyway I can do this?
The Failed Attempts
I have already done some research, and I tried a couple of method below but to no success:
$('#box').stop().effect('bounce');
stop() just doesn't seem to have any effect in this case.
$('#box').clearQueue().effect('bounce');
clearQueue actually works in the sense that the effects don't queue, however there are side-effects which causes the layout to mess up. I assume this is because it prevents the effect from returning the styles to their defaults. It may also be related to using a fixed position for the box.
This should do the trick.
$('#button').click(function (e) {
e.preventDefault();
if( !$('#box').is(':animated') ){
$('#box').effect('bounce');
}
});
Yes you are right, clearQueue makes position changes in div but i tried that and it looks like working
$('#button').click(function (e) {
e.preventDefault();
if ($("#box").is(':animated')) {
$('#box').effect = null
}
else {
$('#box').effect('bounce');
}
});
js fiddle example
Try this:
$('#button').click(function (e) {
e.preventDefault();
$('#box').stop(true).effect({
effect: 'bounce',
complete: function() {
$('#box').removeAttr('style');
}
});
});
stop(true) stops and clears the queue immediately but when stopped, effect() leaves inline styles after completion. They just need to be removed afterwards.
The benefit of this approach is that the clicks feel a little more responsive (for the lack of a better word). The box will seem to react quickly to user's clicks.
However, if you cannot afford to simply remove the style attribute upon completion of animation, say you have previously applied inline styles on your object, you can cache them beforehand and re-apply them upon completion, which is demonstrated in this fiddle.
Hope this helps.
I set .delay() to stop showing on every mouse over the effect but now it is showing on every mouse over just delayed.
Seems .delay() is not the correct way to recognize the mouse over for a minimum time to show after the section.
$(document).ready(function(){
$('.article_wrapper').hover(
function(){
$(this).find('.actions').delay(800).show(300);
},
function(){
$(this).find('.actions').hide(200);
});
});
Which other Functions can I use?
On jQuery 1.9+, you can use finish() to clear all previous delay applied to specific queue:
(although this is still undocumented)
DEMO
UPDATE: indeed, to not break hide animation, you should use clearQueue()
$(document).ready(function(){
$('.article_wrapper').hover(
function(){
$(this).find('.actions').delay(800).show(300);
},
function(){
$(this).find('.actions').clearQueue().hide(200);
});
});
This is unfortunately a slightly annoying issue. The correct way of solving this is with "setTimeout", explained in greater detail here. Trying to add delay to jQuery AJAX request
This can easily be modified for your needs.
Edit
As the better answer pointed out, this isn't neccessary for animations, I'll leave it here because it is relevant to most non-animation delays.
Context: I am making a small jQuery library for modals (in-window popups): https://github.com/hypesystem/d_modal.js
When creating a new modal, it is possible to also fade the page. This is done by adding a div with a semi-transparent black background.
When the modal is removed I want the "fade" to disappear as well. But not just when the modal is .remove()'d - I want the fade to disappear in the same way as the modal on any action that makes the modal disappear: fadeOut(), hide(), etc.
Here is a jsFiddle to test in (if you have any ideas): http://jsfiddle.net/n5fqS/
What I'm looking for is one solution that handles all the cases.
there are many ways of hidding elements (removing content of div, changing css "display" property, fadeOut(), hide(), etc, etc) and Jquery does not have a universal event listener that would group all these events. I think you will have to manually trigger a "hide" event as a callback function in all the places where your first div is being hidden. For example:
$(".dismiss").click(function() {
$("#div-one").hide(function(){
$(this).trigger('hide');
});
});
Then you only have to have once the event handler:
$("#div-one").on('hide', function(){
//code that hides my second div
)};
Of course, you will have to manually add the trigger every place where relevant. So its not "the one solution".
you can use jquery dialog to achieve this functionality.
The short answer seems to be: jQuery does not emit events on hide.
In order to combat this, I have used the best solution I could find, and started an open project to enable sending of the required events: https://github.com/hypesystem/showandtell.js
This should cover, at the moment, the most common use-cases. Any feedback on this is appreciated.
try like this
$(".dismiss").click(function() {
$("#div-one").hide(function(){
$("#div-two").hide('slow');
});
});
I have a BG image animation that relies on the hover callback to revert to it's original state. If I move the mouse quickly over the links, the hovered state sticks. My guess is that I'm moving the mouse off before the first animation completes, so the callback doesn't register.
Is there a more bulletproof way to write this function?
$('.nav li a').hover(function() {
$(this).addClass('hovered', 300);
}, function() {
$(this).removeClass('hovered', 300);
});
(it uses a BGimg plugin to support the speed parameter on add/removeClass)
Testable here: McPherson Industries
This is a common problem and cannot be fixed, I'm afraid – it's up to the browser to keep up with events, and if it can't, well, you're out of luck.
It might be jQuery's fault also, though. Hard to say without dwelling into the source code. Anyways, there's a easy workaround:
$('.nav li a').hover(function() {
// When element is hovered, remove hovered state from all elements..
$('.hovered').removeClass('hovered');
// ..and add it to this one.
$(this).addClass('hovered', 300);
}, function() {
// This is only needed when exiting an element and not enterin another one
$(this).removeClass('hovered', 300);
});
This might not be 100% certain, but it's better than your current.
What is the 300 value in the addClass method ? it does not take two parameters.. just one
Api reference: http://api.jquery.com/addClass/
(ok,noticed the plugin)
It works just fine for me .. all links revert back to their original image, no-matter how fast i move the mouse..
Update
Ok i see the problem now..
Chrome is OK (the only one it seems..)
Firefox shows the problem..
IE shows the problem
Update 2
It seems to me that the problem is with the plugin you use.. It ignores queued requests to the same object until the current animation has finished.. So if you hover out before the first one has completed it will not return to normal..
I can't help more on this, sorry ..