DEV Community

Taevas
Taevas

Posted on

XMLHttpRequest - An amazing object for updating a webpage without reloading

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, 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

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>

Enter fullscreen mode Exit fullscreen mode

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()
}

Enter fullscreen mode Exit fullscreen mode

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

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

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!

Top comments (0)