Właściwy sposób wspólnego korzystania z JQuery-Mobile / Phonegap?

107

Jaki jest poprawny (do tej pory) sposób jednoczesnego używania JQuery Mobile i Phonegap?

Obie platformy muszą zostać załadowane, zanim będą mogły być używane. Jak mogę się upewnić, że oba są załadowane, zanim będę mógł ich użyć?

Juw
źródło
11
Proszę ! wybierz odpowiedź !!!
realtebo
chociaż zasługuje na to, nie zamierzam dawać +1, dopóki nie zostanie wybrana odpowiedź <3
Don Vaughn
1
Jaki jest rzeczywisty problem, który jest tutaj rozwiązany - co jeśli właśnie podam odniesienia do wymaganych plików js dla jQuery i Cordova w moim index.html, a następnie przekierowuję do strony logowania z trzeciego pliku js przy użyciu $ .mobile.changePage jQuery? Mam na myśli, co powstrzymuje ten projekt przed działaniem i dlaczego potrzebuję rozwiązań opisanych poniżej? Czy to dlatego, że istnieją asynchroniczne obciążenia wewnątrz jQuery i / lub Cordova, a mój trzeci plik js może zostać załadowany nawet przed załadowaniem dwóch frameworków? Proszę zasugeruj. Dzięki
Mustafa
@Mustafa na przykład możesz spróbować uzyskać dostęp do bazy danych PRZED ondeviceReadywyzwoleniem zdarzenia z twojego kodu JQM ...
Mirko

Odpowiedzi:

174

Możesz użyć odroczonej funkcji 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
}
Oktawian
źródło
3
ta odpowiedź powinna otrzymać więcej głosów i zostać oznaczona jako poprawna.
memical
4
Czy mógłbyś wyjaśnić trochę więcej? Jak wygląda hierarchia odniesień do plików? Dzięki
farjam
2
Czy mógłbyś dodać kolejność ładowania skryptu, używając najnowszej wersji?
realtebo
7
Dla wszystkich, którzy mówią, że to nie działa - kolejność deklarowania skryptu ma znaczenie. Najpierw dołącz jquery, NASTĘPNIE TEN KOD wewnątrz elementu skryptu, a następnie jquery mobile js.
Manish
1
O co chodzi cordova.js? Czy powinien zostać załadowany przed czy po JQM?
Ferdinand.kraft
17

Oto, jak to zadziałało, na podstawie powyższego przykładu

