Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>For my needs, I found it easier to use an absolute positioned header, hide it before scroll and show it when finish scroll (I need the same code to support iOS4 and Android).</p> <p>For my purposes, I hide the header on a <code>touchstart</code> event, and show it again on <code>touchend</code> or <code>scroll</code> event (plus some timers to improve responsiveness/reduce flickering). It flashes, but is the best compromise I could find. One can detect the start of scrolling using the <code>touchmove</code> event (jQuery does this), but I found <code>touchmove</code> didn't work as well for me because:</p> <ol> <li><p>regularly the iPad fails to do a repaint before scrolling (i.e. the absolute header remains stuck - even though the <code>top</code> was changed before scrolling started).</p></li> <li><p>when an input element gets focus, the iPad auto-centres the element, but the scrollstart event doesn't get fired (because no touchmove if just <code>click</code>ing an input).</p></li> </ol> <p>Implementing a fixed header on iOS5 could be improved by using a hybrid approach of fixed and absolute positioning:</p> <ul> <li><p>used fixed positioning for iOS5 until an input gets focus.</p></li> <li><p>when an input gets focus (keyboard showing), change to the iOS4 absolute positioning code.</p></li> <li><p>when the keyboard is closed, change back to fixed positioning.</p></li> </ul> <p>Code to detect when keyboard is closed (e.g. using keyboard hide key) is to register the <code>DOMFocusOut</code> event on the <code>document</code> element and do something like the following code. The timeout is needed because the <code>DOMFocusOut</code> event can fire between when one element gets the focus and another loses it.</p> <pre><code>function document_DOMFocusOut() { clearTimeout(touchBlurTimer); touchBlurTimer = setTimeout(function() { if (document.activeElement == document.body) { handleKeyboardHide(); } }.bind(this), 400); } </code></pre> <p>My fixed header code is something like:</p> <pre><code>{ setup: function() { observe(window, 'scroll', this, 'onWinScroll'); observe(document, 'touchstart', this, 'onTouchStart'); observe(document, 'touchend', this, 'onTouchEnd'); if (isMobile) { observe(document, 'DOMFocusOut', this, 'docBlurTouch'); } else if (isIE) { // see http://ajaxian.com/archives/fixing-loss-of-focus-on-ie for code to go into this.docBlurIe() observe(document, 'focusout', this, 'docBlurIe'); } else { observe(isFirefox ? document : window, 'blur', this, 'docBlur'); } }, onWinScroll: function() { clearTimeout(this.scrollTimer); this.scrolling = false; this.rehomeAll(); }, rehomeAll: function() { if ((isIOS5 &amp;&amp; this.scrolling) || isIOS4 || isAndroid) { this.useAbsolutePositioning(); } else { this.useFixedPositioning(); } }, // Important side effect that this event registered on document on iOs. Without it event.touches.length is incorrect for any elements in the document using the touchstart event!!! onTouchStart: function(event) { clearTimeout(this.scrollTimer); if (!this.scrolling &amp;&amp; event.touches.length == 1) { this.scrolling = true; this.touchStartTime = inputOrOtherKeyboardShowingElement(event.target) ? 0 : (new Date).getTime(); // Needs to be in touchStart so happens before iPad automatic scrolling to input, also not reliable using touchMove (although jQuery touch uses touchMove to unreliably detect scrolling). this.rehomeAll(); } }, onTouchEnd: function(event) { clearTimeout(this.scrollTimer); if (this.scrolling &amp;&amp; !event.touches.length) { var touchedDuration = (new Date).getTime() - this.touchStartTime; // Need delay so iPad can scroll to the input before we reshow the header. var showQuick = this.touchStartTime &amp;&amp; touchedDuration &lt; 400; this.scrollTimer = setTimeout(function() { if (this.scrolling) { this.scrolling = false; this.rehomeAll(); } }.bind(this), showQuick ? 0 : 400); } }, // ... more code } </code></pre> <p>jQuery mobile supports scrollstart and scrollstop events:</p> <pre><code>var supportTouch = $.support.touch, scrollEvent = "touchmove scroll", touchStartEvent = supportTouch ? "touchstart" : "mousedown", touchStopEvent = supportTouch ? "touchend" : "mouseup", touchMoveEvent = supportTouch ? "touchmove" : "mousemove"; function triggerCustomEvent( obj, eventType, event ) { var originalType = event.type; event.type = eventType; $.event.handle.call( obj, event ); event.type = originalType; } // also handles scrollstop $.event.special.scrollstart = { enabled: true, setup: function() { var thisObject = this, $this = $( thisObject ), scrolling, timer; function trigger( event, state ) { scrolling = state; triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event ); } // iPhone triggers scroll after a small delay; use touchmove instead $this.bind( scrollEvent, function( event ) { if ( !$.event.special.scrollstart.enabled ) { return; } if ( !scrolling ) { trigger( event, true ); } clearTimeout( timer ); timer = setTimeout(function() { trigger( event, false ); }, 50 ); }); } }; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload