web-dev-qa-db-ja.com

jQuery MobileおよびPhoneGapでのテンプレート/永続的なヘッダー/フッターテンプレートの作成

私は、jQuery Mobile/PhoneGapを使用してモバイルアプリの作成に没頭しています。 このサンプルテンプレート を使用して開始し、HTML/JSを使用してページを作成します。すべての_<page>_タグを1つのhtmlファイルに収めるのではなく、編集しやすいように分割しました。

ページごとに個別のファイルがあるため、テンプレートのヘッダー/フッターを含める最良の方法は何ですか?フッター全体をコピーして貼り付ける必要がある場所でのみ見ました-> navbarコード各HTMLページに。これはそうあるべきではないようです。たとえば、1つのメニュー項目を変更する場合は、各ページに移動して変更する必要があります。

私が欠けている解決策は何ですか?

JQuery Mobileを理解していないだけかもしれません。たとえば、ドキュメントに使用するサイドバー-サイドバーコードは各ページにコピーアンドペーストされますか?それは意味がありません。これは、ここでフッターについて質問している質問と同じ考えです。

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

これは私が持っているもので、正しくないようです($.live('pageinit')が機能していません)。このHTMLは、各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;">
_

そして、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

私は数日前からこの問題に取り組もうとしており、本当に解決策に近づきました。次の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>
_

そして、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');.navbar();は、JQMスタイリングを正しく保つために必要なメソッドですが、まだ1つの小さなバグがあります。メニューの位置(css top:... pxを使用して設定)が正しくない場合があり、最初のタップ後に正しい位置に移動します。本当に近い!

編集: _#footer_を_position: fixed;_に設定することで、上記のマイナーなバグはなくなりました。また、JQMによるtop値に起因する位置が正しくない場合、_#footer_のtop(px)を計算するメソッドを作成するのは簡単です。

22
ostroon

これを本当に適切に行いたい場合は、ThoraxやJavascriptMVCなどのjsフレームワークを調べる必要があります。

JMVCアプリでは、任意のビューからこれを行うことができます。

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

jQuery Mobileは、モバイルデバイスのプログレッシブマークアップの強化とスタイリングにのみ有効です。実際のMVCパーツには、MVCフレームワークが必要です。

JQuery Mobileの例は、サーバーからページを取得するため、コードの再利用がサーバー側で行われていると想定しているため、モバイルWebサイトの構築にも主に適しています。 phonegapアプリは、これらのページをオンザフライで、またはローカルの静的ファイルから生成するため、一流の獣です。これは、コントローラー、ビュー、ビューヘルパー、およびモデルクラスを使用してページを構築するためにMVCフレームワークが入っていたものです。 scripting pages のjQmドキュメントページに示されているように、pagebeforeshowイベントをリッスンすることにより、これらすべてをjQuery mobileに結び付けます。

3
Yacine Filali

このようなもの:

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

getTextでrole = footerを定義し、定義されているかどうかを確認するだけです...定義されていない場合は追加します。

3
bmurmistro

各ページのロード方法によって異なります。

Rel = "external"-AJAXを使用しない場合、各ページは完全にリロードされます。

通常のJQM-AJAXを使用する場合、JQMはページを取得して既存のDOMに添付します。最初のページを「アンカー」ページと考えてください。それ以降のすべてのページは追加/削除されます。

2番目のケースでは、すべてのページに含める要素にdata-append-to-all-pages = "true"属性を指定できます。

次に、それぞれのイベント(pagebeforeshow?)をリッスンし、上記のラベルを持つ要素を新しいページに追加してから表示します。この方法では、要素は最初のページで設定するだけでよく、その後、引き込まれてDOMに追加される後続のページに自動的に追加されます。

私は今ログインフォームでこれを調べていますが、ログインフォームはログイン外のすべてのページで必要であり、重複するinput#someIDで終わることを避けなければなりません。

編集-可能な解決策

最初のページにそれぞれの要素を配置し、次のように一意の属性を追加します。

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

他のすべてのページは、一意の要素コンテナを取得するだけです

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

次に、このスクリプトを使用します。

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

もちろん、これはすべてのページに一意のコンテナが必要であることを意味します。しかし、その後、アプリを横断するときにコンテンツを持ち歩くだけです。私のために働いて、DOM内で同じログインフォームを2回以上持つことは避けてください。

さらに、アクティブなクラスを追加するなど、その内容を自由に編集できます。

2
frequent

これを行う良い方法もまだ見つかりませんでした。そのため、実際にカスタムjsファイルでこれを動的に処理しています。閉じているコンテナを探し、最後のコンテンツdivが閉じた後にフッターを動的に追加します。

2
imaginethepoet

Pageinitを使用しないでください。リッスンする必要があるイベントはpagecreateとpageshowです。pagecreateは、ページが最初に読み込まれたときに呼び出されますが、ページに戻るときは呼び出されません。戻るボタン。 pageshowはページが表示されるたびに起動するので、フッターを追加するすべてのページのpageshowイベントにライブリスナーをバインドするだけです(フッターが変更される可能性がある場合は、pagecreateを使用します)。

別の質問でイベントに適切にバインドする方法を示す長い例があります: https://stackoverflow.com/a/9085014/73702

はい、素晴らしい解決策は、PHP/CFインクルードを使用することです。これは、JSの代わりに使用するものです。


[〜#〜] edit [〜#〜]悪いことに、pagecreateの代わりにpageinitが使用されるようになりました (こちらを参照してください 、ただし、ページが表示されるたびにページショーが起動することは変わりません-必要に応じて使用できます

2
Clarence Liu