As part of our weekend tutorial, we will build a Quote generator using Javascript this time. Before we implement it, let’s have a glimpse of the final version of what we will make –
Table of Contents
This Quote Generator application has the following feature –
- A button when clicked generate the Quote
- A Twitter button when clicked put the quote to Twitter
Project Directory Structure
|-- quote-generator
| |-- css
| | |-- style.css
| |-- js
| | |-- main.js
| |-- index.html
After you’ve created the above directories in your local machine, please follow along.
Quote Generator Implementation
Let’s implement the index.html code first.
index.html
Quote Generator
What you are is what you have been. What you'll be is what you do now.
Buddha
At the head of the above HTML file, we have included the quote-specific CSS and font awesome icon CSS (this is for the quote and Twitter icon).
And in the body of the HTML, a quote-container div is added which will hold the quoted content, quote author, Twitter button, and New Quote button.
On click of the New Quote button, the next quote will be generated through AJAX request, and its code is written in the main.js file which has been added at the bottom of the body in the HTML file.
style.css
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&family=Open+Sans:wght@400;600&display=swap');
html {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
background-color: #b59ed9;
background-image: url("data:image/svg+xml,%3Csvg width='42' height='44' viewBox='0 0 42 44' xmlns='http://www.w3.org/2000/svg'%3E%3Cg id='Page-1' fill='none' fill-rule='evenodd'%3E%3Cg id='brick-wall' fill='%2317156c' fill-opacity='0.45'%3E%3Cpath d='M0 0h42v44H0V0zm1 1h40v20H1V1zM0 23h20v20H0V23zm22 0h20v20H22V23z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
color: #000;
font-family: Montserrat, sans-serif;
font-weight: 600;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.quote-container {
width: auto;
max-width: 900px;
border-radius: 10px;
padding: 20px 30px;
background-color: hsl(0deg 31% 73% / 90%);;
box-shadow: 0 10px 10px 10px rgba(0,0,0,0.9);
}
.quote-text {
font-size: 2.75rem;
}
.long-quote {
font-size: 2rem;
}
.fa-quote-left {
font-size: 4rem;
}
.quote-author {
margin-top: 15px;
font-size: 2rem;
font-weight: 400;
font-style: italic;
}
.button-container {
margin-top: 15px;
display: flex;
justify-content: space-between;
}
button {
cursor: pointer;
font-size: 1.2rem;
height: 2.5rem;
border: none;
border-radius: 10px;
color: #fff;
background-color: #333;
outline: none;
padding: 0.5rem 1.8rem;
box-shadow: 0 0.3rem rgba(121,121,121,0.65);
}
button:active {
transform: translate(0, 0.3rem);
box-shadow: 0 0.1rem rgba(255,255,255,0.65);
}
.twitter-button:hover {
color: #38a1f3;
}
.fa-twitter {
font-size: 1.3rem;
}
/* media query: Tablet or Smaller */
@media screen and (max-width: 1000px) {
.quote-container {
margin: auto 10px;
}
.quote-text {
font-size: 2.5rem;
}
}
We are using the Montserrat google font which is added at the top of the CSS file. Quote Container div in the body is centered using the flex.
Rest other CSS codes are self-explanatory.
main.js
// Fetch quote from API
async function fetchQuote() {
const url = 'https://type.fit/api/quotes';
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Request not found');
}
const quotes = await response.json();
return quotes;
} catch (e) {
alert(e);
}
}
function tweetQuote() {
const twitterQuoteUrl = `https://twitter.com/intent/tweet?text=${quoteEl.textContent} - ${quoteAuthorEl.textContent}`;
window.open(twitterQuoteUrl, '_blank');
}
const quotesPromise = fetchQuote();
const quoteEl = document.getElementById('quote');
const quoteAuthorEl = document.getElementById('author');
document.getElementById('new-quote').addEventListener('click', function (e) {
quotesPromise.then(quotes => {
const randomQuoteIndex = Math.floor(Math.random() * quotes.length);
const quoteText = quotes[randomQuoteIndex].text;
let author = quotes[randomQuoteIndex].author;
if (!author) {
author = 'Unknown';
}
if (quoteText.length > 120) {
quoteEl.classList.add('long-quote');
} else {
quoteEl.classList.remove('long-quote');
}
quoteEl.textContent = quoteText;
quoteAuthorEl.textContent = author;
});
});
document.getElementById('twitter').addEventListener('click', tweetQuote);
The above code is written in vanilla javascript. Let me explain each function in detail –
tweetQuote
This function is responsible for tweeting the quote on Twitter. It calls the tweeter intent API with quoted text and quote author as a query param.
fetchQuote
This is an async function that is responsible for fetching the quotes and returning the promise for the quotes.
Click listener is bound over the Twitter button and New Quote button which calls the above functions respectively.
Challenges
To show the next quote on click of the New Quote button, we need to have the quotes list beforehand otherwise UX will be really bad. Now once the API response is received i.e quotes are available, you will feel like storing it to avoid hitting the API again and again on click of the button.
Storing the response is not necessary, yes, you heard it right!
To solve the above without making a request on each button click, we can cache the promise.
A promise is stateful, and as soon as it's fulfilled, its value cannot be changed. You can use .then() multiple times to get its contents, and you'll get the same result every time.
So, with quotesPromise.then we will be getting the quotes list each time and there we pick a random quote that is shown on the quote container.
That is all in this tutorial. If you like the article please share it with your friends and community.
Learning Data structure? read this popular tutorial – How to implement the stack and reverse it in javascript?
Please share the articles on –
The latest tips and news from the industry straight to your inbox!
Join 30,000+ subscribers for exclusive access to our monthly news and tutorials!