Random quote generator(Problem)

I cannot understand why this code is giving error in the console when i click on new quote button 5 or 6 times
https://codepen.io/yog9/pen/pZpjqq

It’s late here and I don’t have time to look for all of the code issues, but I can say that the thing causing the program to crash is this line of code:

else if (viewQuotes.indexOf(ind) >= 0) {
    console.log("at new quote");
    newQuote(); // this right here
  }

Once you have a certain amount of quotes in the array and it comes across one that is already in there, you call the function inside of itself, which is recursion. It just keeps calling itself over and over because there is often no end condition being met. You should only be calling newQuote when the button is clicked.

So what can I do if the Quote is repeated?

Just let it repeat? What you really should consider doing is create a copy of the original array (look into how to copy an array, because doing something like var copy = arr; is not going to work), shuffle the copy (look into shuffle algorithms or how you can create somewhat of a shuffle using the .sort method and Math.random()), and then pop off a value from the copy each time the button is clicked. That value will be the quote you use.

Then, when the copied array is empty, you’ll know all quotes have been used once and it’s time to reset (copy again, shuffle again, etc.).

Since you have a finite number of quotes and the number of quotes is quite small, you are going to repeat quotes. I assume what you are trying to prevent, is the same quote being randomly selected in such a way that the same quote gets displayed two times in a row when the button is clicked two times. I believe trying to prevent that is worth doing, because if the user sees the exact same quote again, or even worse a 3rd time since your quote array is so small, the user could think something is wrong with the app.

If what I have described above is what you want to prevent, then the method suggested by @mewmew could still allow the same quote to be displayed twice in a row. Why? Because what if quote “abc” was the last in the shuffled array. Quote “abc” displays to the screen, so the shuffled array is empty (because of the pop), then you make a copy of the original array and shuffle it. It is possible, the first quote “popped” off the newly shuffled array is quote “abc”.

How to resolve? You will need to do a few things.

#1) You need to add a unique id to each array object (let’s name it id). It is easiest to just start at 1 and count up. You can assign almost any value to be a unique id, but I suggest not using any falsy value (i.e. false 0, null, undefined, blank string, or NaN), because it will make it easier for you to implement step #3 (later in this post). This id will be tracked in such a way as to prevent the same quote from being repeated back-to-back. For example, the first couple of quotes in the array would be:

  {
    //quote 0
    id: 1,
    quote: "Wilderness is not a luxury but necessity of the human spirit.",
    source: "Edward, ",
    citation: "Desert ,",
    year: 1968,
    tags: ["inspirational", "nature", "wilderness"]
  },
  {
    //quote 1
    id: 2,
    quote:
      "We do not see nature with our eyes, but with our understandings and our hearts.",
    source: "William Hazlett",
    citation: "",
    year: 1818,
    tags: ["inspirational", "nature"]
  },

#2) As mentioned in step #1 above, we need to track the previous quote’s id. We can declare a variable named prevQuoteId and leave it unassigned for now.

#3) Now you need to rewrite your newQuote function. Inside the function, you need a loop which continuously executes until a quote is found where the quote’s id value is NOT equal to prevQuoteId. To do that, you need to first get a random index (using the getRandomNumber function) and assign it to a variable. You were already doing that before with the following line, so you can reuse it.

let ind = getRandomNumber();  

Next, you need to check if the quote’s id whose index is ind DOES NOT match prevQuoteId.
If it does not match, you need to do two things:

  1. Assign the randomly select quote’s id (not to be confused with ind which is the index) to prevQuoteId.
  2. Return ind.

If prevQuoteId matches the randomly selected quote’s id, then your loop will just keep iterating until it finds a non-match.

I have given you 95% of the solution here, but you will still need to figure out the correct loop type and loop conditions to make all of this work.

If you get stuck, let me know.

EDIT: One extra bit of advice. In case you add additional quotes to your array, you might want to avoid hard coding the array length as you are currently doing in the line below:

let ranNum = Math.floor(Math.random() * 8);

and instead reference the length property of the quotes array (quotes.length). This will save you headache later if you miscount the number of quotes you put into your array.

Thanks!! This approach solved my problem.