0

I have an array of objects. Within the objects are 2 properties: "quote" and "author". I have a container div in which I want the quotes to display one at a time on an interval of every 2 seconds. Right now it is displaying one letter at a time rather than one (quote + author) at a time. How do I get it to display one (quote + author) at a time?

"use strict";

/*Read JSON quotes file*/
let mainContainer = document.querySelector('.quotes');


let quotesList = [
    {
        "quote": "Whether you think you can or you think you can’t, you’re right.",
        "author": "—Mother Teresa",
    },
    {
        "quote": "Act as if what you do makes a difference. It does.",
        "author": "—William James",
    },
    {
        "quote": "What you get by achieving your goals is not as important as what you become by achieving your goals.",
        "author": "—Zig Ziglar",
    },
];

var counter = 0;
let allQuotes;

quotesList.map(quote => {
    allQuotes = `${quote.quote} ${quote.author}`;
})

function next_quote() {
    mainContainer.innerHTML =  allQuotes[counter %  allQuotes.length];
    counter += 1;
}

setInterval(next_quote, 2000);

HTML:

<div class="quotes">Place quote here</div>
3
  • 1
    You are using the map function incorrectly. It's overriding allQuotes each interation. Commented Aug 21, 2020 at 21:28
  • 1
    Aside: you should not include the leading dash in the author's name — it is not part of the data, it is only how you want to display the data. Add the dash as part of your javascript processing, or using CSS .author::before { content: '- '; } (you'd have to put a <span class="author"> around the author name in your innerHTML) Commented Aug 21, 2020 at 22:28
  • @Stephen P Thank you, duly noted. Fixed this just now. Commented Aug 21, 2020 at 22:30

3 Answers 3

1

I've minimally modified your existing code as I thought it would be helpful for you to learn.


Explanation

allQuotes had not been initialised (assigned a value). I've assigned it an empty array.

.map returns an array whose items will be the return value from .map's callback function (the function we pass as an argument to .map). The callback function is called as many times as there are items on the array (array.length).

I've made it so every item of quotesList ({quote: ..., author: ...}) is added to the allQuotes array.

Finally, in next_quote you can see how we step into the item of the allQuotes array with allQuotes[counter] - which returns the {quote: ..., name: ...}. Then, you can see how we further step in it with .quote or .author - retrieving the values of these properties.

Once the counter is the same as the number of quotes, it resets to zero.

Code

let quotesList = [
    {
        "quote": "Whether you think you can or you think you can’t, you’re right.",
        "author": "—Mother Teresa",
    },
    {
        "quote": "Act as if what you do makes a difference. It does.",
        "author": "—William James",
    },
    {
        "quote": "What you get by achieving your goals is not as important as what you become by achieving your goals.",
        "author": "—Zig Ziglar",
    },
];

var counter = 0;
let allQuotes = [];

quotesList.map((item, index, array) => {
    allQuotes[index] = item;
})

function next_quote() {
    console.log(allQuotes[counter].quote + '\n' + allQuotes[counter].author);
    counter += 1;
    if (counter === allQuotes.length) {
        counter = 0;
    } 
}

function start() {
    console.log(allQuotes[counter].quote + '\n' + allQuotes[counter].author);
    counter += 1;
    setInterval(next_quote, 2000);
}

start();


Refactored into one function - happy to explain if you want

let quotesList = [
    {
        "quote": "Whether you think you can or you think you can’t, you’re right.",
        "author": "—Mother Teresa",
    },
    {
        "quote": "Act as if what you do makes a difference. It does.",
        "author": "—William James",
    },
    {
        "quote": "What you get by achieving your goals is not as important as what you become by achieving your goals.",
        "author": "—Zig Ziglar",
    },
];

function start() {
    let quoteCounter = 0;
    function currentQuote() {
        console.log(quotesList[quoteCounter].quote + '\n' + quotesList[quoteCounter].author);
    }
    for (; ; quoteCounter++) {
        if (quoteCounter === 0) {
            currentQuote();
            continue;
        }
        setInterval(function() {
                currentQuote();
                quoteCounter++;
                quoteCounter === quotesList.length ? quoteCounter = 0 : null
            }, 2000);
        break;
    }
}

start();

Sign up to request clarification or add additional context in comments.

3 Comments

@PA-GW no problem any questions let me know
the only thing I notice is there is a delay for the first item to appear.
@PA-GW edited it so there's no delay on the first item. I just put setInterval inside a new function. If you understand the code though I'm sure you could've thought of that ;). Is there anything in it you don't understand? P.s. This could get refactored (made shorter and perhaps easier to understand). Perhaps I'd do that another day.
1

.map returns an array, you can fix it as follows:

"use strict";

/*Read JSON quotes file*/
let mainContainer = document.querySelector('.quotes');


let quotesList = [
    {
        "quote": "Whether you think you can or you think you can’t, you’re right.",
        "author": "—Mother Teresa",
    },
    {
        "quote": "Act as if what you do makes a difference. It does.",
        "author": "—William James",
    },
    {
        "quote": "What you get by achieving your goals is not as important as what you become by achieving your goals.",
        "author": "—Zig Ziglar",
    },
];

var counter = 0;
let allQuotes;

allQuotes = quotesList.map(quote => {
    return `${quote.quote} ${quote.author}`;
})

function next_quote() {
    mainContainer.innerHTML =  allQuotes[counter %  allQuotes.length];
    counter += 1;
}

setInterval(next_quote, 2000);
<div class="quotes">Place quote here</div>

3 Comments

It can even be a single line: allQuotes = quotesList.map(quote => `${quote.quote} ${quote.author}`);
That works great. I am comparing what I had vs what you put for learning purposes. I was never setting a value for allQuotes. Thank you.
I will accept the answer in 4 minutes when S.O. allows me.
1

Here's a simplified working example based off your code that doesn't need to map the quotes list:

let quotesList = [
    {
        "quote": "Whether you think you can or you think you can’t, you’re right.",
        "author": "—Mother Teresa",
    },
    {
        "quote": "Act as if what you do makes a difference. It does.",
        "author": "—William James",
    },
    {
        "quote": "What you get by achieving your goals is not as important as what you become by achieving your goals.",
        "author": "—Zig Ziglar",
    },
];

let index = 0;

setInterval(() => {
  document.body.innerHTML = `${quotesList[index].quote} ${quotesList[index].author}`;
  index += 1;
  if (index === quotesList.length) {
    index = 0;
  }
}, 2000);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.