Reputation: 79
I have a simple function which change opacity of divs every x seconds.
When I click on "pause button", this one make a pause in this loop, and get the color of the current div. When I click a second time on this button, the loop restart to play after a setTimeout
.
My problem is that when I multi click (fast) on button, there is a bug in the loop.
My condition doesn't work.
Is there a solution to stop effect of click during setTimeout
with stopPropagation
or e.preventDefault
or something else?
var j = 0;
var myElements = document.querySelectorAll('.div_child');
var myButton = document.querySelector('.my_button');
var colorArray = []
for (let i = 0; i < myElements.length; i++) {
let currentColor = getComputedStyle(myElements[i]).backgroundColor;
colorArray[i] = currentColor;
}
function my_fonction() {
myElements[j].style.opacity = 1;
for (let k = 0; k < myElements.length; k++) {
if (k != j) {
myElements[k].style.opacity = 0;
}
}
j++;
if (j == myElements.length) {
j = 0
}
playForbidden = false;
}
function setIntervalAndExecuteFn(fn, t) {
fn();
return (setInterval(fn, t));
}
var myIndice = j;
var myIntervalId = setIntervalAndExecuteFn(my_fonction, 1000);
var play = true;
var playForbidden = false;
myButton.addEventListener('click', function() {
if (playForbidden == false) {
if (play == true) {
play = false;
clearInterval(myIntervalId);
if (j == 0) {
myIndice = myElements.length - 1;
} else {
myIndice = j - 1;
}
myButton.style.backgroundColor = colorArray[myIndice]
} else {
play = true;
myButton.style.backgroundColor = 'transparent';
setTimeout(function() {
myIntervalId = setIntervalAndExecuteFn(my_fonction, 1000);
}, 500);
}
playForbidden == true;
} else {
return;
}
});
.div_parent {
position: relative;
width: 500px;
height: 300px;
border: 1px solid black;
}
.my_button {
width: 300px;
height: 100px;
border: 1px solid black;
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
font-size: 20px;
padding: 20px;
color: black;
}
.div_child {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 500px;
height: 300px;
}
.div_child_one {
opacity: 0;
background-color: red;
}
.div_child_two {
opacity: 0;
background-color: green;
}
.div_child_three {
opacity: 0;
background-color: violet;
}
.div_child_four {
opacity: 0;
background-color: rgb(104, 104, 104);
}
<div class="div_parent">
<div class="div_child div_child_one"></div>
<div class="div_child div_child_two"></div>
<div class="div_child div_child_three"></div>
<div class="div_child div_child_four"></div>
</div>
<div class="my_button">PAUSE BUTTON</div>
Upvotes: 1
Views: 623
Reputation: 2002
The problem in your code is the setTimeout
function. When you execute your setTimeout
, what you are saying is "Start the interval in 0.5 seconds". But the problem is that this command is not stopped if you click on pause again really fast (within 0.5 seconds). What you can do is clearing the timeout at every click of the button. This way, you can cancel the command "Start the interval in 0.5 seconds".
You can see a working snippet of what I mean here below:
var j = 0;
var myElements = document.querySelectorAll('.div_child');
var myButton = document.querySelector('.my_button');
var colorArray = []
for(let i=0; i<myElements.length; i++){
let currentColor = getComputedStyle(myElements[i]).backgroundColor;
colorArray[i] = currentColor;
}
function my_fonction(){
myElements[j].style.opacity = 1;
for(let k = 0; k < myElements.length; k++){
if(k!=j){
myElements[k].style.opacity = 0;
}
}
j++;
if(j == myElements.length){ j = 0}
playForbidden = false;
}
function setIntervalAndExecuteFn(fn, t){
fn();
return(setInterval(fn, t));
}
var myIndice = j;
var myIntervalId = setIntervalAndExecuteFn(my_fonction, 1000);
var myTimeoutId;
var play = true;
var playForbidden = false;
myButton.addEventListener('click', function(){
clearTimeout(myTimeoutId);
if(playForbidden == false){
if(play == true){
play = false;
clearInterval(myIntervalId);
if(j == 0){
myIndice = myElements.length-1;
}else{
myIndice = j-1;
}
myButton.style.backgroundColor = colorArray[myIndice]
}else{
play = true;
myButton.style.backgroundColor = 'transparent';
myTimeoutId = setTimeout(function() {
myIntervalId = setIntervalAndExecuteFn(my_fonction, 1000);
}, 500);
}
playForbidden == true;
}else{
return;
}
});
.div_parent{
position: relative;
width: 500px;
height: 300px;
border: 1px solid black;
}
.my_button{
width: 300px;
height: 100px;
border: 1px solid black;
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
font-size: 20px;
padding: 20px;
color: black;
}
.div_child{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
width: 500px;
height: 300px;
}
.div_child_one{
opacity: 0;
background-color: red;
}
.div_child_two{
opacity: 0;
background-color: green;
}
.div_child_three{
opacity: 0;
background-color: violet;
}
.div_child_four{
opacity: 0;
background-color: rgb(104, 104, 104);
}
<div class="div_parent">
<div class="div_child div_child_one"></div>
<div class="div_child div_child_two"></div>
<div class="div_child div_child_three"></div>
<div class="div_child div_child_four"></div>
</div>
<div class="my_button">PAUSE BUTTON</div>
Upvotes: 1