XMLHttpRequest - An amazing object for updating a webpage without reloading
Tags: javascript, beginners, tutorial, html
Published: 2022-04-17 13:37:39

Let's say you wanna make a simple webpage, where the user can click on a single button to send in the background a request to an API (your website's API or a [publicly available API](https://github.com/public-apis/public-apis), and once a response to that request has been received, display it in a nice way on the webpage

Well, this is all possible from the client-side, thanks to **XMLHttpRequest**!

---

## Choosing the API and the webpage's purpose

For this example, I will be using [waifu.im](https://waifu.im/docs/)

The webpage should be able to display a random image provided by this API (using its `/random/` path) whenever the user clicks a certain button

That image should fit the parameters specified by the user, using two radios (`<input type="radio">`)

---

## Creating the HTML file

```
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>getWaifu</title>
		<script type="text/javascript" src="index.js"></script>
	</head>
	<body>

		<!-- 1st part: Allow the user to specify what sort of image they want -->
		<div id="parameters">
			<div id="img_type" class="parameter">
				<input type="radio" id="png_jpg" name="img_type" value="PNG_JPG" checked>
				<label for="png_jpg">Not Animated (PNG/JPG)</label><br>
				<input type="radio" id="gif" name="img_type" value="GIF">
				<label for="gif">Animated (GIF)</label><br>
			</div>
			<div id="safe" class="parameter">
				<input type="radio" id="sfw" name="safe" value="SFW" checked>
				<label for="sfw">Safe For Work (SFW)</label><br>
				<input type="radio" id="nsfw" name="safe" value="NSFW">
				<label for="nsfw">Not Safe For Work (NSFW)</label><br>
			</div>
		</div>

		<!-- 2nd part: Give the user an image that matches the parameters -->
		<button id="trigger" onclick="waifu('random', document.getElementById('parameters'), document.getElementById('display'))">Get a Waifu!</button>

		<!-- 3rd part: Create a "home" or "container" for the image -->
		<div id="display">
			<span style="display: none">Placeholder~</span>
		</div>
		
	</body>
</html>

```

The **1st part** of the body holds the parameters: the user decides whether or not the image should be animated, and whether or not it should be "safe for work"

The **2nd part** of the body is a single button, calling a function (`waifu()`) specified in our future JS file upon clicking on it, with the string `"random"` as well as the 1st and 3rd parts of the body as arguments

The **3rd part** of the body is where we want the image to appear, replacing the invisible `span` placeholder in the process

---

## Creating the JS file

```
function waifu(route, params, display) {

	// Figure out what are the specified parameters
	let inputs = params.getElementsByTagName("input")
	let gif = inputs.gif.checked
	let nsfw = inputs.nsfw.checked

	// Create the request
	let xhr = new XMLHttpRequest()
	xhr.open("GET", `https://api.waifu.im/${route}?is_nsfw=${nsfw}&gif=${gif}`)
	xhr.setRequestHeader("Accept", "application/json")

	// Specify the behaviour upon receiving a response
	xhr.onreadystatechange = () => {
		if (xhr.readyState !== 4) return
		let data = JSON.parse(xhr.response).images[0]

		// Create the image element
		let image = document.createElement("img")
		image.setAttribute("src", data.url)
		image.setAttribute("alt", "Couldn't load the image... ><")

		// Put it on the website
		display.replaceChild(image, display.lastElementChild)
	}

	// Send the request
	xhr.send()
}

```

Firstly, we deal with the `params` object, which is the second object specified by the button, in order to determine if the image the user wants should be a gif or/and if it should be NSFW

Once that is done, we have everything needed to build the request, so we create a new request with **XMLHttpRequest** and we give it the name `xhr`

In the **request's URL**, `route` will always be `"random"` because the only button calling that function specifies that

We're doing a simple **GET request**, and we expect the response's data to be in **JSON format**

Then, we specify what should happen when the status of the request changes, the `if (xhr.readyState !== 4) return` line means that the code below it should not be executed unless a response has been received

In the code below, we create an `img` element using a property received in the response (`data.url`) and we put that element on the website using `display`, by replacing whatever's in it! (the placeholder if it is the first time the function is called)

Note that **this code only uses 1 of many properties** `data` holds, it has a lot more, which allows you to show lots of details about the image!

Now that all the details of the request have been specified, **the request can be sent** using `xhr.send()`, and the magic will happen!

---

## Seeing the result
_Note: A live example of all the code above (with added CSS) can be found [here](https://static.taevas.xyz/getWaifu/)_

Now that we're all done, you can open your HTML file in your browser, open up its network monitor (CTRL+Shift+E on Firefox, CTRL+Shift+J then click on "Network" for any Chromium-based browser) and click the button to get an image on the webpage!

![How it looks on Firefox](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ydlbburcpo9o0kqqjed4.png)

Do you see the last two requests? **The first request is to the API**, in order to get `data` and to modify your webpage with it!

**The second request is the one actually getting the image**; The first request had only gotten the URL of the image to create an `<img>` element, but now that this element is on the webpage, it needs to be downloaded from its `src` attribute! Of course, its `src` attribute is the URL gotten from the first request

---

I believe this covers pretty much everything!

**XMLHttpRequest** is truly crazy, as it allows you to make the user request and receive any data, anywhen (not only upon clicking anything!) and to do anything with that data, including changing the user's webpage, to its integrity if you wish it so!

I hope you have fun imagining what you can do with this, and even more fun actually making it work!