How I made “Random Quote Machine”

Gordana Minovska
8 min readMar 14, 2017

The Random Quote machine is a Free Code Camp project. It makes an AJAX call to a random quote generator API and displays the response on the page. I wanted to document the process of building this project in detail: write down the steps, the challenges, the google searches and the solutions I came up with.

PREFACE

First thing I do when I encounter an acronym is to find out what it means. Yet, learning that AJAX is “Asynchronous JavaScript and XML” was not very helpful. The only thing less helpful was unraveling that API stands for “Application Programming Interface”. Ouch! I had no clue what could that possibly be. Hence, I developed an apprehension towards them. They sounded scary and difficult to me. In my head those were advanced things, so I kept postponing them.

That is why making this project is a milestone for me. I broke a self-imposed mental barrier. I do have a lot more to learn about this topic, but now, the first (and most important) step is behind me; the fear of these acronyms is gone.

Since this project was significant for me, I wanted to document the process I was going through while working on it. I had one attempt of documenting a project before this and it ended up being abandoned half way. Why? Because there is always a lie I tell myself: I’ll write it later, let’s build the thing first. It is true — “Tomorrow never comes until it’s too late”.

I guess now I understand why developers are notoriously bad at writing documentation. It’s not as fun as writing code, and you only reap the benefits of documentation long after the development, not during the process. Nonetheless, it is very useful. I am sure my future self is going to thank me, and it might be useful to others as well. It is likely that documenting gets easier with practice. If you make it a part of the development process, like Test Driven Development, it should become a second nature.

Initially, the idea was to document the solutions to the various challenges on the way. However, I got inspired to write down all the google searches as well, after reading this article. In it, developers talk about all the things they have to google even after years of experience. It is very encouraging article. I am thankful to all of those professionals who decided to speak up about this topic. It is nice to know that even seasoned developers rely heavily on their search engines, like I do.

BEFORE I BEGAN WORKING ON THE PROJECT

I learned about AJAX, JSON and APIs through Udacity’s course — Intro to AJAX. I found it very helpful. I finished ⅔ of it, up to the point where they started talking about CORS and JSON-P before I felt ready to tackle the FCC project.

Project Requirements:

Free Code Camp Requirements are in the form of user stories:

Fulfill the below user stories. Use whichever libraries or APIs you need. Give it your own personal style.

I can click a button to show me a new random quote.

I can press a button to tweet out a quote.

PROJECT START

Stage 1: Build the basic HTML/CSS for the project.

I focused on semantic HTML and CSS that helps visualize the elements for proper positioning.(Reminder to self:) This phase is not about the project looking pretty.

Google searches:

(By the way, most of my searches are on things I have used in previous projects)

  • Does the blockquote element include p or the text is within the blockquote tags? Which quote is appropriate for the author?

I included a <p> tag that holds the text of the quote, and a <cite> tag for the author.

I used the flexbox approach on the parent element and tested to see how it looks with short, and long quotes.

I wanted the buttons to have the same amount of space between them. The css-tricks article above explains how to easily achieve that, with the properties display: flex and justify-content: space-between applied on the containing <div>.

Here is my project at the end of stage 1:

My fledgling project is not pretty, but it has proper HTML structure and general CSS positioning in place

Stage 2: Implement the random quote functionality

