3

I'm going mad trying to get a spinner to appear. I've bound my heavy processing function to a button thus:

$(document).delegate("#clearread", "tap", onClearRead);

So on tap it calls this:

var onClearRead = function() {

setTimeout($.mobile.showPageLoadingMsg, 5);  

// Civilised cleaning of saved status
var jStorIndex = $.jStorage.index();
for (var i = 0; i < jStorIndex.length; i++) {
    if( jStorIndex[i] != "version" ) {
        $.jStorage.deleteKey(jStorIndex[i]);
    }
}   

// Load articles afresh
loadArticles();

$.mobile.changePage("#choosearticle");

} //onClearRead

I find that the spinner does not appear during the clearing/loading of articles (about 10 secs) but only for a brief period while the #choosearticle page loads (0.5 secs). What am I doing wrong?

I have the spinner working elsewhere in the app.

Thanks

Alveoli
  • 1,202
  • 17
  • 29
  • @Nirmal Patel just fixed my problem, but anybody know _WHY_ a crazy random settimeout is required? I've read it's about CPU contention, anybody able to explain in more detail? – Alveoli Jun 07 '12 at 14:18
  • 1
    The problem is the JS runs in a single thread in the browser. So if you put in heavy processing; the browser does not attempt to redraw/repaint contents until the JS is finished. And by the time the JS is done; we have invoked a changePage()... the setTimeout just gives the browser enough breather to do other tasks before getting back to heavy lifting in the JS. – Nirmal Patel Jun 07 '12 at 14:35
  • finally, some clarity - thank you! – Alveoli Jun 07 '12 at 15:02

2 Answers2

4

Try this:

$(document).delegate("#clearread", "tap", onClearRead);

var onClearRead = function() {
$.mobile.showPageLoadingMsg();
setTimeout(function(){  
        //Your heavy processing
        $.mobile.changePage("#choosearticle");
    }, 5);
} //onClearRead
Nirmal Patel
  • 5,128
  • 8
  • 41
  • 52
  • 1
    **Yes it works - thank you!** I have found that you may need to up the milliseconds (to say 100) if the device is slow. Otherwise the spinner still doesn't appear. – Alveoli Jun 07 '12 at 14:16
0

jQuery.show( [duration ] [, complete ] )

Putting the heavy processing in the "complete" function slot, ensures the object (with show called on it) is visible before the show happens.

Related SO Answers

https://stackoverflow.com/a/25207120/999943

jQuery whole HTML page load with spinner

Example using a CSS based spinner

CSS

@-moz-keyframes spin {
  0% {
    -moz-transform: rotate(0deg); }

  100% {
    -moz-transform: rotate(359deg); } }

@-webkit-keyframes spin {
  0% {
    -webkit-transform: rotate(0deg); }

  100% {
    -webkit-transform: rotate(359deg); } }

@-o-keyframes spin {
  0% {
    -o-transform: rotate(0deg); }

  100% {
    -o-transform: rotate(359deg); } }

@-ms-keyframes spin {
  0% {
    -ms-transform: rotate(0deg); }

  100% {
    -ms-transform: rotate(359deg); } }

@keyframes spin {
  0% {
    transform: rotate(0deg); }

  100% {
    transform: rotate(359deg); } }

.icon-spin {
  display: inline-block;
  -moz-animation: spin 2s infinite linear;
  -o-animation: spin 2s infinite linear;
  -webkit-animation: spin 2s infinite linear;
  animation: spin 2s infinite linear; }

Html using font awesome

<div id="spinner" data-bind="visible: isSpinning" style="padding: 10px; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #cccccc; z-index: 1; filter: alpha(opacity=30);">

    <i class="fa fa-spinner fa-spin fa-5x"></i>
</div>

Javascript

$('#spinner').show(100, function() {
  // Once the spinner is visible then run the heavy function.
  heavyProcessingFunction();
});
phyatt
  • 18,472
  • 5
  • 61
  • 80