Правильный способ совместного использования JQuery-Mobile / Phonegap?


107

Как правильно (на сегодняшний день) использовать JQuery Mobile и Phonegap вместе?

Обе инфраструктуры необходимо загрузить, прежде чем их можно будет использовать. Как я могу убедиться, что оба загружены, прежде чем я смогу их использовать?


11
пожалуйста ! выберите ответ !!!
realtebo

даже при том, что он этого заслуживает, я не собираюсь ставить +1, пока не будет выбран ответ <3
Дон Вон

1
Какова реальная проблема, которая здесь решается - что, если я просто предоставлю ссылки на необходимые файлы js для jQuery и Cordova в моем index.html, а затем перенаправлю на страницу входа из третьего файла js с помощью jQuery $ .mobile.changePage? Я имею в виду, что мешает этой конструкции работать и зачем мне нужны решения, описанные ниже? Это потому, что внутри jQuery и / или Cordova есть асинхронные загрузки, и мой 3-й файл js может быть загружен даже до загрузки двух фреймворков? Пожалуйста, предложите. Спасибо
Мустафа

@Mustafa, например, вы можете попытаться получить доступ к базе данных ДО того, как ondeviceReadyсобытие будет запущено из вашего кода JQM ...
Мирко

Ответы:


174

Вы можете использовать отложенную функцию 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
этот ответ должен получить больше голосов и быть отмечен как правильный.
мем.

4
Не могли бы вы уточнить немного подробнее? Как выглядит иерархия ссылок на файлы? Спасибо
farjam

2
Не могли бы вы добавить порядок загрузки скрипта, используя последнюю версию ??
realtebo

7
Для всех, кто говорит, что это не работает - порядок объявления скрипта имеет значение. Сначала включите jquery, ЗАТЕМ ЭТОТ КОД в элемент скрипта, затем jquery mobile js.
Маниш

1
О чем cordova.js? Должен ли он быть загружен до или после JQM?
Ferdinand.kraft

17

Вот как это сработало для меня, основываясь на примере выше

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

Это тоже сработало для меня, но если я добавлю <div id = "test-index-page" data-role = "page"> </div> на ту же страницу до закрытия тега html, страница не загружается, и я получаю ошибки . Я хочу начать использовать обе структуры, используя третий файл js с момента загрузки обоих. Как я могу это сделать?
Мустафа

Конечно, я попытался загрузить третий js-файл с бизнес-логикой для моего приложения в doInit (), но это не сработало. В этом файле есть логика привязки событий и объявления функций, например $ (document) .delegate ('# fakhera-index-page', 'pageinit', function (event) {...}. Как я могу это сделать?
Мустафа,

7

Чтобы использовать телефонную связь вместе с jQuery Mobile, вам нужно использовать ее следующим образом

<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

Как многие предлагали использовать отложенный вариант, это приемлемый вариант, если вам все равно, в каком порядке devicereadyи что mobileinitпроисходит. Но в моем случае мне понадобилось несколько pageshowсобытий при первой загрузке приложения и, mobileinitсоответственно, эти события pageshow/ pagebeforeshow/ etc были все стрельбы до devicereadyзавершения, поэтому я не мог правильно привязать к ним, используя отложенный для них. Это состояние гонки было не очень хорошо.

Что мне нужно было сделать, так это убедиться, что 'mobileinit' не произойдет до тех пор, пока ' deviceready' уже не будет запущен. Поскольку mobileinitсрабатывает сразу при загрузке JQM, я решил использовать его jQuery.getScriptдля загрузки ПОСЛЕ того, как devicereadyон уже был завершен.

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

Причина, по которой я скрываю тело, заключается в том, что побочным эффектом этого метода является полсекунды видимости исходного HTML-документа до загрузки jquery.mobile. В этом случае скрытие лишних полсекунды пустого пространства предпочтительнее, чем просмотр документа без стиля.


1
+1 к вашему ответу, потому что это вдохновило меня решить мою проблему с небольшим изменением. Сначала переместите код body.hide () в самую первую строку onBodyLoad (); Во-вторых, переместите код body.show () после getScript (jQM_PATH); Потому что mobileInit () вызывается при каждом переходе страницы JQM. Не идеально. Надеюсь, это поможет другим.
GeorgeW

Можете ли вы просто включить остальную часть вашего?index.html
JGallardo

Это не сработало для меня, потому что Кордова удаляла все файлы, которые не были включены с помощью <script>тега.
Крис Сноу

2

Я считаю, что нет необходимости использовать отложенную функцию. (Может быть, в новых версиях телефонного разговора в этом нет необходимости?) У меня есть это в голове моего файла index.html, и все работает нормально. Я действительно думаю, что порядок включения jquery, phonegap и jquery mobile важен.

<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

это работа для меня. на основе dhaval, этот образец, когда я учусь использовать 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

Чтобы основываться на ответе @ Jeffrey, я нашел гораздо более чистый способ, который скрывает разметку HTML до тех пор, пока JQM не завершит обработку страницы и не отобразит первый элемент страницы, поскольку я заметил, что 1/2 секунды мерцает голая разметка перед визуализацией JQM.

Вам нужно только скрыть всю разметку с помощью css ... PageShow () от JQM переключит видимость для вас.

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


попробовал ваше предложение, и это не сработало для меня. JQM pageshow не отображает скрытую первую страницу. Более того, стандартный html все еще отображается до того, как будет скрыт. В конце концов я заставил его работать на основе решения Джеффри с небольшими изменениями во времени. см. мой комментарий под его ответом.
GeorgeW,

0

Следующее работало для меня на PG 2.3 и JQM 1.2, включая. Плагин 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

Загрузка PhoneGap немного отличается от загрузки jQuery. jQuery работает больше как служебная библиотека, поэтому вы включаете ее, и она сразу же доступна для использования. С другой стороны, PhoneGap требует поддержки собственного кода для правильной инициализации, поэтому он не готов к использованию вскоре после включения на страницу.

Phonegap предлагает зарегистрироваться и дождаться devicereadyвыполнения какого-либо нативного кода.

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

Для получения дополнительной информации проверьте документ


1
Но проблема в том, что я хочу использовать телефонные разговоры в своем коде jquery. В вашем примере весь код jquery будет запущен до того, как телефонная связь будет загружена. Может быть, если я помещу весь код в функцию onDeviceReady ()? Примерно так: $ ("# form"). Live ("pageinit", function (event) {// здесь материал phonegapp});
Juw

если ваша #formпервая страница, то вы не получите pageinitобратного вызова, так как уже слишком поздно
dhaval
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.