Création d'un modèle d'en-tête/pied de page templated/persistant dans jQuery Mobile et PhoneGap

Je plonge dans l'écriture d'une application mobile avec jQuery Mobile / PhoneGap. J'utilise cet exemple de modèle pour commencer, qui utilise HTML / JS pour créer les pages. Plutôt que d'avoir toutes les balises <page> dans un seul fichier html, il l'a divisé, il est donc plus facile à éditer.

Puisque j'aurai un fichier séparé pour chaque page, Quelle est la meilleure façon d'inclure l'en-tête/pied de page tempéré? Je l'ai seulement vu où vous devez copier et coller le pied de page entier- > code navbar dans chaque La page HTML. Cela ne semble pas comme il devrait être. Par exemple, si vous voulez changer un élément de menu, vous devez aller dans chaque page et le changer.

Quelle est la solution qui me manque?

Peut-être que je ne comprends tout simplement pas jQuery Mobile. Par exemple, leur barre latérale qu'ils utilisent pour leurs documents-est-ce que le code de la barre latérale est copié et collé sur chaque page? Qui n'a pas de sens. C'est la même idée que la question que je pose ici sur le pied de page.

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

C'est Ce que j'ai qui ne semble pas droit ($.live('pageinit') ne fonctionne pas). Ce code HTML est ce qui se passe sur chaque page 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;">

Et le 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>');
}
60
demandé sur Darin Kolev 2012-02-05 23:53:42

6 réponses

J'essaie de résoudre ce problème depuis quelques jours maintenant et je suis vraiment proche de la solution. J'utilise le code HTML suivant:

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

Et j'ai créé les fonctions suivantes pour charger le menu/contenu en utilisant 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;
}

Les .trigger('create'); et .navbar(); sont les méthodes nécessaires pour garder le style JQM correct, cependant, il y a encore un petit bug. La position du menu (qui est définie en utilisant CSS top: ...px) est parfois pas correct et se déplace à la bonne position après le premier robinet. Vraiment proche cependant!

Edit: {[17] } en définissant #footer à position: fixed; Le bug mineur que j'ai mentionné ci-dessus est parti. En outre, il est facile de faire une méthode qui calcule le top (en px) pour le #footer si la position causée par la valeur top par JQM est incorrecte.

22
répondu bartolsthoorn 2012-02-11 19:47:09

Quelque Chose comme ceci:

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

Vous pouvez simplement définir le role = footer dans le getText et vérifier simplement s'il est défini... si non, alors l'ajouter.

3
répondu bmurmistro 2012-02-09 03:16:04

Si vous voulez vraiment le faire correctement, vous devez regarder dans un framework js comme Thorax ou JavascriptMVC.

Dans une application JMVC, vous pouvez le faire depuis n'importe quelle vue:

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

JQuery Mobile n'est vraiment utile que pour l'amélioration progressive du balisage et du style pour les appareils mobiles. Pour la partie MVC réelle, vous avez besoin d'un framework MVC.

Les exemples pour jQuery Mobile sont également principalement destinés à la construction de sites Web mobiles qui, puisqu'ils récupèrent des pages à partir d'un serveur, supposent votre la réutilisation du code se passe côté serveur. Une application phonegap est une bête entière puisque vous générerez ces pages à la volée ou à partir de fichiers statiques locaux. C'est là que le framework MVC intervient alors que vous construisez vos pages à l'aide de contrôleurs, de vues, d'aides de vue et de classes de modèle. Vous attachez tout cela à jQuery mobile en écoutant l'événement pagebeforeshow comme indiqué sur la page de documentation jQm sur les pages de script

3
répondu Yacine Filali 2012-02-09 22:18:23

Nous n'avons pas encore trouvé un bon moyen de le faire non plus. Nous gérons donc cela dynamiquement dans notre fichier JS personnalisé. Recherche du conteneur de fermeture - puis ajout dynamique du pied de page après la fermeture de la dernière div de contenu.

2
répondu imaginethepoet 2012-02-06 13:36:05

Dépend de la façon dont vous chargez les pages respectives.

Si vous utilisez rel="external" - sans AJAX, chaque page sera rechargée complètement.

Si vous utilisez JQM - AJAX régulier, JQM va saisir la page et l'attacher à votre DOM existant. Pensez à votre première page comme votre page "ancre", que toutes les pages suivantes sont ajoutées/supprimées.

Dans le 2ème cas, vous pouvez spécifier les données-ajouter-pour-tous-pages="true" attribut sur les éléments que vous souhaitez avoir sur chaque page.

Alors écoutez l'événement respectif (pagebeforeshow?) et ajoutez des éléments avec l'étiquette ci-dessus à la nouvelle page avant qu'elle ne soit affichée. De cette façon, les éléments ne devraient être définis que sur la première page, puis automatiquement ajoutés à toute page suivante tirée et ajoutée au DOM.

Je regarde cela en ce moment avec un formulaire de connexion, dont j'ai besoin sur chaque page en dehors de la connexion et je dois éviter de me retrouver avec une entrée en double#someID.

Modifier-solution possible

Mettre chaque élément sur la première page et ajouter des attributs uniques, comme ceci:

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

Toutes les autres pages obtiennent simplement le conteneur d'élément unique

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

Ensuite, utilisez ce script:

$('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();
            }
         });
     }); 

Bien sûr, cela signifierait que vous avez besoin du conteneur unique sur chaque page. Mais alors vous simplement porter le contenu de celui-ci le long que vous traversez à travers l'application. Devrait fonctionner pour moi et éviter d'avoir le même formulaire de connexion 2 + fois dans le DOM.

De plus, vous seriez libre de l'éditer contenu par exemple en ajoutant une classe active.

2
répondu frequent 2012-02-09 07:04:42

N'utilisez pas pageinit, les événements que vous devriez écouter sont pagecreate et pageshow, pagecreate est appelé la première fois qu'une page est chargée, mais pas lorsque vous revenez à la page, par exemple sur le bouton Précédent. Alors que pageshow se déclenche chaque fois qu'une page est affichée, il suffit de lier un écouteur en direct à l'événement pageshow pour chaque page où vous ajoutez votre pied de page (en supposant que votre pied de page peut changer, sinon utilisez pagecreate).

J'ai un plus exemple qui vous montre comment lier l'événement correctement dans une autre question: https://stackoverflow.com/a/9085014/737023

Et oui une bonne solution est juste d'utiliser un include PHP/CF, ce que j'utilise à la place de JS.


modifier Mon mauvais, semble pageinit est maintenant utilisé à la place de pagecreate (voir ici) , mais il reste que pageshow se déclenche chaque fois qu'une page est affichée - de sorte que vous pouvez les utiliser comme vous avez besoin

2
répondu Clarence Liu 2017-05-23 11:46:40