reverted fixed toolbar merge, there are some issues with the branch that need to be addressed

This commit is contained in:
John Bender 2012-01-17 21:46:28 -08:00
parent ca0c1a9c61
commit f2802bdc65
20 changed files with 646 additions and 626 deletions

View file

@ -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; }

View file

@ -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 }

View 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; }

View file

@ -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" );

View file

@ -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>

View file

@ -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'
);

View file

@ -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 );

View file

@ -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",

View 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");

View 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");

View file

@ -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");

View file

@ -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',

View file

@ -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();

View file

@ -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' ] );
});

View file

@ -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() );
}

View file

@ -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

View file

@ -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 ]();

View file

@ -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);

View file

@ -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>

View file

@ -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");
}
});