jQuery animation function timing - javascript

Feel like I'm overlooking the obvious here...
I've got several vars set up like so:
var productOne = function () {
$(".product2").fadeIn(200).animate({"right": "+=75px"}, 500, "easeOutElastic").delay(3000).fadeOut(200).css("right", "0");
$(".product-text.two").fadeIn(200).delay(3500).fadeOut(200);
}
var productTwo = function () {
$(".product2").fadeIn(200).animate({"right": "+=75px"}, 500, "easeOutElastic").delay(3000).fadeOut(200).css("right", "0");
$(".product-text.two").fadeIn(200).delay(3500).fadeOut(200);
}
etc...Then I want to fire them in order, like so, and loop back to the first:
window.setInterval(function() {
$(productTwo);
$(productThree);
//and so on
}, 5000);
but they all fire at the same time. How can I put a specific number of ms between each function call?

You need to fire each one off from the end of the previous one. So productOne would setTimeout to call productTwo, and productRwo would setTimeout to call productThree, and productThree to call productOne.
ETA Example:
var productOne = function () {
$(".product2").fadeIn(200).animate({"right": "+=75px"}, 500, "easeOutElastic").delay(3000).fadeOut(200).css("right", "0");
$(".product-text.two").fadeIn(200).delay(3500).fadeOut(200);
setTimeout(productTwo, 5000);
}
var productTwo = function () {
$(".product2").fadeIn(200).animate({"right": "+=75px"}, 500, "easeOutElastic").delay(3000).fadeOut(200).css("right", "0");
$(".product-text.two").fadeIn(200).delay(3500).fadeOut(200);
setTimeout(productThree, 5000);
}

If you want animations to fire in order then you should call the next one from the complete callback function. Example:
$(".product2").fadeIn(200).animate(
{"right": "+=75px"},
500,
"easeOutElastic",
function() {
// call your next animation here. Add delays here if you want...
}).delay(3000).fadeOut(200).css("right", "0");

// initial product count
var product = 1;
// function which select which animation to call
function fire_product( product ) {
switch ( product ) {
case 1:
$(productTwo);
break;
case 2:
$(productTwo);
break;
case 3:
$(productThree);
break;
}
// go to next product next time
product++;
// reset to first product when we reach the last product
if (product > 3) product = 1;
// self-call this function again
setTimeout( function() {
fire_product( product );
}, 5000);
}
// call the function for the first time with desired parameter
fire_product( 1 );

Related

Trigger second click function only when first click function is finish

