Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Why isn't my button working every time and why is it not printing the first 6 FIRST?

I am building a little project: A random quote generator.

I have 6 quotes stored as objects in a file, quotes.js. Each quote object has a quote and source. Some of them also have a citation and year.

I have an html page (plus CSS) that displays a quote on the screen. There is also a button to click: click to get a new quote.

My code largely runs, when I click the button on my page, it loads a new quote at random. The majority of the time...

However, I am also aiming to NOT display a random quote more than once until ALL quotes from the array have been displayed first.

This is not happening yet.

My button, at random, does not work. I may get 5 successful button clicks, a miss and then another success at random. I'm not sure why this is happening at all.

Can you please suggest what to do here? No errors are being caught in the console.

ACTUALLY, I suppose that the button IS working every time, it's just loading the same quote again.

Here is my main code:

// event listener to respond to "Show another quote" button clicks
// when user clicks anywhere on the button, the "printQuote" function is called
document.getElementById('loadQuote').addEventListener("click", printQuote, false);

var intervalID = window.setInterval(printQuote, 3000);

// prints quote
function printQuote(){

    var finalQuote = buildQuote();
    document.getElementById('quote-box').innerHTML = finalQuote;

    var color = '#'+Math.floor(Math.random()*16777215).toString(16);
    document.body.style.background = color;
    document.getElementById('loadQuote').style.backgroundColor = color; 
}


// builds message for html, adding on citation and/or year if necessary
function buildQuote(){
    var quote2Print = getQuote(); 
    var message;
    message = "<p class='quote'>" + quote2Print.quote + "</p><p class='source'>" + quote2Print.source;

    if(quote2Print.hasOwnProperty('citation') === true){
        citation = quote2Print.citation;
        message += "<span class='citation'>"  + quote2Print.citation + "</span>";

        if(quote2Print.hasOwnProperty('year') === true){
            year = quote2Print.year;
            message += "<span class='year'>" + quote2Print.year  + "</span></p>";
            return message;

        } else {
            return message += "</p>";
        }

    }else {
        return message;
    }
}


// makes sure that if all 6 quotes haven't been printed, getRandomQuote is called again until a new one is found
function getQuote(){
    var countArray = [];
    var quote;

    if(countArray.length < 6){

        quote = getRandomQuote();

        while(countArray.indexOf(quote) === -1)
        {
            if(countArray.indexOf(quote) === -1) {
                countArray.push(quote);
                return quote;

            } else{
                quote = getRandomQuote();
            }
        } 

    } else {
        quote = getRandomQuote();
        return quote;
    }
}


// With random number, goes through array of quotes and chooses one. random number = index position
function getRandomQuote(){
    var randomQuoteNum = randomQuoteNo();
    var quote = quotes[randomQuoteNum];
    return quote;
}


// Gets a random number
function randomQuoteNo() {
    var randomNumber = Math.floor(Math.random() * 7);
    return randomNumber;
}

can you provide the rest of the JS. you are missing the getQuote() method

2 Answers

Oops, yes I'll do that now!

Steven Parker
Steven Parker
243,318 Points

One way to be sure to show all the quotes once before repeating would be to create a viewedQuotes list. So now each time you pick a random quote, remove it from the main list and add it to the "viewed" list. But before you pick one, if the main list is empty move everything back to the main list.

:point_right: Here's sample code for it:

var viewedQuotes = [];                                      // array to hold viewed quotes

function getRandomQuote() {
  if (quotes.length == 0)                                   // if empty, reload the main list
    quotes = viewedQuotes.splice(0, viewedQuotes.length);   // (and empty viewed list)
  var randNum = Math.floor(Math.random() * quotes.length);  // pick a quote at random
  var quote = quotes.splice(randNum, 1)[0];                 // take it out of the main list
  viewedQuotes.push(quote);                                 // now add it to the "viewed" list
  return quote;                                             // return the chosen quote
}

Note that you can still get the same choice twice in a row if the first pick from a fresh list happens to be the same as the last one from the old list. Also, randomQuoteNo is no longer used because the range must be recalculated for each pick, which is easily done right here.