mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-03-25 10:20:34 +00:00
https://github.com/jquery/jquery-mobile/pull/649 - Changed hideOnTouchEnabed to touchToggleEnabled. - Fixed problem that would allow the toolbars to show on touchstop, if the starting state was "inline" to begin with. - Moved the touchToggleEnabled checks in touchstart/touchstop so that they wrap the entire code in the function. We don't want to do any work if we don't need to. - Removed the forced hide() call in touchstart. Added the missing fadeout animation reference inthe fade.in transition rule.
213 lines
No EOL
7.3 KiB
JavaScript
213 lines
No EOL
7.3 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;
|
|
});
|
|
|
|
//function to return another footer already in the dom with the same data-id
|
|
function findStickyFooter(el){
|
|
var thisFooter = el.find('[data-role="footer"]');
|
|
return $( '.ui-footer[data-id="'+ thisFooter.data('id') +'"]:not(.ui-footer-duplicate)' ).not(thisFooter);
|
|
}
|
|
|
|
//before page is shown, check for duplicate footer
|
|
$('.ui-page').live('pagebeforeshow', function(event, ui){
|
|
stickyFooter = findStickyFooter( $(event.target) );
|
|
if( stickyFooter.length ){
|
|
//if the existing footer is the first of its kind, create a placeholder before stealing it
|
|
if( stickyFooter.parents('.ui-page:eq(0)').find('.ui-footer[data-id="'+ stickyFooter.data('id') +'"]').length == 1 ){
|
|
stickyFooter.before( stickyFooter.clone().addClass('ui-footer-duplicate') );
|
|
}
|
|
$(event.target).find('[data-role="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); |