diff --git a/css/structure/jquery.mobile.fixedToolbar.css b/css/structure/jquery.mobile.fixedToolbar.css index 8dd13fc3a0f..37b55c00e07 100644 --- a/css/structure/jquery.mobile.fixedToolbar.css +++ b/css/structure/jquery.mobile.fixedToolbar.css @@ -49,3 +49,6 @@ .ui-footer-fixed .ui-btn { z-index: 10; } +.ui-android-2x-fixed .ui-li-has-thumb { + -webkit-transform: translate3d(0,0,0); +} \ No newline at end of file diff --git a/js/index.php b/js/index.php index 4b826f9aef8..deccf2bc399 100644 --- a/js/index.php +++ b/js/index.php @@ -53,6 +53,7 @@ 'widgets/controlgroup.js', 'jquery.mobile.links.js', 'widgets/fixedToolbar.js', + 'widgets/fixedToolbarWorkarounds.js', 'widgets/popup.js', 'jquery.mobile.zoom.js', 'jquery.mobile.zoom.iosorientationfix.js', diff --git a/js/widgets/fixedToolbar.js b/js/widgets/fixedToolbar.js index 4ae263e22bd..a380b63133c 100644 --- a/js/widgets/fixedToolbar.js +++ b/js/widgets/fixedToolbar.js @@ -253,7 +253,12 @@ define( [ "jquery", "../jquery.mobile.widget", "../jquery.mobile.core", "../jque } }) .bind( "focusin focusout", function( e ) { - if ( screen.width < 500 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( ".ui-header-fixed, .ui-footer-fixed" ).length ) { + //this hides the toolbars on a keyboard pop to give more screen room and prevent ios bug which + //positions fixed toolbars in the middle of the screen on pop if the input is near the top or + //bottom of the screen addresses issues #4410 Footer navbar moves up when clicking on a textbox in an Android environment + //and issue #4113 Header and footer change their position after keyboard popup - iOS + //and issue #4410 Footer navbar moves up when clicking on a textbox in an Android environment + if ( screen.width < 1025 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( ".ui-header-fixed, .ui-footer-fixed" ).length ) { self[ ( e.type === "focusin" && self._visible ) ? "hide" : "show" ](); } }); diff --git a/js/widgets/fixedToolbar.workarounds.js b/js/widgets/fixedToolbar.workarounds.js new file mode 100644 index 00000000000..4df4e1f6aed --- /dev/null +++ b/js/widgets/fixedToolbar.workarounds.js @@ -0,0 +1,104 @@ +//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude); +//>>description: Browser specific workarounds for "fixed" headers and footers +//>>label: Toolbars: Fixed: Workarounds +//>>group: Widgets +//>>css.structure: ../css/structure/jquery.mobile.fixedToolbar.css +define( [ "jquery", "../jquery.mobile.widget", "../jquery.mobile.core", "../jquery.mobile.navigation", "./page", "./page.sections", "../jquery.mobile.zoom", "./fixedToolbar" ], function( $ ) { +//>>excludeEnd("jqmBuildExclude"); +(function( $, undefined ) { + $.widget( "mobile.fixedtoolbar", $.mobile.fixedtoolbar, { + + _create: function() { + this._super(); + this._workarounds(); + }, + + //check the browser and version and run needed workarounds + _workarounds: function() { + var ua = navigator.userAgent, + platform = navigator.platform, + // Rendering engine is Webkit, and capture major version + wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ), + wkversion = !!wkmatch && wkmatch[ 1 ], + os = null, + self = this; + //set the os we are working in if it dosent match one with workarounds return + if( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1 || platform.indexOf( "iPod" ) > -1 ){ + os = "ios"; + } else if( ua.indexOf( "Android" ) > -1 ){ + os = "android"; + } else { + return + } + //check os version if it dosent match one with workarounds return + if( os === "ios" && wkversion && wkversion > 533 && wkversion < 536 ) { + //iOS 5 run all workarounds for iOS 5 + self._bindScrollWorkaround(); + } else if( os === "android" && wkversion && wkversion < 534 ) { + //Android 2.3 run all Android 2.3 workaround + self._bindScrollWorkaround(); + self._bindListThumbWorkaround(); + } else { + return + } + }, + + //Utility class for checking header and footer positions relative to viewport + _viewportOffset: function() { + var $el = this.element, + header = $el.is( ".ui-header" ), + offset = Math.abs($el.offset().top - $( window ).scrollTop()); + if( !header ) { + offset = Math.round(offset - $( window ).height() + $el.outerHeight())-60; + } + return offset; + }, + + //bind events for _triggerRedraw() function + _bindScrollWorkaround: function() { + var self = this; + //bind to scrollstop and check if the toolbars are correctly positioned + this._on( $( window ), { scrollstop: function() { + var viewportOffset = self._viewportOffset(); + //check if the header is visible and if its in the right place + if( viewportOffset > 2 && self._visible) { + self._triggerRedraw(); + } + }}); + }, + + //this addresses issue #4250 Persistent footer instability in v1.1 with long select lists in Android 2.3.3 + //and issue #3748 Android 2.x: Page transitions broken when fixed toolbars used + //the absolutely positioned thumbnail in a list view causes problems with fixed position buttons above in a nav bar + //setting the li's to -webkit-transform:translate3d(0,0,0); solves this problem to avoide potential issues in other + //platforms we scope this with the class ui-android-2x-fix + _bindListThumbWorkaround: function() { + this.element.closest(".ui-page").addClass( "ui-android-2x-fixed" ); + }, + //this addresses issues #4337 Fixed header problem after scrolling content on iOS and Android + //and device bugs project issue #1 Form elements can lose click hit area in position: fixed containers. + //this also addresses not on fixed toolbars page in docs + //adding 1px of padding to the bottom then removing it causes a "redraw" + //which positions the toolbars correctly (they will always be visually correct) + _triggerRedraw: function() { + var paddingBottom = parseFloat( $( ".ui-page-active" ).css( "padding-bottom" ) ); + //trigger page redraw to fix incorrectly positioned fixed elements + $( ".ui-page-active" ).css( "padding-bottom", ( paddingBottom + 1 ) +"px" ); + //if the padding is reset with out a timeout the reposition will not occure. + //this is independant of JQM the browser seems to need the time to react. + setTimeout( function() { + $( ".ui-page-active" ).css( "padding-bottom", paddingBottom + "px" ); + }, 0 ); + }, + + destroy: function() { + this._super(); + //Remove the class we added to the page previously in android 2.x + this.element.closest(".ui-page-active").removeClass( "ui-android-2x-fix" ); + } + }); + + })( jQuery ); +//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude); +}); +//>>excludeEnd("jqmBuildExclude"); \ No newline at end of file