<!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>
Cristian Romanescu
źródło
U mnie też to zadziałało, ale jeśli dodam <div id = "test-index-page" data-role = "page"> </div> do tej samej strony przed zamknięciem tagu HTML, strona się nie ładuje i pojawiają się błędy . Chcę zacząć używać obu frameworków przy użyciu trzeciego pliku js od punktu, w którym oba są załadowane. W jaki sposób mogę to zrobić?
Mustafa
Oczywiście próbowałem załadować trzeci plik js, który ma logikę biznesową dla mojej aplikacji w doInit (), ale to nie zadziałało. Ten plik ma logikę powiązań zdarzeń i deklaracje funkcji, np. $ (Document) .delegate ('# fakhera-index-page', 'pageinit', function (event) {...}. Jak mogę to zrobić?
Mustafa
7

Aby używać phonegap razem z jquery mobile, musisz używać go w ten sposób

<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>  
Coder_sLaY
źródło
6

Jak wiele osób sugerowało użycie odroczonej opcji, o ile nie obchodzi cię, w jakiej kolejności devicereadyi co się mobileinitdzieje. Ale w moim przypadku potrzebowałem kilku pageshowzdarzeń, gdy aplikacja została załadowana po raz pierwszy, mobileinita co za tym idzie, te zdarzenia pageshow/ pagebeforeshow/ etc były wszystkie strzelały przed devicereadyzakończeniem, więc nie mogłem się z nimi prawidłowo związać za pomocą odroczonego na nich. Ten stan wyścigu nie był dobry.

Musiałem upewnić się, że „mobileinit” nie nastąpi, dopóki „ deviceready” nie zostanie już uruchomiony . Ponieważ mobileinituruchamia się natychmiast po załadowaniu JQM, zdecydowałem się użyć go jQuery.getScriptdo załadowania po devicereadyzakończeniu już.

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

Powodem, dla którego ukrywam treść, jest to, że efektem ubocznym tej metody jest pół sekundy widoczności oryginalnego dokumentu HTML przed załadowaniem jquery.mobile. W takim przypadku preferowane jest ukrycie dodatkowego pół sekundy pustego miejsca niż obejrzenie dokumentu bez stylizacji.

Jeffrey Van Alstine
źródło
1
+1 Twojej odpowiedzi, ponieważ zainspirowało mnie to do rozwiązania mojego problemu z niewielką zmianą. Najpierw przenieś kod body.hide () do pierwszego wiersza onBodyLoad (); Po drugie, przenieś kod body.show () tak, aby znajdował się po getScript (jQM_PATH); Ponieważ mobileInit () jest wywoływana przy każdym przejściu strony JQM. Nieidealny. Mam nadzieję, że to pomoże innym.
George W.
Czy możesz po prostu dołączyć resztęindex.html
JGallardo
To nie zadziałało, ponieważ Cordova usuwała wszystkie pliki, które nie były uwzględnione przy użyciu <script>tagu.
Chris Snow,
2

Uważam, że nie ma potrzeby korzystania z funkcji odroczonej. (Może nie jest to konieczne w nowszych wersjach phonegap?) Mam to w nagłówku pliku index.html i wszystko działa dobrze. Myślę, że kolejność włączania jquery, phonegap i jquery mobile jest ważna.

<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>
Allie Hoch Janoch
źródło
1

to jest praca dla mnie. bazuje na dhaval, ten przykład, kiedy uczę się korzystania z 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>
Ztuons Ch
źródło
0

Aby zbudować na odpowiedzi @ Jeffrey, znalazłem znacznie czystszy sposób, który ukrywa znaczniki HTML do czasu zakończenia przetwarzania strony przez JQM i renderowania pierwszego elementu strony, ponieważ zauważyłem, że migotanie nagiego znacznika przez JQM trwa pół sekundy.

Musisz tylko ukryć wszystkie znaczniki za pomocą css ... PageShow () firmy JQM przełączy dla Ciebie widoczność.

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

Erik
źródło
wypróbowałem twoją sugestię i nie zadziałała. Pokaz stron JQM nie pokaże ukrytej pierwszej strony. Co więcej, standardowy html nadal pojawia się, zanim zostanie ukryty. W końcu sprawiłem, że zadziałało w oparciu o rozwiązanie Jeffreya z niewielkimi zmianami w czasie. zobacz mój komentarz pod jego odpowiedzią.
George W.
0

Poniższe działały dla mnie na PG 2.3 i JQM 1.2, w tym. Wtyczka 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>
Jens Peters
źródło
-1

Ładowanie PhoneGap różni się nieco od ładowania jQuery. jQuery działa bardziej jak biblioteka narzędzi, więc dołączasz ją i jest dostępna do natychmiastowego użytku. Z drugiej strony PhoneGap wymaga wsparcia ze strony kodu natywnego w celu poprawnej inicjalizacji, więc nie jest gotowy do użycia wkrótce po umieszczeniu na stronie.

Phonegap sugeruje rejestrację i oczekiwanie na devicereadyzdarzenie, które wykona dowolny natywny kod.

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

Więcej informacji w doc

dhaval
źródło
1
Ale problem polega na tym, że chcę używać rzeczy phonegap w moim kodzie jQuery. W twoim przykładzie cały kod jquery zostałby uruchomiony jeszcze przed załadowaniem phonegap. Może jeśli umieszczę cały kod wewnątrz funkcji onDeviceReady ()? W ten sposób: $ ("# form"). Live ("pageinit", function (event) {// tu coś z phonegapp});
Juw
jeśli #formjest to pierwsza strona, nie otrzymasz pageinitoddzwonienia, ponieważ jest już za późno
dhaval