Difference between $(document).ready and $(document).on('pageinit')

user1903894 picture user1903894 · Dec 14, 2012 · Viewed 24.2k times · Source

I'm using jquery mobile and I'd like to reproduce this code:

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

it shows the spinner until I decide to hide it using in other functions

$.mobile.loading( 'hide' );

Now I see that document.ready() is deprecated in jquery mobile 1.2, so they suggest to replace it with $(document).on('pageinit')

But If I replace my code with the suggested one the spinner autohide... why? This is the new code:

 $(document).on('pageinit',function(){
     $.mobile.loading( 'show' );
 });

Answer

Gajotres picture Gajotres · Dec 14, 2012

Related:

This article can also be found as a part of my blog HERE.

Solution

First off all you need to understand jQM page events and their flow .

$(document).on('pageinit',function(){
    $.mobile.loading( 'show' );
});

is indeed a replacement for:

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

but jQM page consists from few phases. In your case, to be able to show a spinner you need to use pageshow event. Page must be shown to be able to show spinner. I have created an example for you: http://jsfiddle.net/Gajotres/Nncem/. In it go to next page to see a spinner. You can also replace pageshow with pageinit to see a difference.

You should use this code:

$(document).live('pageshow', function (e, data) {
    $.mobile.loading('show');
});  

But even this is not a correct way, best jQM way is to use this syntax:

$('div[data-role="page"]').live('pageshow', function (e, data) {
    $.mobile.loading('show');
});    

Or if you want to bind it to a single page use this:

$('#pageID').live('pageshow', function (e, data) {
    $.mobile.loading('show');
});  

Where pageID is an ID of your page.

$(document).on('pageinit') vs $(document).ready()

The first thing you learn in jQuery is to call code inside the $(document).ready() function so everything will execute as soon as the DOM is loaded. However, in jQuery Mobile, Ajax is used to load the contents of each page into the DOM as you navigate. Because of this $(document).ready() will trigger before your first page is loaded and every code intended for page manipulation will be executed after a page refresh. This can be a very subtle bug. On some systems it may appear that it works fine, but on others it may cause erratic, difficult to repeat weirdness to occur.

Classic jQuery syntax:

$(document).ready() { 

});

To solve this problem (and trust me this is a problem) jQuery Mobile developers created page events. In a nutshell page events are events triggered in a particular point of page execution. One of those page events is a pageinit event and we can use it like this:

$(document).on('pageinit', function(){

});

We can go even further and use a page id instead of document selector. Lets say we have jQuery Mobile page with an id index:

<div data-role="page" id="index">
    <div data-theme="a" data-role="header">
        <h3>
            First Page
        </h3>
        <a href="#second" class="ui-btn-right">Next</a>
    </div>

    <div data-role="content">
        <a href="#" data-role="button" id="test-button">Test button</a>
    </div>

    <div data-theme="a" data-role="footer" data-position="fixed">

    </div>
</div>

To execute a code that will only available to the index page we could use this syntax:

$('#index').on('pageinit', function(){

});

Pageinit event will be executed every time page is about be be loaded and shown for the first time. It will not trigger again unless page is manually refreshed or ajax page loading is turned off. In case you want code to execute every time you visit a page it is better to use pagebeforeshow event.

Here's a working example : http://jsfiddle.net/Gajotres/Q3Usv/ to demonstrate this problem.

Few more notes on this question. No matter if you are using 1 html multiple pages or multiple html files paradigm it is advised to separate all of your custom javascript page handling into a single separate js file. This will note make your code any better but you will have much better code overview, especially while creating a jQuery Mobile application.

There's also another special jQuery Mobile event and it is called mobileinit.When jQuery Mobile starts, it triggers a mobileinit event on the document object. To override default settings, bind them to mobileinit. One of a good examples of mobileinit usage is turning off ajax page loading, or changing default ajax loader behavior.

$(document).on("mobileinit", function(){
  //apply overrides here
});