Tworzenie szablonu/szablonu nagłówka/stopki w jQuery Mobile i PhoneGap

Nurkuję do pisania aplikacji mobilnej z jQuery Mobile / PhoneGap. Używam tego przykładowego szablonu, który używa HTML/JS do tworzenia stron. Zamiast mieć wszystkie tagi <page> w jednym pliku html, ma je podzielone, więc łatwiej jest je edytować.

Ponieważ będę miał osobny plik dla każdej strony, jaki jest najlepszy sposób na dołączenie nagłówka/stopki? widziałem go tylko tam, gdzie trzeba skopiować i wkleić cały kod stopki - > navbar do każdego Strona HTML. Tak nie powinno być. Na przykład, jeśli chcesz zmienić jedną pozycję menu, musisz przejść do każdej strony i zmienić ją.

Jakie rozwiązanie mi umyka?

Może po prostu nie rozumiem jQuery Mobile. Na przykład ich pasek boczny, którego używają do swoich dokumentów - czy kod paska bocznego jest kopiowany i wklejany na każdą stronę? To nie ma sensu. To ten sam pomysł, co pytanie, które tu zadaję o stopkę.

Http://jquerymobile.com/test/docs/pages/page-cache.html

To jest to, co mam, że nie wydaje się w porządku (i $.live('pageinit') nie działa). Ten HTML jest tym, co dzieje się na każdej stronie HTML:

<div id="mainFooter" data-position="fixed" data-id="mainFooter" data-role="footer" class="ui-footer ui-bar-a ui-footer-fixed fade ui-fixed-inline" role="contentinfo" style="top: 58px;">

I JS

$.live('pageinit', function (event) {
    displayFooter();
});

function displayFooter() {
    $('#mainFooter').html('<div data-role="navbar" class="nav-glyphish-example" data-grid="d">' +
        '<ul>' +
        '<li><a href="#" id="menuitem1" data-icon="custom">Menu Item 1</a></li>' +
        '<li><a href="#" id="menuitem2" data-icon="custom">Menu Item 2</a></li>' +
        '<li><a href="#" id="menuitem3" data-icon="custom">Menu Item 3</a></li>' +
        '</ul>' +
        '</div>');
}
Author: Darin Kolev, 2012-02-05

6 answers

Od kilku dni staram się rozwiązać ten problem i bardzo zbliżyłem się do rozwiązania. Używam następującego kodu HTML:

<body>
    <div data-role="page" id="page">

        <div data-role="header">
            <h1 id="title">Title</h1>
        </div><!-- /header -->

        <div data-role="content" id="content">  
            <p>Loading...</p>
        </div><!-- /content -->

        <div data-role="footer" id="footer" data-position="fixed">
            <div data-role="navbar" id="navbar">
            </div>
        </div><!-- /footer -->
    </div><!-- /page -->
</body>

I stworzyłem następujące funkcje do ładowania menu / zawartości za pomocą ajax:

$(document).on('pageinit', "#page", function() {
    // for example: displayFooter();
    loadContent("main");
    loadMenu("default");
});

function loadContent(location) {
    return $('#content').load("views/content/"+location+".html", function() { 
        $(this).trigger('create');
    });
}
function loadMenu(location) {
    $("#menu").remove();
    $("#navbar").remove();

    $("#footer").html('<div data-role="navbar" id="navbar">');
    $("#navbar").html('<ul id="menu"></ul>');

    $("#menu").load("views/menus/"+location+".html", function() { $("#menu").parent().navbar(); });

    return true;
}

.trigger('create'); i .navbar(); są metodami wymaganymi do poprawnej stylizacji JQM, jednak wciąż jest jeden mały błąd. Pozycja menu (które jest ustawiane za pomocą CSS top:...px) czasami nie jest poprawny i przesuwa się do właściwej pozycji po pierwszym dotknięciu. Naprawdę blisko!

Edit: ustawiając #footer na position: fixed; drobny błąd, o którym wspomniałem powyżej, zniknął. Ponadto łatwo jest stworzyć metodę, która oblicza top (w px) dla #footer, jeśli pozycja wywołana przez wartość top przez JQM jest nieprawidłowa.

 22
Author: bartolsthoorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-11 19:47:09

Coś takiego:

function getText() {
    //return footer text here
}


