0

So I have this JS array variable with string values. This generates quotes at each button click. I noticed that after going through all quotes, there's one last click that outputs nothing. So I have to click the button a second time to generate quotes again. Any idea as if it's possible to solve this?

Much thanks

    <div id="enQuoteDisplay">
        <!--English quotes display here-->
    </div>

    <div align="left">
    <button onclick="newQuoteEn()">Next</button>
    </div>

    <script src="translator.js"></script>
#enQuoteDisplay {
    position: absolute;
    top: 400%;
    left: 5%;
    font-size: 30px;
}

button {
    position: absolute; 
    left: 5%;
    top: 1000%;
}
var quotesEn = [
"Hello, how are you?",
"I love you.",
"When does the bus come?",
"Where is the nearest market?",
"What time is it?",
"I don't/didn't understand.",
"I need/want to go home.",
"Dinner was delicious.",
"Congratulations!",
"Happy New Year!",
"I am cold.",
"The battery is dead.",
"We are going to the beach.",
"Let's dance!",
"I sent you an email.",
"You look good."
]

function newQuoteEn() {
    var randomNumber = Math.floor(Math.random() * (quotesEn.length));
    document.getElementById('enQuoteDisplay').innerHTML = quotesEn[randomNumber];
}

One quote at each button click with no interruption.

Akrion
  • 18,117
  • 1
  • 34
  • 54
Lili
  • 333
  • 4
  • 23
  • I don't see the behavior you described. Clicking on the button always shows a quote. What I have seen is that the quote may not change if the same number is generated. Is that what you are talking about? – Ace Jun 20 '19 at 19:10

2 Answers2

1

After looking at this issue by creating a codepen I realized that the randomize button is actually repeating elements in the array and that's why an extra click is needed to get to the next quote. Math.random() does not protect from repeating numbers. You can now see this by continuing to press the button and observing that the same number is used.

Take a look at this answer to see how you can avoid repeating indexes.

1

You are generating random numbers but in your case you want to generate random and unique numbers in a specified range. So you need something like this:

let uniqueRandomGenerator = n => {
  let set = new Set()  // use Set to remove any duplicates as you keep adding #
  while (set.size < n) set.add(Math.floor(Math.random() * n)) // keep adding #
  return Array.from(set) // return an array from the Set
}

Which guarantees you would not have duplicate "random" numbers generated in the specified range (which is assumed to be 0 to n). With being said your code would look something among these lines:

var quotesEn = [ "Hello, how are you?", "I love you.", "When does the bus come?", "Where is the nearest market?", "What time is it?", "I don't/didn't understand.", "I need/want to go home.", "Dinner was delicious.", "Congratulations!", "Happy New Year!", "I am cold.", "The battery is dead.", "We are going to the beach.", "Let's dance!", "I sent you an email.", "You look good." ]

let uniqueRandomGenerator = n => {
  let set = new Set()
  while (set.size < n) set.add(Math.floor(Math.random() * n))
  return Array.from(set)
}

let randomQuotes = uniqueRandomGenerator(quotesEn.length), last = 0

function newQuoteEn() {
  document.getElementById('enQuoteDisplay').innerHTML = quotesEn[randomQuotes[last]];
  last = last == randomQuotes.length - 1 ? 0 : last + 1
}
<div id="enQuoteDisplay">
  <!--English quotes display here-->
</div>

<div align="left">
  <button onclick="newQuoteEn()">Next</button>
</div>

<script src="translator.js"></script>

As you can see now there is no double click needed since there never is a case where you have same index twice etc.

A simpler approach would be to use a sort with Math.random via which to randomize your initial array:

var quotesEn = [ "Hello, how are you?", "I love you.", "When does the bus come?", "Where is the nearest market?", "What time is it?", "I don't/didn't understand.", "I need/want to go home.", "Dinner was delicious.", "Congratulations!", "Happy New Year!", "I am cold.", "The battery is dead.", "We are going to the beach.", "Let's dance!", "I sent you an email.", "You look good." ]

let randomizeValues = arr => arr.sort((a, b) => 0.5 - Math.random());

let randomQuotes = randomizeValues(quotesEn), last = 0

function newQuoteEn() {
  document.getElementById('enQuoteDisplay').innerHTML = randomQuotes[last];
  last = last == randomQuotes.length - 1 ? 0 : last + 1
}
<div id="enQuoteDisplay">
  <!--English quotes display here-->
</div>

<div align="left">
  <button onclick="newQuoteEn()">Next</button>
</div>

<script src="translator.js"></script>
Akrion
  • 18,117
  • 1
  • 34
  • 54