diff --git a/js/jQuery.fixHeaderFooter.js b/js/jQuery.fixHeaderFooter.js index 6c5f3bc3..b4e321e4 100644 --- a/js/jQuery.fixHeaderFooter.js +++ b/js/jQuery.fixHeaderFooter.js @@ -7,27 +7,62 @@ (function($){ $.fn.fixHeaderFooter = function(options){ return $(this).each(function(){ + //make sure these things only get wrapped once if($(this).data('fixedapplied')){ return; } - var el = $uipage = $(this).data('fixedapplied',true); + var el = $uipage = $(this).data('fixedapplied',true), + els = el.find('.ui-header,.ui-footer').wrap('
'); + //wrapper explanation: placehold wrapper sits inline and holds the height of the toolbars open while they are position abs, + //unless it's overlay-only, in which case the height is 0 so it's hidden when pos static + + //config options - currently driven off data attr's var o = $.extend({ - ignoreTargets: 'a,input,textarea,select,button,label,.ui-headfoot-placehold', transition: el.find('[data-headfoottransition]').attr('data-headfoottransition') || ['slidedown','slideup'], //also accepts a string, like 'fade'. All animations work, but fade and slidedown/up look best overlayOnly: el.find('.ui-fullscreen').length },options); - - var els = el.find('.ui-header,.ui-footer').wrap('
'), - tIsArray = $.isArray(o.transition), - currentstate = 'inline'; //add transition types - els.filter('.ui-header').addClass(tIsArray ? o.transition[0] : o.transition); - els.filter('.ui-footer').addClass(tIsArray ? o.transition[1] : o.transition); + els.filter('.ui-header').addClass( $.isArray(o.transition) ? o.transition[0] : o.transition); + els.filter('.ui-footer').addClass( $.isArray(o.transition) ? o.transition[1] : o.transition); + + //set placeholder heights, then bind custom events + els + .each(function(){ + var placehold = $(this).parents('.ui-headfoot-placehold:eq(0)'); + if(o.overlayOnly){ + placehold.height(0).addClass('ui-headfoot-overlayonly'); + } + else{ + placehold.height($(this).parent().height()); + } + }) + .bind('setTop',function(){ + var fromTop = $.scrollY(), + screenHeight = window.innerHeight, + thisHeight = $(this).parent().height(); + return $(this).parent().css('top', ($(this).is('.ui-header')) ? fromTop : fromTop + screenHeight - thisHeight); + }); + }); +}; + + + +//single controller for all showing,hiding,toggling +$.fixedToolbars = (function(){ + var currentstate = 'inline', + showAfterScroll = false, + delayTimer, + ignoreTargets = 'a,input,textarea,select,button,label,.ui-headfoot-placehold'; + + function allToolbars(){ + return $('.ui-header,.ui-footer'); + } + //for determining whether a placeholder is visible on the screen or not function placeHolderOutofView(thisel){ //always return true if it's overlayOnly - if(o.overlayOnly){ return true; } + if(thisel.closest('.ui-headfoot-overlayonly').length){ return true; } var fromTop = $.scrollY(), screenHeight = window.innerHeight, @@ -36,121 +71,95 @@ $.fn.fixHeaderFooter = function(options){ return thisel.is('.ui-header') ? (thisTop + thisHeight <= fromTop) : (thisTop > fromTop + screenHeight); } - - //set placeholder heights, then bind custom events - els - .each(function(){ - var placehold = $(this).parents('.ui-headfoot-placehold:eq(0)'); - if(o.overlayOnly){ - $(this).parent().parent().height(0); + + + $(document) + .bind('tap',function(e){ + if( !$(e.target).closest(ignoreTargets).length ){ + $.fixedToolbars.toggle(); + } + }) + .bind('scrollstart',function(){ + if(currentstate == 'overlay'){ + showAfterScroll = true; + } + $.fixedToolbars.hide(true); + }) + .bind('scrollstop',function(){ + if(showAfterScroll){ + $.fixedToolbars.show(); + showAfterScroll = false; + } + }); + + + //hide on resize? + $(window).resize(function(){ $.fixedToolbars.hide(true); }); + + + return { + show: function(){ + if(currentstate == 'overlay'){ return; } + currentstate = 'overlay'; + var els = allToolbars(); + return els.each(function(){ + var el = $(this), + overlayOnly = el.closest('.ui-headfoot-overlayonly').length; + el.parent().addClass('ui-fixpos'); + //only animate if placeholder is out of view + if( placeHolderOutofView(el) ){ + el.addClass('in').animationComplete(function(){ + el.removeClass('in'); + }); + } + if(overlayOnly){ + el.parent().parent().removeClass('ui-headfoot-hidden'); + } + el.trigger('setTop'); + }); + }, + hide: function(immediately){ + if(currentstate == 'inline'){ return; } + currentstate = 'inline'; + var els = allToolbars(); + return els.each(function(){ + var el = $(this), + overlayOnly = el.closest('.ui-headfoot-overlayonly').length; + + function addOverlayOnlyClass(){ + if(overlayOnly){ + el.parent().parent().addClass('ui-headfoot-hidden'); + } + } + //if immediately flag is true, or the placeholder is in view, don't animate the hide + if(immediately || !placeHolderOutofView(el)){ + el.parent().removeClass('ui-fixpos'); + addOverlayOnlyClass(); } else{ - $(this).parent().parent().height($(this).parent().height()); - } - }) - .bind('setTop',function(){ - var fromTop = $.scrollY(), - screenHeight = window.innerHeight, - thisHeight = $(this).parent().outerHeight(); - return $(this).parent().css('top', ($(this).is('.ui-header')) ? fromTop : fromTop + screenHeight - thisHeight); - }) - .bind('click tap mousedown',function(e){ - e.stopImmediatePropagation(); - return false; - }); - - $uipage - .bind('overlayIn',function(){ - console.log('out') - currentstate = 'overlay'; - return els.each(function(){ - var el = $(this); - el.parent().addClass('ui-fixpos'); - //only animate if placeholder is out of view - if( placeHolderOutofView(el) ){ - el.addClass('in').animationComplete(function(){ - el.removeClass('in'); - }); + var classes = 'out'; + //if it's one of these, we'll need to add the reverse class too + if(el.is('.slidedown,.slideup, .swap, .pop, .flip')){ + classes += ' reverse'; } - if(o.overlayOnly){ - el.parent().parent().removeClass('ui-headfoot-hidden'); - } - el.trigger('setTop'); - }); - }) - .bind('overlayOut',function(e,immediately){ - console.log('in') - currentstate = 'inline'; - return els.each(function(){ - var el = $(this); - if(immediately || !placeHolderOutofView(el)){ + el.addClass(classes).animationComplete(function(){ + el.removeClass(classes); el.parent().removeClass('ui-fixpos'); addOverlayOnlyClass(); - } - else{ - var classes = 'out'; - //if it's one of these, we'll need to add the reverse class too - if(el.is('.slidedown,.slideup, .swap, .pop, .flip')){ - classes += ' reverse'; - } - el.addClass(classes).animationComplete(function(){ - el.removeClass(classes); - el.parent().removeClass('ui-fixpos'); - addOverlayOnlyClass(); - }); - } - function addOverlayOnlyClass(){ - if(o.overlayOnly){ - el.parent().parent().addClass('ui-headfoot-hidden'); - } - } - }); - }) - .bind('overlayToggle',function(){ - return (currentstate == 'overlay') ? $(this).trigger('overlayOut') : $(this).trigger('overlayIn'); - }); - - - - $uipage - .bind('tap',function(e){ - if( !$(e.target).closest(o.ignoreTargets).length ){ - $(this).trigger('overlayToggle'); + }); } - }) - .bind('scrollstart',function(){ - if(currentstate == 'overlay'){ - $uipage.data('visiblebeforescroll', true); - } - $uipage.trigger('overlayOut',[true]); - return false; - }) - .bind('scrollstop',function(){ - if($uipage.data('visiblebeforescroll')){ - $uipage.removeData('visiblebeforescroll').trigger('overlayIn'); - } - return false; }); - + }, + hideAfterDelay: function(){ + delayTimer = setTimeout(function(){ + $.fixedToolbars.hide(); + }, 3000); + }, + toggle: function(){ + return (currentstate == 'overlay') ? $.fixedToolbars.hide() : $.fixedToolbars.show(); + } + }; +})(); - $('body').scrollstart(function(){ - $uipage.trigger('scrollstart'); - }) - .scrollstop(function(){ - $uipage.trigger('scrollstop'); - }); - - $(window) - .bind('load',function(){ - $uipage.trigger('overlayIn'); - - if(o.overlayOnly){ - //to-do...for a photo-viewer or something full-screen - els.parents('.ui-headfoot-placehold:eq(0)').addClass('ui-headfoot-overlayonly'); - } - }) - .resize(function(){ $uipage.trigger('overlayOut',[true]); }); - }); -}; })(jQuery); \ No newline at end of file diff --git a/js/jQuery.mobile.js b/js/jQuery.mobile.js index 9d80baeb..121b14db 100644 --- a/js/jQuery.mobile.js +++ b/js/jQuery.mobile.js @@ -25,11 +25,12 @@ prevUrl = location.hash, //vars for custom event tracking scrolling = false, + scrollListeningOn = true, touching = false, touchstartdata, touchstopdata, - tapNotMoveTime = 50, - tapHoldTime = 700, + tapNotMoveTime = 75, + tapHoldTime = 300, maxSwipeTime = 1000, minSwipeXDistance = 180, maxSwipeYtolerance = 80; @@ -153,7 +154,11 @@ //hide Address bar function hideBrowserChrome(){ //kill addr bar + scrollListeningOn = false; window.scrollTo(0,0); + setTimeout(function(){ + scrollListeningOn = true; + }, 150); } //get vert scroll dist @@ -177,10 +182,11 @@ //detect and trigger some custom events (scrollstart,scrollstop,tap,taphold,swipe,swipeleft,swiperight) $(document) - .scroll(function(e){ + .scroll(function(e){ + if(!scrollListeningOn){ return false; } var prevscroll = $.scrollY(); function checkscrollstop(){ - if(prevscroll === $.scrollY() && scrolling){ + if(prevscroll === $.scrollY() && scrolling && scrollListeningOn){ $body.trigger('scrollstop'); scrolling = false; } @@ -188,6 +194,7 @@ setTimeout(checkscrollstop,50); }) .bind( ($.support.touch ? 'touchmove' : 'scroll'), function(e){ + if(!scrollListeningOn){ return false; } //iPhone triggers scroll a tad late - touchmoved preferred if(!scrolling){ scrolling = true; @@ -294,7 +301,6 @@ //turn on/off page loading message.. also hides the ui-content div function pageLoading(done){ if(done){ - hideToolbarsAfterDelay(); //remove loading msg $html.removeClass('ui-loading'); //fade in page content, remove loading msg @@ -309,7 +315,6 @@ //transition between pages - based on transitions from jQtouch function changePage(from,to,back){ hideBrowserChrome(); - if(!back && !transitionSpecified){ currentTransition = 'slide'; } //kill keyboard (thx jQtouch :) ) @@ -323,8 +328,9 @@ to.animationComplete(function(){ from.add(to).removeClass(' out in reverse '+ transitions); from.removeClass(activePageClass); - to.trigger('overlayIn'); pageLoading(true); + $.fixedToolbars.show(); + $.fixedToolbars.hideAfterDelay(); }); if(back){ currentTransition = 'slide'; } }; @@ -341,14 +347,11 @@ } }; - function hideToolbarsAfterDelay(){ - setTimeout(function(){ - $('.ui-page-active').trigger('overlayOut'); - }, 2000); - } + //markup-driven enhancements, to be called on any ui-page upon loading function mobilize($el){ + //to-do: make sure this only runs one time on a page (or maybe per component) return $el.each(function(){ //checkboxes, radios $el.find('input[type=radio],input[type=checkbox]').customCheckboxRadio(); @@ -434,12 +437,15 @@ changePage(currentPage, startPage, back); } else{ + $.fixedToolbars.show(); startPage.addClass(activePageClass); - startPage.trigger('overlayIn'); pageLoading(true); + $.fixedToolbars.hideAfterDelay(); } } }); + + hideBrowserChrome(); //mobilize all pages present mobilize($('.ui-page'));