Build a lightweight Internet Detect Feature with VanillaJS 
Tags: javascript, userexperience, opensource, internet
Published: 2018-04-06 20:30:54

---
title: Build a lightweight Internet Detect Feature with VanillaJS 
published: true
description: 
tags: Javascript, User Experience, open source, internet
canonical_url: http://ojanti.com/blog/Build-a-lightweight-Internet-Detect-Feature-with-VanilaJS
---

View live demo  [Here](https://ojanti.github.io/Internet-Detect-Feature-with-Javascript/).
Complete Code on Github  [Here](https://github.com/Ojanti/Internet-Detect-Feature-with-Javascript).
Originally Posted on  [my blog](http://ojanti.com/blog/Build-a-lightweight-Internet-Detect-Feature-with-VanilaJS).

I recently worked on an application which was primarily being used by customers in certain areas of West Africa. While Beta testing the app, we received several complaints of it not working properly. After further investigation we noticed most of the issues raised were due to failed or bad internet connectivity. Smooth operation of the software largely depended on stable internet.

So prior to building  more robust features like autosave or temporary storage, I was tasked with implementing a light weight internet detect feature that would check for internet connectivity and notify the user when its bad/restored and the consequences of both. The major requirements' were;

1. It must be light weight and implemented quickly
2. It shouldn't be ugly because of 1 (no javascript alerts lol)
3. It should have minimal to no dependencies (beyond basic/regular requirements for a web application)

I decided to use VanillaJS which will execute firstly once any view of the app runs. I would ping a file on a remote server and check for the response HTTP status. If it wasn’t successful i.e  HTTP status code >= 200 &  < 304. [reference here](http://httpstatuses.com/), then I notify the user and offer some advice while still checking. If eventually the  internet connectivity is restored, the application would notify the user of this.

Here is the core function:
```javascript
var wasInternetConnectionBad = '';      //used to show restored internet notification only once
var internetCheckActions = function() {
    var xhr = new XMLHttpRequest();
    var file = "/img/nKekEaz4i6jeRtvxZRnY.jpg";     // the remote file to check for. You should replace this with yours
    var randomNum = Math.round(Math.random() * 10000);      //initiating a random value to  revv the file

    xhr.open('HEAD', file + "?rand=" + randomNum, true);
    xhr.send();

    xhr.addEventListener("readystatechange", processRequest, false);

    function processRequest(e) {
        if (xhr.readyState == 4) {
            if (xhr.status >= 200 && xhr.status < 304) {
                if (wasInternetConnectionBad == "1") {
                    //  Internet connection is GOOD. Do what ever you like here
                }
                wasInternetConnectionBad = '';      //Clear flag
            } else {
                //  Internet connection is BAD. Do what ever you like here
                wasInternetConnectionBad = '1';
            }
        }
    }
}
```

I decided to invoke the function when the DOM content loads and every subsequent 5 seconds. You can change this as you feel

```javascript

// Invoke when DOM content has loaded
document.addEventListener('DOMContentLoaded', function () {
    internetCheckActions();
});

//& every subsequent 5 seconds
var checkInternetConnection = function() {
    setInterval(function () {
        internetCheckActions();
    }, 5000);
}
checkInternetConnection();

```

The code above is basically what you need. You can end here or continue to see the more complete solution.

The next step was to figure out how to notify the user of the state of things in nice way. This is where I normally just call a fancy Jquery notification plugin but we cant do that. So I built a very light weight and extensible notification widget. The cool thing is it can be used in other utility functions.

First lets create the HTML markup for the notification. Ideally this should be inserted as the first child of the BODY tag and sibling of what ever hosting element is decided should be the page content.

```html
<img src="https://cdnjs.cloudflare.com/ajax/libs/slippry/1.4.0/images/sy-loader.gif" width="1" height="1"
     style="position:absolute; z-index:-2;"> <!-- Attepmting to preload an animated loader image which will be used later. NOTE, different browser behave differently  -->
<div class="rawNotificationArea" id="rawNotificationArea">
    <div class="notification_message"></div>
</div>
```
Then add this CSS snippet inline, in the head tag to style our notification widget

```html
<style>
    .rawNotificationArea {
        position: fixed;
        top: 2px;
        left: 0;
        width: 100%;
        text-align: center;
        padding: 10px 0;
        display: none;
        z-index: 99999999;
    }

    .rawNotificationArea .notification_message {
        max-width: 50%;
        border: solid thin #888888;
        color: #333;
        background-color: #DCDCDC;
        text-align: center;
        padding: 5px 15px;
        border-radius: 4px;
        box-shadow: 2px 3px 20px rgba(0, 0, 0, 0.17);
        display: inline-block;
        text-align: center;
        font-size: 14px;
        letter-spacing: 1px;
    }

    .rawNotificationArea .notification_message.warning {
        background-color: #fcf8e3;
        border-color: #faf2cc;
        color: #8a6d3b;
    }

    .rawNotificationArea .notification_message.success {
        background-color: #dff0d8;
        border-color: #d0e9c6;
        color: #3c763d;
    }

    .rawNotificationArea .notification_message.info {
        background-color: #d9edf7;
        border-color: #bcdff1;
        color: #31708f;
    }

    .rawNotificationArea .notification_message.danger, .rawNotificationArea .notification_message.error {
        background-color: #f2dede;
        border-color: #ebcccc;
        color: #a94442;
    }
</style>

```

And the JS for widget.

```javascript
// Notification Widget
var nativeNotification = {
    fadeEl: function() {
        return (document.getElementById('content_body'));
    },
    messageHolder: function() {
        return (document.getElementById('rawNotificationArea'));
    },
    contentFade: function() {
        this.fadeEl().style.opacity = "0.5";
    },
    contentUnfade: function() {
        this.fadeEl().style.opacity = "1.0";
    },
    notify: function(message, tone) {
        this.messageHolder().innerHTML = '<span class="notification_message ' + tone + '">' + message + '</span>';
        this.messageHolder().style.display = "block";
    },
    unotify: function() {
        while (this.messageHolder().firstChild) {
            this.messageHolder().removeChild(this.messageHolder().firstChild);
        }
    },
    timedUnotify: function(time) {
        setTimeout(function() {
            nativeNotification.unotify();
        }, time);
    }
};

```

So using this in our core function, we will finally have something like this

```javascript

//Detect internet status amd motify user
var wasInternetConnectionBad = '';      //used to show restored internet notification only once
var internetCheckActions = function() {
    var xhr = new XMLHttpRequest();
    var file = "/img/nKekEaz4i6jeRtvxZRnY.jpg"; // the remote file to check for. You should replace this with yours
    var randomNum = Math.round(Math.random() * 10000); //initiating a random value to  revv the file

    xhr.open('HEAD', file + "?rand=" + randomNum, true);
    xhr.send();

    xhr.addEventListener("readystatechange", processRequest, false);

    function processRequest(e) {
        if (xhr.readyState == 4) {
            if (xhr.status >= 200 && xhr.status < 304) {
                if (wasInternetConnectionBad == "1") {
                    nativeNotification.contentUnfade();
                    nativeNotification.notify("Your internet connection has been restored", 'info');
                    nativeNotification.timedUnotify(5000);
                }
                wasInternetConnectionBad = '';
            } else {
                nativeNotification.contentFade();
                nativeNotification.notify("We've detected a problem with your internet connection.\n Some functions may not work as expected<div><strong>Retrying <img src='https://cdnjs.cloudflare.com/ajax/libs/slippry/1.4.0/images/sy-loader.gif' width='20' height='20'></strong></div>", 'warning');
                wasInternetConnectionBad = '1';
            }
        }
    }
}

```

View live demo  [Here](https://ojanti.github.io/Internet-Detect-Feature-with-Javascript/).
Complete Code on Github  [Here](https://github.com/Ojanti/Internet-Detect-Feature-with-Javascript).

P.S

1. This was a quick fix. Im looking forward to interesting ways people can improve this  or even better, more efficient solutions
2. Possible pending improvements' include
    *- Building this out into an easy to use JS plugin
    *- Experiment others ways of revving the file being used to used to check for connectivity. Currently the file is being revved using a querystring. See more on this [here](http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/)
3. Not sure on this but I assume method being used here (i.e pinging a file using the web client to make repeated calls to a static file) is [indempotent ](http://www.restapitutorial.com/lessons/idempotency.html).. Im also looking forward to interesting conversations on this