Progressive Enhancement & Graceful Degradation With Ajax

In the early days of the web, there was often a philosophy (and somewhat of a reality) that web sites/applications would look the same across all browsers.  This was because web content was written using a standardized language (HTML and CSS) to which all browsers would adhere.  Over time, however, newer versions of these specifications developed, with some browsers being quick to incorporate them while others lagged behind.  To further complicate this situation, JavaScript technology was introduced during this time to provide the ability to add dynamic behaviors to web pages.  The result of all these changes created a complicated target for web content creators that were, on one hand, looking to take advantage of the latest browser advances, while on the other hand, needed to have their content still function on legacy browsers.  The end result of these conflicting goals was usually the creation of multiple versions of the same content for different browsers or various CSS tricks and/or use of known browser loopholes or bugs.  Additionally, developers that made use of JavaScript in their web pages found themselves in similar situations as some browsers either didn’t support JavaScript, didn’t support it correctly or completely, or maybe had JavaScript disabled at the user’s request.

During this time, the community developed some best practices and strategies for addressing these complications, two of which are known as “progressive enhancement” and “graceful degradation”, which are really two sides of the same coin.  Progressive enhancement refers to the notion of starting with a lowest common denominator style and behavior that works across all browsers (or an agreed set of browsers) and then progressively “layering” advanced styles and behaviors in more advanced browsers.  This strategy allows developers to support users of older browsers without limiting the end-user experience for users of advanced browsers.

Graceful degradation is really just the opposite of progressive enhancement.  Using this strategy, developers will target the latest browser technologies first and then work backwards to find ways to support users of older browsers using techniques that allow the web application to still function, albeit with less appeal, through the use of older technologies.  The end-goal of both strategies is really the same: support as many browser/version scenarios as possible but without compromising the end-user experience for users of advanced browsers.

As with most everything, the best way to understand this is through example.  I’d like to focus on a simple scenario in which we want our application to work in browser environments in which JavaScript is either unsupported or disabled but then also take advantage of browser environments in which JavaScript is available (progressive enhancement).

Time Grabber 1

The Time Grabber web application is pretty simple. When the user clicks the button, the current UTC and local date and time will be displayed in the fields below the button. Looking at the HTML code, we can see that this app doesn’t require JavaScript to function since it’s just coded as an HTML form.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Time Grabber</title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
    ...

    <form action="/" method="post">
        <input id="btnGetTime" type="submit" value="Get current date/time" />
    </form>

    <p>UTC Time: <span id="utcTime"></span></p>
    <p>UTC Date: <span id="utcDate"></span></p>
    <p>Local Time: <span id="localTime"></span></p>
    <p>Local Date: <span id="localDate"></span></p>

    ...
</body>
</html>

When the user clicks the button, a post is made to the server and some server-side code produces the following response page.

Time Grabber 2

However, if JavaScript is available in the browser, we can avoid a form post and a page transition by using JavaScript/JQuery to make an AJAX call to the server to retrieve the current date/time information and then update the fields in the page using JavaScript/JQuery, as shown in the following code.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Time Grabber</title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
    <script src="/Scripts/modernizr-1.7.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            $("#btnGetTime").click(function() {
                $.ajax({
                    url: "http://localhost:17039/",
                    type: "POST",
                    success: function(result, status, xhr) {
                        $("#utcTime").text(result.UTCTime);
                        $("#utcDate").text(result.UTCDate);
                        $("#localTime").text(result.LocalTime);
                        $("#localDate").text(result.LocalDate);
                    }
                });

                return false;
            });
        });
    </script>
</head>
<body>
    ...

    <form action="/" method="post">
        <input id="btnGetTime" type="submit" value="Get current date/time" />
    </form>

    <p>UTC Time: <span id="utcTime"></span></p>
    <p>UTC Date: <span id="utcDate"></span></p>
    <p>Local Time: <span id="localTime"></span></p>
    <p>Local Date: <span id="localDate"></span></p>

    ...
</body>
</html>

With this additional code, JavaScript-capable browsers will use a progressively enhanced method of retrieving the current date/time while JavaScript-incapable browsers will ignore the script tags in the HTML and just utilize a form post. Boom!

Depending on your knowledge of JQuery, you might be asking yourself how the JavaScript/JQuery code works. While a detailed explanation of this is a topic for another post, in short, it goes something like this:

As soon as the browser completes loading the content of the HTML page, JQuery will trigger the “ready” callback function. The first thing this callback function does is to register a callback function for the button’s click event. This function makes an AJAX call to the server using the “ajax” method, which takes parameters for the url, the method (GET or POST), and a callback function for a successful response (HTTP status code 200). The success callback function takes a few parameters, one of which is the content response from the server (which in this case is formatted as JSON). Inside this callback function, we simply update the values on the page with the values from the response. The final step of the click callback function is to return “false”. This prevents the browser from performing its default behavior to the button click event, which is to post to the server and load a new page. Done.

Whether this whole thing is a case of graceful degradation or progressive enhancement is really a matter of perspective and depends mostly on the developer’s initial goal: optimize for broadest support (progressive enhancement) or optimize for richest user experience (graceful degradation).

If you’d like to play around with the code used in this example, you can download the source code here.

If you found this post helpful or you have questions, please share and/or leave comments.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s