I have a jQuery cycle script (which I wrote, so it's not high quality) that basically cycles <li> elements by animating their opacity. For example, say I have three <li> elements. The script would set the opacity of all elements but the first one to 0, then when a "next" button is clicked, it will animate the opacity of the first one to 0, then animate the opacity of the second one to 1, and so forth. At the same time, I have a setInterval running that literally clicks the "next" button every four seconds.
The problem is, if the user clicks the "next" button at the same time as the setInterval pushes it, the opacity of the elements messes up, and some elements end up on top of each other.
Could anyone suggest a solution? Would it work better if I used the .hide() function instead of the .css('opacity')?
EDIT: This is the code
$('ul#news > li').css({opacity:0.0}).filter('ul#news li.firstNews').css({opacity:1.0});
$('#newsLeft').click(function() {
var $active = $('ul#news li.active');
var $next = $active.next().length ? $active.next() : $('ul#news li.firstNews');
$active.animate({opacity:0.0}, 300, function() {
//when done animating out, animate next in
$next.css({opacity:0.0})
.animate({opacity: 1.0}, 400, function() {
$active.removeClass('active');
$next.addClass('active');
});
});
return false;
}); //clickRight
Reset the animation timer when the next-button is hovered. Example below.
var animTimerDelay = 4000,
animTimerID = null;
function animTick() {
// Animation code here
resetTimer();
}
function resetTimer() {
if (animTimerID !== null) {
clearTimeout(animTimerID);
}
animTimerID = setTimeout(animTick, animTimerDelay);
}
prevent mouse event during animation.
every time I use this method.
like,
$('#newsLeft').click(function() {
if($(this).hasClass('blockEvent')) return false; // return if it's locked
$(this).addClass('blockEvent'); // lock it with 'blockevent' class
var $active = $('ul#news li.active');
var $next = $active.next().length ? $active.next() : $('ul#news li.firstNews');
$active.animate({opacity:0.0}, 300, function() {
//when done animating out, animate next in
$next.css({opacity:0.0})
.animate({opacity: 1.0}, 400, function() {
$active.removeClass('active');
$next.addClass('active');
$('#newsLeft').removeClass('blockEvent'); // unlock after all animations
});
});
return false;
}); //clickRight
good luck :)
Related
I am looking for an way to loop a function as long as an animation is executed.
The reason is: I created an UI-Layout within a parent div. The parent div changes it's width due to an animation. The problem is that the UI-Layout doesn't adjust to the parent's width.
By calling $(window).trigger('resize'); when the animation is finished the UI Layout adjusts to the new width.
But I now want the layout to adjust smoothly to the animation so that the UI-Layout grows in an animated way (just like the parent div).
So my idea was to loop $(window).trigger('resize'); as long as the animation of the width of the parent div is playing.
What is the best way to loop a function while the animation is playing?
Or are there better ways to achieve what I am looking for?
Thanks so much!
You can use the jQuery .animate(properties, options) syntax, which allows you to listen to the progress event.
Example:
$( "#book" ).animate({
width: "+=50px" // whatever CSS properties that are animated...
}, {
duration: 500,
progress: function() { // This gets called several times during the animation
$(window).trigger('resize');
}
complete: function() {
$(window).trigger('resize');
}
});
CSS transitions
If you are using pure CSS transitions, then right after you launch the transition, you could call this function, passing it the element that is being animated:
function manageResize(elem) {
var timer = setInterval(function () {
$(window).trigger('resize');
}, 50);
elem.addEventListener('transitionend', function () {
clearInterval(timer);
}, false);
}
This will resize the window every few milliseconds (adjust as needed) and stop doing that once the transition comes to an end.
If you're using jQuery animation, a way would be:
var animating = true;
$( elem ).animate({
opacity: 0.25,
left: "+=50",
height: "toggle"
}, 5000, function() {
animating = false;
});
var timer = setInterval(function(){
if(animating)
$(window).trigger('resize');
else
clearInterval(timer);
},50);
Or, if you're using CSS animation:
// start animation
var animating = true;
$( elem ).addClass("animating");
$( elem ).one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",
function(event) {
animating = false;
});
var timer = setInterval(function(){
if(animating)
$(window).trigger('resize');
else
clearInterval(timer);
},50);
So I'm making a menu that shows various divs when you hover over the menu buttons, but the problem is that the events fire immediately as you hover over the buttons, which I don't want, because if you slide the mouse over more than one button, then they all fire at once and show / hide the div containers (looks bad).
I want the events to fire only if the user hovers the buttons for a certain amount of time, like 500ms, because that way they will only see one div container at a time.
This is the code I'm using, e.g. for the menu button:
$(".menu-button").hover(function(e) {
e.preventDefault(); //To prevent default anchor tag behaviour
e.stopPropagation(); //To prevent parent container click event from firing
$(".menu-container").delay(300).slideDown(800);
});
var myTimer = false;
$(".menu-button, .menu-container").hover(function(){
//mouse enter
clearTimeout(myTimer);
},function(){
//mouse leav
myTimer = setTimeout(function(){
$(".menu-container").slideUp(500);
},100)
});
Fiddle: http://jsfiddle.net/1g0Lraec/5/
It's driving me nuts, I hope someone can help me out!
Thank you :-)
You can use this :
var upTimer = false ,
downTimer = false ,
isHover = false ;
$(".menu-button, .menu-container").hover(function(){
isHover = true;
clearTimeout(upTimer);
downTimer = setTimeout(function(){
if(isHover)
$(".menu-container").slideDown(500);
},500);
},function(){
isHover = false;
clearTimeout(downTimer);
upTimer = setTimeout(function(){
$(".menu-container").slideUp(500);
},100);
});
JSFIDDLE
This will work also :
var downTimer = false
$(".menu-button, .menu-container").hover(function(){
downTimer = setTimeout(function(){
$(".menu-container").slideDown(500);
},500);
},function(){
clearTimeout(downTimer);
$(".menu-container").slideUp(500);
});
I have created this DEMO for my question.
In my demo you can see when you hover over the thumbnail image with the mouse the bigger picture is changing. What i want to? I want to change the images automatically after a few second.
What i need to do for it ? Anyone can help me ?
$(document).ready(function() {
$("#magazin_sldwr li img").hover(function(){
$('#mainm-img').attr('src',$(this).attr('src').replace('thumb/', ''));
});
var imgSwap = [];
$("#magazin_sldwr li img").each(function(){
imgUrl = this.src.replace('thumb/', '');
imgSwap.push(imgUrl);
});
$(imgSwap).preload();
});
$.fn.preload = function() {
this.each(function(){
$('<img/>')[0].src = this;
});
}
This is a start : demo
The idea is to use an .active class on the parent li of the current image, and then trigger a mouseenter event every 2 seconds :
function autoChangeImage() {
setTimeout(function(){
$("#magazin_sldwr li.active")
.removeClass('active')
.next('li')
.addClass('active')
.children('img')
.trigger('mouseenter');
autoChangeImage();
}, 2000);
}
Of course, you will probably want to go back to the first thumb after having reached the last one, and clearTimeout when hovering a thumb "manually" : demo
use setInterval()
setInterval(function() {
//change image
}, 2000);
Where 2000 is the number of miliseconds. For o ly one change you can use setTimeout()
I am looking for the solution for a navigation menu that I am working. Here is the JSFiddle where you can see the working code.
The fadeIn effect needs to happen only on the nav-item hover, but it is happening while mouseleave from the bottom, left or right side of the menu.
It looks like what you want is: when you move your mouse from a tab to another tab, you don't want the fade-out and in to happen.
In that case, it's because you're not keeping track of whether or not the menu is open. You should only do the fading if the menu was not open, otherwise simply hide and show with no fade.
Code:
var timer;
var isMenuOpen = false;
$('.nav-item').hover(
function() {
$('.subnav--main').hide();
$('.promoted-content--main').hide();
clearTimeout(timer);
if(isMenuOpen){
$(this).find('ul').show();
}
else{
isMenuOpen = true;
$(this).find('ul').fadeIn( 'slow' );
}
},
function() {
timer = setTimeout(function() {
$('.subnav--main').fadeOut( 'fast' );
$('.promoted-content--main').fadeOut( 'fast' );
isMenuOpen = false;
}, 1000);
}
);
And jsfiddle: http://jsfiddle.net/qdafe3uw/
If you're trying to get the menu to stay open and not have it fade out when hovering over different nav-items' the selector should be the nav--main
`var timer;
$('.nav--main').hover(function() {
$('.subnav--main').hide();
$('.promoted-content--main').hide();
clearTimeout(timer);
$(this).find('ul').fadeIn( 'slow' );
},
function() {
timer = setTimeout(function() {
$('.subnav--main').fadeOut( 'fast' );
$('.promoted-content--main').fadeOut( 'fast' );
}, 1000);
});`
Problem: Whenever I click faster or slower I need last .click() call to finish before the next one starts. If you click the button faster , in the given example, you can see it's leaving divisions with 0 opacity.
What I want to achieve is stacking up till 3-4. I tried some queue code examples, couldn't make it work.
$("#addNew").click(function(){
var _this = $("#scrollable");
//Switch classes
_this.find("div.first").switchClass("first","second",500);
_this.find("div.second").switchClass("second","third",500);
_this.find("div.third").switchClass("third","fourth",500);
_this.find("div.fourth").switchClass("fourth","fifth",500);
// Insert first/new line
$("<div class='first'>Hello!</div>").css("opacity","0").hide().prependTo(_this).slideDown(function(){$(this).stop().animate({opacity:1},300)})
$("div.fifth").fadeOut().remove();
});
Here is example: http://jsfiddle.net/gtFyP/5/
Use setInterval
You could combine the below flag solution with setInterval, and thus be able to process clicks occurring during an animation.
Updated your JS Fiddle again with this alternate solution.
$(function() {
var clicking = false;
var clickCache = 0;
window.setInterval(function(){
if (!clicking && clickCache) {
processClick();
clickCache--;
}
}, 100);
var processClick = function() {
var _this = $("#scrollable");
//Switch classes
_this.find("div.first").switchClass("first", "second", 500);
_this.find("div.second").switchClass("second", "third", 500);
_this.find("div.third").switchClass("third", "fourth", 500);
_this.find("div.fourth").switchClass("fourth", "fifth", 500);
clicking = true;
// Insert first/new line
$("<div class='first'>Hello!</div>").css("opacity", "0").hide().prependTo(_this).slideDown(function() {
$(this).stop().animate({
opacity: 1
}, 300, function(){
clicking = false;
});
});
$("div.fifth").fadeOut().remove();
};
$("#addNew").click(function() {
clickCache++;
});
});
Use a Flag
You could use a flag - only start an animation if it's false. When you start animating, set it to true, when the animation is done, set it back to false.
I've modified your JS Fiddle.