mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-03-29 20:20:27 +00:00
470 - Multiple Footers when using data-position=fixed and data-id=[someid] 773 - The fixHeaderFooter pagebeforeshow live function is not triggered for the initial page shown - Removed the findStickyFooter() function. - Reworked the logic in the pagebeforeshow live function. We now add a ui-sticky-footer class to the sticky footer element. This will guarantee that we find the sticky footer if it already exists. We may at some point want to consider the use of ids on the sticky footers so that we don't have to crawl the entire document. - Moved the live pagebeforeshow and pageshow calls outside of the DOMReady function so that they get registered as soon as the plugin is loaded. This guarantees that they will be triggered when the core plugin's DOMReady function fires. - This fix makes issue/pull-request 765 obsolete.
215 lines
No EOL
7.2 KiB
JavaScript
215 lines
No EOL
7.2 KiB
JavaScript
/*
|
|
* jQuery Mobile Framework : "fixHeaderFooter" plugin - on-demand positioning for headers,footers
|
|
* Copyright (c) jQuery Project
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
* http://jquery.org/license
|
|
*/
|
|
(function($, undefined ) {
|
|
$.fn.fixHeaderFooter = function(options){
|
|
if( !$.support.scrollTop ){ return $(this); }
|
|
return $(this).each(function(){
|
|
if( $(this).data('fullscreen') ){ $(this).addClass('ui-page-fullscreen'); }
|
|
$(this).find('.ui-header[data-position="fixed"]').addClass('ui-header-fixed ui-fixed-inline fade'); //should be slidedown
|
|
$(this).find('.ui-footer[data-position="fixed"]').addClass('ui-footer-fixed ui-fixed-inline fade'); //should be slideup
|
|
});
|
|
};
|
|
|
|
//single controller for all showing,hiding,toggling
|
|
$.fixedToolbars = (function(){
|
|
if( !$.support.scrollTop ){ return; }
|
|
var currentstate = 'inline',
|
|
delayTimer,
|
|
ignoreTargets = 'a,input,textarea,select,button,label,.ui-header-fixed,.ui-footer-fixed',
|
|
toolbarSelector = '.ui-header-fixed:first, .ui-footer-fixed:not(.ui-footer-duplicate):last',
|
|
stickyFooter, //for storing quick references to duplicate footers
|
|
supportTouch = $.support.touch,
|
|
touchStartEvent = supportTouch ? "touchstart" : "mousedown",
|
|
touchStopEvent = supportTouch ? "touchend" : "mouseup",
|
|
stateBefore = null,
|
|
scrollTriggered = false,
|
|
touchToggleEnabled = true;
|
|
|
|
$(function() {
|
|
$(document)
|
|
.bind(touchStartEvent,function(event){
|
|
if( touchToggleEnabled ) {
|
|
if( $(event.target).closest(ignoreTargets).length ){ return; }
|
|
stateBefore = currentstate;
|
|
}
|
|
})
|
|
.bind('scrollstart',function(event){
|
|
if( $(event.target).closest(ignoreTargets).length ){ return; } //because it could be a touchmove...
|
|
scrollTriggered = true;
|
|
if(stateBefore == null){ stateBefore = currentstate; }
|
|
if (stateBefore == 'overlay') {
|
|
$.fixedToolbars.hide(true);
|
|
}
|
|
})
|
|
.bind(touchStopEvent,function(event){
|
|
if( touchToggleEnabled ) {
|
|
if( $(event.target).closest(ignoreTargets).length ){ return; }
|
|
if( !scrollTriggered ){
|
|
$.fixedToolbars.toggle(stateBefore);
|
|
stateBefore = null;
|
|
}
|
|
}
|
|
})
|
|
.bind('scrollstop',function(event){
|
|
if( $(event.target).closest(ignoreTargets).length ){ return; }
|
|
scrollTriggered = false;
|
|
if (stateBefore == 'overlay') {
|
|
$.fixedToolbars.show();
|
|
}
|
|
stateBefore = null;
|
|
});
|
|
});
|
|
|
|
//before page is shown, check for duplicate footer
|
|
$('.ui-page').live('pagebeforeshow', function(event, ui){
|
|
var page = $(event.target);
|
|
var footer = page.find('[data-role="footer"]:not(.ui-sticky-footer)');
|
|
var id = footer.data('id');
|
|
if (id)
|
|
{
|
|
stickyFooter = $('.ui-footer[data-id="' + id + '"].ui-sticky-footer');
|
|
if (stickyFooter.length == 0) {
|
|
// No sticky footer exists for this data-id. We'll use this
|
|
// footer as the sticky footer for the group and then create
|
|
// a placeholder footer for the page.
|
|
stickyFooter = footer;
|
|
footer = stickyFooter.clone(); // footer placeholder
|
|
stickyFooter.addClass('ui-sticky-footer').before(footer);
|
|
}
|
|
footer.addClass('ui-footer-duplicate');
|
|
stickyFooter.appendTo($.pageContainer).css('top',0);
|
|
setTop(stickyFooter);
|
|
}
|
|
});
|
|
|
|
//after page is shown, append footer to new page
|
|
$('.ui-page').live('pageshow', function(event, ui){
|
|
if( stickyFooter && stickyFooter.length ){
|
|
stickyFooter.appendTo(event.target).css('top',0);
|
|
}
|
|
$.fixedToolbars.show(true, this);
|
|
});
|
|
|
|
|
|
// element.getBoundingClientRect() is broken in iOS 3.2.1 on the iPad. The
|
|
// coordinates inside of the rect it returns don't have the page scroll position
|
|
// factored out of it like the other platforms do. To get around this,
|
|
// we'll just calculate the top offset the old fashioned way until core has
|
|
// a chance to figure out how to handle this situation.
|
|
//
|
|
// TODO: We'll need to get rid of getOffsetTop() once a fix gets folded into core.
|
|
|
|
function getOffsetTop(ele)
|
|
{
|
|
var top = 0;
|
|
if (ele)
|
|
{
|
|
var op = ele.offsetParent, body = document.body;
|
|
top = ele.offsetTop;
|
|
while (ele && ele != body)
|
|
{
|
|
top += ele.scrollTop || 0;
|
|
if (ele == op)
|
|
{
|
|
top += op.offsetTop;
|
|
op = ele.offsetParent;
|
|
}
|
|
ele = ele.parentNode;
|
|
}
|
|
}
|
|
return top;
|
|
}
|
|
|
|
function setTop(el){
|
|
var fromTop = $(window).scrollTop(),
|
|
thisTop = getOffsetTop(el[0]), // el.offset().top returns the wrong value on iPad iOS 3.2.1, call our workaround instead.
|
|
thisCSStop = el.css('top') == 'auto' ? 0 : parseFloat(el.css('top')),
|
|
screenHeight = window.innerHeight,
|
|
thisHeight = el.outerHeight(),
|
|
useRelative = el.parents('.ui-page:not(.ui-page-fullscreen)').length,
|
|
relval;
|
|
if( el.is('.ui-header-fixed') ){
|
|
relval = fromTop - thisTop + thisCSStop;
|
|
if( relval < thisTop){ relval = 0; }
|
|
return el.css('top', ( useRelative ) ? relval : fromTop);
|
|
}
|
|
else{
|
|
//relval = -1 * (thisTop - (fromTop + screenHeight) + thisCSStop + thisHeight);
|
|
//if( relval > thisTop ){ relval = 0; }
|
|
relval = fromTop + screenHeight - thisHeight - (thisTop - thisCSStop);
|
|
return el.css('top', ( useRelative ) ? relval : fromTop + screenHeight - thisHeight );
|
|
}
|
|
}
|
|
|
|
//exposed methods
|
|
return {
|
|
show: function(immediately, page){
|
|
currentstate = 'overlay';
|
|
var $ap = page ? $(page) : ($.mobile.activePage ? $.mobile.activePage : $(".ui-page-active"));
|
|
return $ap.children( toolbarSelector ).each(function(){
|
|
var el = $(this),
|
|
fromTop = $(window).scrollTop(),
|
|
thisTop = getOffsetTop(el[0]), // el.offset().top returns the wrong value on iPad iOS 3.2.1, call our workaround instead.
|
|
screenHeight = window.innerHeight,
|
|
thisHeight = el.outerHeight(),
|
|
alreadyVisible = (el.is('.ui-header-fixed') && fromTop <= thisTop + thisHeight) || (el.is('.ui-footer-fixed') && thisTop <= fromTop + screenHeight);
|
|
|
|
//add state class
|
|
el.addClass('ui-fixed-overlay').removeClass('ui-fixed-inline');
|
|
|
|
if( !alreadyVisible && !immediately ){
|
|
el.animationComplete(function(){
|
|
el.removeClass('in');
|
|
}).addClass('in');
|
|
}
|
|
setTop(el);
|
|
});
|
|
},
|
|
hide: function(immediately){
|
|
currentstate = 'inline';
|
|
var $ap = $.mobile.activePage ? $.mobile.activePage : $(".ui-page-active");
|
|
return $ap.children( toolbarSelector ).each(function(){
|
|
var el = $(this);
|
|
|
|
var thisCSStop = el.css('top'); thisCSStop = thisCSStop == 'auto' ? 0 : parseFloat(thisCSStop);
|
|
|
|
//add state class
|
|
el.addClass('ui-fixed-inline').removeClass('ui-fixed-overlay');
|
|
|
|
if (thisCSStop < 0 || (el.is('.ui-header-fixed') && thisCSStop != 0))
|
|
{
|
|
if(immediately){
|
|
el.css('top',0);
|
|
}
|
|
else{
|
|
if( el.css('top') !== 'auto' && parseFloat(el.css('top')) !== 0 ){
|
|
var classes = 'out reverse';
|
|
el.animationComplete(function(){
|
|
el.removeClass(classes);
|
|
el.css('top',0);
|
|
}).addClass(classes);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
},
|
|
hideAfterDelay: function(){
|
|
delayTimer = setTimeout(function(){
|
|
$.fixedToolbars.hide();
|
|
}, 3000);
|
|
},
|
|
toggle: function(from){
|
|
if(from){ currentstate = from; }
|
|
return (currentstate == 'overlay') ? $.fixedToolbars.hide() : $.fixedToolbars.show();
|
|
},
|
|
setTouchToggleEnabled: function(enabled) {
|
|
touchToggleEnabled = enabled;
|
|
}
|
|
};
|
|
})();
|
|
|
|
})(jQuery); |