Persistent header in jQuery Mobile
Couldn't figure out a way to put a bounty on my old question, so I'm reposting it because maybe it was a bug.
Short version: I want a persistent header in a PhoneGap+JQM application that stays in-place (never moves) between page transitions like the footer can be designed to do.
Long version: First off, I'm totally new to jQuery and JQM, so please point out any newb mistakes I've made.
I'm trying to get a header that persists between different pages in the application. It would have to be like the persistent footer that stays in place whenever the user is transitioning between pages. The persistent footer was achieved using data-role="footer" data-id="(some consistent id)" data-position="fixed". It worked fairly well (random glitches with it getting misplaced then automatically fixing itself after a couple seconds). For more inf开发者_如何转开发ormation on what I'm looking for, see "Persistent Footer" here: http://jquerymobile.com/test/docs/#/test/docs/toolbars/docs-footers.html
And see the example of the persistent footer at the link below. See how selecting an item in the footer transitions to a completely new page, yet the footer doesn't move: http://jquerymobile.com/test/docs/#/test/docs/toolbars/footer-persist-a.html
Now I'm trying to do the same thing, but I want it to be at the top of the application instead of the bottom. I've tried the following things:
- Shifting the footer to the top of the page (don't know what tag to catch in jQuery. Tried div.(jQuery class) utilizing several jQuery classes, but none work. I used FireBug to determine it is the "top" CSS attribute that needs to be changed.
The HTML on each page:
<div data-role="footer" data-position="fixed" data-id="header">
<img src="images/bgheader.png" />
</div>
The JavaScript:
$('div.ui-footer').css('top', '0px');
$('div.ui-footer-fixed').css('top', '0px');
$('div.fade').css('top', '0px');
$('div.ui-fixed-overlay').css('top', '0px');
$('div.ui-bar-a').css('top', '0px');
- Using data-role="header" (doesn't persist like the footer does). This method will create the header I want (because I overrode some of the CSS), but when I transition between pages, it won't maintain the header at the top. JQM documentation also does not state that they support persistent headers while it does state that it supports persistent footers:
The HTML on each page:
<div data-role="header" data-position="fixed" data-id="header" id="header" data-backbtn="false">
<img src="images/bgheader.png" />
</div>
A little bit of jquery will do the trick
<script type="text/javascript">
$(document).ready(function() {
$('#lpage1:first').addClass('ui-btn-active'); //set the first tab as active
firstContent=$('#content1'); //defining selectors
secondContent=$('#content2');
secondContent.hide(); //hide the second content division
});
// show only the first content div
function showContent1() {
firstContent.show();
secondContent.hide();
}
function showContent2() {
firstContent.hide();
secondContent.show();
}
//clicking on tab 2
$('#lpage2').live('tap',function(event){
//alert("click");
showContent2();
});
</script>
<body>
<!-- Start of first page -->
<div data-role="page" id="page1">
<div data-role="header" data-position="fixed">
<h1>Foo</h1>
<div data-role="navbar">
<ul>
<li><a href="#" id="lpage1" data-transition="pop">Home<br/> </a></li>
<li><a href="#" id="lpage2" data-transition="pop">My<br/>Profile</a></li>
</ul>
</div><!-- /navbar -->
</div><!-- /header -->
<!-- page1 -->
<div data-role="content" id="content1">
<p>I'm first in the source order so I'm shown as the page.</p>
<p>View internal page called <a href="#bar">bar</a></p>
</div><!-- /content -->
<!-- page2 -->
<div data-role="content" id="content2">
<p>I'm second in the source order so I'm shown as the page.</p>
<p>View internal page called <a href="#bar">bar</a></p>
</div><!-- /content -->
<div data-role="footer">
<h4>Page Footer</h4>
</div><!-- /footer -->
</div><!-- /page -->
I've been banging my head against this problem for several days, and for once Google was no help. I finally came up with the following solution. It copies the header HTML onto a new page before the transition begins, then removes the code from the previous page once the transition completes. The header and footer will still move with the page transition, but they will persist even while navigating nested lists.
// dynamically move the header and footer between pages on load events
$('div.ui-page').live('pagebeforeshow', function(event, ui) {
// avoid duplicating the header on the first page load
if (ui.prevPage.length == 0) return;
// remove the jQuery Mobile-generated header
$('.ui-header').addClass('to-remove-now');
$('#header').removeClass('to-remove-now');
$('.to-remove-now').remove();
// grab the code from the current header and footer
header = $('#header')[0].outerHTML;
footer = $('#footer')[0].outerHTML;
// mark the existing header and footer for deletion
$('#header').addClass('to-remove');
$('#footer').addClass('to-remove');
// prepend the header and append the footer to the generated HTML
event.currentTarget.innerHTML = header + event.currentTarget.innerHTML + footer;
});
// remove header from previous page
$('div.ui-page').live('pagehide', function(event, ui) {
$('.to-remove').remove();
});
Then just add id="header"
to the header div and id="footer"
to the footer, and place them as you normally would in your content.
Add the following css to your page or to the bottom of the css file
Please note I have not tested this code on mobile devices..
<style type="text/css">
.ui-header {
position: fixed !important;
top: 0 !important;
z-index: 99;
}
.ui-content {
margin-top: 35px;
}
</style>
1) Besides the jquery.js, jquerymobile.js and .css files download and include: jquery.easing.1.3.js, jquery.mobile.scrollview.js, and scrollview.js. (google)
2) Standard header, listview, and footer with style attribue below:
<div id="home" data-role="page">...</div>
<div data-role="content"><ul data-role="listview"><li>List item 1</li></ul></div>
<div data-role="footer" style="position: fixed;bottom: 0px;">...</div>
As described in detail here.
There's an example of doing this with a Footer here: http://jquerymobile.com/demos/1.0/docs/toolbars/footer-persist-a.html
I haven't had a chance to try it out, but it should work the same way with a header.
Hi it might be late but this worked for me.
[data-role=page]
{
min-height: 100%;
height: auto !important;
height: 100%;
overflow: scroll;
margin: 0 auto -40px;
}
.footerPlaceHolder
{
height: 40px;
}
[data-role=footer]{height:40px; bottom:0; position:fixed !important; top: auto !important; width:100%; z-index: 9999;}
Your html
<div data-role="page">
....Your content....
<div class="footerPlaceHolder"></div>
<div data-role="footer">
<a href="#" data-icon="arrow-l" class="ui-btn-left">Back</a>
<a href="#" onclick="settingsClicked(this);" data-icon="gear" class="ui-btn-right">Settings</a>
</div>
</div>
P.S. Please note I am not good at this things especially css. All comments will be greatly appreciated.
Thanks.
I try to look into jquery mobile source , the magic of persistent footer happen here , i think.
$( document ).delegate( ".ui-page", "pagebeforeshow", function( event, ui ) {
var page = $( event.target ),
footer = page.find( ":jqmData(role='footer')" ),
id = footer.data( "id" ),
prevPage = ui.prevPage,
prevFooter = prevPage && prevPage.find( ":jqmData(role='footer')" ),
prevFooterMatches = prevFooter.length && prevFooter.jqmData( "id" ) === id;
if ( id && prevFooterMatches ) {
stickyFooter = footer;
setTop( stickyFooter.removeClass( "fade in out" ).appendTo( $.mobile.pageContainer ) );
}
})
.delegate( ".ui-page", "pageshow", function( event, ui ) {
var $this = $( this );
if ( stickyFooter && stickyFooter.length ) {
setTimeout(function() {
setTop( stickyFooter.appendTo( $this ).addClass( "fade" ) );
stickyFooter = null;
}, 500);
}
$.mobile.fixedToolbars.show( true, this );
});
I am thinking of adding
setTop( page.find( ":jqmData(role='header')").removeClass( "fade in out" ).appendTo( $.mobile.pageContainer ) );
to it. Wish me luck ...
If you can get by with one single shared header, you can supply the header in your main page: (note: NO jQuery involved, sorry "just use jQuery" guys :-p)
<div class="header">
<div class="logo"></div>
<div class="menu"></div>
</div>
<div data-role="page" class="page" id="loading">
<div data-role="content">
<h1>Your Page</h1>
</div>
</div>
Then use CSS to push the top of each page down:
.ui-page{
top:64px !important;
}
I'm not happy with that !important in there, but the rules jQueryM is using in CSS have the highest specificity w/o using an ID. If you know all of your IDs, you can probably do without it... Feel free to suggest other rules that are better.. I've beat my head against this too long to care any longer.
I think this is added to JQM recently. http://view.jquerymobile.com/1.3.2/dist/demos/widgets/fixed-toolbars/footer-persist-a.html
This link says clearly that you can add the data-id attribute to BOTH. Header AND FOOTER. But that doesn´t work for me.
EDIT: I noticed, that you have to turn on page transitions for the persistent header. But transitions slows down the app too much...
Check this example, under Making footers and headers persistent.
精彩评论