Sean
Sean

Reputation: 5820

Show Page Loading Spinner on Ajax Call in jQuery Mobile

I'm using $.ajax() to populate a list in my mobile web app. What I'd like to do is have the jQuery mobile loading spinner appears while this call is being performed and disappear once the list populates. The current version of JQM uses $.mobile.showPageLoadingMsg() and $.mobile.hidePageLoadingMsg() to show and hide the loading spinner, respectively. I can't figure out where exactly to place these statements to get the correct result. This seems like it should be a fairly easy thing to accomplish, I just haven't been able to find anything about this exact scenario.

Here's the ajax call inside the pagecreate function:

$('#main').live('pagecreate', function(event) {
        $.ajax({
            url: //url
            dataType: 'json',
            headers: //headers
            success: function(data) {
                for(i = 0; i < data.length; i++) {
                    $('#courses').append('<li>' + data[i].name + '<ul id="course' + data[i].id + '"></ul>' + '<span class="ui-li-count">' + data[i].evaluatedUserIds.length + '</span></li>');
                    $('#course' + data[i].id).listview();
                    for(j = 0; j < data[i].evaluatedUserIds.length; j++) {
                        $('#course' + data[i].id).append('<li><a href="">' + data[i].evaluatedUserIds[j] + '</a></li>');
                    }
                    $('#course' + data[i].id).listview('refresh');
                }
                $('#courses').listview('refresh');
            }
        });
    });

Upvotes: 36

Views: 77520

Answers (8)

sandeep talabathula
sandeep talabathula

Reputation: 3308

Or, the simplest way is to put it globally as a separation of concern -

Put below code into your master/layout view

   <script type="text/javascript">

    $(document).bind('mobileinit', function () {
        //Loader settings
        $.mobile.loader.prototype.options.text = "Loading..";
        $.mobile.loader.prototype.options.textVisible = true;
        $.mobile.loader.prototype.options.theme = "b";
        $.mobile.loader.prototype.options.textonly = false; 
    }); 

    $(document).on({
        ajaxSend: function () { $.mobile.showPageLoadingMsg(); },
        ajaxStart: function () { $.mobile.showPageLoadingMsg(); },
        ajaxStop: function () { $.mobile.hidePageLoadingMsg(); },
        ajaxError: function () { $.mobile.hidePageLoadingMsg(); }
    });

</script> 

Edit: Please use instead if you are targeting latest version of JQM (>1.2):

  • $.mobile.loading('show');
  • $.mobile.loading('hide');

Upvotes: 3

Marvin Emil Brach
Marvin Emil Brach

Reputation: 3972

Before JQM 1.2:

$(document).ajaxStart(function() {
    $.mobile.showPageLoadingMsg();
});

$(document).ajaxStop(function() {
    $.mobile.hidePageLoadingMsg();
});

Since JQM 1.2:

$(document).ajaxStart(function() {
    $.mobile.loading('show');
});

$(document).ajaxStop(function() {
    $.mobile.loading('hide');
});

http://api.jquerymobile.com/page-loading/

Upvotes: 50

Alex Turpin
Alex Turpin

Reputation: 47776

You can use the beforeSend and complete events of $.ajax to call $.mobile.showPageLoadingMsg and $.mobile.hidePageLoadingMsg. Would look like this:

$('#main').live('pagecreate', function(event) {
        $.ajax({
            beforeSend: function() { $.mobile.showPageLoadingMsg(); }, //Show spinner
            complete: function() { $.mobile.hidePageLoadingMsg() }, //Hide spinner
            url: //url
            dataType: 'json',
            headers: //headers
            success: function(data) {
                //...
            }
        });
    });

Upvotes: 58

Patrioticcow
Patrioticcow

Reputation: 27058

$(document).ajaxSend(function() {
    $.mobile.loading( 'show');
});
$(document).ajaxComplete(function() {
    $.mobile.loading( 'hide');
});

Upvotes: 9

juleq
juleq

Reputation: 31

The problem here is that the call to $.ajax() happens within the control flow of the event handler (the caller).

A very simple way to decouple the ajax request from this control flow is to let setTimeout() invoke this function for you, like so:

setTimeout(function(){$.ajax( ... )}, 1);

You can then use the 'beforeSend' and 'complete' events of $.ajax() as stated before and be sure, that your spinner is showing up.

Upvotes: 2

Ben
Ben

Reputation: 1454

This is a bit late...but you need to:

  1. Call $.mobile.showPageLoadingMsg() before the AJAX call.
  2. Make the AJAX call. The call needs to be sent asynchronously (put async: true in your call).
  3. Add $.mobile.hidePageLoadingMsg() in your success() function.

Upvotes: 10

Sean
Sean

Reputation: 5820

A few people have asked about the workaround I ended up implementing, so I figured I'd share it. It's nothing particularly elegant or complicated, but it did seem to work. I haven't used the framework since the official 1.0 was released, so this may have been solved in the update. Essentially, I put the $.mobile.showPageLoadingMsg() call into the pageshow function, but wrapped it in an if clause that only fires the first time the page is shown:

var mainloaded = false;

$('#main').live('pageshow', function(event) {   //Workaround to show page loading on initial page load
    if(!mainloaded) {
    $.mobile.showPageLoadingMsg();
    }
});

$('#main').live('pagecreate', function(event) { 
    $.ajax({
        url: //url
        dataType: //datatype,
        headers: //headers
        success: function(data) {
            //
            //...loading stuff
            //
            $.mobile.hidePageLoadingMsg();
            mainloaded = true;
        }
        //
        //...handle error, etc.
        //
    });
});

Upvotes: 14

degenerate
degenerate

Reputation: 1427

You should do $.mobile.showPageLoadingMsg() just before the ajax call, and $.mobile.hidePageLoadingMsg() in the success (or fail) block so it goes away once a result comes back.

I've never used jQuery mobile, but it should operate the same as showing/hiding a regular ol' spinning image.

Upvotes: 3

Related Questions