¿Forma correcta de usar JQuery-Mobile / Phonegap juntos?


107

¿Cuál es la forma correcta (hasta la fecha) de usar JQuery Mobile y Phonegap juntos?

Ambos marcos deben cargarse antes de poder usarse. ¿Cómo puedo estar seguro de que ambos están cargados antes de poder usarlos?


11
Por favor ! escoge una respuesta !!!
Realtebo

aunque se lo merece, no voy a hacer +1 en esto hasta que se elija una respuesta <3
Don Vaughn

1
¿Cuál es el problema real que se resuelve aquí? ¿Qué pasa si solo proporcioné referencias a los archivos js requeridos para jQuery y Cordova en mi index.html y luego redirigí para decir la página de inicio de sesión desde un tercer archivo js usando $ .mobile.changePage de jQuery? Me refiero a qué impide que este diseño funcione y por qué necesito las soluciones que se describen a continuación. ¿Es porque hay cargas asincrónicas dentro de jQuery y / o Cordova y mi tercer archivo js podría cargarse incluso antes de que se carguen los 2 marcos? Por favor recomiende. Gracias
Mustafa

@Mustafa, por ejemplo, puede intentar acceder a la base de datos ANTES de ondeviceReadyque se active el evento desde su código JQM ...
Mirko

Respuestas:


174

Puede utilizar la función diferida de 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
}

3
esta respuesta debería obtener más votos y marcarse como la correcta.
memical

4
¿Podría elaborar un poco más por favor? ¿Cómo es la jerarquía de referencias de archivos? Gracias
farjam

2
Por favor, ¿podría agregar el orden de carga del script, usando la última versión?
realtebo

7
Para todos aquellos que dicen que no funciona, el orden de declaración del guión es importante. Primero incluya jquery, LUEGO ESTE CÓDIGO dentro de un elemento de script, luego jquery mobile js.
Manish

1
¿Qué hay de cordova.js? ¿Debe cargarse antes o después de JQM?
Ferdinand.kraft

17

Así es como funcionó para mí, según el ejemplo anterior

<!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>

Esto también funcionó para mí, pero si agrego <div id = "test-index-page" data-role = "page"> </div> a la misma página antes de que la etiqueta html se cierre, la página no se carga y obtengo errores . Quiero comenzar a usar ambos marcos usando un tercer archivo js desde el punto en que ambos están cargados. ¿Cómo puedo hacer eso?
Mustafa

