2011-12-16 02:09:25 +00:00
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
2012-01-07 00:28:54 +00:00
//>>description: Formats groups of links as nav bars.
//>>label: Navigation Bars
2011-12-20 20:54:05 +00:00
define ( [
2012-01-13 05:22:00 +00:00
"jquery" ,
2011-12-20 20:54:05 +00:00
"jquery.mobile.core" ,
"jquery.mobile.event" ,
2011-12-20 21:29:02 +00:00
"jquery.mobile.hashchange" ,
2012-01-13 05:43:41 +00:00
"jquery.mobile.page" ,
"jquery.mobile.transition" ] , function ( $ ) {
2011-12-16 02:09:25 +00:00
//>>excludeEnd("jqmBuildExclude");
( function ( $ , undefined ) {
2010-11-25 11:13:51 +00:00
//define vars for interal use
2011-05-18 23:38:04 +00:00
var $window = $ ( window ) ,
$html = $ ( 'html' ) ,
$head = $ ( 'head' ) ,
2010-11-25 11:13:51 +00:00
//url path helpers for use in relative url management
path = {
2010-12-13 10:21:02 +00:00
2011-06-01 18:59:13 +00:00
// This scary looking regular expression parses an absolute URL or its relative
// variants (protocol, site, document, query, and hash), into the various
// components (protocol, host, path, query, fragment, etc that make up the
// URL as well as some other commonly used sub-parts. When used with RegExp.exec()
// or String.match, it parses the URL into a results array that looks like this:
//
// [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content
2011-06-04 07:26:25 +00:00
// [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread
// [2]: http://jblas:password@mycompany.com:8080/mail/inbox
// [3]: http://jblas:password@mycompany.com:8080
// [4]: http:
2011-09-15 23:56:54 +00:00
// [5]: //
// [6]: jblas:password@mycompany.com:8080
// [7]: jblas:password
// [8]: jblas
// [9]: password
// [10]: mycompany.com:8080
// [11]: mycompany.com
// [12]: 8080
// [13]: /mail/inbox
// [14]: /mail/
// [15]: inbox
// [16]: ?msg=1234&type=unread
// [17]: #msg-content
2011-06-01 18:59:13 +00:00
//
2011-09-15 23:56:54 +00:00
urlParseRE : /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/ ,
2011-06-01 18:59:13 +00:00
2011-06-06 22:58:21 +00:00
//Parse a URL into a structure that allows easy access to
//all of the URL components by name.
2011-06-01 18:59:13 +00:00
parseUrl : function ( url ) {
2011-06-04 07:26:25 +00:00
// If we're passed an object, we'll assume that it is
// a parsed url object and just return it back to the caller.
2011-07-07 16:22:24 +00:00
if ( $ . type ( url ) === "object" ) {
2011-06-04 07:26:25 +00:00
return url ;
}
2011-09-15 23:56:54 +00:00
var matches = path . urlParseRE . exec ( url || "" ) || [ ] ;
2011-06-10 22:31:09 +00:00
// Create an object that allows the caller to access the sub-matches
// by name. Note that IE returns an empty string instead of undefined,
// like all other browsers do, so we normalize everything so its consistent
// no matter what browser we're running on.
2011-09-15 23:56:54 +00:00
return {
href : matches [ 0 ] || "" ,
hrefNoHash : matches [ 1 ] || "" ,
hrefNoSearch : matches [ 2 ] || "" ,
domain : matches [ 3 ] || "" ,
protocol : matches [ 4 ] || "" ,
doubleSlash : matches [ 5 ] || "" ,
authority : matches [ 6 ] || "" ,
username : matches [ 8 ] || "" ,
password : matches [ 9 ] || "" ,
host : matches [ 10 ] || "" ,
hostname : matches [ 11 ] || "" ,
port : matches [ 12 ] || "" ,
pathname : matches [ 13 ] || "" ,
directory : matches [ 14 ] || "" ,
filename : matches [ 15 ] || "" ,
search : matches [ 16 ] || "" ,
hash : matches [ 17 ] || ""
2011-06-01 18:59:13 +00:00
} ;
} ,
2011-06-06 22:58:21 +00:00
//Turn relPath into an asbolute path. absPath is
//an optional absolute path which describes what
//relPath is relative to.
2011-06-01 18:59:13 +00:00
makePathAbsolute : function ( relPath , absPath ) {
if ( relPath && relPath . charAt ( 0 ) === "/" ) {
2011-06-04 07:26:25 +00:00
return relPath ;
2011-06-01 18:59:13 +00:00
}
2011-07-07 16:19:16 +00:00
2011-06-01 18:59:13 +00:00
relPath = relPath || "" ;
2011-06-27 23:50:01 +00:00
absPath = absPath ? absPath . replace ( /^\/|(\/[^\/]*|[^\/]+)$/g , "" ) : "" ;
2011-07-07 16:19:16 +00:00
2011-06-01 18:59:13 +00:00
var absStack = absPath ? absPath . split ( "/" ) : [ ] ,
2011-06-03 20:57:25 +00:00
relStack = relPath . split ( "/" ) ;
2011-06-01 18:59:13 +00:00
for ( var i = 0 ; i < relStack . length ; i ++ ) {
var d = relStack [ i ] ;
switch ( d ) {
case "." :
break ;
case ".." :
if ( absStack . length ) {
absStack . pop ( ) ;
}
break ;
default :
absStack . push ( d ) ;
break ;
}
}
return "/" + absStack . join ( "/" ) ;
} ,
2011-06-06 22:58:21 +00:00
//Returns true if both urls have the same domain.
2011-06-03 20:57:25 +00:00
isSameDomain : function ( absUrl1 , absUrl2 ) {
return path . parseUrl ( absUrl1 ) . domain === path . parseUrl ( absUrl2 ) . domain ;
} ,
2011-06-06 22:58:21 +00:00
//Returns true for any relative variant.
2011-06-01 18:59:13 +00:00
isRelativeUrl : function ( url ) {
// All relative Url variants have one thing in common, no protocol.
2011-06-10 22:31:09 +00:00
return path . parseUrl ( url ) . protocol === "" ;
2011-06-04 07:26:25 +00:00
} ,
2011-06-06 22:58:21 +00:00
//Returns true for an absolute url.
2011-06-04 07:26:25 +00:00
isAbsoluteUrl : function ( url ) {
2011-06-10 22:31:09 +00:00
return path . parseUrl ( url ) . protocol !== "" ;
2011-06-01 18:59:13 +00:00
} ,
2011-06-06 22:58:21 +00:00
//Turn the specified realtive URL into an absolute one. This function
//can handle all relative variants (protocol, site, document, query, fragment).
2011-06-01 18:59:13 +00:00
makeUrlAbsolute : function ( relUrl , absUrl ) {
2011-06-02 00:15:18 +00:00
if ( ! path . isRelativeUrl ( relUrl ) ) {
2011-06-01 18:59:13 +00:00
return relUrl ;
}
2011-07-07 16:19:16 +00:00
2011-06-02 00:15:18 +00:00
var relObj = path . parseUrl ( relUrl ) ,
absObj = path . parseUrl ( absUrl ) ,
2011-06-01 18:59:13 +00:00
protocol = relObj . protocol || absObj . protocol ,
2011-09-30 16:17:05 +00:00
doubleSlash = relObj . protocol ? relObj . doubleSlash : ( relObj . doubleSlash || absObj . doubleSlash ) ,
2011-06-10 22:31:09 +00:00
authority = relObj . authority || absObj . authority ,
hasPath = relObj . pathname !== "" ,
2011-06-02 00:15:18 +00:00
pathname = path . makePathAbsolute ( relObj . pathname || absObj . filename , absObj . pathname ) ,
search = relObj . search || ( ! hasPath && absObj . search ) || "" ,
2011-06-10 22:31:09 +00:00
hash = relObj . hash ;
2011-07-07 16:19:16 +00:00
2011-09-15 23:56:54 +00:00
return protocol + doubleSlash + authority + pathname + search + hash ;
2011-06-01 18:59:13 +00:00
} ,
2011-06-06 22:58:21 +00:00
//Add search (aka query) params to the specified url.
addSearchParams : function ( url , params ) {
var u = path . parseUrl ( url ) ,
p = ( typeof params === "object" ) ? $ . param ( params ) : params ,
s = u . search || "?" ;
return u . hrefNoSearch + s + ( s . charAt ( s . length - 1 ) !== "?" ? "&" : "" ) + p + ( u . hash || "" ) ;
} ,
2011-06-08 21:47:24 +00:00
convertUrlToDataUrl : function ( absUrl ) {
var u = path . parseUrl ( absUrl ) ;
if ( path . isEmbeddedPage ( u ) ) {
2011-06-23 16:33:06 +00:00
// For embedded pages, remove the dialog hash key as in getFilePath(),
// otherwise the Data Url won't match the id of the embedded Page.
return u . hash . split ( dialogHashKey ) [ 0 ] . replace ( /^#/ , "" ) ;
2011-06-08 21:47:24 +00:00
} else if ( path . isSameDomain ( u , documentBase ) ) {
return u . hrefNoHash . replace ( documentBase . domain , "" ) ;
}
return absUrl ;
} ,
2010-11-25 11:13:51 +00:00
//get path from current hash, or from a file path
2011-05-18 23:38:04 +00:00
get : function ( newPath ) {
if ( newPath === undefined ) {
2010-11-25 11:13:51 +00:00
newPath = location . hash ;
}
2011-05-18 23:38:04 +00:00
return path . stripHash ( newPath ) . replace ( /[^\/]*\.[^\/*]+$/ , '' ) ;
2010-11-25 11:13:51 +00:00
} ,
2010-12-13 10:21:02 +00:00
//return the substring of a filepath before the sub-page key, for making a server request
2011-05-18 23:38:04 +00:00
getFilePath : function ( path ) {
2010-11-25 11:13:51 +00:00
var splitkey = '&' + $ . mobile . subPageUrlKey ;
2011-01-26 19:38:17 +00:00
return path && path . split ( splitkey ) [ 0 ] . split ( dialogHashKey ) [ 0 ] ;
2010-11-25 11:13:51 +00:00
} ,
2011-01-31 06:03:30 +00:00
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
//set location hash to path
2011-05-18 23:38:04 +00:00
set : function ( path ) {
2010-11-25 11:13:51 +00:00
location . hash = path ;
} ,
2010-12-13 10:21:02 +00:00
2011-06-06 22:58:21 +00:00
//test if a given url (string) is a path
//NOTE might be exceptionally naive
2011-05-18 23:38:04 +00:00
isPath : function ( url ) {
2011-06-04 07:26:25 +00:00
return ( /\// ) . test ( url ) ;
2011-01-22 22:42:07 +00:00
} ,
2011-01-31 06:03:30 +00:00
2011-03-12 21:12:42 +00:00
//return a url path with the window's location protocol/hostname/pathname removed
2011-05-18 23:38:04 +00:00
clean : function ( url ) {
2011-06-08 21:47:24 +00:00
return url . replace ( documentBase . domain , "" ) ;
2011-01-22 22:42:07 +00:00
} ,
2011-01-31 06:03:30 +00:00
2011-01-22 22:42:07 +00:00
//just return the url without an initial #
2011-05-18 23:38:04 +00:00
stripHash : function ( url ) {
2011-01-22 22:42:07 +00:00
return url . replace ( /^#/ , "" ) ;
} ,
2011-01-31 06:03:30 +00:00
2011-04-15 04:48:53 +00:00
//remove the preceding hash, any query params, and dialog notations
2011-05-18 23:38:04 +00:00
cleanHash : function ( hash ) {
return path . stripHash ( hash . replace ( /\?.*$/ , "" ) . replace ( dialogHashKey , "" ) ) ;
2011-04-12 07:58:24 +00:00
} ,
2011-01-22 22:42:07 +00:00
//check whether a url is referencing the same domain, or an external domain or different protocol
//could be mailto, etc
2011-05-18 23:38:04 +00:00
isExternal : function ( url ) {
2011-06-04 07:26:25 +00:00
var u = path . parseUrl ( url ) ;
2011-06-09 00:20:01 +00:00
return u . protocol && u . domain !== documentUrl . domain ? true : false ;
2011-01-22 22:42:07 +00:00
} ,
2011-01-31 06:03:30 +00:00
2011-05-18 23:38:04 +00:00
hasProtocol : function ( url ) {
2011-06-04 07:26:25 +00:00
return ( /^(:?\w+:)/ ) . test ( url ) ;
2011-01-22 22:42:07 +00:00
} ,
2011-01-31 06:03:30 +00:00
2011-09-08 16:21:31 +00:00
//check if the specified url refers to the first page in the main application document.
isFirstPageUrl : function ( url ) {
// We only deal with absolute paths.
var u = path . parseUrl ( path . makeUrlAbsolute ( url , documentBase ) ) ,
// Does the url have the same path as the document?
samePath = u . hrefNoHash === documentUrl . hrefNoHash || ( documentBaseDiffers && u . hrefNoHash === documentBase . hrefNoHash ) ,
// Get the first page element.
fp = $ . mobile . firstPage ,
// Get the id of the first page element if it has one.
fpId = fp && fp [ 0 ] ? fp [ 0 ] . id : undefined ;
// The url refers to the first page if the path matches the document and
// it either has no hash value, or the hash is exactly equal to the id of the
// first page element.
return samePath && ( ! u . hash || u . hash === "#" || ( fpId && u . hash . replace ( /^#/ , "" ) === fpId ) ) ;
} ,
2011-05-18 23:38:04 +00:00
isEmbeddedPage : function ( url ) {
2011-06-04 07:26:25 +00:00
var u = path . parseUrl ( url ) ;
//if the path is absolute, then we need to compare the url against
//both the documentUrl and the documentBase. The main reason for this
//is that links embedded within external documents will refer to the
//application document, whereas links embedded within the application
//document will be resolved against the document base.
2011-06-10 22:31:09 +00:00
if ( u . protocol !== "" ) {
2011-06-04 07:26:25 +00:00
return ( u . hash && ( u . hrefNoHash === documentUrl . hrefNoHash || ( documentBaseDiffers && u . hrefNoHash === documentBase . hrefNoHash ) ) ) ;
}
2011-06-08 21:47:24 +00:00
return ( /^#/ ) . test ( u . href ) ;
2010-11-25 11:13:51 +00:00
}
} ,
2010-12-13 10:21:02 +00:00
2010-11-25 11:13:51 +00:00
//will be defined when a link is clicked and given an active class
$activeClickedLink = null ,
2011-01-31 06:03:30 +00:00
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
//urlHistory is purely here to make guesses at whether the back or forward button was clicked
//and provide an appropriate transition
urlHistory = {
2011-08-24 22:22:52 +00:00
// Array of pages that are visited during a single page load.
2011-07-31 14:03:22 +00:00
// Each has a url and optional transition, title, and pageUrl (which represents the file path, in cases where URL is obscured, such as dialogs)
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
stack : [ ] ,
2011-01-31 06:03:30 +00:00
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
//maintain an index number for the active page in the stack
activeIndex : 0 ,
2011-01-31 06:03:30 +00:00
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
//get active
2011-05-18 23:38:04 +00:00
getActive : function ( ) {
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
return urlHistory . stack [ urlHistory . activeIndex ] ;
} ,
2011-01-31 06:03:30 +00:00
2011-05-18 23:38:04 +00:00
getPrev : function ( ) {
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
return urlHistory . stack [ urlHistory . activeIndex - 1 ] ;
} ,
2011-01-31 06:03:30 +00:00
2011-05-18 23:38:04 +00:00
getNext : function ( ) {
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
return urlHistory . stack [ urlHistory . activeIndex + 1 ] ;
} ,
2011-01-31 06:03:30 +00:00
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
// addNew is used whenever a new page is added
2011-08-27 06:30:49 +00:00
addNew : function ( url , transition , title , pageUrl , role ) {
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
//if there's forward history, wipe it
2011-05-18 23:38:04 +00:00
if ( urlHistory . getNext ( ) ) {
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
urlHistory . clearForward ( ) ;
}
2011-01-31 06:03:30 +00:00
2011-08-27 06:30:49 +00:00
urlHistory . stack . push ( { url : url , transition : transition , title : title , pageUrl : pageUrl , role : role } ) ;
2011-04-01 08:48:38 +00:00
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
urlHistory . activeIndex = urlHistory . stack . length - 1 ;
} ,
2011-01-31 06:03:30 +00:00
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
//wipe urls ahead of active index
2011-05-18 23:38:04 +00:00
clearForward : function ( ) {
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
urlHistory . stack = urlHistory . stack . slice ( 0 , urlHistory . activeIndex + 1 ) ;
} ,
2011-02-15 01:23:25 +00:00
2011-05-18 23:38:04 +00:00
directHashChange : function ( opts ) {
2011-08-27 06:46:50 +00:00
var back , forward , newActiveIndex , prev = this . getActive ( ) ;
2011-03-08 00:49:53 +00:00
2011-03-08 01:04:42 +00:00
// check if url isp in history and if it's ahead or behind current page
2011-05-18 23:38:04 +00:00
$ . each ( urlHistory . stack , function ( i , historyEntry ) {
2011-03-08 00:49:53 +00:00
//if the url is in the stack, it's a forward or a back
2011-05-18 23:38:04 +00:00
if ( opts . currentUrl === historyEntry . url ) {
2011-03-08 00:49:53 +00:00
//define back and forward by whether url is older or newer than current page
back = i < urlHistory . activeIndex ;
forward = ! back ;
newActiveIndex = i ;
}
} ) ;
2011-03-08 22:59:23 +00:00
// save new page index, null check to prevent falsey 0 result
2011-03-10 07:27:59 +00:00
this . activeIndex = newActiveIndex !== undefined ? newActiveIndex : this . activeIndex ;
2011-03-08 00:49:53 +00:00
2011-05-18 23:38:04 +00:00
if ( back ) {
2011-08-29 16:11:58 +00:00
( opts . either || opts . isBack ) ( true ) ;
2011-05-18 23:38:04 +00:00
} else if ( forward ) {
2011-08-29 16:11:58 +00:00
( opts . either || opts . isForward ) ( false ) ;
2011-03-08 00:49:53 +00:00
}
} ,
2011-02-01 04:56:56 +00:00
//disable hashchange event listener internally to ignore one change
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
//toggled internally when location.hash is updated to match the url of a successful page load
2011-05-20 22:19:54 +00:00
ignoreNextHashChange : false
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
} ,
2010-12-13 10:21:02 +00:00
2010-11-25 11:13:51 +00:00
//define first selector to receive focus when a page is shown
focusable = "[tabindex],a,button:visible,select:visible,input" ,
2010-12-13 10:21:02 +00:00
2011-02-01 19:52:15 +00:00
//queue to hold simultanious page transitions
pageTransitionQueue = [ ] ,
2011-06-04 07:26:25 +00:00
//indicates whether or not page is in process of transitioning
2011-02-01 19:52:15 +00:00
isPageTransitioning = false ,
2011-01-26 19:38:17 +00:00
//nonsense hash change key for dialogs, so they create a history entry
2011-02-17 03:55:01 +00:00
dialogHashKey = "&ui-state=dialog" ,
2010-12-13 10:21:02 +00:00
2011-01-18 17:18:22 +00:00
//existing base tag?
2011-05-18 23:38:04 +00:00
$base = $head . children ( "base" ) ,
2011-05-21 07:27:09 +00:00
2011-06-04 07:26:25 +00:00
//tuck away the original document URL minus any fragment.
documentUrl = path . parseUrl ( location . href ) ,
2011-05-21 07:27:09 +00:00
2011-06-01 18:59:13 +00:00
//if the document has an embedded base tag, documentBase is set to its
2011-06-04 07:26:25 +00:00
//initial value. If a base tag does not exist, then we default to the documentUrl.
documentBase = $base . length ? path . parseUrl ( path . makeUrlAbsolute ( $base . attr ( "href" ) , documentUrl . href ) ) : documentUrl ,
//cache the comparison once.
2011-06-10 23:13:58 +00:00
documentBaseDiffers = ( documentUrl . hrefNoHash !== documentBase . hrefNoHash ) ;
2011-01-18 17:18:22 +00:00
//base element management, defined depending on dynamic base tag support
2011-02-16 22:22:28 +00:00
var base = $ . support . dynamicBaseTag ? {
2011-01-18 17:18:22 +00:00
//define base element, for use in routing asset urls that are referenced in Ajax-requested markup
2011-06-04 17:51:41 +00:00
element : ( $base . length ? $base : $ ( "<base>" , { href : documentBase . hrefNoHash } ) . prependTo ( $head ) ) ,
2011-01-18 17:18:22 +00:00
//set the generated BASE element's href attribute to a new page's base path
2011-05-16 23:02:26 +00:00
set : function ( href ) {
2011-06-01 18:59:13 +00:00
base . element . attr ( "href" , path . makeUrlAbsolute ( href , documentBase ) ) ;
2011-01-18 17:18:22 +00:00
} ,
//set the generated BASE element's href attribute to a new page's base path
2011-05-16 23:02:26 +00:00
reset : function ( ) {
2011-06-04 17:51:41 +00:00
base . element . attr ( "href" , documentBase . hrefNoHash ) ;
2011-01-18 17:18:22 +00:00
}
} : undefined ;
2010-12-13 10:21:02 +00:00
/ *
2010-11-25 11:13:51 +00:00
internal utility functions
2010-12-13 10:21:02 +00:00
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
2010-11-25 11:13:51 +00:00
//direct focus to the page title, or otherwise first focusable element
Much of the scripting in nav.js's transitionPages function was tied to the animation sequence for our css3transitionhandler. For example, the order was, scroll to top, run transitions, then scroll to the remembered location of the new page (there's more involved, but that's the gist of it). If we want to expand beyond this sequence, much of that scripting needs to move to the css3transitionhandler itself, and also to our "none" transition handler, which comes with nav model.
This commit moves all that logic into the transition handlers, and should provide a better starting point for adding different transition sequences, such as fade-out, scroll, fade-in.
In the process of making this change, the reFocus function was made public as $.mobile.focusPage.
2011-12-28 04:59:48 +00:00
$ . mobile . focusPage = function ( page ) {
2011-09-06 15:45:47 +00:00
var pageTitle = page . find ( ".ui-title:eq(0)" ) ;
2011-04-11 05:58:21 +00:00
2011-09-06 15:45:47 +00:00
if ( pageTitle . length ) {
pageTitle . focus ( ) ;
2011-04-07 20:27:32 +00:00
}
2011-09-06 15:45:47 +00:00
else {
page . focus ( ) ;
2010-11-25 11:13:51 +00:00
}
2011-02-08 21:13:59 +00:00
}
2010-12-13 10:21:02 +00:00
2010-11-25 11:13:51 +00:00
//remove active classes after page transition or error
2011-05-16 23:02:26 +00:00
function removeActiveLinkClass ( forceRemoval ) {
2011-06-04 07:26:25 +00:00
if ( ! ! $activeClickedLink && ( ! $activeClickedLink . closest ( '.ui-page-active' ) . length || forceRemoval ) ) {
2010-11-25 11:13:51 +00:00
$activeClickedLink . removeClass ( $ . mobile . activeBtnClass ) ;
}
$activeClickedLink = null ;
2011-02-08 21:13:59 +00:00
}
2010-11-25 11:13:51 +00:00
2011-05-16 23:02:26 +00:00
function releasePageTransitionLock ( ) {
isPageTransitioning = false ;
2011-05-18 23:38:04 +00:00
if ( pageTransitionQueue . length > 0 ) {
2011-06-04 07:26:25 +00:00
$ . mobile . changePage . apply ( null , pageTransitionQueue . pop ( ) ) ;
2011-05-16 23:02:26 +00:00
}
}
2011-09-12 20:58:24 +00:00
2011-09-07 12:15:00 +00:00
// Save the last scroll distance per page, before it is hidden
2011-09-20 20:46:24 +00:00
var setLastScrollEnabled = true ,
2012-01-18 17:15:09 +00:00
setLastScroll , delayedSetLastScroll ;
2011-09-12 20:58:24 +00:00
2012-01-18 17:15:09 +00:00
setLastScroll = function ( ) {
2011-09-20 19:47:10 +00:00
// this barrier prevents setting the scroll value based on the browser
// scrolling the window based on a hashchange
if ( ! setLastScrollEnabled ) {
return ;
}
var active = $ . mobile . urlHistory . getActive ( ) ;
if ( active ) {
2012-01-18 17:15:09 +00:00
var lastScroll = $window . scrollTop ( ) ;
2011-09-12 20:58:24 +00:00
2011-09-20 17:08:19 +00:00
// Set active page's lastScroll prop.
2011-09-20 19:47:10 +00:00
// If the location we're scrolling to is less than minScrollBack, let it go.
2011-09-20 17:08:19 +00:00
active . lastScroll = lastScroll < $ . mobile . minScrollBack ? $ . mobile . defaultHomeScroll : lastScroll ;
}
} ;
2011-09-07 13:44:34 +00:00
2011-09-20 17:08:19 +00:00
// bind to scrollstop to gather scroll position. The delay allows for the hashchange
// event to fire and disable scroll recording in the case where the browser scrolls
// to the hash targets location (sometimes the top of the page). once pagechange fires
// getLastScroll is again permitted to operate
2011-09-22 15:41:35 +00:00
delayedSetLastScroll = function ( ) {
2012-01-18 17:15:09 +00:00
setTimeout ( setLastScroll , 100 ) ;
2011-09-20 19:47:10 +00:00
} ;
// disable an scroll setting when a hashchange has been fired, this only works
// because the recording of the scroll position is delayed for 100ms after
// the browser might have changed the position because of the hashchange
$window . bind ( $ . support . pushState ? "popstate" : "hashchange" , function ( ) {
setLastScrollEnabled = false ;
2011-09-20 17:08:19 +00:00
} ) ;
2011-09-20 19:47:10 +00:00
// handle initial hashchange from chrome :(
$window . one ( $ . support . pushState ? "popstate" : "hashchange" , function ( ) {
setLastScrollEnabled = true ;
2011-09-20 17:08:19 +00:00
} ) ;
2011-09-12 20:58:24 +00:00
2011-09-20 19:47:10 +00:00
// wait until the mobile page container has been determined to bind to pagechange
$window . one ( "pagecontainercreate" , function ( ) {
// once the page has changed, re-enable the scroll recording
$ . mobile . pageContainer . bind ( "pagechange" , function ( ) {
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
2012-01-18 17:15:09 +00:00
$window . unbind ( "scrollstop" , delayedSetLastScroll ) ;
2011-09-20 19:47:10 +00:00
// 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
2012-01-18 17:15:09 +00:00
$window . bind ( "scrollstop" , delayedSetLastScroll ) ;
2011-09-20 19:47:10 +00:00
} ) ;
2011-09-20 17:08:19 +00:00
} ) ;
2011-09-20 19:47:10 +00:00
2011-09-22 15:53:53 +00:00
// bind to scrollstop for the first page as "pagechange" won't be fired in that case
2012-01-18 17:15:09 +00:00
$window . bind ( "scrollstop" , delayedSetLastScroll ) ;
2011-09-12 20:58:24 +00:00
2011-05-16 23:02:26 +00:00
//function for transitioning between two existing pages
2011-05-18 22:58:15 +00:00
function transitionPages ( toPage , fromPage , transition , reverse ) {
2011-07-07 16:19:16 +00:00
2011-05-18 23:38:04 +00:00
if ( fromPage ) {
2011-05-16 23:02:26 +00:00
//trigger before show/hide events
2011-05-18 22:58:15 +00:00
fromPage . data ( "page" ) . _trigger ( "beforehide" , null , { nextPage : toPage } ) ;
2011-05-16 23:02:26 +00:00
}
2011-09-12 20:58:24 +00:00
2011-09-07 13:44:34 +00:00
toPage . data ( "page" ) . _trigger ( "beforeshow" , null , { prevPage : fromPage || $ ( "" ) } ) ;
2012-01-10 07:06:24 +00:00
//clear page loader
$ . mobile . hidePageLoadingMsg ( ) ;
2011-05-16 23:02:26 +00:00
//find the transition handler for the specified transition. If there
//isn't one in our transitionHandlers dictionary, use the default one.
//call the handler immediately to kick-off the transition.
2012-01-05 10:16:18 +00:00
var th = $ . mobile . transitionHandlers [ transition || "default" ] || $ . mobile . defaultTransitionHandler ,
2011-05-18 23:38:04 +00:00
promise = th ( transition , reverse , toPage , fromPage ) ;
2011-05-18 22:58:15 +00:00
2011-05-18 23:38:04 +00:00
promise . done ( function ( ) {
2011-05-21 07:27:09 +00:00
2011-05-18 22:58:15 +00:00
//trigger show/hide events
2011-05-18 23:38:04 +00:00
if ( fromPage ) {
2011-09-07 13:44:34 +00:00
fromPage . data ( "page" ) . _trigger ( "hide" , null , { nextPage : toPage } ) ;
2011-05-18 22:58:15 +00:00
}
2011-07-07 16:19:16 +00:00
2011-05-18 22:58:15 +00:00
//trigger pageshow, define prevPage as either fromPage or empty jQuery obj
2011-06-16 23:37:38 +00:00
toPage . data ( "page" ) . _trigger ( "show" , null , { prevPage : fromPage || $ ( "" ) } ) ;
2011-05-18 22:58:15 +00:00
} ) ;
2011-05-16 23:02:26 +00:00
2011-05-18 22:58:15 +00:00
return promise ;
2011-06-20 22:09:54 +00:00
}
2011-07-07 16:19:16 +00:00
2011-06-17 20:24:09 +00:00
//simply set the active page's minimum height to screen height, depending on orientation
2011-06-20 17:31:26 +00:00
function getScreenHeight ( ) {
2011-10-21 22:22:36 +00:00
var orientation = $ . event . special . orientationchange . orientation ( ) ,
2011-06-17 20:58:21 +00:00
port = orientation === "portrait" ,
2011-09-24 04:55:50 +00:00
winMin = port ? 480 : 320 ,
2011-06-20 17:31:26 +00:00
screenHeight = port ? screen . availHeight : screen . availWidth ,
2011-06-17 20:58:21 +00:00
winHeight = Math . max ( winMin , $ ( window ) . height ( ) ) ,
pageMin = Math . min ( screenHeight , winHeight ) ;
2011-06-17 20:24:09 +00:00
2011-06-20 17:31:26 +00:00
return pageMin ;
}
2011-09-12 20:58:24 +00:00
2011-08-26 22:16:43 +00:00
$ . mobile . getScreenHeight = getScreenHeight ;
2011-07-07 16:19:16 +00:00
2011-06-20 17:31:26 +00:00
//simply set the active page's minimum height to screen height, depending on orientation
function resetActivePageHeight ( ) {
$ ( "." + $ . mobile . activePageClass ) . css ( "min-height" , getScreenHeight ( ) ) ;
2011-06-17 20:24:09 +00:00
}
2011-05-16 23:02:26 +00:00
//shared page enhancements
function enhancePage ( $page , role ) {
// If a role was specified, make sure the data-role attribute
// on the page element is in sync.
if ( role ) {
$page . attr ( "data-" + $ . mobile . ns + "role" , role ) ;
}
//run page plugin
$page . page ( ) ;
}
/* exposed $.mobile methods */
2010-11-25 11:13:51 +00:00
//animation complete callback
2011-05-18 23:38:04 +00:00
$ . fn . animationComplete = function ( callback ) {
if ( $ . support . cssTransitions ) {
2012-01-05 21:12:46 +00:00
return $ ( this ) . one ( 'webkitAnimationEnd animationend' , callback ) ;
2010-11-25 11:13:51 +00:00
}
else {
2011-01-30 23:06:33 +00:00
// defer execution for consistency between webkit/non webkit
2011-05-18 23:38:04 +00:00
setTimeout ( callback , 0 ) ;
return $ ( this ) ;
2010-11-25 11:13:51 +00:00
}
2010-12-13 10:21:02 +00:00
} ;
2010-11-25 11:13:51 +00:00
2011-01-22 22:42:07 +00:00
//expose path object on $.mobile
$ . mobile . path = path ;
2011-01-31 06:03:30 +00:00
2011-01-22 22:42:07 +00:00
//expose base object on $.mobile
$ . mobile . base = base ;
2010-12-13 10:21:02 +00:00
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
//history stack
$ . mobile . urlHistory = urlHistory ;
2011-01-20 07:48:30 +00:00
2011-08-26 21:47:22 +00:00
$ . mobile . dialogHashKey = dialogHashKey ;
2012-01-05 10:16:18 +00:00
Changes to allow 3rd party transitions. Developers can now register a custom transition by adding their transition handler to the $.mobile.transitionHandlers dictionary. The name of the custom transition is used as the key within the transtionsHandlers dictionary, and should be the same name used within the @data-transtion attribute.
The expected prototype for a transitionHandler is as follows:
function handler(name, reverse, $to, $from)
The name parameter is the name of the transition as specified by @data-transition attribute, reverse is a boolean that is false for a normal transition, and true for a reverse transition. The $to param is a jQuery collection containing the page that is being transitioned "to", and $from is an optional collection that tells us what page we are transitioning "from". Because $from is optional, handler developers should take care and check $from to make sure it is not undefined before attempting to dereference it.
In addition to registering custom transition by name, developers can specify a handler to use in the case where a transition name is specified and does not exist within the $.mobile.transitionHanlders dictionary. Within jQuery Mobile, the default handler for unknown transition types is the $.mobile.css3Transition() handler. This handler always assumes that the transition name is to be used as a CSS class to be placed on the $to and $from elements. To change the default handler, simply set $.mobile.defaultTransitionHandler to you function handler:
$.mobile.defaultTransitionHandler = myTransitionHandler;
The changes to make all this necessary are as follows:
- Created $.mobile.noneTransitionHandler which is the default transitionHandler for the framework that simply adds and removes the page active class on the $from and $to pages with no animations.
- Moved class based transition code into a new plugin jquery.mobile.transition.js file. This plugin, when present, overrides the noneTransitionHandler as the defaultTranstionHandler for the framework so that CSS3 animation transitions are available.
- Removed code related to the setting/removal of the ui-mobile-viewport-perspective class. The css3TransitionHandler plugin takes care of automatically placing a "viewport-<transition name>" class on the viewport (body) element. This allows any other transition to specify properties on the viewport that are necessary to accomplish the transition.
- changed the CSS class ui-mobile-viewport-perspective to viewport-flip to match code changes. This makes it more apparent that setting -webkit-perspective is only used with the flip transition.
- Updated js/index.php, Makefile and build.xml to include the new jquery.mobile.transition.js file.
2011-04-26 21:06:10 +00:00
2011-03-19 00:53:06 +00:00
//enable cross-domain page support
$ . mobile . allowCrossDomainPages = false ;
2011-06-16 22:43:40 +00:00
//return the original document url
$ . mobile . getDocumentUrl = function ( asParsedObject ) {
return asParsedObject ? $ . extend ( { } , documentUrl ) : documentUrl . href ;
} ;
//return the original document base url
$ . mobile . getDocumentBase = function ( asParsedObject ) {
return asParsedObject ? $ . extend ( { } , documentBase ) : documentBase . href ;
} ;
2011-09-23 16:55:17 +00:00
$ . mobile . _bindPageRemove = function ( ) {
var page = $ ( this ) ;
// when dom caching is not enabled or the page is embedded bind to remove the page on hide
if ( ! page . data ( "page" ) . options . domCache
&& page . is ( ":jqmData(external-page='true')" ) ) {
page . bind ( 'pagehide.remove' , function ( ) {
2011-09-28 18:37:46 +00:00
var $this = $ ( this ) ,
prEvent = new $ . Event ( "pageremove" ) ;
$this . trigger ( prEvent ) ;
if ( ! prEvent . isDefaultPrevented ( ) ) {
$this . removeWithDependents ( ) ;
}
2011-09-23 16:55:17 +00:00
} ) ;
}
} ;
2011-05-18 22:58:15 +00:00
// Load a page into the DOM.
$ . mobile . loadPage = function ( url , options ) {
// This function uses deferred notifications to let callers
// know when the page is done loading, or if an error has occurred.
var deferred = $ . Deferred ( ) ,
// The default loadPage options with overrides specified by
// the caller.
settings = $ . extend ( { } , $ . mobile . loadPage . defaults , options ) ,
// The DOM element for the page after it has been loaded.
page = null ,
// If the reloadPage option is true, and the page is already
// in the DOM, dupCachedPage will be set to the page element
// so that it can be removed after the new version of the
// page is loaded off the network.
2011-06-08 21:47:24 +00:00
dupCachedPage = null ,
2011-07-15 17:46:39 +00:00
// determine the current base url
findBaseWithDefault = function ( ) {
var closestBase = ( $ . mobile . activePage && getClosestBaseUrl ( $ . mobile . activePage ) ) ;
return closestBase || documentBase . hrefNoHash ;
} ,
2011-06-08 21:47:24 +00:00
// The absolute version of the URL passed into the function. This
// version of the URL may contain dialog/subpage params in it.
2011-07-15 17:46:39 +00:00
absUrl = path . makeUrlAbsolute ( url , findBaseWithDefault ( ) ) ;
2011-05-18 22:58:15 +00:00
2011-05-19 01:06:15 +00:00
2011-05-18 22:58:15 +00:00
// If the caller provided data, and we're using "get" request,
// append the data to the URL.
if ( settings . data && settings . type === "get" ) {
2011-06-06 22:58:21 +00:00
absUrl = path . addSearchParams ( absUrl , settings . data ) ;
2011-05-18 22:58:15 +00:00
settings . data = undefined ;
}
2011-09-23 23:15:56 +00:00
2011-09-23 13:28:43 +00:00
// If the caller is using a "post" request, reloadPage must be true
if ( settings . data && settings . type === "post" ) {
settings . reloadPage = true ;
}
2011-05-18 22:58:15 +00:00
2011-06-08 21:47:24 +00:00
// The absolute version of the URL minus any dialog/subpage params.
// In otherwords the real URL of the page to be loaded.
var fileUrl = path . getFilePath ( absUrl ) ,
// The version of the Url actually stored in the data-url attribute of
// the page. For embedded pages, it is just the id of the page. For pages
// within the same domain as the document base, it is the site relative
// path. For cross-domain pages (Phone Gap only) the entire absolute Url
// used to load the page.
dataUrl = path . convertUrlToDataUrl ( absUrl ) ;
// Make sure we have a pageContainer to work with.
settings . pageContainer = settings . pageContainer || $ . mobile . pageContainer ;
2011-05-18 22:58:15 +00:00
// Check to see if the page already exists in the DOM.
2011-06-08 21:47:24 +00:00
page = settings . pageContainer . children ( ":jqmData(url='" + dataUrl + "')" ) ;
2011-05-18 22:58:15 +00:00
2011-09-21 22:46:15 +00:00
// If we failed to find the page, check to see if the url is a
// reference to an embedded page. If so, it may have been dynamically
// injected by a developer, in which case it would be lacking a data-url
// attribute and in need of enhancement.
2011-09-29 22:16:21 +00:00
if ( page . length === 0 && dataUrl && ! path . isPath ( dataUrl ) ) {
2011-09-21 22:46:15 +00:00
page = settings . pageContainer . children ( "#" + dataUrl )
2011-10-25 18:15:19 +00:00
. attr ( "data-" + $ . mobile . ns + "url" , dataUrl ) ;
2011-09-21 22:46:15 +00:00
}
2011-09-08 16:21:31 +00:00
// If we failed to find a page in the DOM, check the URL to see if it
2011-10-26 00:06:01 +00:00
// refers to the first page in the application. If it isn't a reference
// to the first page and refers to non-existent embedded page, error out.
if ( page . length === 0 ) {
if ( $ . mobile . firstPage && path . isFirstPageUrl ( fileUrl ) ) {
2011-11-04 17:58:44 +00:00
// Check to make sure our cached-first-page is actually
// in the DOM. Some user deployed apps are pruning the first
// page from the DOM for various reasons, we check for this
// case here because we don't want a first-page with an id
// falling through to the non-existent embedded page error
// case. If the first-page is not in the DOM, then we let
// things fall through to the ajax loading code below so
// that it gets reloaded.
if ( $ . mobile . firstPage . parent ( ) . length ) {
page = $ ( $ . mobile . firstPage ) ;
}
2011-10-26 00:06:01 +00:00
} else if ( path . isEmbeddedPage ( fileUrl ) ) {
deferred . reject ( absUrl , options ) ;
return deferred . promise ( ) ;
}
2011-09-08 16:21:31 +00:00
}
2011-05-18 22:58:15 +00:00
// Reset base to the default document base.
if ( base ) {
base . reset ( ) ;
}
// If the page we are interested in is already in the DOM,
// and the caller did not indicate that we should force a
// reload of the file, we are done. Otherwise, track the
// existing page as a duplicated.
if ( page . length ) {
if ( ! settings . reloadPage ) {
enhancePage ( page , settings . role ) ;
2011-05-27 17:53:19 +00:00
deferred . resolve ( absUrl , options , page ) ;
2011-05-18 22:58:15 +00:00
return deferred . promise ( ) ;
}
dupCachedPage = page ;
}
2011-09-23 21:12:40 +00:00
var mpc = settings . pageContainer ,
pblEvent = new $ . Event ( "pagebeforeload" ) ,
triggerData = { url : url , absUrl : absUrl , dataUrl : dataUrl , deferred : deferred , options : settings } ;
// Let listeners know we're about to load a page.
mpc . trigger ( pblEvent , triggerData ) ;
// If the default behavior is prevented, stop here!
if ( pblEvent . isDefaultPrevented ( ) ) {
return deferred . promise ( ) ;
}
2011-05-18 22:58:15 +00:00
if ( settings . showLoadMsg ) {
2011-08-24 22:22:52 +00:00
2011-07-30 12:33:04 +00:00
// This configurable timeout allows cached pages a brief delay to load without showing a message
var loadMsgDelay = setTimeout ( function ( ) {
$ . mobile . showPageLoadingMsg ( ) ;
} , settings . loadMsgDelay ) ,
2011-08-24 22:22:52 +00:00
2011-07-30 12:33:04 +00:00
// Shared logic for clearing timeout and removing message.
hideMsg = function ( ) {
2011-08-24 22:22:52 +00:00
2011-07-30 12:33:04 +00:00
// Stop message show timer
clearTimeout ( loadMsgDelay ) ;
2011-08-24 22:22:52 +00:00
2011-07-30 12:33:04 +00:00
// Hide loading message
$ . mobile . hidePageLoadingMsg ( ) ;
} ;
2011-05-18 22:58:15 +00:00
}
2011-06-30 20:40:06 +00:00
if ( ! ( $ . mobile . allowCrossDomainPages || path . isSameDomain ( documentUrl , absUrl ) ) ) {
deferred . reject ( absUrl , options ) ;
} else {
// Load the new page.
$ . ajax ( {
url : fileUrl ,
type : settings . type ,
data : settings . data ,
dataType : "html" ,
2011-10-26 18:34:27 +00:00
success : function ( html , textStatus , xhr ) {
2011-06-30 20:40:06 +00:00
//pre-parse html to check for a data-url,
//use it as the new fileUrl, base path, etc
var all = $ ( "<div></div>" ) ,
2011-05-18 22:58:15 +00:00
//page title regexp
newPageTitle = html . match ( /<title[^>]*>([^<]*)/ ) && RegExp . $1 ,
// TODO handle dialogs again
2011-09-29 05:08:30 +00:00
pageElemRegex = new RegExp ( "(<[^>]+\\bdata-" + $ . mobile . ns + "role=[\"']?page[\"']?[^>]*>)" ) ,
2011-05-18 22:58:15 +00:00
dataUrlRegex = new RegExp ( "\\bdata-" + $ . mobile . ns + "url=[\"']?([^\"'>]*)[\"']?" ) ;
2011-06-30 20:40:06 +00:00
// data-url must be provided for the base tag so resource requests can be directed to the
// correct url. loading into a temprorary element makes these requests immediately
if ( pageElemRegex . test ( html )
&& RegExp . $1
&& dataUrlRegex . test ( RegExp . $1 )
&& RegExp . $1 ) {
url = fileUrl = path . getFilePath ( RegExp . $1 ) ;
}
2011-05-18 22:58:15 +00:00
2011-06-30 20:40:06 +00:00
if ( base ) {
base . set ( fileUrl ) ;
}
2011-05-18 22:58:15 +00:00
2011-06-30 20:40:06 +00:00
//workaround to allow scripts to execute when included in page divs
all . get ( 0 ) . innerHTML = html ;
page = all . find ( ":jqmData(role='page'), :jqmData(role='dialog')" ) . first ( ) ;
2011-07-27 18:25:58 +00:00
2011-07-17 18:52:49 +00:00
//if page elem couldn't be found, create one and insert the body element's contents
if ( ! page . length ) {
page = $ ( "<div data-" + $ . mobile . ns + "role='page'>" + html . split ( /<\/?body[^>]*>/gmi ) [ 1 ] + "</div>" ) ;
}
2011-05-18 22:58:15 +00:00
2011-06-30 20:40:06 +00:00
if ( newPageTitle && ! page . jqmData ( "title" ) ) {
2011-11-04 20:08:10 +00:00
if ( ~ newPageTitle . indexOf ( "&" ) ) {
2011-11-04 17:33:07 +00:00
newPageTitle = $ ( "<div>" + newPageTitle + "</div>" ) . text ( ) ;
}
2011-06-30 20:40:06 +00:00
page . jqmData ( "title" , newPageTitle ) ;
}
2011-05-18 22:58:15 +00:00
2011-06-30 20:40:06 +00:00
//rewrite src and href attrs to use a base url
if ( ! $ . support . dynamicBaseTag ) {
var newPath = path . get ( fileUrl ) ;
page . find ( "[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]" ) . each ( function ( ) {
var thisAttr = $ ( this ) . is ( '[href]' ) ? 'href' :
$ ( this ) . is ( '[src]' ) ? 'src' : 'action' ,
thisUrl = $ ( this ) . attr ( thisAttr ) ;
// XXX_jblas: We need to fix this so that it removes the document
// base URL, and then prepends with the new page URL.
//if full path exists and is same, chop it - helps IE out
thisUrl = thisUrl . replace ( location . protocol + '//' + location . host + location . pathname , '' ) ;
if ( ! /^(\w+:|#|\/)/ . test ( thisUrl ) ) {
$ ( this ) . attr ( thisAttr , newPath + thisUrl ) ;
}
} ) ;
}
2011-05-18 22:58:15 +00:00
2011-06-30 20:40:06 +00:00
//append to page and enhance
2011-09-12 21:06:47 +00:00
// TODO taging a page with external to make sure that embedded pages aren't removed
// by the various page handling code is bad. Having page handling code in many
// places is bad. Solutions post 1.0
2011-06-30 20:40:06 +00:00
page
. attr ( "data-" + $ . mobile . ns + "url" , path . convertUrlToDataUrl ( fileUrl ) )
2011-09-12 21:06:47 +00:00
. attr ( "data-" + $ . mobile . ns + "external-page" , true )
2011-06-30 20:40:06 +00:00
. appendTo ( settings . pageContainer ) ;
2011-05-18 22:58:15 +00:00
2011-07-29 19:55:40 +00:00
// wait for page creation to leverage options defined on widget
2011-09-23 16:55:17 +00:00
page . one ( 'pagecreate' , $ . mobile . _bindPageRemove ) ;
2011-07-27 18:25:58 +00:00
2011-06-30 20:40:06 +00:00
enhancePage ( page , settings . role ) ;
2011-05-18 22:58:15 +00:00
2011-06-30 20:40:06 +00:00
// Enhancing the page may result in new dialogs/sub pages being inserted
// into the DOM. If the original absUrl refers to a sub-page, that is the
// real page we are interested in.
if ( absUrl . indexOf ( "&" + $ . mobile . subPageUrlKey ) > - 1 ) {
page = settings . pageContainer . children ( ":jqmData(url='" + dataUrl + "')" ) ;
}
2011-07-27 18:25:58 +00:00
2011-07-25 13:16:09 +00:00
//bind pageHide to removePage after it's hidden, if the page options specify to do so
2011-05-18 22:58:15 +00:00
2011-06-30 20:40:06 +00:00
// Remove loading message.
if ( settings . showLoadMsg ) {
2011-07-30 12:33:04 +00:00
hideMsg ( ) ;
2011-06-30 20:40:06 +00:00
}
2011-05-18 22:58:15 +00:00
2011-10-26 18:34:27 +00:00
// Add the page reference and xhr to our triggerData.
triggerData . xhr = xhr ;
triggerData . textStatus = textStatus ;
2011-09-23 21:12:40 +00:00
triggerData . page = page ;
// Let listeners know the page loaded successfully.
settings . pageContainer . trigger ( "pageload" , triggerData ) ;
2011-06-30 20:40:06 +00:00
deferred . resolve ( absUrl , options , page , dupCachedPage ) ;
} ,
2011-10-26 18:34:27 +00:00
error : function ( xhr , textStatus , errorThrown ) {
2011-06-30 20:40:06 +00:00
//set base back to current path
if ( base ) {
base . set ( path . get ( ) ) ;
}
2011-05-18 22:58:15 +00:00
2011-10-26 18:34:27 +00:00
// Add error info to our triggerData.
triggerData . xhr = xhr ;
triggerData . textStatus = textStatus ;
triggerData . errorThrown = errorThrown ;
2011-09-23 21:12:40 +00:00
var plfEvent = new $ . Event ( "pageloadfailed" ) ;
// Let listeners know the page load failed.
settings . pageContainer . trigger ( plfEvent , triggerData ) ;
// If the default behavior is prevented, stop here!
// Note that it is the responsibility of the listener/handler
// that called preventDefault(), to resolve/reject the
// deferred object within the triggerData.
if ( plfEvent . isDefaultPrevented ( ) ) {
return ;
}
2011-06-30 20:40:06 +00:00
// Remove loading message.
if ( settings . showLoadMsg ) {
2011-08-24 22:22:52 +00:00
2011-07-30 12:33:04 +00:00
// Remove loading message.
hideMsg ( ) ;
2011-06-30 20:40:06 +00:00
//show error message
$ ( "<div class='ui-loader ui-overlay-shadow ui-body-e ui-corner-all'><h1>" + $ . mobile . pageLoadErrorMessage + "</h1></div>" )
. css ( { "display" : "block" , "opacity" : 0.96 , "top" : $window . scrollTop ( ) + 100 } )
. appendTo ( settings . pageContainer )
. delay ( 800 )
. fadeOut ( 400 , function ( ) {
$ ( this ) . remove ( ) ;
} ) ;
}
2011-05-18 22:58:15 +00:00
2011-06-30 20:40:06 +00:00
deferred . reject ( absUrl , options ) ;
}
} ) ;
}
2011-05-16 23:02:26 +00:00
2011-05-18 22:58:15 +00:00
return deferred . promise ( ) ;
} ;
$ . mobile . loadPage . defaults = {
type : "get" ,
2011-05-27 00:04:27 +00:00
data : undefined ,
2011-05-18 22:58:15 +00:00
reloadPage : false ,
2011-06-16 20:36:39 +00:00
role : undefined , // By default we rely on the role defined by the @data-role attribute.
2011-07-21 12:04:12 +00:00
showLoadMsg : false ,
2011-07-30 12:33:04 +00:00
pageContainer : undefined ,
loadMsgDelay : 50 // This delay allows loads that pull from browser cache to occur without showing the loading message.
2011-05-18 22:58:15 +00:00
} ;
// Show a specific page in the page container.
$ . mobile . changePage = function ( toPage , options ) {
2011-05-16 23:02:26 +00:00
// If we are in the midst of a transition, queue the current request.
// We'll call changePage() once we're done with the current transition to
// service the request.
if ( isPageTransitioning ) {
2011-05-18 23:38:04 +00:00
pageTransitionQueue . unshift ( arguments ) ;
2011-05-16 23:02:26 +00:00
return ;
}
2011-01-31 06:03:30 +00:00
2011-05-18 23:38:04 +00:00
var settings = $ . extend ( { } , $ . mobile . changePage . defaults , options ) ;
2011-05-18 22:58:15 +00:00
2011-05-19 01:06:15 +00:00
// Make sure we have a pageContainer to work with.
settings . pageContainer = settings . pageContainer || $ . mobile . pageContainer ;
2011-09-08 01:03:38 +00:00
// Make sure we have a fromPage.
settings . fromPage = settings . fromPage || $ . mobile . activePage ;
2011-09-05 17:05:57 +00:00
var mpc = settings . pageContainer ,
2011-09-08 01:03:38 +00:00
pbcEvent = new $ . Event ( "pagebeforechange" ) ,
triggerData = { toPage : toPage , options : settings } ;
2011-09-05 17:05:57 +00:00
// Let listeners know we're about to change the current page.
2011-09-08 01:03:38 +00:00
mpc . trigger ( pbcEvent , triggerData ) ;
2011-09-05 17:05:57 +00:00
// If the default behavior is prevented, stop here!
2011-09-08 01:03:38 +00:00
if ( pbcEvent . isDefaultPrevented ( ) ) {
2011-09-05 17:05:57 +00:00
return ;
}
2011-09-08 01:03:38 +00:00
// We allow "pagebeforechange" observers to modify the toPage in the trigger
// data to allow for redirects. Make sure our toPage is updated.
toPage = triggerData . toPage ;
2011-09-06 23:56:20 +00:00
// Set the isPageTransitioning flag to prevent any requests from
// entering this method while we are in the midst of loading a page
// or transitioning.
isPageTransitioning = true ;
2011-05-18 22:58:15 +00:00
// If the caller passed us a url, call loadPage()
// to make sure it is loaded into the DOM. We'll listen
// to the promise object it returns so we know when
// it is done loading or if an error ocurred.
if ( typeof toPage == "string" ) {
2011-06-04 07:26:25 +00:00
$ . mobile . loadPage ( toPage , settings )
. done ( function ( url , options , newPage , dupCachedPage ) {
isPageTransitioning = false ;
options . duplicateCachedPage = dupCachedPage ;
$ . mobile . changePage ( newPage , options ) ;
} )
. fail ( function ( url , options ) {
isPageTransitioning = false ;
//clear out the active button state
removeActiveLinkClass ( true ) ;
//release transition lock so navigation is free again
releasePageTransitionLock ( ) ;
2011-09-08 01:03:38 +00:00
settings . pageContainer . trigger ( "pagechangefailed" , triggerData ) ;
2011-06-04 07:26:25 +00:00
} ) ;
return ;
2011-05-18 22:58:15 +00:00
}
2011-10-10 18:04:04 +00:00
// If we are going to the first-page of the application, we need to make
// sure settings.dataUrl is set to the application document url. This allows
// us to avoid generating a document url with an id hash in the case where the
// first-page of the document has an id attribute specified.
if ( toPage [ 0 ] === $ . mobile . firstPage [ 0 ] && ! settings . dataUrl ) {
settings . dataUrl = documentUrl . hrefNoHash ;
}
2011-05-18 22:58:15 +00:00
// The caller passed us a real page DOM element. Update our
// internal state and then trigger a transition to the page.
2011-09-08 01:03:38 +00:00
var fromPage = settings . fromPage ,
url = ( settings . dataUrl && path . convertUrlToDataUrl ( settings . dataUrl ) ) || toPage . jqmData ( "url" ) ,
2011-07-31 14:03:22 +00:00
// The pageUrl var is usually the same as url, except when url is obscured as a dialog url. pageUrl always contains the file path
pageUrl = url ,
2011-05-18 23:38:04 +00:00
fileUrl = path . getFilePath ( url ) ,
2011-05-18 22:58:15 +00:00
active = urlHistory . getActive ( ) ,
2011-06-15 22:28:52 +00:00
activeIsInitialPage = urlHistory . activeIndex === 0 ,
2011-05-18 22:58:15 +00:00
historyDir = 0 ,
pageTitle = document . title ,
2011-05-18 23:38:04 +00:00
isDialog = settings . role === "dialog" || toPage . jqmData ( "role" ) === "dialog" ;
2011-05-18 22:58:15 +00:00
Fix for issue 2529 - Transition to the same page
- Added a new allowSamePageTransition option to the changePage() method default settings.
By default, we prevent changePage() requests when the fromPage and toPage are the same element, but folks that generate content manually/dynamically and reuse pages want to be able to transition to the same page. To allow
this, they will need to change the default value of allowSamePageTransition to true, *OR*, pass it in as an option when they manually call changePage().
It should be noted that our default transition animations assume that the formPage and toPage are different elements, so they may behave unexpectedly. It is up to the developer that turns on the allowSamePageTransitiona option
to either turn off transition animations, or make sure that an appropriate animation transition is used.
// To toggle the default behavior for all changePage() calls,
// set the default value of allowSamePageTransition to whatever
// you want it to be. The default is false.
$.mobile.changePage.defaults.allowSamePageTransition = true;
// To specify the behavior when manually calling changePage(),
// pass it as an option. If not specified, the default value
// specified by $.mobile.changepage.defaults.allowSamePageTransition
// is used.
$.mobile.changePage( "#reused-page", { allowSamePageTransition: true } );
2011-09-26 17:23:47 +00:00
// By default, we prevent changePage requests when the fromPage and toPage
// are the same element, but folks that generate content manually/dynamically
// and reuse pages want to be able to transition to the same page. To allow
// this, they will need to change the default value of allowSamePageTransition
// to true, *OR*, pass it in as an option when they manually call changePage().
// It should be noted that our default transition animations assume that the
// formPage and toPage are different elements, so they may behave unexpectedly.
// It is up to the developer that turns on the allowSamePageTransitiona option
// to either turn off transition animations, or make sure that an appropriate
// animation transition is used.
if ( fromPage && fromPage [ 0 ] === toPage [ 0 ] && ! settings . allowSamePageTransition ) {
2011-05-23 21:30:40 +00:00
isPageTransitioning = false ;
2011-09-08 01:03:38 +00:00
mpc . trigger ( "pagechange" , triggerData ) ;
2011-02-01 19:52:15 +00:00
return ;
}
2011-02-15 01:23:25 +00:00
2011-05-18 22:58:15 +00:00
// We need to make sure the page we are given has already been enhanced.
enhancePage ( toPage , settings . role ) ;
2011-05-16 23:02:26 +00:00
// If the changePage request was sent from a hashChange event, check to see if the
// page is already within the urlHistory stack. If so, we'll assume the user hit
// the forward/back button and will try to match the transition accordingly.
2011-05-18 22:58:15 +00:00
if ( settings . fromHashChange ) {
2011-03-08 00:49:53 +00:00
urlHistory . directHashChange ( {
2011-05-16 23:02:26 +00:00
currentUrl : url ,
2011-05-18 23:38:04 +00:00
isBack : function ( ) { historyDir = - 1 ; } ,
isForward : function ( ) { historyDir = 1 ; }
Refactored urlStack and updated dialog and page plugins to match. jQuery Mobile's internal history now attempts to follow the history menu when urls change from hashchange, even for changes that go multiple steps forward or back. The internal history stack is now pruned based on whether a user goes back and then changes direction, whereas before a back-button click would result in a pop off the history. Instead we now maintain an active index number in the history stack, which allows us to maintain references to transitions that are saved on pages reached through clicking the forward button as well. This fixes #636.
In the process, some other small changes should be noted:
urlStack is now urlHistory, a hash of methods and properties used for history stack management (stack, activeIndex, getActive, getPrev, getNext, addNew, clearForward, and listening Enabled). All these are documented inline and exposed on $.mobile.urlHistory (I'm not sure these will be publicly documented, but just exposed internally for plugins for now).
$.changePage has two argument changes: the "back" argument is now called "reverse"; this results in no change from an end-user standpoint, but reflects the fact that it only reverses the direction of a transition without affecting the internal history stack, and second, a new argument at the end defines whether changePage was called from a hashChange which makes that url open to history menu guessing.
2011-01-23 22:33:36 +00:00
} ) ;
2010-12-03 22:07:39 +00:00
}
2011-01-31 06:03:30 +00:00
2011-05-16 23:02:26 +00:00
// Kill the keyboard.
// XXX_jblas: We need to stop crawling the entire document to kill focus. Instead,
2011-11-10 00:01:37 +00:00
// we should be tracking focus with a delegate() handler so we already have
2011-05-16 23:02:26 +00:00
// the element in hand at this point.
2011-07-27 12:53:27 +00:00
// Wrap this in a try/catch block since IE9 throw "Unspecified error" if document.activeElement
// is undefined when we are in an IFrame.
try {
2011-11-11 19:20:30 +00:00
if ( document . activeElement && document . activeElement . nodeName . toLowerCase ( ) != 'body' ) {
$ ( document . activeElement ) . blur ( ) ;
2011-11-02 20:09:25 +00:00
} else {
$ ( "input:focus, textarea:focus, select:focus" ) . blur ( ) ;
}
2011-07-27 12:53:27 +00:00
} catch ( e ) { }
2010-11-25 11:13:51 +00:00
2011-05-18 22:58:15 +00:00
// If we're displaying the page as a dialog, we don't want the url
// for the dialog content to be used in the hash. Instead, we want
// to append the dialogHashKey to the url of the current page.
2011-05-20 00:01:26 +00:00
if ( isDialog && active ) {
2011-08-24 22:28:57 +00:00
// on the initial page load active.url is undefined and in that case should
// be an empty string. Moving the undefined -> empty string back into
// urlHistory.addNew seemed imprudent given undefined better represents
// the url state
url = ( active . url || "" ) + dialogHashKey ;
2010-11-25 11:13:51 +00:00
}
2010-12-13 10:21:02 +00:00
2011-05-18 22:58:15 +00:00
// Set the location hash.
2011-05-18 23:38:04 +00:00
if ( settings . changeHash !== false && url ) {
2011-05-18 22:58:15 +00:00
//disable hash listening temporarily
2011-05-20 22:19:54 +00:00
urlHistory . ignoreNextHashChange = true ;
2011-05-18 22:58:15 +00:00
//update hash and history
path . set ( url ) ;
}
2011-10-28 05:27:41 +00:00
// if title element wasn't found, try the page div data attr too
// If this is a deep-link or a reload ( active === undefined ) then just use pageTitle
var newPageTitle = ( ! active ) ? pageTitle : toPage . jqmData ( "title" ) || toPage . children ( ":jqmData(role='header')" ) . find ( ".ui-title" ) . getEncodedText ( ) ;
2011-05-18 23:38:04 +00:00
if ( ! ! newPageTitle && pageTitle == document . title ) {
2011-05-18 22:58:15 +00:00
pageTitle = newPageTitle ;
2010-11-25 11:13:51 +00:00
}
2011-11-07 20:23:27 +00:00
if ( ! toPage . jqmData ( "title" ) ) {
toPage . jqmData ( "title" , pageTitle ) ;
}
2011-01-31 06:03:30 +00:00
2011-10-14 16:30:26 +00:00
// Make sure we have a transition defined.
settings . transition = settings . transition
|| ( ( historyDir && ! activeIsInitialPage ) ? active . transition : undefined )
|| ( isDialog ? $ . mobile . defaultDialogTransition : $ . mobile . defaultPageTransition ) ;
2011-05-18 22:58:15 +00:00
//add page to history stack if it's not back or forward
2011-05-18 23:38:04 +00:00
if ( ! historyDir ) {
2011-08-27 06:30:49 +00:00
urlHistory . addNew ( url , settings . transition , pageTitle , pageUrl , settings . role ) ;
2011-05-18 22:58:15 +00:00
}
//set page title
document . title = urlHistory . getActive ( ) . title ;
//set "toPage" as activePage
$ . mobile . activePage = toPage ;
// If we're navigating back in the URL history, set reverse accordingly.
settings . reverse = settings . reverse || historyDir < 0 ;
2011-06-04 07:26:25 +00:00
transitionPages ( toPage , fromPage , settings . transition , settings . reverse )
2011-12-30 07:43:12 +00:00
. done ( function ( name , reverse , $to , $from , alreadyFocused ) {
2011-06-04 07:26:25 +00:00
removeActiveLinkClass ( ) ;
2011-07-07 16:19:16 +00:00
2011-06-04 07:26:25 +00:00
//if there's a duplicateCachedPage, remove it from the DOM now that it's hidden
if ( settings . duplicateCachedPage ) {
settings . duplicateCachedPage . remove ( ) ;
}
2011-07-07 16:19:16 +00:00
2011-06-04 07:26:25 +00:00
//remove initial build class (only present on first pageshow)
$html . removeClass ( "ui-mobile-rendering" ) ;
2011-07-07 16:19:16 +00:00
Much of the scripting in nav.js's transitionPages function was tied to the animation sequence for our css3transitionhandler. For example, the order was, scroll to top, run transitions, then scroll to the remembered location of the new page (there's more involved, but that's the gist of it). If we want to expand beyond this sequence, much of that scripting needs to move to the css3transitionhandler itself, and also to our "none" transition handler, which comes with nav model.
This commit moves all that logic into the transition handlers, and should provide a better starting point for adding different transition sequences, such as fade-out, scroll, fade-in.
In the process of making this change, the reFocus function was made public as $.mobile.focusPage.
2011-12-28 04:59:48 +00:00
// Send focus to the newly shown page. Moved from promise .done binding in transitionPages
// itself to avoid ie bug that reports offsetWidth as > 0 (core check for visibility)
// despite visibility: hidden addresses issue #2965
// https://github.com/jquery/jquery-mobile/issues/2965
2011-12-30 07:43:12 +00:00
if ( ! alreadyFocused ) {
$ . mobile . focusPage ( toPage ) ;
}
Much of the scripting in nav.js's transitionPages function was tied to the animation sequence for our css3transitionhandler. For example, the order was, scroll to top, run transitions, then scroll to the remembered location of the new page (there's more involved, but that's the gist of it). If we want to expand beyond this sequence, much of that scripting needs to move to the css3transitionhandler itself, and also to our "none" transition handler, which comes with nav model.
This commit moves all that logic into the transition handlers, and should provide a better starting point for adding different transition sequences, such as fade-out, scroll, fade-in.
In the process of making this change, the reFocus function was made public as $.mobile.focusPage.
2011-12-28 04:59:48 +00:00
2011-06-04 07:26:25 +00:00
releasePageTransitionLock ( ) ;
2011-07-07 16:19:16 +00:00
2011-06-04 07:26:25 +00:00
// Let listeners know we're all done changing the current page.
2011-09-08 01:03:38 +00:00
mpc . trigger ( "pagechange" , triggerData ) ;
2011-06-04 07:26:25 +00:00
} ) ;
2011-05-18 22:58:15 +00:00
} ;
2011-03-30 07:42:42 +00:00
2011-05-18 22:58:15 +00:00
$ . mobile . changePage . defaults = {
transition : undefined ,
reverse : false ,
changeHash : true ,
fromHashChange : false ,
2011-06-16 20:36:39 +00:00
role : undefined , // By default we rely on the role defined by the @data-role attribute.
2011-05-19 01:06:15 +00:00
duplicateCachedPage : undefined ,
2011-07-21 12:04:12 +00:00
pageContainer : undefined ,
2011-09-08 01:03:38 +00:00
showLoadMsg : true , //loading message shows by default when pages are being fetched during changePage
dataUrl : undefined ,
Fix for issue 2529 - Transition to the same page
- Added a new allowSamePageTransition option to the changePage() method default settings.
By default, we prevent changePage() requests when the fromPage and toPage are the same element, but folks that generate content manually/dynamically and reuse pages want to be able to transition to the same page. To allow
this, they will need to change the default value of allowSamePageTransition to true, *OR*, pass it in as an option when they manually call changePage().
It should be noted that our default transition animations assume that the formPage and toPage are different elements, so they may behave unexpectedly. It is up to the developer that turns on the allowSamePageTransitiona option
to either turn off transition animations, or make sure that an appropriate animation transition is used.
// To toggle the default behavior for all changePage() calls,
// set the default value of allowSamePageTransition to whatever
// you want it to be. The default is false.
$.mobile.changePage.defaults.allowSamePageTransition = true;
// To specify the behavior when manually calling changePage(),
// pass it as an option. If not specified, the default value
// specified by $.mobile.changepage.defaults.allowSamePageTransition
// is used.
$.mobile.changePage( "#reused-page", { allowSamePageTransition: true } );
2011-09-26 17:23:47 +00:00
fromPage : undefined ,
allowSamePageTransition : false
2010-11-25 11:13:51 +00:00
} ;
2010-12-13 10:21:02 +00:00
/* Event Bindings - hashchange, submit, and click */
2011-05-18 23:38:04 +00:00
function findClosestLink ( ele )
2011-04-18 23:13:50 +00:00
{
2011-05-18 23:38:04 +00:00
while ( ele ) {
2011-11-16 00:17:14 +00:00
// Look for the closest element with a nodeName of "a".
// Note that we are checking if we have a valid nodeName
// before attempting to access it. This is because the
// node we get called with could have originated from within
// an embedded SVG document where some symbol instance elements
// don't have nodeName defined on them, or strings are of type
// SVGAnimatedString.
if ( ( typeof ele . nodeName === "string" ) && ele . nodeName . toLowerCase ( ) == "a" ) {
2011-04-18 23:13:50 +00:00
break ;
}
ele = ele . parentNode ;
}
return ele ;
}
2011-06-02 00:15:18 +00:00
// The base URL for any given element depends on the page it resides in.
function getClosestBaseUrl ( ele )
{
// Find the closest page and extract out its url.
2011-06-04 08:22:16 +00:00
var url = $ ( ele ) . closest ( ".ui-page" ) . jqmData ( "url" ) ,
base = documentBase . hrefNoHash ;
2011-06-02 00:15:18 +00:00
2011-06-06 22:58:21 +00:00
if ( ! url || ! path . isPath ( url ) ) {
2011-06-04 08:22:16 +00:00
url = base ;
2011-06-02 00:15:18 +00:00
}
2011-06-06 22:58:21 +00:00
return path . makeUrlAbsolute ( url , base ) ;
2011-06-02 00:15:18 +00:00
}
2011-07-07 16:19:16 +00:00
2011-06-21 15:33:38 +00:00
//The following event bindings should be bound after mobileinit has been triggered
//the following function is called in the init file
$ . mobile . _registerInternalEvents = function ( ) {
2011-07-07 16:19:16 +00:00
2011-06-22 15:43:22 +00:00
//bind to form submit events, handle with Ajax
2011-11-10 00:01:37 +00:00
$ ( document ) . delegate ( "form" , "submit" , function ( event ) {
2011-06-22 15:43:22 +00:00
var $this = $ ( this ) ;
if ( ! $ . mobile . ajaxEnabled ||
$this . is ( ":jqmData(ajax='false')" ) ) {
return ;
}
var type = $this . attr ( "method" ) ,
2011-06-27 17:25:13 +00:00
target = $this . attr ( "target" ) ,
url = $this . attr ( "action" ) ;
// If no action is specified, browsers default to using the
// URL of the document containing the form. Since we dynamically
// pull in pages from external documents, the form should submit
// to the URL for the source document of the page containing
// the form.
if ( ! url ) {
// Get the @data-url for the page containing the form.
url = getClosestBaseUrl ( $this ) ;
if ( url === documentBase . hrefNoHash ) {
// The url we got back matches the document base,
// which means the page must be an internal/embedded page,
// so default to using the actual document url as a browser
// would.
url = documentUrl . hrefNoSearch ;
}
}
url = path . makeUrlAbsolute ( url , getClosestBaseUrl ( $this ) ) ;
2011-06-22 15:43:22 +00:00
//external submits use regular HTTP
if ( path . isExternal ( url ) || target ) {
return ;
}
$ . mobile . changePage (
url ,
{
2011-06-27 17:25:13 +00:00
type : type && type . length && type . toLowerCase ( ) || "get" ,
2011-06-22 15:43:22 +00:00
data : $this . serialize ( ) ,
transition : $this . jqmData ( "transition" ) ,
direction : $this . jqmData ( "direction" ) ,
reloadPage : true
}
) ;
event . preventDefault ( ) ;
} ) ;
2011-06-21 15:33:38 +00:00
//add active state on vclick
$ ( document ) . bind ( "vclick" , function ( event ) {
2011-09-15 17:16:40 +00:00
// if this isn't a left click we don't care. Its important to note
// that when the virtual event is generated it will create
2011-10-20 22:15:18 +00:00
if ( event . which > 1 || ! $ . mobile . linkBindingEnabled ) {
2011-09-15 17:16:40 +00:00
return ;
}
2011-06-21 15:33:38 +00:00
var link = findClosestLink ( event . target ) ;
if ( link ) {
if ( path . parseUrl ( link . getAttribute ( "href" ) || "#" ) . hash !== "#" ) {
2011-09-01 04:39:58 +00:00
removeActiveLinkClass ( true ) ;
2011-08-18 00:32:55 +00:00
$activeClickedLink = $ ( link ) . closest ( ".ui-btn" ) . not ( ".ui-disabled" ) ;
$activeClickedLink . addClass ( $ . mobile . activeBtnClass ) ;
2011-06-21 15:33:38 +00:00
$ ( "." + $ . mobile . activePageClass + " .ui-btn" ) . not ( link ) . blur ( ) ;
2012-01-11 03:50:22 +00:00
// By caching the href value to data and switching the href to a #, we can avoid address bar showing in iOS. The click handler resets the href during its initial steps if this data is present
$ ( link )
. jqmData ( "href" , $ ( link ) . attr ( "href" ) )
. attr ( "href" , "#" ) ;
2011-06-21 15:33:38 +00:00
}
2011-04-22 17:53:24 +00:00
}
2011-06-21 15:33:38 +00:00
} ) ;
2010-12-13 10:21:02 +00:00
2011-06-21 15:33:38 +00:00
// click routing - direct to HTTP or Ajax, accordingly
2011-06-30 00:38:00 +00:00
$ ( document ) . bind ( "click" , function ( event ) {
2011-10-20 22:15:18 +00:00
if ( ! $ . mobile . linkBindingEnabled ) {
return ;
}
2011-06-21 15:33:38 +00:00
var link = findClosestLink ( event . target ) ;
2011-09-15 17:16:40 +00:00
// If there is no link associated with the click or its not a left
// click we want to ignore the click
if ( ! link || event . which > 1 ) {
2011-06-21 15:33:38 +00:00
return ;
}
2011-01-31 06:03:30 +00:00
2011-06-21 15:33:38 +00:00
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 ) ;
} ;
2012-01-11 03:50:22 +00:00
// If there's data cached for the real href value, set the link's href back to it again. This pairs with an address bar workaround from the vclick handler
if ( $link . jqmData ( "href" ) ) {
$link . attr ( "href" , $link . jqmData ( "href" ) ) ;
}
2011-02-15 01:23:25 +00:00
2011-06-21 15:33:38 +00:00
//if there's a data-rel=back attr, go back in history
if ( $link . is ( ":jqmData(rel='back')" ) ) {
window . history . back ( ) ;
return false ;
}
2011-07-07 16:19:16 +00:00
2011-09-19 18:32:13 +00:00
var baseUrl = getClosestBaseUrl ( $link ) ,
//get href, if defined, otherwise default to empty hash
href = path . makeUrlAbsolute ( $link . attr ( "href" ) || "#" , baseUrl ) ;
2011-06-21 15:33:38 +00:00
//if ajax is disabled, exit early
2011-09-19 18:32:13 +00:00
if ( ! $ . mobile . ajaxEnabled && ! path . isEmbeddedPage ( href ) ) {
2011-06-21 15:33:38 +00:00
httpCleanup ( ) ;
//use default click handling
2011-06-08 21:47:24 +00:00
return ;
}
2011-07-07 16:19:16 +00:00
2011-06-21 15:33:38 +00:00
// 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 ) ;
}
}
2011-01-31 06:03:30 +00:00
2011-06-21 15:33:38 +00:00
// 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]" ) ,
2011-01-31 07:43:53 +00:00
2011-06-21 15:33:38 +00:00
// 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 ) ,
2011-03-21 17:32:24 +00:00
2011-06-21 15:33:38 +00:00
//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 ) ;
2010-12-13 10:21:02 +00:00
2011-06-21 15:33:38 +00:00
if ( isExternal ) {
httpCleanup ( ) ;
//use default click handling
return ;
}
2010-12-13 10:21:02 +00:00
2011-06-21 15:33:38 +00:00
//use ajax
var transition = $link . jqmData ( "transition" ) ,
direction = $link . jqmData ( "direction" ) ,
reverse = ( direction && direction === "reverse" ) ||
// deprecated - remove by 1.0
$link . jqmData ( "back" ) ,
2011-03-31 19:38:36 +00:00
2011-06-21 15:33:38 +00:00
//this may need to be more specific as we use data-rel more
role = $link . attr ( "data-" + $ . mobile . ns + "rel" ) || undefined ;
2012-01-11 03:50:22 +00:00
2011-06-21 15:33:38 +00:00
$ . mobile . changePage ( href , { transition : transition , reverse : reverse , role : role } ) ;
event . preventDefault ( ) ;
} ) ;
2011-07-27 18:25:58 +00:00
2011-07-15 17:16:31 +00:00
//prefetch pages when anchors with data-prefetch are encountered
2011-11-10 00:01:37 +00:00
$ ( document ) . delegate ( ".ui-page" , "pageshow.prefetch" , function ( ) {
2011-07-15 17:16:31 +00:00
var urls = [ ] ;
$ ( this ) . find ( "a:jqmData(prefetch)" ) . each ( function ( ) {
2011-10-11 23:18:51 +00:00
var $link = $ ( this ) ,
url = $link . attr ( "href" ) ;
2011-07-15 17:16:31 +00:00
if ( url && $ . inArray ( url , urls ) === - 1 ) {
urls . push ( url ) ;
2011-10-11 23:18:51 +00:00
$ . mobile . loadPage ( url , { role : $link . attr ( "data-" + $ . mobile . ns + "rel" ) } ) ;
2011-07-15 17:16:31 +00:00
}
} ) ;
2011-10-11 23:18:51 +00:00
} ) ;
2010-12-13 10:21:02 +00:00
2011-08-27 07:13:47 +00:00
$ . mobile . _handleHashChange = function ( hash ) {
2011-06-21 15:33:38 +00:00
//find first page via hash
2011-08-27 07:13:47 +00:00
var to = path . stripHash ( hash ) ,
2011-06-21 15:33:38 +00:00
//transition is false if it's the first page, undefined otherwise (and may be overridden by default)
2011-08-27 06:46:50 +00:00
transition = $ . mobile . urlHistory . stack . length === 0 ? "none" : undefined ,
2011-08-27 07:13:47 +00:00
// default options for the changPage calls made after examining the current state
// of the page and the hash
2011-08-27 06:46:50 +00:00
changePageOptions = {
transition : transition ,
changeHash : false ,
fromHashChange : true
} ;
2011-02-15 01:23:25 +00:00
2011-06-21 15:33:38 +00:00
//if listening is disabled (either globally or temporarily), or it's a dialog hash
if ( ! $ . mobile . hashListeningEnabled || urlHistory . ignoreNextHashChange ) {
urlHistory . ignoreNextHashChange = false ;
return ;
}
2011-03-07 07:47:40 +00:00
2011-06-21 15:33:38 +00:00
// special case for dialogs
2011-08-27 06:30:49 +00:00
if ( urlHistory . stack . length > 1 && to . indexOf ( dialogHashKey ) > - 1 ) {
2011-06-21 15:33:38 +00:00
// If current active page is not a dialog skip the dialog and continue
// in the same direction
2012-01-04 16:27:52 +00:00
if ( ! $ . mobile . activePage . is ( ".ui-dialog-page" ) ) {
2011-06-21 15:33:38 +00:00
//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 ( ) ; }
} ) ;
2011-03-07 07:47:40 +00:00
2011-09-20 23:59:30 +00:00
// prevent changePage()
2011-06-21 15:33:38 +00:00
return ;
} else {
// if the current active page is a dialog and we're navigating
// to a dialog use the dialog objected saved in the stack
2011-08-27 07:13:47 +00:00
urlHistory . directHashChange ( {
currentUrl : to ,
// regardless of the direction of the history change
// do the following
either : function ( isBack ) {
var active = $ . mobile . urlHistory . getActive ( ) ;
to = active . pageUrl ;
// make sure to set the role, transition and reversal
// as most of this is lost by the domCache cleaning
$ . extend ( changePageOptions , {
role : active . role ,
transition : active . transition ,
reverse : isBack
} ) ;
}
} ) ;
2011-06-21 15:33:38 +00:00
}
2011-03-28 06:59:28 +00:00
}
2011-08-24 22:22:52 +00:00
2011-06-21 15:33:38 +00:00
//if to is defined, load it
if ( to ) {
2011-09-13 07:23:03 +00:00
// At this point, 'to' can be one of 3 things, a cached page element from
// a history stack entry, an id, or site-relative/absolute URL. If 'to' is
// an id, we need to resolve it against the documentBase, not the location.href,
// since the hashchange could've been the result of a forward/backward navigation
// that crosses from an external page/dialog to an internal page/dialog.
to = ( typeof to === "string" && ! path . isPath ( to ) ) ? ( path . makeUrlAbsolute ( '#' + to , documentBase ) ) : to ;
2011-08-27 07:13:47 +00:00
$ . mobile . changePage ( to , changePageOptions ) ;
} else {
//there's no hash, go to the first page in the dom
$ . mobile . changePage ( $ . mobile . firstPage , changePageOptions ) ;
2011-06-21 15:33:38 +00:00
}
2011-08-27 06:46:50 +00:00
} ;
//hashchange event handler
$window . bind ( "hashchange" , function ( e , triggered ) {
2011-08-27 07:13:47 +00:00
$ . mobile . _handleHashChange ( location . hash ) ;
2011-06-21 15:33:38 +00:00
} ) ;
2011-07-07 16:19:16 +00:00
2011-06-21 15:33:38 +00:00
//set page min-heights to be device specific
$ ( document ) . bind ( "pageshow" , resetActivePageHeight ) ;
$ ( window ) . bind ( "throttledresize" , resetActivePageHeight ) ;
2011-07-07 16:19:16 +00:00
} ; //_registerInternalEvents callback
2011-03-31 16:19:05 +00:00
2011-12-16 02:09:25 +00:00
} ) ( jQuery ) ;
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
2011-10-31 05:03:56 +00:00
} ) ;
2011-12-16 02:09:25 +00:00
//>>excludeEnd("jqmBuildExclude");