Back to Labs

Delayed-Loading Indicator

This article presents the third example in a series from Progressively Enhance It! at Barcamp Philly.

In this example, we have a product detail page. When the user chooses a different color, new images are loaded into the page via ajax.

Color Loading on Product Detail Page

In our initial implementation, we add a loading indicator as soon as the user clicks a color and then remove the loading indicator after a successful ajax response. If the response fails, we show an error to the user. Our initial HTML and JavaScript look like this:

<div class="product-detail">
    <!-- … -->
    <li>
        <a class="color" href="/products/transcend-jacket?color=black">Black</a>
    </li>
    <!-- … -->
</div>
var addLoadingIndicator = function (element) { /* … */ },
    removeLoadingIndicator = function (element) { /* … */ },
    updateProduct = function () { /* … */ },
    alertError = function () { /* … */ };

$('.product-detail').on('click', 'a.color', function (e) {
    e.preventDefault();

    var button = this;

    addLoadingIndicator(button);

    $.ajax({
        url: button.href
        complete: function () {
            removeLoadingIndicator(button);
        },
        success: function () {
            updateProduct();
        },
        error: function () {
            alertError();
        }
    });
});

The problem with this code is our servers are fast and the ajax response usually occurs so quickly that the loading indicator isn’t needed. It actually makes the response feel slower, and a quick flicker of a loading indicator may even look like a bug. We want to show the loading indicator only if the response takes more than 300 milliseconds. Our code to do so looks like this:

$('.product-detail').on('click', 'a.color', function (e) {
    e.preventDefault();

    var button = this,
        loading = true;

    _.delay(function () {
        if (loading) {
            addLoadingIndicator(button);
        }
    }, 300);

    $.ajax({
        url: button.href
        complete: function () {
            loading = false;
            removeLoadingIndicator(button);
        },
        success: function () {
            updateProduct();
        },
        error: function () {
            alertError();
        }
    });
});

When the color button is clicked, we start a 300ms timer using delay and then make our ajax request. After the request completes (regardless of success or failure), we set a flag to indicate the response is finished. When our timer expires, it checks the flag to see if the request has finished or is still in progress. If still in progress, we show a loading indicator.

This example demonstrates another use of Underscore’s delay method and also provides a foundation we will build on in future examples.

Summary of features

The library features covered by this example are:

Leave a Comment

Your email address will not be published. Required fields are marked *

Top of Page