mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-03-16 22:10:25 +00:00
reverted fixed toolbar merge, there are some issues with the branch that need to be addressed
This commit is contained in:
parent
ca0c1a9c61
commit
f2802bdc65
20 changed files with 646 additions and 626 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/* some unsets - more probably needed */
|
||||
.ui-mobile, .ui-mobile body { height: 100%; }
|
||||
.ui-mobile, .ui-mobile body { height: 99.9%; }
|
||||
.ui-mobile fieldset, .ui-page { padding: 0; margin: 0; }
|
||||
.ui-mobile a img, .ui-mobile fieldset { border-width: 0; }
|
||||
|
||||
|
|
@ -24,6 +24,41 @@ div.ui-mobile-viewport { overflow-x: hidden; }
|
|||
.ui-mobile, .ui-mobile .ui-page { min-height: 300px; }
|
||||
}
|
||||
|
||||
/* native overflow scrolling */
|
||||
.ui-page.ui-mobile-touch-overflow,
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-content {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
-moz-overflow-scrolling: touch;
|
||||
-o-overflow-scrolling: touch;
|
||||
-ms-overflow-scrolling: touch;
|
||||
overflow-scrolling: touch;
|
||||
}
|
||||
.ui-page.ui-mobile-touch-overflow,
|
||||
.ui-page.ui-mobile-touch-overflow * {
|
||||
/* some level of transform keeps elements from blinking out of visibility on iOS */
|
||||
-webkit-transform: rotateY(0);
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-content .ui-listview {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-content .ui-listview-inset {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-content .ui-listview-filter {
|
||||
margin-top: .2em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-content .ui-listview-filter-inset {
|
||||
margin-bottom: -.9em;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-header .ui-btn {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* loading screen */
|
||||
.ui-loading .ui-loader { display: block; }
|
||||
.ui-loader { background-color: #000; opacity: .18; display: none; z-index: 9999999; position: fixed; width: 46px; height: 46px; top: 50%; box-shadow: 0 1px 1px -1px #fff; margin-left: -18px; margin-top: -18px; left: 50%; padding: 1px; border:0; -webkit-border-radius: 36px; -moz-border-radius: 36px; border-radius: 36px; }
|
||||
|
|
@ -38,7 +73,8 @@ div.ui-mobile-viewport { overflow-x: hidden; }
|
|||
.ui-bar { font-size: 16px; margin: 0; }
|
||||
.ui-bar h1, .ui-bar h2, .ui-bar h3, .ui-bar h4, .ui-bar h5, .ui-bar h6 { margin: 0; padding: 0; font-size: 16px; display: inline-block; }
|
||||
|
||||
.ui-header, .ui-footer { position: relative; overflow: hidden; width: 100%; border-left-width: 0; border-right-width: 0; }
|
||||
.ui-header, .ui-footer { display: block; }
|
||||
.ui-page .ui-header, .ui-page .ui-footer { position: relative; }
|
||||
.ui-header .ui-btn-left { position: absolute; left: 10px; top: .4em; }
|
||||
.ui-header .ui-btn-right { position: absolute; right: 10px; top: .4em; }
|
||||
.ui-header .ui-title, .ui-footer .ui-title { min-height: 1.1em; text-align: center; font-size: 16px; display: block; margin: .6em 30% .8em; padding: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; outline: 0 !important; }
|
||||
|
|
@ -46,14 +82,51 @@ div.ui-mobile-viewport { overflow-x: hidden; }
|
|||
|
||||
/*content area*/
|
||||
.ui-content { border-width: 0; overflow: visible; overflow-x: hidden; padding: 15px; }
|
||||
.ui-page-fullscreen .ui-content { padding:0; }
|
||||
|
||||
/* native fixed headers and footers */
|
||||
.ui-mobile-touch-overflow.ui-page.ui-native-fixed,
|
||||
.ui-mobile-touch-overflow.ui-page.ui-native-fullscreen {
|
||||
overflow: visible;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-header,
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-page.ui-native-fixed .ui-footer {
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fixed .ui-content {
|
||||
padding-top: 2.5em;
|
||||
padding-bottom: 3em;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fullscreen .ui-content {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.ui-mobile-touch-overflow.ui-native-fullscreen .ui-header,
|
||||
.ui-mobile-touch-overflow.ui-native-fullscreen .ui-footer {
|
||||
opacity: .9;
|
||||
}
|
||||
.ui-native-bars-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* icons sizing */
|
||||
.ui-icon { width: 18px; height: 18px; }
|
||||
|
||||
/* fluid images */
|
||||
.ui-mobile img {
|
||||
max-width: 100%;
|
||||
}
|
||||
/* fullscreen class on ui-content div */
|
||||
.ui-fullscreen { }
|
||||
.ui-fullscreen img { max-width: 100%; }
|
||||
|
||||
/* non-js content hiding */
|
||||
.ui-nojs { position: absolute; left: -9999px; }
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ select.ui-slider-switch { display: none; }
|
|||
div.ui-slider { position: relative; display: inline-block; overflow: visible; height: 15px; padding: 0; margin: 0 2% 0 20px; top: 4px; width: 65%; }
|
||||
div.ui-slider-switch { width: 99.8%; }
|
||||
.ui-field-contain div.ui-slider-switch { width: 50%; }
|
||||
a.ui-slider-handle { position: absolute; z-index: 1; top: 50%; width: 28px; height: 28px; margin-top: -15px; margin-left: -15px; outline: 0; }
|
||||
a.ui-slider-handle { position: absolute; z-index: 10; top: 50%; width: 28px; height: 28px; margin-top: -15px; margin-left: -15px; outline: 0; }
|
||||
a.ui-slider-handle .ui-btn-inner { padding-left: 0; padding-right: 0; }
|
||||
@media all and (min-width: 480px){
|
||||
.ui-field-contain label.ui-slider { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; }
|
||||
|
|
@ -21,7 +21,7 @@ div.ui-slider-switch div.ui-slider-labelbg-b { width: 60%; height: 100%; right:
|
|||
.ui-slider-switch-a div.ui-slider-labelbg-a, .ui-slider-switch-b div.ui-slider-labelbg-b { z-index: -1; }
|
||||
.ui-slider-switch-a div.ui-slider-labelbg-b, .ui-slider-switch-b div.ui-slider-labelbg-a { z-index: 0; }
|
||||
|
||||
div.ui-slider-switch a.ui-slider-handle { z-index: 1; width: 100%; height: 30px; margin-top: -17px; margin-left: -100%; }
|
||||
div.ui-slider-switch a.ui-slider-handle { z-index: 20; width: 100%; height: 30px; margin-top: -17px; margin-left: -100%; }
|
||||
span.ui-slider-label { width: 100%; position: absolute; height: 32px; font-size: 16px; text-align: center; line-height: 1.8; background: none; border-color: transparent; }
|
||||
span.ui-slider-label-a { left: -100%; margin-right: -1px }
|
||||
span.ui-slider-label-b { right: -100%; margin-left: -1px }
|
||||
|
|
|
|||
8
css/structure/jquery.mobile.headerfooter.css
Normal file
8
css/structure/jquery.mobile.headerfooter.css
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/* fixed page header & footer configuration */
|
||||
.ui-header, .ui-footer, .ui-page-fullscreen .ui-header, .ui-page-fullscreen .ui-footer { position: absolute; overflow: hidden; width: 100%; border-left-width: 0; border-right-width: 0; }
|
||||
.ui-header-fixed, .ui-footer-fixed {
|
||||
z-index: 1000;
|
||||
-webkit-transform: translateZ(0); /* Force header/footer rendering to go through the same rendering pipeline as native page scrolling. */
|
||||
}
|
||||
.ui-footer-duplicate, .ui-page-fullscreen .ui-fixed-inline { display: none; }
|
||||
.ui-page-fullscreen .ui-header, .ui-page-fullscreen .ui-footer { opacity: .9; }
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
@import url( "../../structure/jquery.mobile.transitions.turn.css" );
|
||||
@import url( "../../structure/jquery.mobile.transitions.flow.css" );
|
||||
@import url( "../../structure/jquery.mobile.grids.css" );
|
||||
@import url( "../../structure/jquery.mobile.fixedToolbar.css" );
|
||||
@import url( "../../structure/jquery.mobile.headerfooter.css" );
|
||||
@import url( "../../structure/jquery.mobile.navbar.css" );
|
||||
@import url( "../../structure/jquery.mobile.button.css" );
|
||||
@import url( "../../structure/jquery.mobile.collapsible.css" );
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<div data-role="page" class="type-interior">
|
||||
<div data-role="page" data-fullscreen="true" class="type-interior">
|
||||
|
||||
<div data-role="header" data-position="fixed" data-theme="f" data-fullscreen="true">
|
||||
<div data-role="header" data-position="fixed" data-theme="f">
|
||||
<h1>Fullscreen fixed header</h1>
|
||||
<a href="../../" data-icon="home" data-iconpos="notext" data-direction="reverse" class="ui-btn-right jqm-home">Home</a>
|
||||
</div>
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
</div><!-- /content -->
|
||||
|
||||
<div data-role="footer" class="footer-docs" data-theme="a" data-position="fixed" data-fullscreen="true">
|
||||
<div data-role="footer" class="footer-docs" data-theme="a" data-position="fixed">
|
||||
<h1>Fullscreen Fixed Footer</h1>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ $files = array(
|
|||
'jquery.mobile.buttonMarkup.js',
|
||||
'jquery.mobile.controlGroup.js',
|
||||
'jquery.mobile.links.js',
|
||||
'jquery.mobile.fixedToolbar.js',
|
||||
'jquery.mobile.fixHeaderFooter.js',
|
||||
'jquery.mobile.fixHeaderFooter.native.js',
|
||||
'jquery.mobile.init.js'
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ $.fn.buttonMarkup = function( options ) {
|
|||
el.removeClass( "ui-link" ).addClass( buttonClass );
|
||||
|
||||
buttonInner.className = innerClass;
|
||||
buttonInner.setAttribute("aria-hidden", "true");
|
||||
|
||||
buttonText.className = textClass;
|
||||
buttonInner.appendChild( buttonText );
|
||||
|
|
|
|||
|
|
@ -47,9 +47,6 @@ define( [ "jquery", "jquery.mobile.widget" ], function( $ ) {
|
|||
|
||||
// Minimum scroll distance that will be remembered when returning to a page
|
||||
minScrollBack: 10,
|
||||
|
||||
// DEPRECATED: the following property is no longer in use, but defined until 2.0 to prevent conflicts
|
||||
touchOverflowEnabled: false,
|
||||
|
||||
// Set default dialog transition - 'none' for no transitions
|
||||
defaultDialogTransition: "pop",
|
||||
|
|
|
|||
384
js/jquery.mobile.fixHeaderFooter.js
Normal file
384
js/jquery.mobile.fixHeaderFooter.js
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* "fixHeaderFooter" plugin - on-demand positioning for headers,footers
|
||||
*/
|
||||
|
||||
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
|
||||
//>>description: Fixed positioning polyfull (deprecated)
|
||||
//>>label: Fixed header/footer
|
||||
|
||||
define( [ "jquery", "jquery.mobile.core", "jquery.mobile.vmouse" ], function( $ ) {
|
||||
//>>excludeEnd("jqmBuildExclude");
|
||||
(function( $, undefined ) {
|
||||
|
||||
var slideDownClass = "ui-header-fixed ui-fixed-inline fade",
|
||||
slideUpClass = "ui-footer-fixed ui-fixed-inline fade",
|
||||
|
||||
slideDownSelector = ".ui-header:jqmData(position='fixed')",
|
||||
slideUpSelector = ".ui-footer:jqmData(position='fixed')";
|
||||
|
||||
$.fn.fixHeaderFooter = function( options ) {
|
||||
|
||||
if ( !$.support.scrollTop || ( $.support.touchOverflow && $.mobile.touchOverflowEnabled ) ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return this.each(function() {
|
||||
var $this = $( this );
|
||||
|
||||
if ( $this.jqmData( "fullscreen" ) ) {
|
||||
$this.addClass( "ui-page-fullscreen" );
|
||||
}
|
||||
|
||||
// Should be slidedown
|
||||
$this.find( slideDownSelector ).addClass( slideDownClass );
|
||||
|
||||
// Should be slideup
|
||||
$this.find( slideUpSelector ).addClass( slideUpClass );
|
||||
});
|
||||
};
|
||||
|
||||
// single controller for all showing,hiding,toggling
|
||||
$.mobile.fixedToolbars = (function() {
|
||||
|
||||
if ( !$.support.scrollTop || ( $.support.touchOverflow && $.mobile.touchOverflowEnabled ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var stickyFooter, delayTimer,
|
||||
currentstate = "inline",
|
||||
autoHideMode = false,
|
||||
showDelay = 100,
|
||||
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",
|
||||
// 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 showEventCallback( event ) {
|
||||
// An event that affects the dimensions of the visual viewport has
|
||||
// been triggered. If the header and/or footer for the current page are in overlay
|
||||
// mode, we want to hide them, and then fire off a timer to show them at a later
|
||||
// point. Events like a resize can be triggered continuously during a scroll, on
|
||||
// some platforms, so the timer is used to delay the actual positioning until the
|
||||
// flood of events have subsided.
|
||||
//
|
||||
// If we are in autoHideMode, we don't do anything because we know the scroll
|
||||
// callbacks for the plugin will fire off a show when the scrolling has stopped.
|
||||
if ( !autoHideMode && currentstate === "overlay" ) {
|
||||
if ( !delayTimer ) {
|
||||
$.mobile.fixedToolbars.hide( true );
|
||||
}
|
||||
|
||||
$.mobile.fixedToolbars.startShowTimer();
|
||||
}
|
||||
}
|
||||
|
||||
$(function() {
|
||||
var $document = $( document ),
|
||||
$window = $( window );
|
||||
|
||||
$document
|
||||
.bind( "vmousedown", function( event ) {
|
||||
if ( touchToggleEnabled ) {
|
||||
stateBefore = currentstate;
|
||||
}
|
||||
})
|
||||
.bind( "vclick", function( event ) {
|
||||
if ( touchToggleEnabled ) {
|
||||
|
||||
if ( $(event.target).closest( ignoreTargets ).length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !scrollTriggered ) {
|
||||
$.mobile.fixedToolbars.toggle( stateBefore );
|
||||
stateBefore = null;
|
||||
}
|
||||
}
|
||||
})
|
||||
.bind( "silentscroll", showEventCallback );
|
||||
|
||||
|
||||
// The below checks first for a $(document).scrollTop() value, and if zero, binds scroll events to $(window) instead.
|
||||
// If the scrollTop value is actually zero, both will return zero anyway.
|
||||
//
|
||||
// Works with $(document), not $(window) : Opera Mobile (WinMO phone; kinda broken anyway)
|
||||
// Works with $(window), not $(document) : IE 7/8
|
||||
// Works with either $(window) or $(document) : Chrome, FF 3.6/4, Android 1.6/2.1, iOS
|
||||
// Needs work either way : BB5, Opera Mobile (iOS)
|
||||
|
||||
( ( $document.scrollTop() === 0 ) ? $window : $document )
|
||||
.bind( "scrollstart", function( event ) {
|
||||
|
||||
scrollTriggered = true;
|
||||
|
||||
if ( stateBefore === null ) {
|
||||
stateBefore = currentstate;
|
||||
}
|
||||
|
||||
// We only enter autoHideMode if the headers/footers are in
|
||||
// an overlay state or the show timer was started. If the
|
||||
// show timer is set, clear it so the headers/footers don't
|
||||
// show up until after we're done scrolling.
|
||||
var isOverlayState = stateBefore == "overlay";
|
||||
|
||||
autoHideMode = isOverlayState || !!delayTimer;
|
||||
|
||||
if ( autoHideMode ) {
|
||||
$.mobile.fixedToolbars.clearShowTimer();
|
||||
|
||||
if ( isOverlayState ) {
|
||||
$.mobile.fixedToolbars.hide( true );
|
||||
}
|
||||
}
|
||||
})
|
||||
.bind( "scrollstop", function( event ) {
|
||||
|
||||
if ( $( event.target ).closest( ignoreTargets ).length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
scrollTriggered = false;
|
||||
|
||||
if ( autoHideMode ) {
|
||||
$.mobile.fixedToolbars.startShowTimer();
|
||||
autoHideMode = false;
|
||||
}
|
||||
stateBefore = null;
|
||||
});
|
||||
|
||||
$window.bind( "resize updatelayout", showEventCallback );
|
||||
});
|
||||
|
||||
// 1. Before page is shown, check for duplicate footer
|
||||
// 2. After page is shown, append footer to new page
|
||||
$( document ).delegate( ".ui-page", "pagebeforeshow", function( event, ui ) {
|
||||
var page = $( event.target ),
|
||||
footer = page.find( ":jqmData(role='footer')" ),
|
||||
id = footer.data( "id" ),
|
||||
prevPage = ui.prevPage,
|
||||
prevFooter = prevPage && prevPage.find( ":jqmData(role='footer')" ),
|
||||
prevFooterMatches = prevFooter.length && prevFooter.jqmData( "id" ) === id;
|
||||
|
||||
if ( id && prevFooterMatches ) {
|
||||
stickyFooter = footer;
|
||||
setTop( stickyFooter.removeClass( "fade in out" ).appendTo( $.mobile.pageContainer ) );
|
||||
}
|
||||
})
|
||||
.delegate( ".ui-page", "pageshow", function( event, ui ) {
|
||||
var $this = $( this );
|
||||
|
||||
if ( stickyFooter && stickyFooter.length ) {
|
||||
setTimeout(function() {
|
||||
setTop( stickyFooter.appendTo( $this ).addClass( "fade" ) );
|
||||
stickyFooter = null;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
$.mobile.fixedToolbars.show( true, this );
|
||||
});
|
||||
|
||||
// When a collapsible is hidden or shown we need to trigger the fixed toolbar to reposition itself (#1635)
|
||||
$( document ).delegate( ".ui-collapsible-contain", "collapse expand", showEventCallback );
|
||||
|
||||
// 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,
|
||||
op, body;
|
||||
|
||||
if ( ele ) {
|
||||
body = document.body;
|
||||
op = ele.offsetParent;
|
||||
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 ) {
|
||||
|
||||
$.mobile.fixedToolbars.clearShowTimer();
|
||||
|
||||
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(),
|
||||
// el.offset().top returns the wrong value on iPad iOS 3.2.1, call our workaround instead.
|
||||
thisTop = getOffsetTop( el[ 0 ] ),
|
||||
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),
|
||||
thisCSStop = el.css( "top" ),
|
||||
classes;
|
||||
|
||||
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 ) {
|
||||
|
||||
classes = "out reverse";
|
||||
|
||||
el.animationComplete(function() {
|
||||
el.removeClass( classes ).css( "top", 0 );
|
||||
}).addClass( classes );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
startShowTimer: function() {
|
||||
|
||||
$.mobile.fixedToolbars.clearShowTimer();
|
||||
|
||||
var args = [].slice.call( arguments );
|
||||
|
||||
delayTimer = setTimeout(function() {
|
||||
delayTimer = undefined;
|
||||
$.mobile.fixedToolbars.show.apply( null, args );
|
||||
}, showDelay);
|
||||
},
|
||||
|
||||
clearShowTimer: function() {
|
||||
if ( delayTimer ) {
|
||||
clearTimeout( delayTimer );
|
||||
}
|
||||
delayTimer = undefined;
|
||||
},
|
||||
|
||||
toggle: function( from ) {
|
||||
if ( from ) {
|
||||
currentstate = from;
|
||||
}
|
||||
return ( currentstate === "overlay" ) ? $.mobile.fixedToolbars.hide() :
|
||||
$.mobile.fixedToolbars.show();
|
||||
},
|
||||
|
||||
setTouchToggleEnabled: function( enabled ) {
|
||||
touchToggleEnabled = enabled;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
//auto self-init widgets
|
||||
$( document ).bind( "pagecreate create", function( event ) {
|
||||
|
||||
if ( $( ":jqmData(position='fixed')", event.target ).length ) {
|
||||
|
||||
$( event.target ).each(function() {
|
||||
|
||||
if ( !$.support.scrollTop || ( $.support.touchOverflow && $.mobile.touchOverflowEnabled ) ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var $this = $( this );
|
||||
|
||||
if ( $this.jqmData( "fullscreen" ) ) {
|
||||
$this.addClass( "ui-page-fullscreen" );
|
||||
}
|
||||
|
||||
// Should be slidedown
|
||||
$this.find( slideDownSelector ).addClass( slideDownClass );
|
||||
|
||||
// Should be slideup
|
||||
$this.find( slideUpSelector ).addClass( slideUpClass );
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery );
|
||||
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
|
||||
});
|
||||
//>>excludeEnd("jqmBuildExclude");
|
||||
65
js/jquery.mobile.fixHeaderFooter.native.js
Normal file
65
js/jquery.mobile.fixHeaderFooter.native.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
|
||||
//>>description: Behavior for "fixed" headers,footers, and scrolling inner content
|
||||
//>>label: Fixed Toolbars
|
||||
|
||||
define( [ "jquery", "jquery.mobile.core" ], function( $ ) {
|
||||
//>>excludeEnd("jqmBuildExclude");
|
||||
(function( $, undefined ) {
|
||||
|
||||
// Enable touch overflow scrolling when it's natively supported
|
||||
$.mobile.touchOverflowEnabled = false;
|
||||
|
||||
// Enabled zoom when touch overflow is enabled. Can cause usability issues, unfortunately
|
||||
$.mobile.touchOverflowZoomEnabled = false;
|
||||
|
||||
$( document ).bind( "pagecreate", function( event ) {
|
||||
if( $.support.touchOverflow && $.mobile.touchOverflowEnabled ){
|
||||
|
||||
var $target = $( event.target ),
|
||||
scrollStartY = 0;
|
||||
|
||||
if( $target.is( ":jqmData(role='page')" ) ){
|
||||
|
||||
$target.each(function() {
|
||||
var $page = $( this ),
|
||||
$fixies = $page.find( ":jqmData(role='header'), :jqmData(role='footer')" ).filter( ":jqmData(position='fixed')" ),
|
||||
fullScreen = $page.jqmData( "fullscreen" ),
|
||||
$scrollElem = $fixies.length ? $page.find( ".ui-content" ) : $page;
|
||||
|
||||
$page.addClass( "ui-mobile-touch-overflow" );
|
||||
|
||||
$scrollElem.bind( "scrollstop", function(){
|
||||
if( $scrollElem.scrollTop() > 0 ){
|
||||
window.scrollTo( 0, $.mobile.defaultHomeScroll );
|
||||
}
|
||||
});
|
||||
|
||||
if( $fixies.length ){
|
||||
|
||||
$page.addClass( "ui-native-fixed" );
|
||||
|
||||
if( fullScreen ){
|
||||
|
||||
$page.addClass( "ui-native-fullscreen" );
|
||||
|
||||
$fixies.addClass( "fade in" );
|
||||
|
||||
$( document ).bind( "vclick", function(){
|
||||
$fixies
|
||||
.removeClass( "ui-native-bars-hidden" )
|
||||
.toggleClass( "in out" )
|
||||
.animationComplete(function(){
|
||||
$(this).not( ".in" ).addClass( "ui-native-bars-hidden" );
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})( jQuery );
|
||||
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
|
||||
});
|
||||
//>>excludeEnd("jqmBuildExclude");
|
||||
|
|
@ -1,271 +0,0 @@
|
|||
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
|
||||
//>>description: Behavior for "fixed" headers and footers
|
||||
//>>label: Fixedtoolbar
|
||||
|
||||
define( [ "jquery", "jquery.mobile.widget", "jquery.mobile.core", "jquery.mobile.navigation", "jquery.mobile.page", "jquery.mobile.page.sections" ], function( $ ) {
|
||||
//>>excludeEnd("jqmBuildExclude");
|
||||
(function( $, undefined ) {
|
||||
|
||||
|
||||
$.widget( "mobile.fixedtoolbar", $.mobile.widget, {
|
||||
options: {
|
||||
visibleOnPageShow: true,
|
||||
togglePageZoom: true,
|
||||
transition: "fade", //can be none, fade, slide (slide maps to slideup or slidedown)
|
||||
fullscreen: false,
|
||||
tapToggle: true,
|
||||
|
||||
// Browser detection! Weeee, here we go...
|
||||
// Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.
|
||||
// Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.
|
||||
// Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window
|
||||
// The following function serves to rule out some popular browsers with known fixed-positioning issues
|
||||
// This is a plugin option like any other, so feel free to improve or overwrite it
|
||||
supportBlacklist: 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 ],
|
||||
ffmatch = ua.match( /Fennec\/([0-9]+)/ ),
|
||||
ffversion = !!ffmatch && ffmatch[ 1 ],
|
||||
operammobilematch = ua.match( /Opera Mobile\/([0-9]+)/ ),
|
||||
omversion = !!operammobilematch && operammobilematch[ 1 ],
|
||||
|
||||
w = window;
|
||||
|
||||
if(
|
||||
// iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
|
||||
( ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1 || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534 )
|
||||
||
|
||||
// Opera Mini
|
||||
( w.operamini && ({}).toString.call( w.operamini ) === "[object OperaMini]" )
|
||||
||
|
||||
( operammobilematch && omverson < 7458 )
|
||||
||
|
||||
//Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
|
||||
( ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533 )
|
||||
||
|
||||
// Firefox Mobile before 6.0 -
|
||||
( ffversion && ffversion < 6 )
|
||||
||
|
||||
// WebOS less than 3
|
||||
( "palmGetResource" in window && wkversion && wkversion < 534 )
|
||||
){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
initSelector: ":jqmData(position='fixed')"
|
||||
},
|
||||
|
||||
_create: function() {
|
||||
|
||||
var self = this,
|
||||
o = self.options,
|
||||
$el = self.element,
|
||||
tbtype = $el.is( ".ui-header" ) ? "header" : "footer",
|
||||
$page = $el.closest(".ui-page");
|
||||
|
||||
// Feature detecting support for
|
||||
if( o.supportBlacklist() ){
|
||||
self.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
$el.addClass( "ui-"+ tbtype +"-fixed" );
|
||||
|
||||
// "fullscreen" overlay positioning
|
||||
// NOTE - this used to be only "data-fullscreen" on page element. Support both or deprecate page?
|
||||
if( $el.jqmData( "fullscreen" ) || $page.jqmData( "fullscreen" ) ){
|
||||
$el.addClass( "ui-"+ tbtype +"-fullscreen" );
|
||||
$page.addClass( "ui-page-" + tbtype + "-fullscreen" );
|
||||
}
|
||||
// If not fullscreen, add class to page to set top or bottom padding
|
||||
else{
|
||||
$page.addClass( "ui-page-" + tbtype + "-fixed" );
|
||||
}
|
||||
|
||||
self._addTransitionClass();
|
||||
self._bindPageEvents();
|
||||
self._bindToggleHandlers();
|
||||
},
|
||||
|
||||
_addTransitionClass: function(){
|
||||
var tclass = this.options.transition;
|
||||
|
||||
if( tclass && tclass !== "none" ){
|
||||
// use appropriate slide for header or footer
|
||||
if( tclass === "slide" ){
|
||||
tclass = this.element.is( ".ui-header" ) ? "slidedown" : "slideup";
|
||||
}
|
||||
|
||||
this.element.addClass( tclass );
|
||||
}
|
||||
},
|
||||
|
||||
_bindPageEvents: function(){
|
||||
var self = this,
|
||||
o = self.options,
|
||||
$el = self.element;
|
||||
|
||||
//page event bindings
|
||||
$el.closest( ".ui-page" )
|
||||
.bind( "pagebeforeshow", function(){
|
||||
if( o.togglePageZoom ){
|
||||
self.disablePageZoom();
|
||||
}
|
||||
if( o.visibleOnPageShow ){
|
||||
self.show();
|
||||
}
|
||||
} )
|
||||
.bind( "pagehide", function(){
|
||||
if( o.togglePageZoom ){
|
||||
self.restorePageZoom();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_visible: false,
|
||||
|
||||
show: function(){
|
||||
var hideClass = "ui-fixed-hidden",
|
||||
$el = this.element,
|
||||
scroll = $( window ).scrollTop(),
|
||||
elHeight = $el.height(),
|
||||
pHeight = $el.closest( ".ui-page" ).height(),
|
||||
viewportHeight = Math.min( screen.height, $( window ).height() ),
|
||||
tbtype = $el.is( ".ui-header" ) ? "header" : "footer";
|
||||
|
||||
if( this.options.transition && this.options.transition !== "none" &&
|
||||
(
|
||||
( tbtype === "header" && !this.options.fullscreen && scroll > elHeight ) ||
|
||||
( tbtype === "footer" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )
|
||||
) || this.options.fullscreen ){
|
||||
$el
|
||||
.removeClass( "out " + hideClass )
|
||||
.addClass( "in" );
|
||||
}
|
||||
else {
|
||||
$el.removeClass( hideClass );
|
||||
}
|
||||
this._visible = true;
|
||||
},
|
||||
|
||||
hide: function(){
|
||||
var hideClass = "ui-fixed-hidden",
|
||||
$el = this.element,
|
||||
scroll = $( window ).scrollTop(),
|
||||
elHeight = $el.height(),
|
||||
pHeight = $el.closest( ".ui-page" ).height(),
|
||||
viewportHeight = Math.min( screen.height, $( window ).height() ),
|
||||
tbtype = $el.is( ".ui-header" ) ? "header" : "footer";
|
||||
|
||||
if( this.options.transition && this.options.transition !== "none" &&
|
||||
(
|
||||
( tbtype === "header" && !this.options.fullscreen && scroll > elHeight ) ||
|
||||
( tbtype === "footer" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )
|
||||
) || this.options.fullscreen ){
|
||||
$el
|
||||
.removeClass( "in" )
|
||||
.addClass( "out" )
|
||||
.animationComplete( function(){
|
||||
$el.addClass( hideClass );
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.element.addClass( hideClass );
|
||||
}
|
||||
this._visible = false;
|
||||
},
|
||||
|
||||
toggle: function(){
|
||||
this[ this._visible ? "hide" : "show" ]();
|
||||
},
|
||||
|
||||
_bindToggleHandlers: function(){
|
||||
var self = this,
|
||||
o = self.options,
|
||||
$el = self.element;
|
||||
|
||||
// tap toggle
|
||||
$el.closest( ".ui-page" )
|
||||
.bind( "vclick", function( e ){
|
||||
if( o.tapToggle && $el.find( e.target ).length === 0 ){
|
||||
self.toggle();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
this.element.removeClass( "ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden" )
|
||||
this.element.closest( ".ui-page" ).removeClass( "ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen" );
|
||||
},
|
||||
|
||||
// for caching reference to meta viewport elem
|
||||
_metaViewport: null,
|
||||
|
||||
// on pageshow, does a meta viewport element exist in the head?
|
||||
_metaViewportPreexists: false,
|
||||
|
||||
// used for storing value of meta viewport content at page show, for restoration on hide
|
||||
_metaViewportContent: "",
|
||||
|
||||
// Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up
|
||||
// This method is meant to disable zoom while a fixed-positioned toolbar page is visible
|
||||
disablePageZoom: function(){
|
||||
if( !this.options.togglePageZoom ){
|
||||
return;
|
||||
}
|
||||
var cont = "user-scalable=no";
|
||||
this._metaViewport = $( "meta[name='viewport']" );
|
||||
this._metaViewportPreexists = this._metaViewport.length;
|
||||
|
||||
var currentContent = this._metaViewport.attr( "content" );
|
||||
|
||||
// If scaling's already disabled, or another plugin is handling it on this page already
|
||||
if( currentContent.indexOf( cont ) > -1 ){
|
||||
return;
|
||||
}
|
||||
else {
|
||||
this._metaViewportContent = currentContent;
|
||||
}
|
||||
|
||||
if( !this._metaViewportPreexists ){
|
||||
this._metaViewport = $( "<meta>", { "name": "viewport", "content": cont } ).prependTo( "head" );
|
||||
}
|
||||
else{
|
||||
this._metaViewport.attr( "content", this._metaViewportContent + ", " + cont );
|
||||
}
|
||||
},
|
||||
|
||||
// restore the meta viewport tag to its original state, or remove it
|
||||
restorePageZoom: function(){
|
||||
if( !this.options.togglePageZoom ){
|
||||
return;
|
||||
}
|
||||
var cont = "user-scalable=no";
|
||||
if( this._metaViewport.attr( "content" ).indexOf( cont ) < 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( this._metaViewportPreexists ){
|
||||
this._metaViewport.attr( "content", this._metaViewportContent );
|
||||
}
|
||||
else {
|
||||
this._metaViewport.remove();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//auto self-init widgets
|
||||
$( document ).bind( "pagecreate create", function( e ){
|
||||
$( $.mobile.fixedtoolbar.prototype.options.initSelector, e.target ).fixedtoolbar();
|
||||
});
|
||||
|
||||
})( jQuery );
|
||||
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
|
||||
});
|
||||
//>>excludeEnd("jqmBuildExclude");
|
||||
|
|
@ -83,8 +83,6 @@
|
|||
// part of jQuery BBQ, but also be available separately.
|
||||
|
||||
(function($,window,undefined){
|
||||
'$:nomunge'; // Used by YUI compressor.
|
||||
|
||||
// Reused string.
|
||||
var str_hashchange = 'hashchange',
|
||||
|
||||
|
|
|
|||
|
|
@ -85,13 +85,27 @@ define( [ "jquery", "jquery.mobile.core", "jquery.mobile.navigation", "jquery.mo
|
|||
// find and enhance the pages in the dom and transition to the first page.
|
||||
initializePage: function() {
|
||||
// find present pages
|
||||
var $pages = $( ":jqmData(role='page')" );
|
||||
var $dialogs, $pages = $( ":jqmData(role='page')" );
|
||||
|
||||
// if no pages are found, create one with body's inner html
|
||||
// if no pages are found, check for dialogs or create one with body's inner html
|
||||
if ( !$pages.length ) {
|
||||
$pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 );
|
||||
$dialogs = $( ":jqmData(role='dialog')" );
|
||||
|
||||
// if there are no pages but a dialog is present, load it as a page
|
||||
if( $dialogs.length ) {
|
||||
// alter the attribute so it will be treated as a page unpon enhancement
|
||||
// TODO allow for the loading of a dialog as the first page (many considerations)
|
||||
$dialogs.first().attr( "data-" + $.mobile.ns + "role", "page" );
|
||||
|
||||
// remove the first dialog from the set of dialogs since it's now a page
|
||||
// add it to the empty set of pages to be loaded by the initial changepage
|
||||
$pages = $pages.add( $dialogs.get().shift() );
|
||||
} else {
|
||||
$pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add dialogs, set data-url attrs
|
||||
$pages.add( ":jqmData(role='dialog')" ).each(function() {
|
||||
var $this = $(this);
|
||||
|
|
@ -126,6 +140,24 @@ define( [ "jquery", "jquery.mobile.core", "jquery.mobile.navigation", "jquery.mo
|
|||
}
|
||||
});
|
||||
|
||||
// This function injects a meta viewport tag to prevent scaling. Off by default, on by default when touchOverflow scrolling is enabled
|
||||
function disableZoom() {
|
||||
var cont = "user-scalable=no",
|
||||
meta = $( "meta[name='viewport']" );
|
||||
|
||||
if( meta.length ){
|
||||
meta.attr( "content", meta.attr( "content" ) + ", " + cont );
|
||||
}
|
||||
else{
|
||||
$( "head" ).prepend( "<meta>", { "name": "viewport", "content": cont } );
|
||||
}
|
||||
}
|
||||
|
||||
// if touch-overflow is enabled, disable user scaling, as it creates usability issues
|
||||
if( $.support.touchOverflow && $.mobile.touchOverflowEnabled && !$.mobile.touchOverflowZoomEnabled ){
|
||||
disableZoom();
|
||||
}
|
||||
|
||||
// initialize events now, after mobileinit has occurred
|
||||
$.mobile._registerInternalEvents();
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ define([
|
|||
'order!jquery.mobile.buttonMarkup',
|
||||
'order!jquery.mobile.controlGroup',
|
||||
'jquery.mobile.links',
|
||||
'jquery.mobile.fixedToolbar'
|
||||
'jquery.mobile.fixHeaderFooter',
|
||||
'jquery.mobile.fixHeaderFooter.native'
|
||||
], function() {
|
||||
require( [ 'jquery.mobile.init' ] );
|
||||
});
|
||||
|
|
|
|||
|
|
@ -406,9 +406,21 @@ define( [
|
|||
|
||||
// Save the last scroll distance per page, before it is hidden
|
||||
var setLastScrollEnabled = true,
|
||||
setLastScroll, delayedSetLastScroll;
|
||||
firstScrollElem, getScrollElem, setLastScroll, delayedSetLastScroll;
|
||||
|
||||
setLastScroll = function() {
|
||||
getScrollElem = function() {
|
||||
var scrollElem = $window, activePage,
|
||||
touchOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled;
|
||||
|
||||
if( touchOverflow ){
|
||||
activePage = $( ".ui-page-active" );
|
||||
scrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage;
|
||||
}
|
||||
|
||||
return scrollElem;
|
||||
};
|
||||
|
||||
setLastScroll = function( scrollElem ) {
|
||||
// this barrier prevents setting the scroll value based on the browser
|
||||
// scrolling the window based on a hashchange
|
||||
if( !setLastScrollEnabled ) {
|
||||
|
|
@ -418,7 +430,7 @@ define( [
|
|||
var active = $.mobile.urlHistory.getActive();
|
||||
|
||||
if( active ) {
|
||||
var lastScroll = $window.scrollTop();
|
||||
var lastScroll = scrollElem && scrollElem.scrollTop();
|
||||
|
||||
// Set active page's lastScroll prop.
|
||||
// If the location we're scrolling to is less than minScrollBack, let it go.
|
||||
|
|
@ -431,7 +443,7 @@ define( [
|
|||
// to the hash targets location (sometimes the top of the page). once pagechange fires
|
||||
// getLastScroll is again permitted to operate
|
||||
delayedSetLastScroll = function() {
|
||||
setTimeout( setLastScroll, 100 );
|
||||
setTimeout( setLastScroll, 100, $(this) );
|
||||
};
|
||||
|
||||
// disable an scroll setting when a hashchange has been fired, this only works
|
||||
|
|
@ -450,22 +462,23 @@ define( [
|
|||
$window.one( "pagecontainercreate", function(){
|
||||
// once the page has changed, re-enable the scroll recording
|
||||
$.mobile.pageContainer.bind( "pagechange", function() {
|
||||
var scrollElem = getScrollElem();
|
||||
|
||||
setLastScrollEnabled = true;
|
||||
|
||||
// remove any binding that previously existed on the get scroll
|
||||
// which may or may not be different than the scroll element determined for
|
||||
// this page previously
|
||||
$window.unbind( "scrollstop", delayedSetLastScroll );
|
||||
scrollElem.unbind( "scrollstop", delayedSetLastScroll );
|
||||
|
||||
// determine and bind to the current scoll element which may be the window
|
||||
// or in the case of touch overflow the element with touch overflow
|
||||
$window.bind( "scrollstop", delayedSetLastScroll );
|
||||
scrollElem.bind( "scrollstop", delayedSetLastScroll );
|
||||
});
|
||||
});
|
||||
|
||||
// bind to scrollstop for the first page as "pagechange" won't be fired in that case
|
||||
$window.bind( "scrollstop", delayedSetLastScroll );
|
||||
getScrollElem().bind( "scrollstop", delayedSetLastScroll );
|
||||
|
||||
//function for transitioning between two existing pages
|
||||
function transitionPages( toPage, fromPage, transition, reverse ) {
|
||||
|
|
@ -516,6 +529,10 @@ define( [
|
|||
|
||||
//simply set the active page's minimum height to screen height, depending on orientation
|
||||
function resetActivePageHeight(){
|
||||
// Don't apply this height in touch overflow enabled mode
|
||||
if( $.support.touchOverflow && $.mobile.touchOverflowEnabled ){
|
||||
return;
|
||||
}
|
||||
$( "." + $.mobile.activePageClass ).css( "min-height", getScreenHeight() );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ var dataPropertyName = "virtualMouseBindings",
|
|||
touchTargetPropertyName = "virtualTouchID",
|
||||
virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ),
|
||||
touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ),
|
||||
mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],
|
||||
mouseEventProps = $.event.props.concat( mouseHookProps ),
|
||||
activeDocHandlers = {},
|
||||
resetTimerID = 0,
|
||||
startX = 0,
|
||||
|
|
@ -64,6 +66,12 @@ function createVirtualEvent( event, eventType ) {
|
|||
oe = event.originalEvent;
|
||||
props = $.event.props;
|
||||
|
||||
// addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280
|
||||
// https://github.com/jquery/jquery-mobile/issues/3280
|
||||
if ( t.search(/mouse/) >-1 ) {
|
||||
props = mouseEventProps;
|
||||
}
|
||||
|
||||
// copy original event properties over to the new event
|
||||
// this would happen if we could call $.event.fix instead of $.Event
|
||||
// but we don't have a way to force an event to be fixed multiple times
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ $.widget( "mobile.widget", {
|
|||
// TODO remove dependency on the page widget for the keepNative.
|
||||
// Currently the keepNative value is defined on the page prototype so
|
||||
// the method is as well
|
||||
var page = $(target).closest(":jqmData(role='page')").data( "page" ),
|
||||
var page = $.mobile.closestPageData( $(target) ),
|
||||
keepNative = (page && page.keepNativeSelector()) || "";
|
||||
|
||||
$( this.options.initSelector, target ).not( keepNative )[ this.widgetName ]();
|
||||
|
|
|
|||
|
|
@ -1,215 +0,0 @@
|
|||
/*
|
||||
* mobile Fixed Toolbar unit tests
|
||||
*/
|
||||
(function($){
|
||||
module('jquery.mobile.fixedToolbar.js');
|
||||
|
||||
var defaultMeta = "width=device-width, initial-scale=1";
|
||||
|
||||
function injectMeta( content ){
|
||||
content = content || defaultMeta;
|
||||
$( "meta[name=viewport]" ).remove();
|
||||
$( "<meta name='viewport' content='"+ content +"'>" ).prependTo( "head" );
|
||||
}
|
||||
|
||||
$( "html" ).height( screen.height * 3 );
|
||||
|
||||
function scrollDown(){
|
||||
window.scrollTo(0,screen.height );
|
||||
}
|
||||
|
||||
function scrollUp(){
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
|
||||
|
||||
// add meta viewport tag
|
||||
injectMeta();
|
||||
|
||||
test( "Fixed Header Structural Classes are applied correctly", function(){
|
||||
|
||||
//footer
|
||||
ok( !$('#classes-test-a').hasClass('ui-header-fixed'), 'An ordinary header should not have fixed classes');
|
||||
ok( $('#classes-test-b').hasClass('ui-header-fixed'), 'An header with data-position=fixed should have ui-header-fixed class');
|
||||
ok( $('#classes-test-c').hasClass('ui-header-fullscreen'), 'An header with data-position=fixed and data-fullscreen should have ui-header-fullscreen class');
|
||||
|
||||
//footer
|
||||
ok( !$('#classes-test-d').hasClass('ui-footer-fixed'), 'An ordinary footer should not have fixed classes');
|
||||
ok( $('#classes-test-e').hasClass('ui-footer-fixed'), 'A footer with data-position=fixed should have ui-footer-fixed class"');
|
||||
ok( $('#classes-test-f').hasClass('ui-footer-fullscreen'), 'A footer with data-position=fixed and data-fullscreen should have ui-footer-fullscreen class');
|
||||
|
||||
//parent
|
||||
ok( $('#classes-test-b').closest( ".ui-page" ).hasClass( "ui-page-header-fixed" ), "Parent page of a fixed header has class ui-page-header-fixed" )
|
||||
ok( $('#classes-test-e').closest( ".ui-page" ).hasClass( "ui-page-footer-fixed" ), "Parent page of a fixed footer has class ui-page-header-fixed" )
|
||||
ok( $('#classes-test-c').closest( ".ui-page" ).hasClass( "ui-page-header-fullscreen" ), "Parent page of a fullscreen header has class ui-page-header-fullscreen" )
|
||||
ok( $('#classes-test-f').closest( ".ui-page" ).hasClass( "ui-page-footer-fullscreen" ), "Parent page of a fullscreen footer has class ui-page-header-fullscreen" )
|
||||
|
||||
|
||||
});
|
||||
|
||||
asyncTest( "Fixed header and footer transition classes are applied correctly", function(){
|
||||
|
||||
expect( 6 );
|
||||
|
||||
$.testHelper.sequence([
|
||||
function(){
|
||||
scrollDown();
|
||||
},
|
||||
|
||||
function(){
|
||||
//show first
|
||||
$( '#classes-test-b, #classes-test-g, #classes-test-e,#classes-test-h,#classes-test-i,#classes-test-j' ).fixedtoolbar( "show" );
|
||||
},
|
||||
|
||||
function() {
|
||||
|
||||
ok( $( '#classes-test-g' ).hasClass('fade'), 'The fade class should be applied by default');
|
||||
ok( $( '#classes-test-b' ).hasClass('in'), 'The "in" class should be applied by default');
|
||||
ok( !$( '#classes-test-h' ).hasClass('fade'), 'The fade class should not be applied when the header has a data-transition of "none"');
|
||||
|
||||
ok( !$( '#classes-test-h' ).hasClass('in'), 'The "in" class should not be applied when the header has a data-transition of "none"');
|
||||
ok( $( '#classes-test-i' ).hasClass('slidedown'), 'The "slidedown" class should be applied when the header has a data-transition of "slide"');
|
||||
ok( $( '#classes-test-j' ).hasClass('slideup'), 'The "slideup" class should be applied when the footer has a data-transition of "slide"');
|
||||
|
||||
},
|
||||
|
||||
function(){
|
||||
scrollUp();
|
||||
start();
|
||||
}
|
||||
], 500);
|
||||
|
||||
});
|
||||
|
||||
test( "User zooming is disabled when the header is visible", function(){
|
||||
injectMeta();
|
||||
ok( $( "meta[name=viewport]" ).attr( "content" ).indexOf( ", user-scalable=no" ) < 0, "The meta viewport tag's content does not contain , user-scalable=no by default" );
|
||||
$( ".ui-page-active" ).trigger( "pagebeforeshow" );
|
||||
ok( $( "meta[name=viewport]" ).attr( "content" ).indexOf( ", user-scalable=no" ) > -1, "After pagebeforeshow, the meta viewport tag's content contains , user-scalable=no" );
|
||||
|
||||
});
|
||||
|
||||
test( "Meta viewport content is restored to previous state, and zooming renabled, after pagehide", function(){
|
||||
injectMeta();
|
||||
ok( $( "meta[name=viewport]" ).attr( "content" ).indexOf( ", user-scalable=no" ) < 0, "The meta viewport tag's content does not contain , user-scalable=no by default" );
|
||||
$( ".ui-page-active" ).trigger( "pagebeforeshow" );
|
||||
ok( $( "meta[name=viewport]" ).attr( "content" ).indexOf( ", user-scalable=no" ) > -1, "After pagebeforeshow, the meta viewport tag's content contains , user-scalable=no" );
|
||||
$( ".ui-page-active" ).trigger( "pagehide" );
|
||||
ok( $( "meta[name=viewport]" ).attr( "content" ).indexOf( ", user-scalable=no" ) < 0, "After pagehide, the meta viewport tag's content does not contain , user-scalable=no by default" );
|
||||
ok( $( "meta[name=viewport]" ).attr( "content" ) == defaultMeta, "After pagehide, meta viewport content is restored to previous state" );
|
||||
$( ".ui-page-active" ).trigger( "pageshow" );
|
||||
});
|
||||
|
||||
test( "disablePageZoom and restorePageZoom methods properly toggle user-scalable=no on the meta viewport tag", function(){
|
||||
injectMeta();
|
||||
$( '#classes-test-b' ).fixedtoolbar( "disablePageZoom" );
|
||||
ok( $( "meta[name=viewport]" ).attr( "content" ).indexOf( ", user-scalable=no" ) > -1, "After pagebeforeshow, the meta viewport tag's content contains , user-scalable=no" );
|
||||
$( '#classes-test-b' ).fixedtoolbar( "restorePageZoom" );
|
||||
ok( $( "meta[name=viewport]" ).attr( "content" ) == defaultMeta, "After calling restorePageZoom, meta viewport content is restored to previous state" );
|
||||
});
|
||||
|
||||
|
||||
asyncTest( "The hide method is working properly", function() {
|
||||
|
||||
expect( 2 );
|
||||
|
||||
$.testHelper.sequence([
|
||||
function(){
|
||||
scrollDown();
|
||||
},
|
||||
|
||||
function() {
|
||||
$( '#classes-test-g' ).fixedtoolbar( "hide" );
|
||||
|
||||
ok( $( '#classes-test-g' ).hasClass('out'), 'The out class should be applied when hide is called');
|
||||
},
|
||||
|
||||
function() {
|
||||
ok( $( '#classes-test-g' ).hasClass('ui-fixed-hidden'), 'The toolbar has the ui-fixed-hidden class applied after hide');
|
||||
$( '#classes-test-g' ).fixedtoolbar( "show" );
|
||||
|
||||
},
|
||||
|
||||
function(){
|
||||
scrollUp();
|
||||
start();
|
||||
}
|
||||
|
||||
], 500);
|
||||
});
|
||||
|
||||
|
||||
|
||||
asyncTest( "The show method is working properly", function() {
|
||||
|
||||
expect( 2 );
|
||||
|
||||
$.testHelper.sequence([
|
||||
function(){
|
||||
scrollDown();
|
||||
},
|
||||
|
||||
function() {
|
||||
$( '#classes-test-g' ).fixedtoolbar( "hide" );
|
||||
},
|
||||
|
||||
function() {
|
||||
$( '#classes-test-g' ).fixedtoolbar( "show" );
|
||||
|
||||
ok( $( '#classes-test-g' ).hasClass('in'), 'The in class should be applied when show is called');
|
||||
},
|
||||
|
||||
function() {
|
||||
ok( !$( '#classes-test-g' ).hasClass('ui-fixed-hidden'), 'The toolbar does not have the ui-fixed-hidden class applied after show');
|
||||
|
||||
},
|
||||
|
||||
function(){
|
||||
scrollUp();
|
||||
start();
|
||||
}
|
||||
], 500);
|
||||
});
|
||||
|
||||
|
||||
asyncTest( "The toggle method is working properly", function() {
|
||||
|
||||
expect( 3 );
|
||||
|
||||
$.testHelper.sequence([
|
||||
function(){
|
||||
scrollDown();
|
||||
},
|
||||
|
||||
function(){
|
||||
$( '#classes-test-g' ).fixedtoolbar( "show" );
|
||||
},
|
||||
|
||||
function() {
|
||||
ok( !$( '#classes-test-g' ).hasClass('ui-fixed-hidden'), 'The toolbar does not have the ui-fixed-hidden class');
|
||||
$( '#classes-test-g' ).fixedtoolbar( "toggle" );
|
||||
},
|
||||
|
||||
function() {
|
||||
ok( $( '#classes-test-g' ).hasClass('ui-fixed-hidden'), 'The toolbar does have the ui-fixed-hidden class');
|
||||
$( '#classes-test-g' ).fixedtoolbar( "toggle" );
|
||||
},
|
||||
|
||||
function() {
|
||||
ok( !$( '#classes-test-g' ).hasClass('ui-fixed-hidden'), 'The toolbar does not have the ui-fixed-hidden class');
|
||||
|
||||
},
|
||||
|
||||
function(){
|
||||
scrollUp();
|
||||
start();
|
||||
}
|
||||
|
||||
], 500);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})(jQuery);
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>jQuery Mobile Fixed Toolbar Integration Test</title>
|
||||
|
||||
|
||||
<script src="../../../external/requirejs/require.js"></script>
|
||||
<script src="../../../js/jquery.js"></script>
|
||||
<script src="../jquery.setNameSpace.js"></script>
|
||||
<script src="../../../tests/jquery.testHelper.js"></script>
|
||||
<script src="../../../external/qunit.js"></script>
|
||||
<script>
|
||||
$.testHelper.asyncLoad([
|
||||
[
|
||||
"jquery.mobile.fixedToolbar"
|
||||
],
|
||||
[ "jquery.mobile.init" ],
|
||||
[
|
||||
"./fixedToolbar.js"
|
||||
]
|
||||
]);
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="../../../css/themes/default/jquery.mobile.css"/>
|
||||
<link rel="stylesheet" href="../../../external/qunit.css"/>
|
||||
|
||||
<script src="../swarminject.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1 id="qunit-header">jQuery Mobile FieldContainer Test Suite</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests">
|
||||
</ol>
|
||||
|
||||
<div data-nstest-role="page">
|
||||
<!-- structural classes -->
|
||||
<div data-nstest-role="header" id="classes-test-a"></div>
|
||||
<div data-nstest-role="header" data-nstest-position="fixed" id="classes-test-b"></div>
|
||||
<div data-nstest-role="header" data-nstest-position="fixed" data-nstest-fullscreen="true" id="classes-test-c"></div>
|
||||
<div data-nstest-role="footer" id="classes-test-d"></div>
|
||||
<div data-nstest-role="footer" data-nstest-position="fixed" id="classes-test-e"></div>
|
||||
<div data-nstest-role="footer" data-nstest-position="fixed" data-nstest-fullscreen="true" id="classes-test-f"></div>
|
||||
|
||||
<!-- transition classes -->
|
||||
<div data-nstest-role="header" data-nstest-position="fixed" id="classes-test-g"></div>
|
||||
<div data-nstest-role="header" data-nstest-position="fixed" data-nstest-transition="none" id="classes-test-h"></div>
|
||||
<div data-nstest-role="header" data-nstest-position="fixed" data-nstest-transition="slide" id="classes-test-i"></div>
|
||||
<div data-nstest-role="footer" data-nstest-position="fixed" data-nstest-transition="slide" id="classes-test-j"></div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -15,7 +15,7 @@ $.testHelper.excludeFileProtocol(function(){
|
|||
|
||||
// NOTE following two tests have debatable value as they only
|
||||
// prevent property name changes and improper attribute checks
|
||||
asyncTest( "detects functionality from basic affirmative properties and attributes", 5, function(){
|
||||
test( "detects functionality from basic affirmative properties and attributes", function(){
|
||||
// TODO expose properties for less brittle tests
|
||||
$.extend(window, {
|
||||
WebKitTransitionEvent: true,
|
||||
|
|
@ -30,29 +30,23 @@ $.testHelper.excludeFileProtocol(function(){
|
|||
|
||||
$.mobile.media = function(){ return true; };
|
||||
|
||||
$.testHelper.reloadModule(libName).done(
|
||||
function() {
|
||||
ok($.support.orientation);
|
||||
ok($.support.touch);
|
||||
ok($.support.cssTransitions);
|
||||
ok($.support.pushState);
|
||||
ok($.support.mediaquery);
|
||||
start();
|
||||
}
|
||||
);
|
||||
$.testHelper.reloadLib(libName);
|
||||
|
||||
ok($.support.orientation);
|
||||
ok($.support.touch);
|
||||
ok($.support.cssTransitions);
|
||||
ok($.support.pushState);
|
||||
ok($.support.mediaquery);
|
||||
});
|
||||
|
||||
asyncTest( "detects functionality from basic negative properties and attributes (where possible)", 2, function(){
|
||||
test( "detects functionality from basic negative properties and attributes (where possible)", function(){
|
||||
delete window["orientation"];
|
||||
delete document["ontouchend"];
|
||||
|
||||
$.testHelper.reloadModule(libName).done(
|
||||
function() {
|
||||
ok(!$.support.orientation);
|
||||
ok(!$.support.touch);
|
||||
start();
|
||||
}
|
||||
);
|
||||
$.testHelper.reloadLib(libName);
|
||||
|
||||
ok(!$.support.orientation);
|
||||
ok(!$.support.touch);
|
||||
});
|
||||
|
||||
// NOTE mocks prependTo to simulate base href updates or lack thereof
|
||||
|
|
@ -67,44 +61,32 @@ $.testHelper.excludeFileProtocol(function(){
|
|||
};
|
||||
};
|
||||
|
||||
asyncTest( "detects dynamic base tag when new base element added and base href updates", 1, function(){
|
||||
test( "detects dynamic base tag when new base element added and base href updates", function(){
|
||||
mockBaseCheck(location.protocol + '//' + location.host + location.pathname + "ui-dir/");
|
||||
$.testHelper.reloadModule(libName).done(
|
||||
function() {
|
||||
ok($.support.dynamicBaseTag);
|
||||
start();
|
||||
}
|
||||
);
|
||||
$.testHelper.reloadLib(libName);
|
||||
ok($.support.dynamicBaseTag);
|
||||
});
|
||||
|
||||
asyncTest( "detects no dynamic base tag when new base element added and base href unchanged", 1, function(){
|
||||
test( "detects no dynamic base tag when new base element added and base href unchanged", function(){
|
||||
mockBaseCheck('testurl');
|
||||
|
||||
$.testHelper.reloadModule(libName).done(
|
||||
function() {
|
||||
ok(!$.support.dynamicBaseTag);
|
||||
start();
|
||||
}
|
||||
);
|
||||
$.testHelper.reloadLib(libName);
|
||||
ok(!$.support.dynamicBaseTag);
|
||||
});
|
||||
|
||||
asyncTest( "jQM's IE browser check properly detects IE versions", 1, function(){
|
||||
//here we're just comparing our version to what the conditional compilation finds
|
||||
var ie = !!$.browser.msie, //get a boolean
|
||||
version = parseInt( $.browser.version, 10),
|
||||
jqmdetectedver = $.mobile.browser.ie;
|
||||
test( "jQM's IE browser check properly detects IE versions", function(){
|
||||
$.testHelper.reloadLib(libName);
|
||||
|
||||
$.testHelper.reloadModule(libName).done(
|
||||
function() {
|
||||
if( ie ){
|
||||
same(version, jqmdetectedver, "It's IE and the version is correct");
|
||||
}
|
||||
else{
|
||||
same(ie, jqmdetectedver, "It's not IE");
|
||||
}
|
||||
start();
|
||||
}
|
||||
);
|
||||
//here we're just comparing our version to what the conditional compilation finds
|
||||
var ie = !!$.browser.msie, //get a boolean
|
||||
version = parseInt( $.browser.version, 10),
|
||||
jqmdetectedver = $.mobile.browser.ie;
|
||||
|
||||
if( ie ){
|
||||
same(version, jqmdetectedver, "It's IE and the version is correct");
|
||||
}
|
||||
else{
|
||||
same(ie, jqmdetectedver, "It's not IE");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue