vkosyj vkosyj - 19 days ago 8
Javascript Question

try to setTimeout to show and hide the balls

I tried to write a program to practice my js skills. There are 3 balls and they are hidden at first. Then the ball_1 shows up and hides after 1 second; ball_2 then shows up and hides after another 1 second; same logic goes with the ball_3. When I run my code, the first two balls does not hide. I am not sure what is going wrong. The code below are the html, css, and js code that i wrote. Hope someone could help me out. Thank you in advance.



$(document).ready(function() {
var notes = ['ball_1', 'ball_2', 'ball_3'];
for (i = notes.length; i > 0; i--) {
var note = notes.shift();
$('#' + note).addClass('shown');
setTimeout(function() {
$('#' + note).removeClass('shown');
}, 1000);
}
});

#ball_1 {
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2 {
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3 {
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1,
#ball_2,
#ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>

<div id="ball">
<div id="ball_1" class="not_shown"></div>
<div id="ball_2" class="not_shown"></div>
<div id="ball_3" class="not_shown"></div>
</div>




Answer

You are looking for an asnychronous play of events - first ball_1 shows up for 1 sec and after that ball_2 shows up for 1 sec and so forth.

Something like this won't work:

    for( var i = 0; i < notes.length; i++){
        $('#' + notes[i]).addClass('shown');
        setTimeout(function() {
            $('#' + notes[i]).removeClass('shown');
        },1000);
    }

because the timeouts will be registered one after the other in quick succession and all the balls will show up and hide in little over one second.

So you can create a callback and set the timeout for the next ball only after the previous ball has been shown fully for 1 sec - see demo below:

$(document).ready(function() {
  var notes = ['ball_1', 'ball_2', 'ball_3'];
  hideBall(notes,0);
});

function hideBall(notes,i) {
  $('#' + notes[i]).addClass('shown');
  hide(function() {
    if(++i < notes.length) {
      hideBall(notes,i);
    } 
  }, notes[i]);
}

function hide(callback, note) {
   setTimeout(function() {
      $('#' + note).removeClass('shown');
      callback();
   }, 1000);
}
#ball_1 {
  width: 10px;
  height: 10px;
  background: #000000;
  border: 2px solid #ccc;
  border-radius: 50%;
}
#ball_2 {
  width: 10px;
  height: 10px;
  background: #0000FF;
  border: 2px solid #ccc;
  border-radius: 50%;
}
#ball_3 {
  width: 10px;
  height: 10px;
  background: #7FFF00;
  border: 2px solid #ccc;
  border-radius: 50%;
}
#ball_1,
#ball_2,
#ball_3 {
  width: 10px;
  height: 10px;
  border: 2px solid #ccc;
  border-radius: 50%;
}
.not_shown {
  display: none;
}
.shown {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="ball">
  <div id="ball_1" class="not_shown"></div>
  <div id="ball_2" class="not_shown"></div>
  <div id="ball_3" class="not_shown"></div>
</div>