Por supuesto, intenté cargar el tercer archivo js que tiene lógica comercial para mi aplicación en doInit () pero no funcionó. Ese archivo tiene lógica de enlace de eventos y declaraciones de funciones, por ejemplo, $ (documento) .delegate ('# fakhera-index-page', 'pageinit', function (event) {...}. ¿Cómo puedo hacer esto?
Mustafa

7

Para usar phonegap junto con jquery mobile, debe usarlo así

<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>  

6

Como muchas personas sugirieron que usar un diferido es una buena opción siempre y cuando no te importe qué orden devicereadyy qué mobileinitsucede. Pero en mi caso, necesitaba algunos pageshoweventos cuando la aplicación se cargó por primera vez mobileinity, por extensión, esos eventos pageshow/ pagebeforeshow/ etc. todos disparando antes de devicereadyterminar, por lo que no pude unirlos correctamente usando un diferido en ellos. Esta condición de carrera no fue buena.

Lo que tenía que hacer era asegurarme de que 'mobileinit' no se llevara a cabo hasta después de que ' deviceready' ya fuera despedido. Porque se mobileinitdispara inmediatamente cuando cargas JQM que elegí usar jQuery.getScriptpara cargarlo DESPUÉS de que devicereadyya estuviera terminado.

<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>

La razón por la que oculto el cuerpo es que un efecto secundario de este método es medio segundo de visibilidad del documento HTML original antes de que se cargue jquery.mobile. En este caso, se prefiere ocultarlo medio segundo adicional de espacio vacío a ver el documento sin estilo.


1
+1 en su respuesta porque me inspiró a resolver mi problema con un pequeño cambio. Primero, mueva el código body.hide () a la primera línea de onBodyLoad (); En segundo lugar, mueva el código body.show () para que esté después de getScript (jQM_PATH); Porque, mobileInit () se llama en cada transición de página JQM. No es ideal. Espero que esto ayude a otros.
GeorgeW

¿Puedes incluir el resto de tuindex.html
JGallardo

Esto no funcionó para mí porque cordova estaba eliminando todos los archivos que no estaban incluidos con la <script>etiqueta.
Chris Snow

2

Creo que no es necesario utilizar la función diferida. (¿Quizás esto no sea necesario con las versiones más nuevas de phonegap?) Tengo esto en el encabezado de mi archivo index.html y todo funciona bien. Creo que el orden de inclusión de jquery, phonegap y jquery mobile es importante.

<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>

1

esto es trabajo para mi base en dhaval, esta muestra cuando aprendo a usar sqlite

<!DOCTYPE html>
<html>
 <head>
<title>Cordova Sqlite+Jquery</title>
<script type="text/javascript" charset="utf-8" src="js/jquery-1.8.3.min.js"></script>   
<script type="text/javascript" charset="utf-8" src="cordova-2.2.0.js"></script>
<script type="text/javascript" charset="utf-8">`

// Call onDeviceReady when Cordova is loaded.
//
// At this point, the document has loaded but cordova-1.8.0.js has not.
// When Cordova is loaded and talking with the native device,
// it will call the event `deviceready`.
//
function onLoad() {
    document.addEventListener("deviceready", onDeviceReady, false);
}

// Populate the database 
//
function populateDB(tx) {
    tx.executeSql('DROP TABLE IF EXISTS DEMO');
    tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, data)');
    tx.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")');
    tx.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")');
}

// Query the database
//
function queryDB(tx) {
    tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}

// Query the success callback
//
function querySuccess(tx, results) {
    var len = results.rows.length;
    //console.log("DEMO table: " + len + " rows found.");
    $('#result').html("DEMO table: " + len + " rows found.");
    var listval = '';
    for (var i=0; i<len; i++){
        //console.log("Row = " + i + " ID = " + results.rows.item(i).id + " Data =  " + results.rows.item(i).data);
         listval += '<li>'+ results.rows.item(i).data + '[' + results.rows.item(i).id + '] </li>';
    }

    $('#listItem').html(listval);

}

// Transaction error callback
//
function errorCB(err) {
    console.log("Error processing SQL: "+err.code);
}

// Transaction success callback
//
function successCB() {
    var db = window.openDatabase("Database", "1.0", "PhoneGap Demo", 200000);
    db.transaction(queryDB, errorCB);
}

// Cordova is loaded and it is now safe to make calls Cordova methods
//
function onDeviceReady() {
    // Now safe to use the Cordova API
    //alert('ready');
    var db = window.openDatabase("Database", "1.0", "PhoneGap Demo", 200000);
    db.transaction(populateDB, errorCB, successCB);
    //$('#result').html('hello');
}

</script>
  </head>
 <body onload="onLoad()">
  <div>result:</div><div id="result"></div>
  <ul id="listItem">
  </ul>
 </body>
 </html>

0

Para aprovechar la respuesta de @ Jeffrey, encontré una forma mucho más limpia que oculta el marcado HTML hasta que JQM haya terminado de procesar la página y muestre el primer elemento de la página, ya que he notado que 1/2 segundo parpadea en el marcado desnudo antes de que se procese JQM.

Solo necesita ocultar todo el marcado con css ... PageShow () de JQM alternará la visibilidad por usted.

//snip
<style type="text/css">
.hide {
  display:none;
}
</style>

//snip - now the markup notice the hide class
<div id="page1" data-role="page" class="hide">
     //all your regular JQM / html form markup
</div>

//snip -- down to the end of /body
<script src="cordova-2.2.0.js"></script>
<script src="js/jquery-1.8.2.min.js"></script>
<script>
   document.addEventListener(
     'deviceready',
      function () {
         $(document).one("mobileinit", function () {
         //any JQM init methods

       });
      $.getScript('js/jquery.mobile-1.2.0.min.js');
   },
   false);
</script>


Probé tu sugerencia y no funcionó para mí. La presentación de páginas de JQM no mostrará la primera página oculta. Además, el HTML estándar sigue apareciendo antes de ocultarse. Finalmente lo hice funcionar basado en la solución de Jeffrey con ligeros cambios en el tiempo. vea mi comentario debajo de su respuesta.
GeorgeW

0

Lo siguiente funcionó para mí en PG 2.3 y JQM 1.2, incl. Complemento de Facebook Connect:

<head>
<script src="./js/jquery-1.8.2.min.js"></script>
<script>
    $.ajaxSetup({
        dataType : 'html'
    });

    var dd = $.Deferred();
    var jqd = $.Deferred();
    $.when(dd, jqd).done(function() {                

        FB.init({ appId: auth.fbId, nativeInterface: CDV.FB, useCachedDialogs: false });
    });

    $(document).bind('mobileinit', function () {
        jqd.resolve();
    });                        
</script>
<script src="./js/jquery.mobile-1.2.0.min.js"></script>
<script>
    $.mobile.loader.prototype.options.text = "loading";
    $.mobile.loader.prototype.options.textVisible = true;
    $.mobile.loader.prototype.options.theme = "a";
    $.mobile.loader.prototype.options.html = "";

    $.mobile.ajaxEnabled = false;
    $.mobile.allowCrossDomainPages = true;
    $.support.cors = true;       

    $('[data-role=page]').live('pagecreate', function(event) {                      
        tpl.renderReplace('login', {}, '#content-inner', function() {                   
            auth.init();
        });
    });
</script>
<script src="./js/cordova-2.3.0.js"></script>
<script src="./js/cdv-plugin-fb-connect.js"></script>
<script src="./js/facebook_js_sdk.js"></script>                     
<!--some more scripts -->
<script>        
    document.addEventListener('deviceready', function() {
        dd.resolve();
    }, false);                        
</script>  
<head>

-1

La carga de PhoneGap es ligeramente diferente a la carga de jQuery. jQuery funciona más como una biblioteca de utilidades, por lo que incluye eso y está disponible para su uso de inmediato. Por otro lado, PhoneGap requiere soporte de código nativo para una inicialización adecuada, por lo que no está listo para usarse poco después de incluirse en la página.

Phonegap sugiere registrarse y esperar a que el devicereadyevento ejecute cualquier código nativo específico.

<!DOCTYPE html>
<html>
  <head>
    <title>PhoneGap Example</title>

    <script type="text/javascript" charset="utf-8" src="lib/jquery.min.js"></script>
    <script type="text/javascript">
        // jquery code here
    </script>
    <script type="text/javascript" charset="utf-8" src="lib/android/cordova-1.7.0.js"></script>
    <script type="text/javascript" charset="utf-8">

    function onLoad(){
        document.addEventListener("deviceready", onDeviceReady, false);
    }

    // Cordova is ready
    function onDeviceReady() {
        // write code related to phonegap here
    }
    </script>
  </head>
  <body onload="onLoad()">
    <h1>Phonegap Example</h1>
  </body>
</html>

Para obtener más información, consulte el documento.


1
Pero el problema es que quiero usar cosas de phonegap en mi código jquery. En su ejemplo, todo el código jquery se ejecutará antes de que se cargue phonegap. ¿Quizás si pongo todo el código dentro de la función onDeviceReady ()? Así: $ ("# formulario"). Live ("pageinit", function (evento) {// cosas de phonegapp aquí});
Juw

si su #formes la primera página, entonces no recibirá pageinitdevolución de llamada porque es demasiado tarde
dhaval
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.