Stopping increment at specific height - javascript

I am animating images within a logo in a slot-machine type of animation. I need it to stop animating once it gets to the top of the image (and send a callback if possible).
Currently, this is how I'm accomplishing the animation:
window.setInterval(function() {
$('#title-1 img').animate({bottom : '-=60px'})
}, 5000);
Any ideas on how I would get it to stop, and to send the callback?

So I assume you have a sprite image containing multiple logos, you want them to slide each 5 seconds until you reach the last one, and then call the callback?
var cnt = 6,
$img = $('#title-1 img'),
i = 0;
function animate_logo(cb) {
if (i < cnt) {
$('#title-1 img').animate({bottom : '-=60px'});
i += 1;
setTimeout(function () {animate_logo(cb)}, 5000);
}
else {
cb();
}
}();

var interval = window.setInterval(function() {
$('#title-1 img').animate({bottom : '-=60px'},
function(){
if(`some stop point`) clearInterval(interval);
}
);
}, 5000);

I would not suggest using a setInterval when dealing with animations due to the way newer browsers are making changes to the way setInterval and setTimeout work when the tab is not the active tab.
var $title1 = $("#title-1");
var $title1img = $title1.find('img');
function anim(){
if ($title1.height() < parseInt($title1img.css("bottom"))) {
setTimeout(function(){
$title1img.animate({bottom : '-=60px'},anim);
},5000);
}
}
$title1img.animate({bottom : '-=60px'},anim);
Edit: another reason not to use setInterval to fire off animations is due to the reqeustAnimationFrame that was implemented in 1.6 and removed in 1.6.3, which will more than likely be added back in 1.7. If you write code now that will be compatible later, that's less maintenance you will have to do later if you end up being required to upgrade.
Here's a jsfiddle http://jsfiddle.net/czUnU/
Edit: function...
function animColumn(title,img){
function anim(){
if (title.height() < parseInt(img.css("bottom")) {
setTimeout(function(){
img.animate({bottom : '-=60px'},anim);
},5000);
}
}
img.animate({bottom : '-=60px'},anim);
}
animColumn($("#title-1"),$("#title-1 img"));
animColumn($("#title-2"),$("#title-2 img"));
animColumn($("#title-3"),$("#title-3 img"));
http://jsfiddle.net/czUnU/1/

Related

Allowing for maximum number of opened accordion sections using jQuery

I've looked all over the internet and I can't seem to find a good way to do this.
I've got an accordion menu that I've built primarily using addClass/removeClass and css. It has special functionality, the accordion tabs open after a delay on mouseover and they open and close on click. I can currently open all of them at once, but I'd like to limit this to 2 or 3 with the earliest selected panel closing after I hit that limit. So I'd either need to make the classes numbered and switch them on every action, or perhaps apply a variable that keeps track of the order in which the panels were selected and switch them.
Below is the code I have so far. I've only been able to get as far as keeping count of how many tabs there currently are open. Does anyone have an idea as to what the best way to approach this is?
var timer;
var counter = 0;
$('li.has-dropdown').mouseenter(function() {
dd_item = $(this);
if(!$(this).hasClass('expand-tab')){
timer = setTimeout ( function () {
$(dd_item).addClass('expand-tab');
counter++;
}, 200);
};
}).mouseleave(function(){
clearTimeout(timer);
console.log(counter);
}).click(function() {
if ($(this).hasClass('expand-tab')){
$(this).removeClass('expand-tab');
counter--;
console.log(counter);
}else{
$(this).addClass('expand-tab');
console.log(counter);
}
});
Add a incrementting data-index to each opened tab.
count the tabs on the end of the hover effect, if they are to many, sort them by the index, and hide the lowest/oldest.
var timer;
var index = 1;
$('li.has-dropdown').mouseenter(function() {
dd_item = $(this);
if(!$(this).hasClass('expand-tab')){
timer = setTimeout ( function () {
$(dd_item).addClass('expand-tab');
$(dd_item).attr('data-index', index++);
counter++;
}, 200);
};
}).mouseleave(function(){
clearTimeout(timer);
console.log(counter);
}).click(function() {
$(this).taggleClass('expand-tab'); // see jQuery toggleClass();
$(this).attr('data-index', index++);//this will add index on closed tabs also.. but it does not matter at the end.
});
if($('.expand-tab').length> 3){
//custom inline sorting function.
var expanded_tabs = $('.expand-tab').sort(function (a, b) {
return (parseInt( $(a).attr('data-index')) < parseInt( $(b).attr('data-index')) ? -1 : 1 ;
});
//time out .. effect etc.
expanded_tabs[0].removeClass('expand-tab');
}
P.S I don't like havving Hover and Click in the same place ... try to separate the events and call a unified collapseIfToMany function in on each event
This is a corrected version. I decided to use a variable for the maximum panels opened, this way you don't have to dig if you decide you want to change it, or if you add more to the code.
var timer;
var index = 1;
var maxOpen = 2;
$('li.has-dropdown').mouseenter(function() {
dd_item = $(this);
if(!$(this).hasClass('expand-tab')){
timer = setTimeout ( function () {
$(dd_item).addClass('expand-tab');
$(dd_item).attr('data-index', index++);
collapseIfTooMany();
}, 200);
};
}).mouseleave(function(){
clearTimeout(timer);
}).click(function() {
$(this).toggleClass('expand-tab'); // see jQuery toggleClass();
$(this).attr('data-index', index++);//this will add index on closed tabs also.. but it does not matter at the end.
});
function collapseIfTooMany(){
if($('.expand-tab').length > maxOpen){
//custom inline sorting function.
var expanded_tabs = $('.expand-tab').sort(function (a, b) {
return (parseInt( $(a).attr('data-index')) < parseInt( $(b).attr('data-index'))) ? -1 : 1 ;
});
//time out .. effect etc.
$(expanded_tabs[0]).removeClass('expand-tab');
}
};

jQuery fade image loop

I want to make a loop in my function so that the slideshow effect always restarts.
Here's my fiddle : http://jsfiddle.net/Be67B/
It's all good for the image 1 to go to image 2, but I want it to fade it back to the image 1, and then go the image 2, and so on...to always loop like that.
What do I need to add in my code to make this work?
Don't use a loop, just ask the browser to repetitively call your animation step :
setInterval(function(){
// your animation (in fact just a step)
}, someDelay);
Demonstration : http://jsfiddle.net/dystroy/nPh6S/
In this precise case, the animation is done with :
setInterval(function(){
$("#top").fadeOut(function() {
$(this).attr("src","http://1.bp.blogspot.com/-cFt5KNrHsHc/TZMH6XUBu-I/AAAAAAAAAR4/R6hOP7lffx0/s1600/apple-logo.png").fadeIn().delay(1000).fadeOut(function(){
$(this).attr('src', 'http://coreldrawtips.com/images/applebig.jpg').fadeIn().delay(1000);
});
}
);
}, 4000);
see this jquery cycle plugin:
http://jquery.malsup.com/cycle/
may be this is what you want
You can create a function that does the transition, which has a callback function as part of the fadeIn method that will call back to itself to trigger the next transition, and it would just be in a constant loop.
Here's your modified jsfiddle:
http://jsfiddle.net/Be67B/1/
HTML:
<img id="top" src="http://coreldrawtips.com/images/applebig.jpg" width="300" height="300" />​
Javascript:
$(document).ready(function(){
transition(false);
});
function transition(first)
{
var src = first ? "http://coreldrawtips.com/images/applebig.jpg" : "http://1.bp.blogspot.com/-cFt5KNrHsHc/TZMH6XUBu-I/AAAAAAAAAR4/R6hOP7lffx0/s1600/apple-logo.png";
$("#top").delay(1000).fadeOut(function() {
$(this).attr("src",src).fadeIn(function() {
transition(!first);
});
});
}
​
I just made this code:
$(document).ready(function(){
// images in the pool
var images=["http://1.bp.blogspot.com/-cFt5KNrHsHc/TZMH6XUBu- I/AAAAAAAAAR4/R6hOP7lffx0/s1600/apple-logo.png",
"http://1.bp.blogspot.com/-cFt5KNrHsHc/TZMH6XUBu-I/AAAAAAAAAR4/R6hOP7lffx0/s1600/apple-logo.png"];
// next image to display
var next = 0;
// interval beetween images
var INTERVAL = 1000;
// main function
var doCarrousel = function() {
$("#top").fadeOut(function() {
$(this).attr("src", images[next]).fadeIn(
function() {
setTimeout(doCarrousel, INTERVAL);
});
});
if (++next >= images.length)
next = 0;
};
//start carrousel
doCarrousel();
});
fiddler: http://jsfiddle.net/Be67B/
I would use a plugin. But you can do it by hand. I just recommend against changing the src of the images, because some browsers don't handle it very well, like safari not firing load event.
Instead, have all images inside a container, and cycle their visibility:
$(document).ready(function(){
var currentImage = $("#images img:first");
setInterval(function(){
currentImage.fadeOut();
if(currentImage.next().size())
currentImage = currentImage.next();
else
currentImage = currentImage.siblings().first();
currentImage.fadeIn();
}, 1000)
});
See fiddle: http://jsfiddle.net/Be67B/2/
Quick and dirty: jsFiddle example
function swap(img) {
img = (img == 'http://coreldrawtips.com/images/applebig.jpg') ? 'http://1.bp.blogspot.com/-cFt5KNrHsHc/TZMH6XUBu-I/AAAAAAAAAR4/R6hOP7lffx0/s1600/apple-logo.png' : 'http://coreldrawtips.com/images/applebig.jpg';
$('#top').delay(2000).fadeOut(function() {
$(this).attr('src', img)
}).fadeIn(function() {
setTimeout(function() {
swap(img)
}, 1000);
});
};
swap($('#top').attr('src'));​

Execute after cleartimeout function finished (jQuery)

I have this istuation. I have a setTimeout to a function in which I fade out and fade in an element. In a few seconds this timeout is cleared with cleartimeout and right after is called .hide() to hide this element. The problem is that sometimes it doesnt hide the element. I have a feeling it has something to do with timing.
Example:
function first_func(){
$('.element').fadeOut(function(){
// Do other stuff like change element's position
$('.element').fadeIn();
});
interval1 = setTimeout(function(){first_func()},500);
}
function second_func(){
countdown--;
if (countdown<0){
last_func();
}
interval2 = setTimeout(function(){second_func()},1000);
}
function begin_func(){
first_func();
second_func();
}
function last_func(){
clearTimeout(interval1);
clearTimeout(interval2);
$('.element').hide();
}
So basically the problem is that in last_func I clear both intervals and HIDE the element, but sometimes the element is still visible on the page. So I am guessing that it does hide but the interval is still in progress and it fades back in.
If anyone would have some suggestion please
Just a suggestion, but this bit appears wrong to me:
function second_func(){
countdown--;
if (countdown<0){
end_func();
}
interval2 = setTimeout(function(){second_func()},1000);
}
Even if you're calling end_func() to stop everything, you're setting a new timeout after that.
function second_func(){
countdown--;
if (countdown<0){
end_func();
} else {
interval2 = setTimeout(second_func, 1000);
}
}
Another hint: To avoid that running fadeIn/fadeOuts affect the hiding of the element, you should clear the animation queue:
$('.element').stop(true, true).hide();
By default fadeIn and fadeOut use duration of 400 milliseconds, u can change it by set first parameter.
$('.element').fadeOut( [duration] [, callback] );
You seem to never call last_func, is end_func() supposed to be last_func()?
This works:
http://jsfiddle.net/CZ9hr/1/
May I suggest a simpler approach for what you seem to want to achieve: http://jsfiddle.net/fSEjR/2/
var countdown = 3,
$element = $('.element');
for (var i = 0; i < countdown; i++) {
$element.fadeOut().fadeIn(function() {
countdown--;
if (countdown === 0) $element.hide();
});
};
This works because animations are automatically queued in jquery.

window.clearInterval is not working?

I'm using JS to animate two images by having them toggle on and off. I have an initial image which, when the animation is turned on, appears on the screen and stays on. The second image, which has a higher z value, is then set to toggle on and off every 1 second in the same location as the first image, so it appears as if the two are alternating.
I'm using window.setInterval to make the second image blink, but when I need to turn the animation off (and I'm removing both images from the screen), my window.clearInterval is not "working" The first image will be gone, but the second one keeps blinking on and off every second.
Code:
function notebookNotification(setting)
{
$("#lightNotificationContainer").show();
var notificationAnimation = window.setInterval('$("#darkNotificationContainer").toggle()', 1000);
if(setting == 0)
{
window.clearInterval(notificationAnimation);
$("#lightNotificationContainer").hide();
$("#darkNotificationContainer").hide();
}
}
Anyone see why it isn't working?
Reading between the lines, I think what you're saying is this:
You execute notebookNotification(1); and the animation starts
You execute notebookNotification(0); and the animation does not stop.
My guess is that you want notebookNotification(0) to disable the flashing.
In order to do that, you need to rework this function considerably. You need to store the intervalID that comes from setInterval in a variable that survives outside of the scope of this function and can be used for clearInterval on subsequent calls to this function.
For example:
var intervalID;
function notebookNotification(setting)
{
if(setting == 0)
{
if(intervalID) {
window.clearInterval(intervalID);
intervalID = null;
}
$("#lightNotificationContainer").hide();
$("#darkNotificationContainer").hide();
}
else
{
$("#lightNotificationContainer").show();
if(!intervalID) {
intervalID = window.setInterval('$("#darkNotificationContainer").toggle()', 1000);
}
}
}
Here, try this:
http://jsfiddle.net/WGxmy/
Saving the interval to a global variable -- not one inside a function -- lets you clear it later.
var keepflashing = true;
var isShowing = true;
function notebookNotification()
{
if(!isShowing)
$("#lightNotificationContainer").show();
else
$("#lightNotificationContainer").show();
isShowing = !isShowing;
if(keepflashing)
setTimeout( function(){ notebookNotification(setting); },100);
else
{
$("#lightNotificationContainer").hide();
$("#darkNotificationContainer").hide();
}
}
Maybe you can avoid calling clearInterval() generally?
function notebookNotification(setting)
{
if(setting == 0)
{
$("#lightNotificationContainer").hide();
$("#darkNotificationContainer").hide();
}
else
{
$("#lightNotificationContainer").show();
window.setInterval('$("#darkNotificationContainer").toggle()', 1000);
}
}

jQuery text() does not work before a setTimeout?

After an Ajax request, I perform the following.
$('#change_ts').text('Defaults Changed!');
//blinking part
var t = setTimeout($('#change_ts').fadeIn('slow'), 500);
clearTimeout(t);
var t = setTimeout($('#change_ts').fadeOut('slow'), 500);
clearTimeout(t);
var t = setTimeout($('#change_ts').fadeIn('slow'), 500);
clearTimeout(t);
var t = setTimeout($('#change_ts').fadeOut('slow'), 500);
clearTimeout(t);
var t = setTimeout($('#change_ts').fadeIn('slow'), 500);
clearTimeout(t);
var t = setTimeout($('#change_ts').fadeOut('slow'), 500);
clearTimeout(t);
var t = setTimeout($('#change_ts').fadeIn('slow'), 500);
clearTimeout(t);
var t = setTimeout($('#change_ts').text('Change Text/Size'), 500);
clearTimeout(t);
It is my make-shift fade in/out blinker. It works well.
However, the first line has no effect when I perform the blinking part. If I remove the blinking the text of the span is changed. But as soon as I uncomment the blinker, it doesn't change the text at all?!
Any ideas why this is?
Thanks all for any help
Update
The set timeout is useless for what I need to do. I have removed it now and I have the following, but I still can not change the text before the fade in/outs?
$('#change_ts').text('Defaults Changed!');
$('#change_ts').fadeIn('slow');
$('#change_ts').fadeOut('slow');
$('#change_ts').fadeIn('slow');
$('#change_ts').fadeOut('slow');
$('#change_ts').fadeIn('slow');
$('#change_ts').fadeOut('slow');
$('#change_ts').fadeIn('slow');
$('#change_ts').text('Change Text/Size');
How about using the jQuery Blink plugin instead. You can see the demo here :)
You should pass a callback function to setTimeout, like this:
var t = setTimeout(function() { $('#change_ts').fadeIn('slow') }, 500);
Right now, you're calling the fade function immediately and sending the return value to setTimeout. You should also change the timeout values to be increasing, like 500, 1000, 1500 etc., otherwise all the fade in/out will occur at the same time. You could use a loop to set-up the values for you. And why are you clearing the timers immediately - they won't have any effect if you do so.
for (var i = 1; i <= 6; i += 2) {
setTimeout(function() { $('#change_ts').fadeIn('slow') }, 500 * i);
setTimeout(function() { $('#change_ts').fadeOut('slow') }, 500 * (i + 1));
}
You can also make a generic blinker like this, which will keep blinking until you clear the timer:
var state = true;
function blink() {
state = !state;
if (state)
$('#change_ts').fadeIn('slow');
else
$('#change_ts').fadeOut('slow');
}
var t = setInterval(blink, 500);
This will keep going until you call clearInterval(t).
Update: The reason the first text call has no effect is because the second text call is executed immediately and the text is overwritten. Note that the fadeIn and fadeOut return immediately, before the animation is completed, so the second text call executes right after that. If you want to wait until the animation is complete, you need to attach a callback to the last fade function, like this:
$('#change_ts').fadeIn('slow', function() {
$('#change_ts').text('Change Text/Size');
});

Categories

Resources