mirror of
https://github.com/Hopiu/jquery-mobile.git
synced 2026-03-17 06:20:26 +00:00
moved page load event bindings to a post-mobileinit callback so that the useFastClick option can be set before it is used. Unit test included. Fixes #1869
This commit is contained in:
parent
40b1e16693
commit
ffdfa4e7c2
4 changed files with 184 additions and 162 deletions
|
|
@ -101,6 +101,9 @@
|
|||
}
|
||||
});
|
||||
|
||||
//initialize events now, after mobileinit has occurred
|
||||
$.mobile._registerInternalEvents();
|
||||
|
||||
//check which scrollTop value should be used by scrolling to 1 immediately at domready
|
||||
//then check what the scroll top is. Android will report 0... others 1
|
||||
//note that this initial scroll won't hide the address bar. It's just for the check.
|
||||
|
|
|
|||
|
|
@ -981,168 +981,175 @@
|
|||
|
||||
return path.makeUrlAbsolute( url, base);
|
||||
}
|
||||
|
||||
//add active state on vclick
|
||||
$( document ).bind( "vclick", function( event ) {
|
||||
var link = findClosestLink( event.target );
|
||||
if ( link ) {
|
||||
if ( path.parseUrl( link.getAttribute( "href" ) || "#" ).hash !== "#" ) {
|
||||
$( link ).closest( ".ui-btn" ).not( ".ui-disabled" ).addClass( $.mobile.activeBtnClass );
|
||||
$( "." + $.mobile.activePageClass + " .ui-btn" ).not( link ).blur();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// click routing - direct to HTTP or Ajax, accordingly
|
||||
// TODO: most of the time, vclick will be all we need for fastClick bulletproofing.
|
||||
// However, it seems that in Android 2.1, a click event
|
||||
// will occasionally arrive independently of the bound vclick
|
||||
// binding to click as well seems to help in this edge case
|
||||
// we'll dig into this further in the next release cycle
|
||||
$( document ).bind( $.mobile.useFastClick ? "vclick click" : "click", function( event ) {
|
||||
var link = findClosestLink( event.target );
|
||||
if ( !link ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $link = $( link ),
|
||||
//remove active link class if external (then it won't be there if you come back)
|
||||
httpCleanup = function(){
|
||||
window.setTimeout( function() { removeActiveLinkClass( true ); }, 200 );
|
||||
};
|
||||
|
||||
//if there's a data-rel=back attr, go back in history
|
||||
if( $link.is( ":jqmData(rel='back')" ) ) {
|
||||
window.history.back();
|
||||
return false;
|
||||
}
|
||||
|
||||
//if ajax is disabled, exit early
|
||||
if( !$.mobile.ajaxEnabled ){
|
||||
httpCleanup();
|
||||
//use default click handling
|
||||
return;
|
||||
}
|
||||
|
||||
var baseUrl = getClosestBaseUrl( $link ),
|
||||
|
||||
//get href, if defined, otherwise default to empty hash
|
||||
href = path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );
|
||||
|
||||
// XXX_jblas: Ideally links to application pages should be specified as
|
||||
// an url to the application document with a hash that is either
|
||||
// the site relative path or id to the page. But some of the
|
||||
// internal code that dynamically generates sub-pages for nested
|
||||
// lists and select dialogs, just write a hash in the link they
|
||||
// create. This means the actual URL path is based on whatever
|
||||
// the current value of the base tag is at the time this code
|
||||
// is called. For now we are just assuming that any url with a
|
||||
// hash in it is an application page reference.
|
||||
if ( href.search( "#" ) != -1 ) {
|
||||
href = href.replace( /[^#]*#/, "" );
|
||||
if ( !href ) {
|
||||
//link was an empty hash meant purely
|
||||
//for interaction, so we ignore it.
|
||||
event.preventDefault();
|
||||
return;
|
||||
} else if ( path.isPath( href ) ) {
|
||||
//we have apath so make it the href we want to load.
|
||||
href = path.makeUrlAbsolute( href, baseUrl );
|
||||
} else {
|
||||
//we have a simple id so use the documentUrl as its base.
|
||||
href = path.makeUrlAbsolute( "#" + href, documentUrl.hrefNoHash );
|
||||
}
|
||||
}
|
||||
|
||||
// Should we handle this link, or let the browser deal with it?
|
||||
var useDefaultUrlHandling = $link.is( "[rel='external']" ) || $link.is( ":jqmData(ajax='false')" ) || $link.is( "[target]" ),
|
||||
|
||||
// Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
|
||||
// requests if the document doing the request was loaded via the file:// protocol.
|
||||
// This is usually to allow the application to "phone home" and fetch app specific
|
||||
// data. We normally let the browser handle external/cross-domain urls, but if the
|
||||
// allowCrossDomainPages option is true, we will allow cross-domain http/https
|
||||
// requests to go through our page loading logic.
|
||||
isCrossDomainPageLoad = ( $.mobile.allowCrossDomainPages && documentUrl.protocol === "file:" && href.search( /^https?:/ ) != -1 ),
|
||||
|
||||
//check for protocol or rel and its not an embedded page
|
||||
//TODO overlap in logic from isExternal, rel=external check should be
|
||||
// moved into more comprehensive isExternalLink
|
||||
isExternal = useDefaultUrlHandling || ( path.isExternal( href ) && !isCrossDomainPageLoad );
|
||||
|
||||
$activeClickedLink = $link.closest( ".ui-btn" );
|
||||
|
||||
if( isExternal ) {
|
||||
httpCleanup();
|
||||
//use default click handling
|
||||
return;
|
||||
}
|
||||
|
||||
//use ajax
|
||||
var transition = $link.jqmData( "transition" ),
|
||||
direction = $link.jqmData( "direction" ),
|
||||
reverse = ( direction && direction === "reverse" ) ||
|
||||
// deprecated - remove by 1.0
|
||||
$link.jqmData( "back" ),
|
||||
|
||||
//this may need to be more specific as we use data-rel more
|
||||
role = $link.attr( "data-" + $.mobile.ns + "rel" ) || undefined;
|
||||
|
||||
$.mobile.changePage( href, { transition: transition, reverse: reverse, role: role } );
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
//hashchange event handler
|
||||
$window.bind( "hashchange", function( e, triggered ) {
|
||||
//find first page via hash
|
||||
var to = path.stripHash( location.hash ),
|
||||
//transition is false if it's the first page, undefined otherwise (and may be overridden by default)
|
||||
transition = $.mobile.urlHistory.stack.length === 0 ? "none" : undefined;
|
||||
|
||||
//if listening is disabled (either globally or temporarily), or it's a dialog hash
|
||||
if( !$.mobile.hashListeningEnabled || urlHistory.ignoreNextHashChange ) {
|
||||
urlHistory.ignoreNextHashChange = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// special case for dialogs
|
||||
if( urlHistory.stack.length > 1 &&
|
||||
to.indexOf( dialogHashKey ) > -1 ) {
|
||||
|
||||
// If current active page is not a dialog skip the dialog and continue
|
||||
// in the same direction
|
||||
if(!$.mobile.activePage.is( ".ui-dialog" )) {
|
||||
//determine if we're heading forward or backward and continue accordingly past
|
||||
//the current dialog
|
||||
urlHistory.directHashChange({
|
||||
currentUrl: to,
|
||||
isBack: function() { window.history.back(); },
|
||||
isForward: function() { window.history.forward(); }
|
||||
});
|
||||
|
||||
// prevent changepage
|
||||
return;
|
||||
} else {
|
||||
var setTo = function() { to = $.mobile.urlHistory.getActive().page; };
|
||||
// if the current active page is a dialog and we're navigating
|
||||
// to a dialog use the dialog objected saved in the stack
|
||||
urlHistory.directHashChange({ currentUrl: to, isBack: setTo, isForward: setTo });
|
||||
}
|
||||
}
|
||||
|
||||
//if to is defined, load it
|
||||
if ( to ) {
|
||||
to = ( typeof to === "string" && !path.isPath( to ) ) ? ( '#' + to ) : to;
|
||||
$.mobile.changePage( to, { transition: transition, changeHash: false, fromHashChange: true } );
|
||||
}
|
||||
//there's no hash, go to the first page in the dom
|
||||
else {
|
||||
$.mobile.changePage( $.mobile.firstPage, { transition: transition, changeHash: false, fromHashChange: true } );
|
||||
}
|
||||
});
|
||||
|
||||
//set page min-heights to be device specific
|
||||
$( document ).bind( "pageshow", resetActivePageHeight );
|
||||
$( window ).bind( "throttledresize", resetActivePageHeight );
|
||||
|
||||
//The following event bindings should be bound after mobileinit has been triggered
|
||||
//the following function is called in the init file
|
||||
$.mobile._registerInternalEvents = function(){
|
||||
|
||||
//add active state on vclick
|
||||
$( document ).bind( "vclick", function( event ) {
|
||||
var link = findClosestLink( event.target );
|
||||
if ( link ) {
|
||||
if ( path.parseUrl( link.getAttribute( "href" ) || "#" ).hash !== "#" ) {
|
||||
$( link ).closest( ".ui-btn" ).not( ".ui-disabled" ).addClass( $.mobile.activeBtnClass );
|
||||
$( "." + $.mobile.activePageClass + " .ui-btn" ).not( link ).blur();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// click routing - direct to HTTP or Ajax, accordingly
|
||||
// TODO: most of the time, vclick will be all we need for fastClick bulletproofing.
|
||||
// However, it seems that in Android 2.1, a click event
|
||||
// will occasionally arrive independently of the bound vclick
|
||||
// binding to click as well seems to help in this edge case
|
||||
// we'll dig into this further in the next release cycle
|
||||
$( document ).bind( $.mobile.useFastClick ? "vclick click" : "click", function( event ) {
|
||||
var link = findClosestLink( event.target );
|
||||
if ( !link ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $link = $( link ),
|
||||
//remove active link class if external (then it won't be there if you come back)
|
||||
httpCleanup = function(){
|
||||
window.setTimeout( function() { removeActiveLinkClass( true ); }, 200 );
|
||||
};
|
||||
|
||||
//if there's a data-rel=back attr, go back in history
|
||||
if( $link.is( ":jqmData(rel='back')" ) ) {
|
||||
window.history.back();
|
||||
return false;
|
||||
}
|
||||
|
||||
//if ajax is disabled, exit early
|
||||
if( !$.mobile.ajaxEnabled ){
|
||||
httpCleanup();
|
||||
//use default click handling
|
||||
return;
|
||||
}
|
||||
|
||||
var baseUrl = getClosestBaseUrl( $link ),
|
||||
|
||||
//get href, if defined, otherwise default to empty hash
|
||||
href = path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );
|
||||
|
||||
// XXX_jblas: Ideally links to application pages should be specified as
|
||||
// an url to the application document with a hash that is either
|
||||
// the site relative path or id to the page. But some of the
|
||||
// internal code that dynamically generates sub-pages for nested
|
||||
// lists and select dialogs, just write a hash in the link they
|
||||
// create. This means the actual URL path is based on whatever
|
||||
// the current value of the base tag is at the time this code
|
||||
// is called. For now we are just assuming that any url with a
|
||||
// hash in it is an application page reference.
|
||||
if ( href.search( "#" ) != -1 ) {
|
||||
href = href.replace( /[^#]*#/, "" );
|
||||
if ( !href ) {
|
||||
//link was an empty hash meant purely
|
||||
//for interaction, so we ignore it.
|
||||
event.preventDefault();
|
||||
return;
|
||||
} else if ( path.isPath( href ) ) {
|
||||
//we have apath so make it the href we want to load.
|
||||
href = path.makeUrlAbsolute( href, baseUrl );
|
||||
} else {
|
||||
//we have a simple id so use the documentUrl as its base.
|
||||
href = path.makeUrlAbsolute( "#" + href, documentUrl.hrefNoHash );
|
||||
}
|
||||
}
|
||||
|
||||
// Should we handle this link, or let the browser deal with it?
|
||||
var useDefaultUrlHandling = $link.is( "[rel='external']" ) || $link.is( ":jqmData(ajax='false')" ) || $link.is( "[target]" ),
|
||||
|
||||
// Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
|
||||
// requests if the document doing the request was loaded via the file:// protocol.
|
||||
// This is usually to allow the application to "phone home" and fetch app specific
|
||||
// data. We normally let the browser handle external/cross-domain urls, but if the
|
||||
// allowCrossDomainPages option is true, we will allow cross-domain http/https
|
||||
// requests to go through our page loading logic.
|
||||
isCrossDomainPageLoad = ( $.mobile.allowCrossDomainPages && documentUrl.protocol === "file:" && href.search( /^https?:/ ) != -1 ),
|
||||
|
||||
//check for protocol or rel and its not an embedded page
|
||||
//TODO overlap in logic from isExternal, rel=external check should be
|
||||
// moved into more comprehensive isExternalLink
|
||||
isExternal = useDefaultUrlHandling || ( path.isExternal( href ) && !isCrossDomainPageLoad );
|
||||
|
||||
$activeClickedLink = $link.closest( ".ui-btn" );
|
||||
|
||||
if( isExternal ) {
|
||||
httpCleanup();
|
||||
//use default click handling
|
||||
return;
|
||||
}
|
||||
|
||||
//use ajax
|
||||
var transition = $link.jqmData( "transition" ),
|
||||
direction = $link.jqmData( "direction" ),
|
||||
reverse = ( direction && direction === "reverse" ) ||
|
||||
// deprecated - remove by 1.0
|
||||
$link.jqmData( "back" ),
|
||||
|
||||
//this may need to be more specific as we use data-rel more
|
||||
role = $link.attr( "data-" + $.mobile.ns + "rel" ) || undefined;
|
||||
|
||||
$.mobile.changePage( href, { transition: transition, reverse: reverse, role: role } );
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
//hashchange event handler
|
||||
$window.bind( "hashchange", function( e, triggered ) {
|
||||
//find first page via hash
|
||||
var to = path.stripHash( location.hash ),
|
||||
//transition is false if it's the first page, undefined otherwise (and may be overridden by default)
|
||||
transition = $.mobile.urlHistory.stack.length === 0 ? "none" : undefined;
|
||||
|
||||
//if listening is disabled (either globally or temporarily), or it's a dialog hash
|
||||
if( !$.mobile.hashListeningEnabled || urlHistory.ignoreNextHashChange ) {
|
||||
urlHistory.ignoreNextHashChange = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// special case for dialogs
|
||||
if( urlHistory.stack.length > 1 &&
|
||||
to.indexOf( dialogHashKey ) > -1 ) {
|
||||
|
||||
// If current active page is not a dialog skip the dialog and continue
|
||||
// in the same direction
|
||||
if(!$.mobile.activePage.is( ".ui-dialog" )) {
|
||||
//determine if we're heading forward or backward and continue accordingly past
|
||||
//the current dialog
|
||||
urlHistory.directHashChange({
|
||||
currentUrl: to,
|
||||
isBack: function() { window.history.back(); },
|
||||
isForward: function() { window.history.forward(); }
|
||||
});
|
||||
|
||||
// prevent changepage
|
||||
return;
|
||||
} else {
|
||||
var setTo = function() { to = $.mobile.urlHistory.getActive().page; };
|
||||
// if the current active page is a dialog and we're navigating
|
||||
// to a dialog use the dialog objected saved in the stack
|
||||
urlHistory.directHashChange({ currentUrl: to, isBack: setTo, isForward: setTo });
|
||||
}
|
||||
}
|
||||
|
||||
//if to is defined, load it
|
||||
if ( to ) {
|
||||
to = ( typeof to === "string" && !path.isPath( to ) ) ? ( '#' + to ) : to;
|
||||
$.mobile.changePage( to, { transition: transition, changeHash: false, fromHashChange: true } );
|
||||
}
|
||||
//there's no hash, go to the first page in the dom
|
||||
else {
|
||||
$.mobile.changePage( $.mobile.firstPage, { transition: transition, changeHash: false, fromHashChange: true } );
|
||||
}
|
||||
});
|
||||
|
||||
//set page min-heights to be device specific
|
||||
$( document ).bind( "pageshow", resetActivePageHeight );
|
||||
$( window ).bind( "throttledresize", resetActivePageHeight );
|
||||
|
||||
};//_registerInternalEvents callback
|
||||
|
||||
})( jQuery );
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
<script src="../../../js/jquery.mobile.init.js"></script>
|
||||
<link rel="stylesheet" href="../../../themes/default" />
|
||||
<link rel="stylesheet" href="../../../external/qunit.css"/>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,17 @@
|
|||
|
||||
ok($("html").hasClass("ui-mobile"));
|
||||
});
|
||||
|
||||
test( "useFastClick is configurable via mobileinit", function(){
|
||||
$(document).bind( "mobileinit", function(){
|
||||
$.mobile.useFastClick = false;
|
||||
});
|
||||
|
||||
$.testHelper.reloadLib(libName);
|
||||
|
||||
ok( $.mobile.useFastClick == false );
|
||||
$.mobile.useFastClick = true;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue