JQuery Animation Queue Never Stops - javascript

I have created a simple drop-down menu with JQuery, following a tutorial. LINK :
http://wabism.com/development/jquerydropdown/
Its jQuery code is this:
$('body').ready(function() {
// Add the 'hover' event listener to our drop down class
$('.dropdown').hover(function() {
// When the event is triggered, grab the current element 'this' and
// find it's children '.sub_navigation' and display/hide them
$(this).find('.sub_navigation').slideToggle();
});
});
Drop-down works fine with 1 error. If you rollover and out a menu item 3 or 4 times quickly, it does all the 3 or 4 slidetoggle() 's. How can I overcome this problem ?

Use .stop() method before animation.
As you described, animations in jQuery would be queued and all of them would be executed, unless you explicitly specify that you want any pending animation to stop. You would do this using .stop() function. In your case you should write:
$(this)
.find('.sub_navigation')
.stop()
.slideToggle();
It has some parameters too which would give you more granular level of control. See here.

Related

jquery functions overloading

I have a function binded to a .click() event. Each time the user clicks, the browser fadeOut() the current element and animate() the marginLeft of the new element. For some reason when I click fast on the button which is binded to this click event, in Chrome it jumpes the animation and just go on directly to the next on (only if I click like 5 times in 1 second) and don't add the marginLeft, in this case it causes a major usability issue for the UI. Is there any fallback for this scenario? Like if the animation is not completed directly add it with css() or something like that?
Thanks
E: The click() event calls a function where all the magic happens, if it helps ..
You may want to look into jquery's .stop() method. It allows you to short-circuit any currently-running animations on an element.
Simple example:
$myElement.on('click', function() {
// first 'true' clears animations in the queue for this element
// second 'true' completes the currently-running animation immediately
$(this).stop(true, true).fadeOut();
});
http://api.jquery.com/stop/

Firing events in Twitter Bootstrap's Carousel

Once the carousel has slid, I want to add a value to an input outside of the ID myCarousel.
The function to implement an event once the carousel has slid is this:
$('#myCarousel').bind('slid', function() {
$('input[name=linkOnly]').val('Test')
}
I want to fire an event once a particular slide slides. I've tried something like $('#myCarousel li[data-slide-to=1]').bind('slid', function() ... but it doesn't register.
Any help appreciated, thanks.
You could just setup an event handler on the appropriate event and then choose to do anything based on which slide is .current. For example, to trigger some javascript when slide 1 cycles in:
$(document).on("slid", function(event) {
if ($(event.target).find(".active").data("slide-to") == 1) {
// do stuff
}
});
From a quick test, this doesn't seem to work unless it attached to an element above the carousel (you'd also need to change things a little if you had more than one carousel).
EDIT: After a quick look, the reason the above doesn't work if bound to the carousel itself is that the active class isn't added until immediately after the slid event is triggered (it seems that if the handler is added to a parent element, the active class gets added while the slid event bubbles up). You can get around this by using setTimeout to delay the triggered behaviour (works even with a timeout of 0):
$("#myCarousel").on("slid", function(event) {
var carousel = $(event.target);
setTimeout(function() {
if (carousel.find(".carousel-indicators .active").data("slide-to") === 1) {
// do stuff
}
}, 0);
});
Whether the extra code is worth it is up to you, although it may be a little more stable. It may even be worth putting in a small delay (instead of 0), just to make sure that things do work the way you expect them to.

Utilise the Bootstrap Carousel "slide" event and the .next class

