Using JavaScript to display a random quote

On a forum I ran when I was 16, there was an area under the logo that would display a random quote on every page load. It was a small PHP script that picked a random line from a text file. I loved how fun this was, and wanted to bring it back to my site. I still had the original text file, and after some modifications (cringe removal), it was ready to be used again!

Things are different now: my site doesn’t run on a server with PHP available, it’s a static site generated by 11ty on CloudFlare Pages. There’s options such as CloudFlare Workers if I wanted to keep this server-side, and while I plan to look into that in the future, I decided to implement it with a small client-side script for now. The feature isn’t necessary and I consider it a good candidate for progressive enhancement: if the JavaScript doesn’t load, visitors won’t see a silly quote.

The code

I have a file named quotes.txt that lives in /static/, and you can view it here. I decided to keep it as a text file instead of JSON to make it easier to throw new quotes in.

Next we need to convert the text to JSON! There’s a template file named quotes.11ty.js that lives in /content/. This reads the text file, converts it to JSON, and writes out quotes.json when 11ty builds my site. While I decided to hook into 11ty’s build process for this, it wouldn’t take much to convert it to a standalone Node script.

/**
* @file Generates a JSON file from a txt file
*/


const fs = require("fs");
const txt = "static/quotes.txt";

// Read the file
const data = fs.readFileSync(txt, "utf-8");
// Split into new lines
const split = data.split("\n");
// Split into values and remove whitespace/new line characters
const quotes = split.map((line) => line.trim());

exports.data = {
permalink: "/quotes.json",
eleventyExcludeFromCollections: true,
};

exports.render = function () {
return JSON.stringify(quotes);
}

Next, on the frontend, I need to display a random quote. I have a JavaScript file named quotes.js that lives in /static/js/. This one fetches quotes.json, shuffles the array, and then updates an element in the DOM with the first quote in the array.

/**
* @file Displays a random quote from a predefined list.
*/


let element = document.querySelector("#quote");

/**
* Randomly shuffle an array
* https://stackoverflow.com/a/2450976/1293256
* @param {Array} array The array to shuffle
* @return {String} The first item in the shuffled array
*/

function shuffle(array) {
let currentIndex = array.length;
let temporaryValue, randomIndex;

// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;

// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}

return array;
}

/**
* Fetch JSON, shuffle the quotes, and use the first one to update the DOM
*/

async function getQuote() {
try {
let response = await fetch('/quotes.json');
if (!response.ok) throw response.status;
let quotes = await response.json();
if (!quotes) throw "No quotes returned.";

shuffle(quotes);

element.innerHTML = `${quotes[1]}`;
} catch (error) {
console.log(error);
}
}

// Initialize
getQuote();

The result

You can see it live in action in the header of my site. Here’s a screenshot for RSS readers and posterity:

Screenshot of the header on Luke’s Wild Website. A quote appears with the text, “It’s random!”