For some reason, I can't get a function to run after the each function is complete. This is what I tried and the each function works perfectly but it does not run the other function when it is complete.
var delay = 0;
$('h1 span').each(function() {
var $span = $(this);
setTimeout(function() { $span.addClass('visible'); }, delay+=1000, function(){
$('header').addClass('visible');
});
});
If i understand your expected behaviour, you can use following logic inside delayed function:
var delay = 0;
$('h1 span').each(function () {
var $span = $(this);
setTimeout(function () {
$span.addClass('visible');
// if $span is last of 'h1 span' matched set
if ($span.is($('h1 span').last())) {
$('header').addClass('visible');
}
}, delay += 1000);
});
-DEMO-
I think what you want to do is this http://jsfiddle.net/gon250/8mdodywe/
setTimeout() function doesn't support two callbacks.
$.when($('span').each(function() {
$(this).addClass('visible');
})).then(function(){
$('header').addClass('visible');
});
I guess that's what you want:
var delay = 0;
$('h1 span').each(function() {
var $span = $(this);
setTimeout(function() { $span.addClass('visible'); }, delay+=1000);
});
setTimeout(function() { $('header').addClass('visible'); }, delay);
Check it out: http://jsfiddle.net/zsm4xegr/
I'm assuming, you want two timeouts? From your Code it seems you would like to execute the first timeout after "delay 0". In that case simply execute the first "callback" and set a timout for the second.
If you do indeed want two timeouts (each after 1000ms):
$('h1 span').each(function() {
var $span = $(this);
setTimeout(
function() {
$span.addClass('visible');
setTimeout(
function() {
$('header').addClass('visible');
},
1000
);
},
1000
);
});
Related
I wondered what is the most easy way to add call back function to the function below:
<script>
$(document).on('focus', '#inputbox', function(e) {
$( this).contents().filter(function() {
return this.nodeType === 3;
}).wrap("<span class='new'></span>");
//I tried add function here but it would execute infinite times.
});
</script>
The same you already try, but skip all redundant calls for cb
<script>
function cb() { alert('Wow!'); }
(function() {
var timer;
var delay = 1000; // call cb delay
$(document).on('focus', '#inputbox', function(e) {
$( this).contents().filter(function() {
return this.nodeType === 3;
}).wrap("<span class='new'></span>");
clearTimeout(timer);
timer = setTimeout(cb, delay);
});
})();
</script>
one quick question!
I am using the following code which does a "flip" card effect to flip a specific div element, when a certain link is mouse clicked. Is it possible to make the "flip" effect reverse after some time? Exactly as if I was clicking again with the mouse, but timed. I can do it now by cliking, but I would like to time it.
$(document).ready(function () {
$('.flip_card').click(function () {
var x = $(this).attr("id");
var i = x.substring(10);
$('.flip' + i + '').find('.card').toggleClass('flipped');
});
});
I have tried using the jquery functions delay() or settimeout, but I can only achieve that the first "flip" effect is delayed and happens after certain time. That is not what I want...
I hope my question is understanble enough.
Many thanks!
Try this.
$(document).ready(function () {
$('.flip_card').click(function () {
var x = $(this).attr("id");
var i = x.substring(10);
var ele = '.flip' + i + '';
$(ele).find('.card').toggleClass('flipped');
setTimeout(function(){
$(ele).find('.card').toggleClass('flipped');
}, 1000);
});
});
Try utilizing .queue()
$(document).ready(function () {
$(".flip_card").click(function () {
var x = this.id;
var i = x.substring(10);
$(".flip" + i).find(".card").toggleClass("flipped")
.queue("reset", function() {
setTimeout(function() {
$(".flip"+ i + " .card.flipped:eq(-1)").toggleClass("flipped");
// set duration here
}, 3000);
}).dequeue("reset");
});
});
You can use setTimeout(), but you should keep track of the timer ID so you can cancel it if the user clicks again before the timeout has executed. You can use the .data() function to store the timer ID so each card keeps track of its own timer ID.
$(document).ready(function () {
$('.flip_card').click(function () {
var i = $(this).attr('id').substring(10);
var $card = $('.flip' + i).find('.card');
// Clear the timeout if there is one.
var timerId = $card.data('timerId');
if (timerId) {
clearTimeout(timerId);
}
// Flip the card.
if (!$card.hasClass('flipped')) {
$card.addClass('flipped');
// Set the timeout so the card is flipped back after 3 seconds.
$card.data('timerId', setTimeout(function () {
$card.removeClass('flipped');
}, 3000));
} else {
$card.removeClass('flipped');
}
});
});
jsfiddle
How about something this simple. Just chaining should make it.
$(document).ready(function () {
$('.flip_card').bind('click', function() {
var x = $(this).attr("id");
var i = x.substring(10);
var ele = '.flip' + i + '';
$(ele).find('.card').toggleClass('flipped').delay(3000).toggleClass('flipped');
});
});
On a form-field I work with two active functions: keyup and focusout.
The functions execute the same code, only the key-up uses a delay-function.
Function for delay:
$(function() {
var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
Functions for keyup and focusout:
$("#name").on('keyup', function (){
var textn = $(this).val();
var nbrCharn = textn.length;
delay(function(){
if(nbrCharn > '2'){ $('#nameMsg').html('Nice.');
}else { $('#nameMsg').html(''); }
}, 1000 );
});
$("#name").on('focusout', function (){
var textn = $(this).val();
var nbrCharn = textn.length;
if(nbrCharn > '2'){ $('#nameMsg').html('Nice.');
}else { $('#nameMsg').html(''); }
});
The keyup needs the delay, the focusout does not.
This code works fine, but is it possible to merge those functions, so I don't have the same code twice?
you could define a handler that takes an argument which is a completion function
var handler = function (completion){
return function(){
var textn = $(this).val(),
nbrCharn = textn.length;
completion(function(){
if(nbrCharn > '2'){
$('#nameMsg').html('Nice.');
} else {
$('#nameMsg').html('');
}
});
};
};
and then define the handlers
$("#name").on('keyup',handler(function(cb){delay(cb,1000);}));
$("#name").on('focusout',handler(function(cb){cb();}));
If you use several events in one handler use the event object argument to check event.type
$("#name").on('keyup focusout', function (evt){
if(evt.type === 'keyup'){
/* keyup only code */
}
});
Or something like
var delay = evt.type === 'keyup' ? 0 :1000;
then use delay() for both
You could try passing the relevant jquery this object to a function:
var delay =
(function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
}
)()
$(document).ready(init);
function init() {
$("#name").on('keyup', function (){
var self = this;
delay(
(function(self){
return function(){
writeNameMsg(self)
};
})(self)
, 1000 );
});
$("#name").on('focusout', function (){
writeNameMsg(this);
});
}
function writeNameMsg(self){
var textn = $(self).val();
var nbrCharn = textn.length;
if(nbrCharn > '2'){
$('#nameMsg').html('Nice.');
} else {
$('#nameMsg').html(''); }
}
};
One straightforward way is to .trigger() one event from the other after a delay:
$("#name").on('keyup', function (){
var $this = $(this);
setTimeout(function() {
$this.trigger('focusout');
}, 1000); // milliseconds
});
Alternatively, use an external callback function for both, using .call() to pass along the same element as this:
$("#name").on('keyup', function() {
var el = this;
setTimeout(function() { callbackFunc.call(el) }, 1000); // milliseconds
});
$("#name").on('focusout', callbackFunc);
I have this (simplified for here) code which change the background position on click,
but i need to put them in a auto loop too
<script type="text/javascript">
$(window).load(function(){
$(".sle1").click(function() {
$(".slimgs").animate({backgroundPosition: '-908px 0px'});
});
$(".sle2").click(function() {
$(".slimgs").animate({backgroundPosition: '-681px 0px'});
});
$(".sle3").click(function() {
$(".slimgs").animate({backgroundPosition: '-454px 0px'});
});
});
</script>
I mean after 5 seconds of page load this first function runs
$(".sle1").click(function() {
$(".slimgs").animate({backgroundPosition: '-908px 0px'});
});
then after 5 second the .sle2 and when it reachs the .sle3 (last function) after 5 seconds it should go back and run the first function again (a loop)
i tried putting ", 5000)" after each function but it didn't work
any help is appreciated
Use window.setInterval to execute a function every 5 seconds.
To cycle through those three functions, you could store all of them in an array and set i every time to the function that should be called next.
var i = 0;
var functions = [
function() {
// instead of copying that code, you could also do
// $(".sle1").click() - or you can just use functions[0]
// as argument when assigning the click listener.
$(".slimgs").animate({backgroundPosition: '-908px 0px'});
i = 1;
},
function() {
// second animation here
i = 2
},
function() {
// third animation here
i = 0
}
];
window.setInterval(function () {
functions[i]();
}, 5000);
[Edit]: no more ring-counter as that wouldn't work with the clicking.
For future reference: If you don't need the clicking to interfere with the automatic switching and want to archive something similar with only automatic cycling, get rid of th i= statements in the functions and instead insert i++; i%= functions.length after functions[i]();.
This should work, altough there are more ellegant ways to do it
$(window).load(function(){
$(".sle1").click(function() {
$(".slimgs").animate({backgroundPosition: '-908px 0px'});
window.setTimeout(function() {
$(".sle2").click();
},5000);
});
$(".sle2").click(function() {
$(".slimgs").animate({backgroundPosition: '-681px 0px'});
window.setTimeout(function() {
$(".sle3").click();
},5000);
});
$(".sle3").click(function() {
$(".slimgs").animate({backgroundPosition: '-454px 0px'});
window.setTimeout(function() {
$(".sle1").click();
},5000);
});
window.setTimeout(function() {
$(".sle1").click();
},5000);
});
setTimeout(
function() {
$(".sle1").trigger('click');
setInterval(
function() {
$(".sle1").trigger('click');
},
15000
);
},
5000
);
setTimeout(
function() {
$(".sle2").trigger('click');
setInterval(
function() {
$(".sle2").trigger('click');
},
15000
);
},
10000
);
setTimeout(
function() {
$(".sle3").trigger('click');
setInterval(
function() {
$(".sle3").trigger('click');
},
15000
);
},
15000
);
In case you're willing to improve your code, making it more concise, you could try the following, using window.setInterval:
function changeBackground(interval, frames) {
var int = 1;
function changer() {
document.body.id = "b" + int;
int++;
if (int === frames) {
int = 1;
}
}
var swap = window.setInterval(changer, interval);
}
changeBackground(2000, 10); //milliseconds, frames
Example online
Talking about your example, it's harder to tell as it's not very clear.
Try adding .stop() and duration for your .animate() effects:
$(window).load(function(){
$(".sle1").click(function() {
$(".slimgs").stop().animate({backgroundPosition: '-908px 0px'}, 5000);
});
$(".sle2").click(function() {
$(".slimgs").stop().animate({backgroundPosition: '-681px 0px'}, 5000;
});
$(".sle3").click(function() {
$(".slimgs").stop().animate({backgroundPosition: '-454px 0px'}, 5000);
});
});
.stop() - The jQuery .stop() method is used to stop animations or effects before it is finished.
I'd like to structure my JQuery to fade in each individual item at a time. Here's an example of the behavior, and here's the JQuery I have so far:
$('li').css('display', 'none') .delay(1000).fadeIn(800)
This probably not the best solution but it should work:
$('li').each(function(i){
var el = this;
setTimeout(function(){
$(el).fadeIn(800);
},800*i)
});
Just for fun, a recursive version:
function animateLi(i){
$('li').eq(i).fadeIn(800);
if ($('li').eq(i+1).length>0)
{
setTimeout(function(){animateLi(i+1)},800);
}
}
animateLi(0);
Maybe something like this:
var delay = 500, t = 0;
$("li").css('display', 'none').each(function(){
t += delay;
var $li = $(this);
setTimeout(function(){
$li.fadeIn();
},t);
});
Loop through the li, and use setTimeout to queue the animation for that li.
$('li').each(function () {
var li = this;
animateLi = function () {
li.fadeIn(800);
}
setTimeout(animateLi, timeout);
timeout += 100;
});
A slight variation on Ivans method
$(function() {
$('ul li:hidden').each(function(idx) {
setTimeout(function(el) {
el.fadeIn();
}, idx* 1000, $(this));
});
});
And a recursive function using fadeIn callback function instead of setTimeout
function DisplayOneByOne(){
$('ul li:hidden:first').fadeIn('2000', DisplayOneByOne);
}
Here is how you do it:
var delay = 200, t = 0;
$("li").css('display', 'none').each(function(){
t += delay;
var $li = $(this);
setTimeout(function(){
$li.fadeIn(1900);
},t);
});
There is another way to fade in elements after each other:
$.fn.fadeInNext = function(delay) {
return $(this).fadeIn(delay,function() {
$(this).next().fadeInNext();
});
};
$('li').hide().first().fadeInNext(1000);