Before I jumped into this exciting part of the project, I did the usual groundwork:

  1. Start a new script.js file and connect it to the HTML document properly. Before proceeding further, test if the script is connected properly, by calling alert("I am properly connected");
  2. Plug in the JQuery CDN link and test it with $('body').append("Jquery in da house");
  3. Begin with $(document).ready(function(){//all the code goes here });This allows the script to run only after the entire DOM has loaded and it is ready for manipulation.

Next was to find a random quotes API I can use for my project. I recently learned about the mashape marketplace and decided to use the Random Famous Quotes API. This was my first time using both an API and mashape, so I took some time exploring the information on how to make a successful request. There was no code example for JavaScript, but looking at the examples for node.js, I saw that this API necessitates header information be passed along with the request. It was time to fire up my search engine:

How to set headers with .getJSON()?

As usual, stack overflow gave me a valuable insight; what I needed was the more robust .ajax() method in which I can set the header information. I wrote my ajax request, and I decided to test if it is successful by logging the response to the console:

$.ajax({
type: "POST",
url: "https://andruxnet-random-famous-quotes.p.mashape.com/?cat=famous",
dataType: "json",
success: function (response) {
console.log(response);
},
beforeSend: setHeader
});
function setHeader(xhr) {
xhr.setRequestHeader("X-Mashape-Key", "[myMashapeAPIkey]");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("Accept", "application/json");
}

What I saw next gave me an endorphin rush. My console was logging out my success! Well, technically it was an AJAX success, but those two were synonymous for me. Oh happy day :)

Next, I implemented the functionality of getting a new quote on a button click. I achieved this by wrapping the ajax call into a function getRandomQuote(), and placing it as an event handler for the “next quote” button click: $("#next_quote").click(getRandomQuote);

Displaying the result on the page is easy with JQuery. The following function is the ajax success callback.

function displayQuote(response) {
$("#quote").text(response.quote);
$('#author').text(response.author);
}

Update (06/01/2018): The API has changed the format of the response, now an array of object(s) is being returned from the call. Consequently, the displayQuote() function needs to be modified/rewritten:

function displayAPIQuote(response) {
$("#quote").text(response[0].quote);
$("#author").text(response[0].author);

But what if the ajax call is unsuccessful? I decided to implement an error handling function and test it. My first thought was to have just a simple message notifying the user the quote could not be retrieved. But that is not a great user experience.

Thinking about possible solutions, I realized that the application user doesn’t really care where the quote is coming from, if it’s an ajax call to an API or a local array of quote objects. Additionally, by having an array of quotes, I would grab the first quote that shows up on page load from the array, and thus avoid the delay that happens before the ajax call returns. Yet, I wanted to simulate the behavior of the API and have a random quote display every time the page loads. I achieved this with the following function:

function displayQuoteFromArray() {
var myQuotes = [
{
author: "Author Name",
quote:"Very famous quote"
}
//+ more quote objects with the same format
];
var random = Math.floor(Math.random() * x);
//x is the number of quotes in the array
displayQuote(myQuotes[random]);
}

I am calling this function at the beginning of the script to have the first quote come from the array. I also added an error setting in the ajax function that points to this function as well, so if the request fails, this function will display a quote from the array. With that, I had the first user story fulfilled, and it was time to research how to implement the tweeting functionality.

The Twitter documentation helped me figure out how to pre-populate a tweet with the quote. I wrote the following function that creates the tweet url that is appended to the tweet button’s <a id=”tweet”> href attribute with:
$("#tweet").attr("href", tweetQuote()):

function tweetQuote() {
var twitterURL = 'https://twitter.com/intent/tweet?hashtags=quotes,freeCodeCamp&related=freecodecamp&text="';
var quote = $("#quote").text();
var author = $('#author').text();
twitterURL +=quote +'" - '+ author;
return twitterURL;
}

Let’s test the twitter functionality. Hmmm, there is a bug: the tweetURL doesn’t update when the next quote is clicked, it displays the previous quote, not the current one. :(
I realized why. It is because the tweetQuote() runs before the AJAX completes. When the AJAX returns, it just updates the text but not the tweet url.

I fixed the bug by adding a call to the tweetQuote() inside the displayQuote function. This function gets called on AJAX success, and when a quote is loaded from the array (on page load, or ajax error). Now the twitter button is functioning like it should. Once clicked, it pops up a pre-populated tweet, with the both the current quote and the quote author:

Stage 3: Add styles

I used the following to style my app:

  • Background image from Pixabay
  • Google fonts: Merriweather & Special Elite
  • Bootstap to style the buttons
  • Font Awesome to add icons

I added media query to make it responsive, and JQuery easings to make the quotes appear smoothly on the page.

Stage 4: Share with other Free Code Campers and get feedback

This stage is particularly important. It helps having fresh pair of eyes look at your work and point out things you might have overlooked. True enough, I have not noticed the blue outline that shows when a button is active until my fellow Beluga that goes by @mahaveer suggested I should remove it:

I was not sure how to do that, suspected it’s a CSS pseudoclass that has that effect, but couldn’t find that styles via Chrome DevTool.

I had better luck with the search: bootstap button blue outline. I added the following CSS in order to remove the outline.

.btn:focus, .btn:active {
outline: none !important;
}

In general, I avoid using the !important, but the styles were getting overridden without it so I found it necessary in this case.

With regards to Chrome DevTools and inspecting the CSS, @muir_fionn gave me incredibly useful tip:

“If you are using Chrome and inspect the element with DevTools, on the right side of the element tab click :hov in the toolbar and select different states to see what styles are being applied.” — by @muir-fionn

Thank you my Chingu cohort friends for making this journey better for me! Being part of this wonderful community is truly invaluable experience!

This project is on my GitHub and it is hosted on GitHub Pages, click here to check it out.

Happy coding!

--

--

Gordana Minovska

React Developer & UX/UI Designer passionate about closing the empathy gap between engineers & users.