web-dev-qa-db-fra.com

Création de modèles / modèle d'en-tête / pied de page 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é afin qu'il soit plus facile à modifier.

Étant donné que 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 ne l'ai vu que là où vous en avez besoin pour copier et coller tout le pied de page-> code barre de navigation dans chaque page HTML. Cela ne semble pas être le cas. Par exemple, si vous souhaitez modifier un élément de menu, vous devez accéder à chaque page et le modifier.

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 - ce code de barre latérale est-il copié et collé sur chaque page? Cela n'a aucun 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 correct (et $.live('pageinit') ne fonctionne pas). Ce 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>');
}
61
Luke Shaheen

J'essaie de résoudre ce problème depuis quelques jours et je me suis vraiment approché de la solution. J'utilise le 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;
}

La .trigger('create'); et .navbar(); sont les méthodes requises pour maintenir le style JQM correct, cependant, il y a encore un petit bogue. La position du menu (qui est définie à l'aide de css top: ... px) n'est parfois pas correcte et se déplace à la position correcte après le premier tapotement. Vraiment très proche!

Edit: En définissant #footer Sur position: fixed; Le bug mineur que j'ai mentionné ci-dessus a disparu. En outre, il est facile de créer une méthode qui calcule le top (en px) pour le #footer Si la position provoquée par la valeur top par JQM est incorrecte.

22
ostroon

Si vous voulez vraiment le faire correctement, vous devez vous pencher sur 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 et le style du balisage progressif pour les appareils mobiles. Pour la partie MVC réelle, vous avez besoin d'un framework MVC.

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

3
Yacine Filali

Quelque chose comme ça:

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 rôle = pied de page dans le getText et vérifier simplement s'il est défini ... sinon, ajoutez-le.

3
bmurmistro

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

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

Si vous utilisez JQM - AJAX, JQM saisira la page et la joindra à votre DOM existant. Considérez votre première page comme votre page "d'ancrage", à laquelle toutes les pages suivantes sont ajoutées/supprimées.

Dans le deuxième cas, vous pouvez spécifier un attribut data-append-to-all-pages = "true" sur les éléments que vous souhaitez avoir sur chaque page.

Écoutez ensuite 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 extraite et ajoutée au DOM.

J'examine en ce moment avec un formulaire de connexion, dont j'ai besoin sur chaque page en dehors de la connexion et éviter de se retrouver avec une entrée en double # someID.

EDIT - solution possible

Mettez l'élément respectif sur la première page et ajoutez des attributs uniques, comme ceci:

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

Toutes les autres pages reçoivent simplement le conteneur d'élément unique

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

Utilisez ensuite 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 en transporteriez simplement le contenu pendant que vous parcourez 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 modifier son contenu, par exemple en ajoutant une classe active.

2
frequent

Nous n'avons pas encore trouvé un bon moyen de le faire. Nous gérons donc cela de manière dynamique 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
imaginethepoet

N'utilisez pas pageinit, les événements que vous devez é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 ex. sur le bouton arrière. Alors que pageshow se déclenche chaque fois qu'une page est affichée, il suffit donc 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 puisse changer, sinon utilisez pagecreate).

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

Et oui, une excellente solution consiste simplement à utiliser un PHP/CF include, qui est ce que j'utilise au lieu de JS.


[~ # ~] modifier [~ # ~] Mon mauvais, semble pageinit est maintenant utilisé au lieu de pagecreate ( voir ici) , mais il semble toujours que pageshow se déclenche chaque fois qu'une page est affichée - vous pouvez donc les utiliser selon vos besoins

2
Clarence Liu