Gohan Garzon
Gohan Garzon

Reputation: 35

How to show and hide each item of the array in ona HTML element?

I have this array:

   let learning = [
      "HTML",
      "CSS",
      "JavaScript",
      "JQuery",
      "Git",
      "GitHub",
      "Bootstrap",
      "Sass",
      "JSon"
   ];

and want to show each of them, one by one, in an span element with id="learning-here"

I tried like this:

   for (const iterator of learning) {
      setTimeout(writeList(iterator), 1000);
   }

   function writeList(i) {
      $("#learning-here").text(i);
      console.log(i); 
   }

It seems like setTimeout doesn't work as I thought. The last item on the array is shown on the span as soon as I reload the page and the whole array is console-logged.

Also tried with my poor JQuery knowledge like this:

   $.each(learning, function(key, value) {
      setTimeout(writeList, 1000);

      function writeList() {
         $("#learning-here").text(value);
      }
      console.log(value);
   });

How could I show one by one array element on the span? What am I doing wrong on my two tries above?

Thank you.

Upvotes: 0

Views: 61

Answers (4)

Ram Segev
Ram Segev

Reputation: 2571

This is a simple function that will recursively run until it loop through all the words

let learning = [
  "HTML",
  "CSS",
  "JavaScript",
  "JQuery",
  "Git",
  "GitHub",
  "Bootstrap",
  "Sass",
  "JSon"
];

var i = 0;

function writeList() {
  $("#learning-here").text(learning[i]);
  i++;
  if (i < learning.length) {
    setTimeout(writeList, 1000);
  }
}
writeList();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="learning-here"></span>

Upvotes: 1

Nicolas
Nicolas

Reputation: 8670

the setTimeout function might not be the best choice here. I think you should use the function setInterval which run a particular callback / function at a certain interval until the interval is cleared.

let learning = [
  "HTML",
  "CSS",
  "JavaScript",
  "JQuery",
  "Git",
  "GitHub",
  "Bootstrap",
  "Sass",
  "JSon"
];

// the index to show 
let currentIndex = 0;
let learningElement = document.getElementById('learning-here');

// we create an interval variable to clear it later,
// we are also using an arrow function to have access to variable outside the function's scope.
let interval = setInterval(() => {
  // we show the string at the current index and then increment the index.
  learningElement.innerHTML = learning[currentIndex++];
  // if the index if bigger than the length of our array, we've shown every element in the array.
  if(currentIndex >= learning.length) {
    // we clear the interval so it stops.
    clearInterval(interval);
    
    // alternativaly, we could start over by setting the current index back to 0
    //currentIndex = 0;
  }
}, 1000);
<div id="learning-here"></div>

I have choosen to use pure Javascript since you said your Jquery knowledge was limited.

Upvotes: 2

Shilly
Shilly

Reputation: 8589

Since all your timeouts are 1 second, there's no time to actually see the word change. Try to multiply the timeout with the index, so that the word changes every x seconds until the last word is reached.

let learning = [
  "HTML",
  "CSS",
  "JavaScript",
  "JQuery",
  "Git",
  "GitHub",
  "Bootstrap",
  "Sass",
  "JSon"
];
learning.forEach(( word, index ) => {
  setTimeout(() => {
    document.querySelector( '#learning-here' ).innerText = word;
  }, index * 2000 );
});
<span id="learning-here"></span>

Upvotes: 1

ADyson
ADyson

Reputation: 61983

There are a few issues with your approach:

1) setTimeout requires a reference to a function, which it can execute later - whereas writeList(iterator) causes the function to be executed immediately, and then the result of that is passed to setTimeout, and since that result is not a function, it's no use.

2) You're setting all the timers off at the same time (because the loop runs all the way through instantly, it doesn't wait for timers declared within the loop to fire before looping again). Therefore they all also complete at the same time, and so you just see the results of the last one. So if you want a 1-second delay you'll need to increase the timeout in each iteration.

Here's one way you can make it work. There are probably a few different ways to achieve it, though.

let learning = [
  "HTML",
  "CSS",
  "JavaScript",
  "JQuery",
  "Git",
  "GitHub",
  "Bootstrap",
  "Sass",
  "JSon"
];

var timer = 0;
$.each(learning, function(key, value) {
  timer = timer + 1000;
  setTimeout(function() {
    writeList(value)
  }, timer);
});

function writeList(val) {
  $("#learning-here").text(val);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="learning-here"></span>

Upvotes: 1

Related Questions