HPI Spinners - tsgrp/HPI GitHub Wiki

HPI uses two methods for displaying loading spinners: a loading spinner GIF or the spin.js library. The spin.js library method is the preferred method for displaying loading indications to the user because of its high configurability and it's small size (it's actually smaller than the loading GIF - 10.1 KB vs. 14.5 KB). Of course, you may have good reason to use the loading spinner GIF instead...and you know what, good for you.

Loading spinner GIF

To use the loading spinner GIF in your code, you simple insert an img tag into your markup and reference the loading spinner GIF image. The following is an example:

<img src="assets/css/styles/img/loading.gif" />

This is typically given some sort of knockout data bind or Handlebars conditional to control its visibility. The following knockout data bind example will only should the img tag if the value of loading is truthy.

<img src="assets/css/styles/img/loading.gif" data-bind="visible: loading()" />

Likewise, the following Handlebars example only shows the img tag if the value of loading is truthy.

{{#if loading}}
    <img src="assets/css/styles/img/loading.gif" />
{{/if}}

To style the loading image GIF, it is strongly recommended to style it using CSS (in fact, don't ever style it inline). You could accomplish your styling by first giving your img tag an id or class attribute, and then adding some style via CSS:

<!-- HTML -->
<img class="autoCompleteLoadingSpinner" src="assets/css/styles/img/loading.gif" />

<!-- CSS Style -->
/* The below selector would probably be scoped better as well */
.autoCompleteLoadingSpinner {
    height: 20px;
    width: 20px;
}

Spin.js Library

The other option for displaying spinners in HPI is to use the spin.js library. It's a very simple plugin that has pretty good documentation here. However, we no longer directly use the spin.js library - there is an HPISpinner module that is used instead.

HPISpinner module

The HPISpinner module abstracts the spin.js functionality.

To use the HPISpinner module, you first must include the module in your module:

define("myModule", [
    "app",
    "modules/common/spinner"
],
function(app, HPISpinner) {
    /* My Module code */
}

After including the HPISpinner module, you can create a spinner by calling the createSpinner method.

HPISpinner.createSpinner(options, domElement);

The createSpinner method takes two arguments: the options you want to use to create the spinner and the DOM element where this spinner should be added as a first child. The options object can contain any of the options found in the spin.js documentation. If you don't need any special options, just provide an empty object as the first argument to the createSpinner method and the following defaults will be used (slightly different than the defaults on the spin.js library for good reason):

var defaults = {
    lines: 10, // The number of lines to draw
    length: 4, // The length of each line
    width: 3, // The line thickness
    radius: 6, // The radius of the inner circle
    corners: 1, // Corner roundness (0..1)
    rotate: 25, // The rotation offset
    direction: 1, // 1: clockwise, -1: counterclockwise
    color: '#000', // #rgb or #rrggbb or array of colors
    speed: 1, // Rounds per second
    trail: 60, // Afterglow percentage
    shadow: false, // Whether to render a shadow
    hwaccel: false, // Whether to use hardware acceleration
    className: 'loading-spinner', // The CSS class to assign to the spinner
    zIndex: 2e9, // The z-index (defaults to 2000000000)
    top: '50%', // Top position relative to parent
    left: '50%' // Left position relative to parent
};

The DOM element argument to the createSpinner method is the DOM element to add the created spinner as the first child. This is not a jQuery object - it is the DOM element (jQuery selectors return an array of matched DOM elements).

The following example shows a valid and invalid example of calling the createSpinner method:

<!-- VALID -->
HPISpinner.createSpinner({
    shadow: true,
    color: #666
}, $(".myElement")[0]);

<!-- INVALID - the .myElement selector returns an array of matched DOM elements -->
HPISpinner.createSpinner({
    shadow: true,
    color: #666
}, $(".myElement"));

The createSpinner method returns the spinner object that it creates. This is useful if you want to create multiple spinners on the same page and for when you are done with a spinner and want to stop it.

To stop a spinner, call the destroySpinner method.

HPISpinner.destroySpinner(spinner);

The destroySpinner method takes a spinner object that was created by the createSpinner method and removes it from the DOM.

Example

The below example creates a spinner object, makes an AJAX call to do some processing and stops the spinner that it created when it is done:

MyModule.doAjaxWork = function(myRestEndpoint) {
    // create our loading spinner, which also starts it spinning
    var loadingSpinner = HPISpinner.createSpinner({
        shadow: true,
        color: #666
    }, $(".loadingWork")[0]);

    // make our AJAX call now that we're displaying our loading spinner to the user
    $.ajax({
        url: app.serviceUrlRoot + myRestEndpoint,
        data: { takeAwhile: true },
        success: function(data) {
            // display my data here
        }
    }).always(function() {
        // done processing so we want to destroy our loading spinner
        HPISpinner.destroySpinner(loadingSpinner);
    });
}