So I've got a little problem (similar to this one I posted the other day: http://bit.ly/11JpbdY) with using SlabText on a piece of content that is hidden on load. This time, I'm trying to get slabText to update the display of some content that is in a slider (using Twitter Bootstrap's Carousel plugin).
Following Twitter's documentation (http://twitter.github.com/bootstrap/javascript.html#carousel) for Bootstrap's Carousel plugin, I'm trying to use slide event so that I re-call SlabText to make it display correctly.
Using developer tools I can see that Carousel adds a .next class as it processes the slide of one .item element to the next. This is then removed before the .active class is transferred.
I can access the "slide" event without any issue, but trying to get hold of the .next element is proving troublesome. Here is a JSFiddle of my code thus far: http://jsfiddle.net/peHDQ/
To put my question simply; how should I correctly use the slide event to trigger a function?
Please let me know if any additional information would be useful.
Further notes:
As I've been unable to get hold of the .next class, I'm attempting to do this with some jQuery. Here is my code thus far:
$('.carousel').carousel({
interval: 5000
}).on('slide', function (e) {
$(this).find('.active').next().find('.slab').slabText();
});
From what I understand this should be grabbing each .slab element and triggering the SlabText plugin.... alas I get an error:
"Uncaught TypeError: Object [object Object] has no method 'slabtext' "
Can anyone advise what I am doing wrong here...? I've used the exact same process to add a class and it works fine (as per this JSFiddle: http://jsfiddle.net/peHDQ/2/)
I identified the problem. The issue is that the event 'slide' is called before the next slide is made visible. I added a little delay, and it works fine now. Try this:
$('.carousel').carousel({
interval: 5000
}).on('slide', function (e) {
var xx = $(this);
setTimeout(function() {
xx.find('.active').next().find('.slab').slabText();
} , 0);
});
Per the documentation you should be using Slid not Slide
https://getbootstrap.com/docs/4.3/components/carousel/#events
Event Type: slid.bs.carousel
This event is fired when the carousel has completed its slide transition.

jQuery addClass/removeClass transition not smooth but stuttering

In a picture gallery I try to make all pictures not hovered greyscale:
$('.featured_product_item').mouseover(function() {
$('.featured_product_item').not(this).addClass('greyscale',200);
});
$('.featured_product_item').mouseout(function() {
$('.featured_product_item').removeClass('greyscale',200);
});
However, it is not smooth if you move your mouse to another item before the first animation has finished... how could you achieve that in a better way?
You should try .mouseenter() and .mouseleave().
http://api.jquery.com/mouseenter/
http://api.jquery.com/mouseleave/
The mouseenter event will only fire when the mouse changes from being outside of the element to inside the element. The opposite is true for mouseleave.
This way you should not see the stuttering behavior as seen with mouseover because every time the mouse shifts and you are over the element, the event will fire.
Something to the effect of this using stop
$(document).ready(function() {
$(".featured_product_item").mouseover(function () {
$('.featured_product_item').not(this).stop(true,true).addClass("selected", 1000);
});
$(".featured_product_item").mouseout(function () {
$('.featured_product_item').stop(true,true).removeClass("selected",1000);
});
});​
Please check the jQuery Manual for stop
Here is the JSFiddle for this
NOTE
Im not sure you are using addClass and removeClass correctly. I have not found any reference in the manual of using an animation time for the second param. From the manual:
.addClass( function(index, currentClass) )
function(index, currentClass) A function returning one or more space-separated class names to be added to the existing class name(s). Receives the index position of the element in the set and the existing class name(s) as arguments. Within the function, this refers to the current element in the set.
UPDATE
I had some code in the wrong place and missed the extra params for stop. Please check the code above and the new jsfiddle.

jQuery mouseleave delay

Got a simple problem, which it doesn't look like HoverIntent would solve.
I have two elements (lets say a button and a div), one element is the trigger to start the div expanding, which is triggered by a mouseenter event (this would be a suitable candidate for HoverIntent).
However when the mouse leaves the expanded div for a given amount of time I need it to contract again, however if they re-enter the div it should NOT contract. Most hoverintent style plugins would give me this functionality but only for 1 element, and as one element controls the expanding (button - mouseenter) and one controls the contracting (div - mouseleave).
I know I could write some code to just do a setTimeout to delay for a period and make sure that the mouse is still outside of the area, but I would rather use a pre-made plugin if one exists.
So could anyone advise if this exists?
-- Edited --
Edited the above question to make clear that the main intent part is to stop it contracting the div if the mouse re-enters the div within a given amount of time, lets say 2 seconds. So the div should expand on mouseenter button, then contract if mouseleaves the div for >= 2 seconds.
Not something like this?
$('.hover-items').each(function(idx, el){
$(el).mouseenter(function() {
$(this).slideDown(300);
$('#target_div').unbind().mouseleave(function() {$(this).slideUp(300)});
});
});
The unbind is there so that you don't wind up with a bunch of events tied to the element. Just reset and go.
Added to satisfy clarification of question.
$('.hover-items').each(function(idx, el){
$(el).mouseenter(function() {
clearTimeout($(el).data('timer'));
$('#target_div').slideDown(300)
.unbind()
.mouseleave(function() {
var closure = function(){$('#target_div').slideUp(300)};
$(el).data('timer', setTimeout(closure,2000));
});
});
});

Categories

Resources