Share
Explore

JavaScript lab for building a random joke generator using the JokeAPI:

Tomorrow we will add CSS for styling.
Planning Whiteboard:

First step in building the NPM application is:

Making a Directory.
Initializing the Project by making a Package.json file with npm -init

Let's create a simple Node.js API server which serves jokes stored in a JSON file.

For now: our datastore will be a JSON file on the file system of the Server =
Nex step: We will see how to put these jokes into a MONGO Database.
A MONGO database is a collection of JSON documents. Each document is a collection of KEY:VALUE pairs.
Here's your directory structure:
index.js
jokes.json
To get started, first, initiate a new Node.js project by running npm init -y in your terminal.
Next, install the needed dependencies. We'll use express to create the server and cors to handle Cross-Origin Resource Sharing:
npm install express cors
Now, let's create a index.js file and a jokes.json file in your project root.
Your jokes.json file could look something like this:
[
{
"id": 1,
"joke": "Why don't scientists trust atoms? Because they make up everything!"
},
{
"id": 2,
"joke": "Why was the math book sad? Because it had too many problems."
},
{
"id": 3,
"joke": "Why can't you give Elsa a balloon? Because she will let it go."
}
]
In your index.js file:
const express = require('express');
const cors = require('cors');
const fs = require('fs');

// Create an express app
const app = express();

// Enable CORS
app.use(cors());

// Load jokes from JSON file
let jokes = JSON.parse(fs.readFileSync('jokes.json', 'utf8'));

// Create a route to get all jokes
app.get('/jokes', function (req, res) {
res.send(jokes);
});

// Create a route to get a joke by id
app.get('/jokes/:id', function (req, res) {
const joke = jokes.find(j => j.id === parseInt(req.params.id));
if (!joke) return res.status(404).send('The joke with the given ID was not found.');
res.send(joke);
});

// Start the server
app.listen(3000, () => {
console.log('Server is running at http://localhost:3000');
});
This creates an Express server which will serve all jokes from your jokes.json file when someone sends a GET request to http://localhost:3000/jokes.
And if a client sends a GET request to http://localhost:3000/jokes/:id, it will return the joke with the specific id.
You can start your server with node index.js.
Now your server is ready to serve jokes!

Below is a basic example of how you could create a web page that interacts with your Node.js jokes API server. This example assumes your server has a "/jokes" endpoint that responds to GET requests with a JSON object containing an array of jokes.

HTML and JavaScript for accessing your jokes API server:
The provided code is an HTML page that includes jQuery and provides a button that, when clicked, fetches a random joke from a local server (http://localhost:3000/jokes) and displays it on the page.
Here's a quick breakdown of the code:
Dependencies:
You have included the jQuery library which simplifies JavaScript operations.
HTML Structure:
A heading <h1> displays "My Joke:".
There's a button with the id getJoke which the user can click to fetch a new joke.
A paragraph <p> with the id joke which is where the fetched joke will be displayed.
JavaScript/jQuery:
Once the document is fully loaded ($(document).ready()), an event listener is attached to the button with the id getJoke.
When this button is clicked, an AJAX request using jQuery's $.ajax() method is made to fetch jokes from http://localhost:3000/jokes.
Upon a successful response, it randomly selects a joke from the array of jokes received and displays it in the paragraph with the id joke.
If there's an error in the AJAX request, it will be logged in the console.
Note:
Ensure your server at http://localhost:3000/jokes is running and properly set up to handle the GET request and return an array of jokes.
The way the joke is accessed (data[jokeIndex].joke) assumes that the server returns an array of objects where each object has a property joke that contains the joke text. If the server's response structure is different, you'll need to adjust this code accordingly.
Always remember about CORS (Cross-Origin Resource Sharing) when making requests from one domain to another. If you run into issues related to CORS, you'll need to set up proper headers on your server to allow the request from this page.
Overall, this is a simple and straightforward way to display random jokes from a local API. If you have more complex requirements or data structures, additional adjustments might be needed.
<!DOCTYPE html>
<html>
<head>
<title>Jokes API</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<h1>My Joke:</h1>
<button id="getJoke">Get a Joke</button>
<p id="joke"></p>

<script>
$(document).ready(function(){
$('#getJoke').click(function(){
$.ajax({
url: 'http://localhost:3000/jokes', // Your localhost address here.
type: 'GET',
dataType: 'json',
success: function(data) {
var jokeIndex = Math.floor(Math.random() * data.length); // Assuming server returns an array of jokes.
$('#joke').text(data[jokeIndex].joke); // Adjust this line based on how the joke text is stored in your API.
},
error: function(error) {
console.log("There was an error", error);
},
});
});
});
</script>
</body>
</html>
Within the success function, it randomly selects a joke from the returned array and displays it in the paragraph with id joke.
Remember to replace the URL in the ajax call 'http://localhost:3000/jokes' with the actual URL of your local API.

Let's enhance the page with some CSS and minor UI/UX adjustments:

Loading state: When the joke is being fetched, the button will be disabled and display a loading text.
Success state: Upon successfully fetching a joke, let's change the background color of the joke paragraph to give a visual feedback to the user.
Error state: In case of an error, display an error message in red.
Here's the enhanced code:
<!DOCTYPE html>
<html>
<head>
<title>Jokes API</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
body {
font-family: 'Arial', sans-serif;
text-align: center;
margin-top: 50px;
}

#joke {
padding: 10px;
border-radius: 5px;
transition: background-color 0.3s;
}

.loading {
background-color: #f0f0f0; /* A neutral grey to indicate loading state */
}

.success {
background-color: #d4edda; /* A light green to indicate successful fetch */
}

.error {
color: red;
}

button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
</style>
</head>
<body>
<h1>My Joke:</h1>
<button id="getJoke">Get a Joke</button>
<p id="joke"></p>
<p id="errorMsg" class="error"></p>

<script>
$(document).ready(function(){
$('#getJoke').click(function(){
// Set loading state
$('#getJoke').prop('disabled', true).text('Loading...');
$('#joke').addClass('loading').text('');
$('#errorMsg').text(''); // Clear any previous error messages
$.ajax({
url: 'http://localhost:3000/jokes',
type: 'GET',
dataType: 'json',
success: function(data) {
var jokeIndex = Math.floor(Math.random() * data.length);
$('#joke').removeClass('loading').addClass('success').text(data[jokeIndex].joke);
$('#getJoke').prop('disabled', false).text('Get a Joke');
},
error: function(error) {
$('#joke').removeClass('loading success');
$('#errorMsg').text('Oops! Something went wrong. Please try again later.');
$('#getJoke').prop('disabled', false).text('Get a Joke');
console.log("There was an error", error);
},
});
});
});
</script>
</body>
</html>

Changes made:
Added styles for different states like loading, success, and error.
Enhanced the JavaScript to toggle these states when needed. For instance, the button is disabled with a 'Loading...' text when a joke is being fetched. Once fetched, it goes back to its original state.
Added an error message area (#errorMsg) to provide feedback when there's an error fetching the joke.
This version provides a much better user experience by clearly communicating what's happening during the various stages of fetching a joke.
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.