$("div:jqmData(role='page')").live("pagebeforecreate",function() {
    // get find the footer of the page
    var $footer =$(this).page().find('div:jqmData(role="footer")')
    // insert it where you want it... 
}

Możesz po prostu zdefiniować role = footer w getText i po prostu sprawdzić, czy jest zdefiniowany... jeśli nie, dodaj go.

 3
Author: bmurmistro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-09 03:16:04

Jeśli naprawdę chcesz to zrobić poprawnie, musisz zajrzeć do frameworka js, takiego jak Thorax lub JavascriptMVC.

W aplikacji JMVC można to zrobić z dowolnego widoku:

<div data-role="page">
    <%== $.View('./header.ejs') %>
    <div data-role="content">
    ...
    </div>
    <%== $.View('./footer.ejs') %>
</div>

JQuery Mobile jest naprawdę przydatny tylko dla progresywnego ulepszania znaczników i stylizacji dla urządzeń mobilnych. Dla rzeczywistej części MVC potrzebujesz frameworku MVC.

Przykłady dla jQuery Mobile są również głównie przeznaczone do budowania mobilnych stron internetowych, które ponieważ pobierają strony z serwera zakładają ponowne użycie kodu odbywa się po stronie serwera. Aplikacja phonegap to zupełnie inna bestia, ponieważ będziesz generować te strony w locie lub z lokalnych plików statycznych. To było, gdy Framework MVC przychodzi jak budujesz swoje strony za pomocą kontrolerów, widoków, pomocników widoku i klas modelu. Połącz to wszystko z jQuery mobile, słuchając zdarzenia pagebeforeshow pokazanego na stronie dokumentacji jQm na stronach skryptów

 3
Author: Yacine Filali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-09 22:18:23

Jeszcze nie znaleźliśmy na to dobrego sposobu. Tak więc w rzeczywistości obsługujemy to dynamicznie w naszym niestandardowym pliku js. Szukanie kontenera zamykającego-a następnie dynamiczne dodawanie stopki po zamknięciu ostatniej zawartości div.

 2
Author: imaginethepoet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-06 13:36:05

Zależy, jak załadujesz odpowiednie strony.

Jeśli użyjesz rel= "external" - no AJAX, każda strona zostanie całkowicie załadowana.

Jeśli używasz zwykłego JQM-AJAX, JQM chwyci stronę i dołączy ją do istniejącego DOM. Pomyśl o swojej pierwszej stronie jako o swojej stronie "kotwicy", którą wszystkie kolejne strony są dodawane/usuwane.

W drugim przypadku możesz określić atrybut data-append-to-all-pages="true" dla elementów, które chcesz mieć na każdej stronie.

Potem po prostu posłuchaj odpowiednie wydarzenie (pagebeforeshow?) i dodać elementy z powyższą etykietą do nowej strony przed jej wyświetlaniem. W ten sposób elementy muszą być ustawiane tylko na pierwszej stronie, a następnie automatycznie dodawane do każdej kolejnej strony, która jest wciągana i dodawana do DOM.

Sprawdzam to teraz z formularzem logowania, który potrzebuję na każdej stronie poza loginem i muszę uniknąć skończenia z duplikatem input#someID.

Edycja-możliwe rozwiązanie

Put odpowiedni element na pierwszej stronie i dodać unikalne atrybuty, w ten sposób:

 <div data-role="navbar" data-unique="true" data-unique-id="log">
     // full navbar
 </div>

Wszystkie inne strony po prostu dostać unikalny kontener elementu

<div data-role="navbar" data-unique="true" data-unique-id="log"></div>

Następnie użyj tego skryptu:

$('div:jqmData(role="page")').live('pagebeforehide', function(e, data) {

    //  check page you are leaving for unique items 
    $(this).find('div:jqmData(unique="true")').each(function(){

         // more or less 1:1 stickyFooter
         var uniqueID = $(this).jqmData("unique-id"),
             nextPage = data.nextPage,
             nextUnique = nextPage && nextPage.find( "div:jqmData(unique-id='"+uniqueID+"')" ),
             nextMatches = nextUnique.length && nextUnique.jqmData('unique-id') === uniqueID;

         // if unique items on previous and new page are matching
         if ( uniqueID && nextMatches ) {
            nextUnique.replaceWith( uniqueID );
            $(this).jqmData("unique-id").empty();
            }
         });
     }); 

Oczywiście oznaczałoby to, że potrzebujesz unikalnego kontenera na każdej stronie. Ale wtedy po prostu nosisz jej zawartość podczas przechodzenia przez aplikację. Powinno działać dla mnie i unikać tego samego formularza logowania 2 + razy wewnątrz DOM.

Dodatkowo będziesz mógł edytować to zawartość na przykład dodanie active class.

 2
Author: frequent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-09 07:04:42

Nie używaj pageinit, zdarzenia, których powinieneś słuchać to pagecreate i pageshow, pagecreate jest wywoływany przy pierwszym załadowaniu strony, ale nie podczas powrotu do strony, np. przy przycisku Wstecz. Podczas gdy pageshow jest uruchamiany za każdym razem, gdy strona jest wyświetlana, więc po prostu powiązaj Live listener ze zdarzeniem pageshow dla każdej strony, na której dodasz stopkę (zakładając, że stopka może się zmienić, w przeciwnym razie użyj pagecreate).

Mam dłuższy przykład, który pokazuje, jak powiązać Zdarzenie prawidłowo w innym pytaniu: https://stackoverflow.com/a/9085014/737023

I tak świetnym rozwiązaniem jest po prostu użycie PHP / CF include, którego używam zamiast JS.


EDIT Mój błąd, wygląda na to, że pageinit jest teraz używany zamiast pagecreate (patrz tutaj), ale nadal stoi, że pageshow jest uruchamiany za każdym razem, gdy strona jest wyświetlana-więc możesz używać tych, których potrzebujesz

 2
Author: Clarence Liu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:40