Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. I want the ball_1 shows up first, and after 1 sec, ball_1 disappears. Next, ball_2 shows up and after 1 sec it disappears; same logic goes with 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>
like image 943
vkosyj Avatar asked Nov 20 '25 08:11

vkosyj


2 Answers

In general never modify an array when iterating using a for loop. The shift method will remove the first item from the array thus modifying it's length. Instead do this:

$(document).ready(function() {
  var notes = ['ball_1','ball_2','ball_3'];
  var i; // You were declaring "i" in global namespace before.  Don't do that.
  for(i = 0; i < notes.length; i++){
    var note = notes[i];
    $('#' + note).addClass('shown');
      setTimeout(function() {
        $('#' + note).removeClass('shown');
      },1000);
    }
});

Also you will see from my note that you were defining "i" in the global namespace. It is never good to do that so always make sure to define your variables at the beginning of the function block if using "var".

EDIT: missed a semicolon

EDIT2: completely missed that i needed to change up the loop condition.

like image 62
Adrian Avatar answered Nov 22 '25 23:11

Adrian


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>
like image 44
kukkuz Avatar answered Nov 22 '25 21:11

kukkuz