Correct way of using JQuery-Mobile/Phonegap together?

You can use deferred feature of JQuery.

var deviceReadyDeferred = $.Deferred();
var jqmReadyDeferred = $.Deferred();

document.addEventListener("deviceReady", deviceReady, false);

function deviceReady() {
  deviceReadyDeferred.resolve();
}

$(document).one("mobileinit", function () {
  jqmReadyDeferred.resolve();
});

$.when(deviceReadyDeferred, jqmReadyDeferred).then(doWhenBothFrameworksLoaded);

function doWhenBothFrameworksLoaded() {
  // TBD
}

Here's how it worked for me, based on the example above

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
        <link rel="stylesheet" type="text/css" href="css/bootstrap.css" />
        <title>InforMEA</title>
    </head>
    <body>
        <script type="text/javascript" src="js/jquery-1.8.3.js"></script>
        <script type="text/javascript">
            var dd = $.Deferred();
            var jqd = $.Deferred();
            $.when(dd, jqd).done(doInit);

            $(document).bind('mobileinit', function () {
                jqd.resolve();
            });
        </script>
        <script type="text/javascript" src="js/jquery.mobile-1.2.0.js"></script>
        <script type="text/javascript" src="cordova-2.2.0.js"></script>
        <script type="text/javascript">
            document.addEventListener('deviceready', deviceReady, false);
            function deviceReady() {
                dd.resolve();
            }

            function doInit() {
                alert('Ready');
            }
        </script>
    </body>
</html>

In order to use phonegap along with jquery mobile, you need to use it like this

<head>
<title>Index Page</title>

<!-- Adding viewport -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no">

<!-- Adding jQuery scripts -->
<script type="text/javascript" src="jquery/jquery-1.7.1.min.js"></script>

<!-- Since jQuery Mobile relies on jQuery core's $.ajax() functionality,
 $.support.cors & $.mobile.allowCrossDomainPages must be set to true to tell
 $.ajax to load cross-domain pages. -->
<script type="text/javascript">
    $(document).bind("mobileinit", function() {
        $.support.cors = true;
        $.mobile.allowCrossDomainPages = true;
    });
</script>

<!-- Adding Phonegap scripts -->
<script type="text/javascript" charset="utf-8"
    src="cordova/cordova-1.8.0.js"></script>

<!-- Adding jQuery mobile scripts & CSS -->
<link rel="stylesheet" href="jquerymobile/jquery.mobile-1.1.0.min.css" />
<script type="text/javascript"
    src="jquerymobile/jquery.mobile-1.1.0.min.js"></script>

</head>
<script type="text/javascript">
    // Listener that will invoke the onDeviceReady() function as soon as phonegap has loaded properly
    document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
        navigator.splashscreen.hide();

        document.addEventListener("backbutton", onBackClickEvent, false); // Adding the back button listener    

    }
    </script>
<body>
<div data-role="page" id="something" data-ajax="false">
        <script type="text/javascript">
            $("#something").on("pageinit", function(e) {

            });

            $("#something").on("pageshow", function(e) {

            });

            $("#something").on("pagebeforeshow", function(e) {

            });
        </script>

        <div data-role="header">            
        </div>

        <div data-role="content">           
        </div>      
    </div>
</body>  

As many people suggested using a deferred is an okay option as long as you don't care what order deviceready and mobileinit happe in. But in my case, I needed a few pageshow events when the application first loaded and mobileinit and by extension those pageshow/pagebeforeshow/etc events were all firing before deviceready finished, so I couldn't bind to them properly using a deferred on them. This race condition was not a good thing.

What I needed to do was make sure 'mobileinit' didn't take place until after 'deviceready' was already fired. Because mobileinit fires immediately when you load JQM I chose to use jQuery.getScript to load it AFTER deviceready was already finished.

<script src="cordova-2.2.0.js"></script>
<script src="js/jquery-1.8.2.min.js"></script>
<script src="js/async.min.js"></script>
<script src="js/app.js"></script>
<script>
  document.addEventListener(
    'deviceready',
    function () {
      $('body').css('visibility', 'hidden');
      $(document).one("mobileinit", function () {
        app.init();
        $('body').css('visibility', '');
      });
      $.getScript('js/jquery.mobile-1.2.0.min.js');
    },
    false
  );
</script>

The reason I'm hiding the body is that a side effect of this method is a half second of visibility of the original HTML document before jquery.mobile loads. In this case hiding it an extra half second of empty space is preferred to seeing the unstyled document.


I believe that it isn't necessary to use the deferred feature. (Maybe this isn't necessary with newer versions of phonegap?) I have this in the head of my index.html file and everything works fine. I do think that the order of including jquery, phonegap and jquery mobile are important.

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="format-detection" content="telephone=no" />
    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />

    <!-- Adding jQuery -->
    <script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>

    <!-- Add Phonegap scripts -->
    <script type="text/javascript" src="phonegap.js"></script>

    <!-- Add jQuery mobile -->
    <link rel="stylesheet" href="css/jquery.mobile-1.3.2.css" />
    <script type="text/javascript" src="js/jquery.mobile-1.3.2.min.js"></script>

    <title>MY TITLE</title>
</head>