I have four divs that I want to show one after the other by hiding the previous one. I use a counter with modulo operator to select the divs for displaying. So I require to execute my functions in the following way.
function show_div(counter)
***after delay***
function hide_div(counter)
***after delay***
function show_div(counter+1)
***after delay***
function hide_div(counter+1)
***after delay***
function show_div(counter+2)
How can I achieve this?
A short solution:
show_div(0);
function show_div(counter) {
// code here
setTimeout(hide_div, 2000, counter);
}
function hide_div(counter) {
// code here
setTimeout(show_div, 2000, (counter + 1) % 4);
}
You could use setInterval():
var counter = 0;
var divVisible = false;
function toggleDiv() {
if (divVisible) {
hide_div(counter);
counter = (counter + 1) % 4;
divVisible = false;
} else {
show_div(counter);
divVisible = true;
}
}
window.setInterval(toggleDiv, 1000);
First time it is run, the counter is 0 and divVisible is false, so it will show the div and flip the boolean divVisible. Next time (after 1000ms), it will hide the div, increase counter, then flip the boolean divVisible again. And so it will continue forever for your 4 divs.
You can use setTimeout.
setTimeout(function(){show_div(counter)},delay)
But be careful. If using a while loop, you need to a separate function that creates the timeout, due to variable scope.
function timeout(func, args, delay){
setTimeout(function(){func(args)}, delay);
}
var counter = 0
while(1){
timeout(show_div, counter, counter*500);
timeout(hide_div, counter, counter*500+500);
counter++;
}
An alternative solution would be some sort of chaining function:
function show(delay, counter){
setTimeout(function(){
show_div(counter);
},delay);
setTimeout(function(){
hide_div(counter);
show(delay, counter+1);
},delay*2);
}
This uses setTimeout to call other setTimeouts when it is finished. This will use less memory than the other solution.
You can do it this way:
var divs = $('.someClass'),
numOfDivs = divs.length,
delay = 500,
index = -1;
showNextDiv();
function showNextDiv(){
index = (index == numOfDivs-1) ? 0 : ++index;
divs.eq(index).show();
setTimeout(hideDiv, delay);
}
function hideDiv(){
divs.eq(index).hide();
setTimeout(showNextDiv, delay);
}
.someClass{ display: none }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div class="someClass">1</div>
<div class="someClass">2</div>
<div class="someClass">3</div>
<div class="someClass">4</div>
Related
let timer = document.querySelector("#timer");
var counter = 3;
function myFn() {
counter--
if (counter === -1) {
counter = 3
}
timer.innerText = counter
}
btn.onclick = function() {
text.innerHTML += 'clicked' + '<br>'
}
var myTimer = setInterval(myFn, 1000);
<div id="timer"></div>
<button id="btn">Button</button>
<div id="text"></div>
I'm trying with this small code to read the div#timer every second and check for a click condition in console.log() F12. It gives me different error in every way I try to do it.
let timer = document.querySelector("#timer");
let btn = document.querySelector("#btn");
setInterval(() => {
console.log(timer.textContent)
if (timer.textContent === '0') {
btn.click()
}
}, 1000);
Consider the following jQuery example.
$(function() {
var timer = 0;
var counter = 3;
var timeObj = $("#timer");
var btnObj = $("#btn");
var txtObj = $("#text");
var interval;
function myFn() {
if (--counter >= 0) {
txtObj.append("Clicked<br />");
} else {
clearInterval(interval);
}
}
interval = setInterval(function() {
timeObj.html(++timer);
}, 1000);
btnObj.click(myFn);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="timer">0</div>
<button id="btn">Button</button>
<div id="text"></div>
You will want to use setInterval() and not setTimeout().
The setInterval() method, offered on the Window and Worker interfaces, repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.
This method returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval().
See more: https://developer.mozilla.org/en-US/docs/Web/API/setInterval
Using the -- and ++ before the variable will also apply the change before it is used.
The decrement operator (--) decrements (subtracts one from) its operand and returns the value before or after the decrement, depending on where the operator is placed.
Adjusting the logic here can also ensure that the button click does allow the user to keep performing actions.
Pretty much what the title says. When the countdown starts, it goes "3", "2", and then executes the function that's supposed to launch when the timer hits zero, skipping the display of the number "1".
The actual timer output is displayed in a separate div element, you'll see in my code below.
I've seen some answers on here about faulty countdown clocks but a lot of them use jQuery whereas I'm just using vanilla JavaScript and the use of libraries is still a bit confusing to me.
var count = 3;
function startTimer() {
var timer = setInterval(function() {startTimer(count);}, 1000);
if(count === 0){
clearInterval(timer);
ranCoord(); //function to run when timer hits zero.
} else {
document.getElementById("target").innerText = count;
count--;
}
}
<div class="start">
<img src="images/start-default.png" onclick="startTimer();" alt="Click Here"/>
</div>
<div id="target"></div>
I noticed that if I include the var count=3 variable inside the startTimer(); function, the countdown doesn't work either, it just stays at number 3. Does anyone know why this is?
Also, if I include the var timer = setInterval(function() {startTimer(count);}, 1000); outside the function then it runs automatically on page load, which is not what I want. I want the countdown to start on the click of a button, and found that this worked when placed inside the function.
Thanks in advance!
If the count variable is declared inside of the startTimer function, then each iteration of the timer will have its count value overwritten and so will not count down.
setInterval repeats its function indefinitely, so only needs to be called once outside of the loop, as opposed to setTimeout which only runs once and needs to be called each iteration.
An alternative approach using setTimeout would be:
function startTimer(count) {
if (count <= 0) {
ranCoord();
} else {
document.getElementById("target").innerText = count;
setTimeout(function() { startTimer(--count); }, 1000);
}
}
This version also avoids the use of a global variable, by passing the remaining count in as a parameter.
You dont need to call startTimer in the setInterval
var count = 3;
function startTimer() {
var timer = setInterval(function() {
if (count === 0) {
clearInterval(timer);
ranCoord(); //function to run when timer hits zero.
} else {
document.getElementById("target").innerText = count;
count--;
}
}, 1000);
}
function ranCoord() {
console.log("Timer hit 0")
}
img {
height: 100px;
width: 100px;
outline: 1px solid blue;
}
<div class="start">
<img src="images/start-default.png" onclick="startTimer();" />
</div>
<div id="target"></div>
I think you not need to add more code you just need to simplify it like that
var count = 3;
function startTimer() {
const timer = setInterval(function () {
document.getElementById("target").innerText = count;
count--;
if (count <= 0) {
clearInterval(timer);
ranCoord();
}
}, 1000)
}
I have 31 images and I want to display them one after another as the background of a div. I only want it to change when the user hovers over the div. My problem right now is that it just flips through all the images really fast. I am attempting to use setTimeout, but it isn't working. How can I make the delay work?
The name of the div is About_Me_Block and the images are called frame1.gif,frame2.gif ...etc
Here is my code:
function changeImg(counter) {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
}
$(document).ready(function() {
var hoverAnimate = []
"use strict";
$('#About_Me_Block').mouseenter(function() {
hoverAnimate[0] = true;
var counter = 0;
while (hoverAnimate[0]) {
console.log(counter);
setTimeout(changeImg(counter), 1000);
counter++;
if (counter === 32)
hoverAnimate[0] = false;
}
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate[0] = false;
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
setTimeout doesn't wait for the function to end, it works lile threading in other languages.
To achieve a what you want, you need to call setTimeout from the changeImg function.
var counter = 0;
$(document).ready(function() {
var hoverAnimate = []
"use strict";
$('#About_Me_Block').mouseenter(function() {
hoverAnimate[0] = true;
counter = 0;
changeImg();
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate[0] = false;
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
function changeImg() {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
counter++;
if (counter < 32 && hoverAnimate[0]) {
setTimeout(changeImg, 1000);
} else {
hoverAnimate[0] = false;
}
}
the reason they happen all at once is because while statement doesn't have delay, so all setTimeout will be set up at the same time, thus, calling changeImg all at once.
To solve this problem, you can replace setTimeout with setInterval. Instead of using while, you can just call setInterval like
var counter = 0;
var myTimer = setInterval(changeImg, 1000);
and update counter inside changeImg every time it gets called. After looping, don't forget to
clearInterval(myTimer)
It seems you need to read up on how setTimeout works. It essentially places a reminder to run a function after a given amount of milliseconds have passed. So, when you do setTimeout(changImg(counter), 1000) you are calling changImg(counter) which returns undefined. Therein producing this setTimeout(undefined, 1000) which is why it flips really fast.
So, you can use bind to allow the function to be called later with that parameter built in. Also, make sure you remove the reminders once done with clearTimeout.
function changeImg(counter) {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
}
$(document).ready(function() {
var hoverAnimate = false, id;
function loop(counter) {
if(hoverAnimate || counter < 32) {
changeImg(counter);
id = setTimeout(loop.bind(this, counter++), 1000);
}
}
$('#About_Me_Block').mouseenter(function() {
hoverAnimate = true;
id = setTimeout(loop.bind(this, 0), 1000);
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate = false;
// Don't want a reminder for a random counter to wake up.
clearTimeout(id);
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
Two methods for timers - setTimeout and SetInterval (single / repeating)
// setInterval is also in milliseconds
var intervalHandle = setInterval(<yourFuncToChangeImage>,5000);
//this handle loop and make example loop stop
yourelement.yourEvent = function() {
clearInterval(intervalHandle);
};
There are other questions with almost the same title as this but they don't seem to answer my question.
I am trying to make a simple javascript function that uses jQuery to fade div blocks in and out one after the other, and goes back to the first div once it get's to the end. This should continue while the user is on the page, much like a slideshow.
There are 5 'slides' or divs to be shown and hidden in sequence. They have the classes 'content1', 'content2', 'content3' etc.
$(document).ready(function() {
var slide = 1;
nextSlide(slide);
function nextSlide(slide) {
$('.content' + slide.toString()).fadeTo(2000, 1.0).delay(5000).fadeTo(2000, 0.0).delay(2000);
if(slide > 5) {
slide = 1;
} else {
slide++;
}
nextSlide(slide);
};
});
This does not fade each div in and out in sequence, what it actually does is fade all of the slides in and out simultaneously.
How do I get it to reference each slides class in turn and then loop back to the first slide?
Many thanks.
Your function will recurse immediately, dispatching all of the animation requests around the same time.
To stagger them, you should recurse with a timeout:
$(document).ready(function() {
var slide = 1;
nextSlide();
function nextSlide() {
$('.content' + slide.toString()).fadeTo(2000, 1.0).delay(5000).fadeTo(2000, 0.0).delay(2000);
if(slide > 5) {
slide = 1;
} else {
slide++;
}
setTimeout(nextSlide, 2000); // second param is delay in ms
};
});
This will cause the next call to occur after 2000ms. Thanks to closure, your slide variable should be captured and will persist its value between calls.
No need for a timeout. Simply call the next iteration as a callback of the last fadeTo method:
$(document).ready(function() {
var slide = 1;
nextSlide(slide);
function nextSlide(slide) {
$('.content' + slide.toString())
.fadeTo(2000, 1.0)
.delay(5000)
.fadeTo(2000, 0.0, function(){
if(slide > 5) {
slide = 1;
} else {
slide++;
}
nextSlide(slide);
});
};
});
http://jsfiddle.net/3L09b505/
I have a table with checkbox in each row. When the checkboxes are checked, the function will loop through to update the status of each row.
here is my working fiddle: http://jsfiddle.net/qJdaA/2/
I used setInterval() to loop the function. as the table is dynamic, i do not know how long the list is going to be. so i set the period as a variable index*4000 as follow:
$('#monitor').click(function () {
$('#monitor').attr('disabled','true');
bigloop=setInterval(function () {
var checked = $('#status_table tr [id^="monitor_"]:checked');
if (checked.index()==-1){
$('#monitor').attr('disabled','true');
}else{
(function loop(i) {
$('#monitor').removeAttr('disabled');
//monitor element at index i
monitoring($(checked[i]).parents('tr'));
//delay
setTimeout(function () {
//when incremented i is less than the number of rows, call loop for next index
if (++i < checked.length) loop(i);
}, 3000);
}(0)); //start with 0
}
}, index*4000);
however, the problem is that it will wait for the first loop to get over without doing anything. let say i have 10 items in the list, then it will wait for 40 seconds before doing its task. How can i eliminate that problem?
Then if out of the 10 items, only 1 row is checked, i have to wait 40 seconds to update just that one row, which is inefficient.
I have tried to set var clength = checked.length and use it to multiply with 4000. but it won't work. Why and how should i do it?
Example how to remove interval
<script>
var myVar=setInterval(function(){myTimer()},1000);
function myTimer()
{
// do things here
}
function myStopFunction()
{
// clear interval here
clearInterval(myVar);
}
</script>
Or
<script>
var myVar=setInterval(myTimer,1000);
function myTimer()
{
// do things here
}
function myStopFunction()
{
// clear interval here
clearInterval(myVar);
}
</script>