here is my situation,
I'm triggering some functions on click like this:
on first click, trigger function A.
On second click, trigger function B,
On third click, trigger function C,
etc
etc
All the click are on the same div ( body).
However, I would like the second click to trigger only one the first function is finish. ( all the functions are some animations)
Then the thrid click, to trigger only when the second function is finish, etc, etc.
I'm using the code below to have multi click:
var clickCounter = 0;
$("#body").click(function() {
clickCounter++;
switch (clickCounter) {
case 1:
showpanel();
setTimeout(function() {
hidepanel();
}, 1820);
setTimeout(function() {
movetotop();
}, 1820);
setTimeout(function() {
movetotopheight();
}, 1820);
setTimeout(function() {
nav();
}, 1820);
break;
case 2:
centralbutton();
break;
case 3:
footerarea();
break;
case 4:
side();
break;
}
});
Any pointers / help to achieve this will be really fantastic !!
Thanks so much
You can do something like this by updating the counter in the functions when the function is done, while running set counter to 0 so no action will be triggered.
<div id="body">
<h1>Demo</h1>
</div>
var clickCounter = 1;
function showpanel() {
//Set counter 0 so no action is started
clickCounter = 0;
//Do animation and stuff and after set counter to the right step.
setTimeout(function(){
clickCounter = 2;
}, 5000);
}
function centralbutton() {
//After 5 seconds this function can be used
alert('STEP 2');
}
$("#body").click(function() {
console.log('test');
switch (clickCounter){
case 1:
showpanel();
break;
case 2:
centralbutton();
break;
case 3:
footerarea();
break;
case 4:
side();
break;
}
});
https://jsfiddle.net/3u177cs3/
In each function you could attach a specific CSS class to the div, e.g. named by the last function executed. For example at the end of function A append the class "aFinished". Then when performing a click check for the existing classes on the div and by that pick the right function to be executed.
This way you would not even need a clickcounter variable.
var clickCounter = 1;
function showpanel() {
console.log("pan")
//Set counter 0 so no action is started
clickCounter = 0;
//Do animation and stuff and after set counter to the right step.
setTimeout(function(){
clickCounter = 2;
}, 5000);
$("#body").addClass("aFinished")
}
function centralbutton() {
console.log("cen")
//After 5 seconds this function can be used
alert('STEP 2');
$("#body").removeClass("aFinished")
$("#body").addClass("bFinished")
}
$("#body").click(function() {
console.log('click');
if ($("#body").hasClass("aFinished")) {
centralbutton();
}
else if ($("#body").hasClass("bFinished")) {
footerarea();
}
else if ($("#body").hasClass("cFinished")) {
side();
}
else {
showpanel();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="body">
<h1>Demo</h1>
</div>

hide and show div every x time AngularJS

I'm having troubles to hide and show a div that works as an alert to my application.
Currently I'm using the $interval for make this a permanent hide and show action, but the result I'm expecting is that the DIV remains visible X time and then hide the same X time.
Here is how I0'm doing it now:
function showNotification(idNotification) {
$('[id*=noti_]').addClass('dis_none');
$('#noti_' + idNotification).removeClass('dis_none');
}
function hideNotification() {
// $('#noti_' + idNotification).addClass('dis_none');
$('[id*=noti_]').addClass('dis_none');
}
function checkCalendar() {
var tomorrow = moment().add(1, "d").format("YYYY-MM-DD");
WebApiFactory.GetShiftPeriod("BodyShop", "2017-11-07").then(function (data) {
// WebApiFactory.GetShiftPeriod("BodyShop", tomorrow).then(function (data) {
if(data[0].TargetPlantValue === 0){
showNotification("alert");
}
});
}
function notifications(type, time) {
switch (type) {
case "calendar":
// checkCalendar();
$interval(function () {
checkCalendar();
console.log("Active");
},time * 1000);
$interval(function () {
hideNotification();
console.log("Hide");
}, time * 1001);
break;
}
}
Thanks for the help.
Not sure what are you trying to achieve, but if you want to show the dialog for some 'x' time, and then hide it, you shouldn't start both intervals at the same time. Just wait when the dialog is shown and then start a timer for hiding it.
For example if you need to hide the timer after a '100' ms.
function notifications(type, time) {
switch (type) {
case "calendar":
$interval(function () {
checkCalendar();
$timeout(hideNotification, 100);
}, time * 1000);
break;
}
}
Also be aware that I used a $timeout directive here. It's almost the same as $interval but will be invoked only once.
how can I make that the time that the div is shown is the same as the
time when is hide
It's a bit trickier, so let's use another algorithm.
There we just have a single $interval, but keep a current state isNotificationActive and show/hide the element according to this state.
Also be aware that I use $interval.cancel to stop a previous launched interval, if you have one.
var notificationInterval = null,
isNotificationActive = false;
function notifications(type, time) {
switch (type) {
case "calendar":
$interval.cancel(notificationInterval);
notificationInterval = $interval(updateNotificationState, time * 1000);
break;
}
}
function updateNotificationState() {
if(isNotificationActive) {
//hide the element here;
} else {
//show the element here;
}
isNotificationActive = !isNotificationActive;
}
I would do something like this ...
Make your notification element(s) "responsible" for hiding themselves, as follows :
function showNotification(idNotification, hideAfter) {
var $el = $('#noti_' + idNotification);
$timeout.cancel($el.data('timoutRef')); // kill latent auto-hide (if scheduled)
$el.removeClass('dis_none'); // show
if(hideAfter) {
// Schedule auto-hide after `hideAfter` milliseconds,
// and keep a reference to the timeout so it can be cleared.
$el.data('timoutRef', $timeout(function() {
$el.addClass('dis_none'); // hide
}), hideAfter);
}
}
Now adjust checkCalendar() and notifications()
function checkCalendar() {
WebApiFactory.GetShiftPeriod("BodyShop", "2017-11-07").then(function (data) {
if(data[0].TargetPlantValue === 0) {
// Make sure the value passed below is one half the total cycle time
showNotification("alert", 1000/2); // show immediately, hide after 1/2 second
}
});
}
function notifications(type, time) {
switch (type) {
case "calendar":
// Here, everything can be nice and simple
$interval(checkCalendar, time * 1000); // total cycle time
break;
}
}
Providing your various notification elements don't try to occupy the same real-estate on screen, you (probably) don't need to worry about hiding other notifications.
If the notification elements do try to occupy the same real-estate, you need to consider reducing their number to just one.

setInterval triggers function multiple times

EDIT: what i mean by fires multiple times, is that newjob() will fire 3 times, every 5 seconds...so in 20 seconds i'll have it 12 times triggered, instead of the 4 times that i would want. so it's triggeres multiple times every 5 seconds, instead of once every 5 seconds.
I have a function that i created using Toastr to display a message on my web application. i'm eventually going to tie it to an ajax request to an API to determine whether or not to display a message, but for now i'm just testing how it looks.
i am setting an interval, but it fires the function inside of it multiple times (usually 3).
$(document).ready(function() {
setInterval(function () {
newJob();
}, 5000);
});
i can't do setInterval( function(e) { } as e is undefined, as there is no event associated with it, on click, i've used e.stopImmediatePropagation(); to have it only fire once.
how can i stop this immediate propagation on set interval if i don't have e?
thank you.
EDIT: full code:
var newJob = function(e) {
var i = -1;
var $toastlast;
var getMessage = function () {
var msgs = ["There's a new job in the job dispatch queue", "A job pending approval has timed out"];
i++;
if (i === msgs.length) {
i = 0;
}
return msgs[i];
};
var shortCutFunction = "success"; // 'success' or 'error'
toastr.options = {
closeButton: true,
progressBar: true,
debug: false,
positionClass: 'toast-top-full-width',
onclick: null,
timeOut: "0",
extendedTimeOut: "0",
showDuration: "0",
hideDuration: "0",
showEasing: "swing",
hideEasing: "linear",
showMethod: "fadeIn",
hideMethod: "fadeOut",
};
toastr.options.onclick = function () {
window.location.href = "/dispatcher";
};
var msg = getMessage();
$("#toastrOptions").text("Command: toastr["
+ shortCutFunction
+ "](\""
+ msg
+ "\")\n\ntoastr.options = "
+ JSON.stringify(toastr.options, null, 2)
);
var $toast = toastr[shortCutFunction](msg);
};
$(document).ready(function() {
setInterval(function () {
console.log('set interval');
newJob();
}, 5000);
});
and this is my index.phtml file:
<?php
echo $this->headScript()->appendFile($this->basePath() . '/plugins/toastr/toastr.js')
echo $this->headScript()->appendFile($this->basePath().'/js/dispatchernotification.js');
?>
all i'm doing is adding the javascript of what i want running to my index.phtml file and the toastr library.
by console.loging inside interval, i get three logs.
here's a fiddle..not sure how to run it though as it's on ready
http://jsfiddle.net/efecarranza/rfvbhr1o/
setInterval will continue endlessly. I think you're looking for setTimeout.
Make sure to put your setInterval outside of $(document).ready(function() {...}). So it will be like:
<script>
$(document).ready(function() {
... some code ...
});
var myInterval;
clearInterval(myInterval);
myInterval = setInterval(function() {
... your code is here ...
}, 5000);
</script>
For some reason, if it's within $(document).ready() every time you dynamically bring the same page again it double-sets the setInterval in progression and clearInterval function doesn't help until you actually refresh the browser.
setInterval: call a function repeatedly every x milliseconds
setTimeOut: call a function after x milliseconds.
You have two options:
Clear the interval when it isn't necessary anymore:
var intervalId;
$(document).ready(function() {
intervalId = setInterval(function () {
newJob();
}, 5000);
});
// At some other point
clearInterval(intervalId);
Or, the simpler solution in your case, use setTimeout:
$(document).ready(function() {
setTimeout(function () {
newJob();
}, 5000);
});
It would help if you can add a jsfiddle with your code so we can see what's going wrong exactly. It's possible that for whatever reason the setInterval function is being called multiple times. Try adding a console.log statement at the start of that function to check if that's the case.
If it is and you can't figure out why (and neither can we without knowing your code), you could place a check at the start of the function like this:
if (typeof this.installInterval.done == "undefined") {
/*a bunch of code*/
this.installInterval.done = true
}
May be by mistake you are calling your script twice as I did!
In the code below I have called 'testLoop.js' two times.
<script src="../js/testLoop.js"></script>
<script type="text/javascript" src="../js/testLoop.js"></script>
<script type="text/javascript" src="../js/cube.js"></script>

Repeat code every x seconds but not if [insert check here]

This is a followup to this question, where I found out how to make code be repeated every x seconds. Is it possible to make an event that can change this? I.e. I have a checkbox which is meant to control whether this is repeated or not, so I figured I'd need something like this:
$(checkbox).bind("change", function() {
switch(whether if it is ticked or not) {
case [ticked]:
// Make the code repeat, while preserving the ability to stop it repeating
case [unticked]:
// Make the code stop repeating, while preserving the ability to start again
}
});
I have no idea what I could put in the cases.
You can do it by assigning your setInterval function to a variable.
var interval = setInterval(function() { }, 1000);
and then you can stop setInterval by
clearInterval(interval);
p.s.
to start your interval you need to call var interval = setInterval(function() { }, 1000); again
You can either stop and start the interval:
var timer;
function start() {
timer = window.setInterval(function(){
// do something
}, 1000);
}
function stop() {
window.clearInterval(timer);
}
start();
$(checkbox).bind("change", function() {
if ($(this).is(':checked')) {
start();
} else {
stop();
}
});
Or you can have a flag causing the interval to skip the code:
var enabled = true;
var timer = window.setInterval(function(){
if (!enabled) {
// do something
}
}, 1000);
$(checkbox).bind("change", function() {
enabled = $(this).is(':checked');
});
function fooFunc() {
$('#foo').text(+new Date());
}
var id;
var shouldBeStopped = false;
$('input').change(function() {
if (shouldBeStopped)
clearInterval(id);
else
id = setInterval(fooFunc, 200);
shouldBeStopped = !shouldBeStopped;
});​
Live DEMO

jquery combining each and setInterval on elements with shared class

I have a series of links with a class "bloglink".
They have a click event associated with them - but that is irrelevant at this point. I am trying to cycle through them and trigger the click event every X seconds. This is where I'm at:
$('a.bloglink').each(function(){
var $bl = $(this);
setInterval(function(){
$bl.trigger('click')
},2000);
})
But it just triggers the click event for all of them at once.
Any tips?
You could do something like this:
(​function Loop()​{
var arry = $("a.bloglink").get();
var traverse = function(){
$(arry.shift()).trigger('click');
if (arry.length)
setTimeout(traverse, 2000);
};
setTimeout(traverse,2000);
})();
You can see it in action here: http://jsfiddle.net/Shmiddty/B7Hpf/
To start it over again, you can just add an else case:
(​function Loop()​{
var arry = $("a.bloglink").get();
var traverse = function(){
$(arry.shift()).trigger('click');
if (arry.length)
setTimeout(traverse, 2000);
else
Loop(); // Do the whole thing again
};
setTimeout(traverse,2000);
})();
See here: http://jsfiddle.net/Shmiddty/B7Hpf/1/
Create a function that sets the timer to run your code, clears the timer, then calls itself on the next element...
function processNext($current)
{
$h = setInterval(function() {
$current.css('color', 'green');//do your business here
clearTimeout($h);
if ($current.next('a.blah').size()>0)
{
processNext($current.next('a.blah'));
}
}, 750);
}
processNext($('a.blah').eq(0));
See here: http://jsfiddle.net/skeelsave/6xqWd/2/

Categories