5

I have a single-page web-app built with knockout.js and jQuery Mobile.

The view-model initialization (i.e. the ko.applyBindings() function) takes about 7-8 seconds. During this time, the page shows blank.

$(document).ready(function () {
    ko.applyBindings(viewModel);
})

Is there a way to show the JQM loader in the meantime, or to show a kind of "splash screen", to give to the user a feedback that the "page is loading"?

Note that it seems to me that the solution proposed by @Jeroen is also good together with the default page transitions of jQuery Mobile, at least as I can see in this jsfiddle.

To be honest, the tip proposed by @Omar seems to me to have better integration with JQM, and I will try in the future to combine both answers, with a writeable computed observable to switch the JQM loader on/off.

Jeroen
  • 60,696
  • 40
  • 206
  • 339
user2308978
  • 187
  • 3
  • 14
  • use `$.mobile.loading('show')` and `$.mobile.loading('hide')`. – Omar Aug 29 '13 at 14:06
  • can you post a copy of your viewModel? Why is it taking so long? Is it because of AJAX? – Bradley Trager Aug 29 '13 at 16:03
  • @Omar: i tried it, but maybe i'm doing something wrong, its not showing. The viewModel is about 2000 rows long, but its online at http://preciso-enjoy.it/ppc/product_configurator.html – user2308978 Aug 29 '13 at 16:40
  • @BradleyTrager: yes, you are right if you wonder for this delay! Its not because of Ajax, its only client-side. There is for sure something wrong, i'm investigating now, but i don't know exactly how to debug that. – user2308978 Aug 30 '13 at 08:09
  • There are several methods here (http://stackoverflow.com/questions/111368/how-do-you-performance-test-javascript-code) for testing performance – Bradley Trager Aug 30 '13 at 14:19
  • Or you can post another question with your code and ask why it is slow. – Bradley Trager Aug 30 '13 at 14:19

1 Answers1

10

Keep it simple! Show a loading overlay in your html by default, but use a visible: false binding of some kind. That way when the applyBindings call is done the UI will hide the overlay.

For example, suppose this view:

<div id="main">
    <div id="loading-overlay" data-bind="visible: loading"></div>
    Some content<br />
    Some content
</div>

And suppose this view model:

vm = { loading: ko.observable(true) };

Then calling this:

ko.applyBindings(vm);

If for whatever reason it takes 7 secs to load, the loading-overlay will be shown until the UI is updated.

This approach is great if you have a client side DAL or some single point where you run Ajax calls, because you can follow this pattern:

  1. vm.loading(true)
  2. Ajax call with callbacks for success and failure
  3. On callback do vm.loading(false)

Knockout will handle the overlay visibility for you.

See this fiddle for a demo, or check out this Stack Snippet:

vm = { loading: ko.observable(true) };

ko.applyBindings(vm);

// Mock long loading time:
window.setTimeout(function() {
    vm.loading(false);
}, 5000);
html { height: 100%; }

body {
    position: relative;
    height: 100%;
    width: 100%;
}

#loading-overlay {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: url('http://img.cdn.tl/loading51.gif') white no-repeat center;
    opacity: 0.75;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<div id="main">
    <div id="loading-overlay" data-bind="visible: loading"></div>
    Some content<br />
    Some content<br />
    Some content<br />
    Some content<br />
    Some content<br />
    <input type='text' value='cant edit me until overlay is gone' /><br />
    <button>can't press me until overlay's gone!</button><br />
    Some content<br />
    Some content<br />
    Some content
</div>
Jeroen
  • 60,696
  • 40
  • 206
  • 339
  • Great tip! BTW, if any reason, can i ask you why you propose a self-made solution with the div instead of a more standard solution, like the one that Omar proposed? – user2308978 Aug 31 '13 at 09:24
  • i found right now that your solution has, among others, also the advantage that it works before JQM applies the DOM transformation. I mean, it could be also useful to prevent the flashing of unstyled elements at the very beginning of the page initialization. – user2308978 Aug 31 '13 at 10:25
  • Aye, the solution is simple and doesn't rely on jQuery to be initially shown. One disadvantage is browser support, particularly IE7 can be grumpy about absolute positioning (not sure about mobile browsers though). – Jeroen Aug 31 '13 at 10:49