From 0d8956cf0c48cc6480d17e84b499f3594b51142e Mon Sep 17 00:00:00 2001
From: scottjehl
Date: Thu, 21 Oct 2010 13:11:46 -0400
Subject: [PATCH 01/13] big refactor of hashchange event handler - moved logic
over to changePage function.
---
js/jquery.mobile.js | 317 ++++++++++++++++++++++++--------------------
1 file changed, 171 insertions(+), 146 deletions(-)
diff --git a/js/jquery.mobile.js b/js/jquery.mobile.js
index 5a23073a511..1899844665b 100644
--- a/js/jquery.mobile.js
+++ b/js/jquery.mobile.js
@@ -46,6 +46,7 @@
$pageContainer,
startPageId = 'ui-page-start',
activePageClass = 'ui-page-active',
+ $activePage,
pageTransition,
forceBack,
transitions = 'slide slideup slidedown pop flip fade',
@@ -56,7 +57,8 @@
transition: "slide"
} ],
focusable = "[tabindex],a,button:visible,select:visible,input",
- nextPageRole = null;
+ nextPageRole = null,
+ preventLoad = false;
// TODO: don't expose (temporary during code reorg)
$.mobile.urlStack = urlStack;
@@ -80,8 +82,10 @@
}, 150 );
}
- function getBaseURL(){
- var newBaseURL = location.hash.replace(/#/,'').split('/');
+ function getBaseURL( nonHashPath ){
+ var newPath = nonHashPath || location.hash,
+ newBaseURL = newPath.replace(/#/,'').split('/');
+
if(newBaseURL.length && /[.|&]/.test(newBaseURL[newBaseURL.length-1]) ){
newBaseURL.pop();
}
@@ -158,174 +162,195 @@
}
}
- // transition between pages - based on transitions from jQtouch
- function changePage( from, to, transition, back ) {
- jQuery( document.activeElement ).blur();
-
-
- //trigger before show/hide events
- from.trigger("pagebeforehide", {nextPage: to});
- to.trigger("pagebeforeshow", {prevPage: from});
-
- function loadComplete(){
- pageLoading( true );
- //trigger show/hide events, allow preventing focus change through return false
- if( from.trigger("pagehide", {nextPage: to}) !== false && to.trigger("pageshow", {prevPage: from}) !== false ){
- reFocus( to );
- }
+ //function for setting role of next page
+ function setPageRole( newPage ) {
+ if ( nextPageRole ) {
+ newPage.attr( "data-role", nextPageRole );
+ nextPageRole = undefined;
}
-
- if(transition){
- // animate in / out
- from.addClass( transition + " out " + ( back ? "reverse" : "" ) );
- to.addClass( activePageClass + " " + transition +
- " in " + ( back ? "reverse" : "" ) );
+ }
+
+ //wrap page and transfer data-attrs if it has an ID
+ function wrapNewPage( newPage ){
+ var copyAttrs = ['data-role', 'data-theme', 'data-fullscreen'], //TODO: more page-level attrs?
+ wrapper = newPage.wrap( "" ).parent();
- // callback - remove classes, etc
- to.animationComplete(function() {
- from.add( to ).removeClass(" out in reverse " + transitions );
- from.removeClass( activePageClass );
- loadComplete();
- });
- }
- else{
- from.removeClass( activePageClass );
- to.addClass( activePageClass );
- loadComplete();
- }
- };
+ $.each(copyAttrs,function(i){
+ if( newPage.attr( copyAttrs[ i ] ) ){
+ wrapper.attr( copyAttrs[ i ], newPage.attr( copyAttrs[ i ] ) );
+ newPage.removeAttr( copyAttrs[ i ] );
+ }
+ });
+ return wrapper;
+ }
- jQuery(function() {
- var preventLoad = false;
- $body = jQuery( "body" );
- pageLoading();
+ //for getting or creating a new page
+ function changePage( to, transition, back ){
+ //if an error occurred, preventLoad will be true
+ if ( preventLoad ) {
+ preventLoad = false;
+ return;
+ }
- // needs to be bound at domready (for IE6)
- // find or load content, make it active
- $window.bind( "hashchange", function(e, extras) {
- if ( preventLoad ) {
- preventLoad = false;
- return;
- }
-
- var url = location.hash.replace( /^#/, "" ),
- stackLength = urlStack.length,
- // pageTransition only exists if the user clicked a link
- back = !pageTransition && stackLength > 1 &&
- urlStack[ stackLength - 2 ].url === url,
- transition = (extras && extras.manuallyTriggered) ? false : pageTransition || "slide",
- fileUrl = url;
- pageTransition = undefined;
+ //from is always the currently viewed page
+ var from = $activePage,
+ url = fileUrl = $.type(to) === "string" ? to.replace( /^#/, "" ) : null,
+ back = forceBack || ( urlStack.length > 1 && urlStack[ urlStack.length - 2 ].url === url ),
+ transition = (transition !== undefined) ? transition : ( pageTransition || "slide" );
+
+ //unset pageTransition, forceBack
+ pageTransition = undefined;
+ forceBack = undefined;
- //reset base to pathname for new request
- resetBaseURL();
+ //reset base to pathname for new request
+ resetBaseURL();
- // if the new href is the same as the previous one
- if ( back ) {
- transition = urlStack.pop().transition;
- } else {
- urlStack.push({ url: url, transition: transition });
- if ( forceBack ) back = true;
- }
- forceBack = undefined;
+ // if the new href is the same as the previous one
+ if ( back ) {
+ transition = urlStack.pop().transition;
+ } else {
+ urlStack.push({ url: url, transition: transition });
+ }
+
+ //function for transitioning between two existing pages
+ function transitionPages() {
+
+ //kill the keyboard
+ jQuery( document.activeElement ).blur();
- //function for setting role of next page
- function setPageRole( newPage ) {
- if ( nextPageRole ) {
- newPage.attr( "data-role", nextPageRole );
- nextPageRole = undefined;
+ //trigger before show/hide events
+ from.trigger("pagebeforehide", {nextPage: to});
+ to.trigger("pagebeforeshow", {prevPage: from});
+
+ function loadComplete(){
+ pageLoading( true );
+ //trigger show/hide events, allow preventing focus change through return false
+ if( from.trigger("pagehide", {nextPage: to}) !== false && to.trigger("pageshow", {prevPage: from}) !== false ){
+ $activePage = to;
+ reFocus( to );
}
}
- //wrap page and transfer data-attrs if it has an ID
- function wrapNewPage( newPage ){
- var copyAttrs = ['data-role', 'data-theme', 'data-fullscreen'], //TODO: more page-level attrs?
- wrapper = newPage.wrap( "
" ).parent();
-
- $.each(copyAttrs,function(i){
- if( newPage.attr( copyAttrs[ i ] ) ){
- wrapper.attr( copyAttrs[ i ], newPage.attr( copyAttrs[ i ] ) );
- newPage.removeAttr( copyAttrs[ i ] );
- }
+ if(transition){
+ // animate in / out
+ from.addClass( transition + " out " + ( back ? "reverse" : "" ) );
+ to.addClass( activePageClass + " " + transition +
+ " in " + ( back ? "reverse" : "" ) );
+
+ // callback - remove classes, etc
+ to.animationComplete(function() {
+ from.add( to ).removeClass(" out in reverse " + transitions );
+ from.removeClass( activePageClass );
+ loadComplete();
});
- return wrapper;
}
+ else{
+ from.removeClass( activePageClass );
+ to.addClass( activePageClass );
+ loadComplete();
+ }
+ };
+
+ //
+ function enhancePage(){
+ setPageRole( to );
+ to.page();
+ }
- if ( url ) {
- var active = jQuery( ".ui-page-active" );
- // see if content is present already
- var localDiv = jQuery( "[id='" + url + "']" );
- if ( localDiv.length ) {
- if ( localDiv.is( "[data-role]" ) ) {
- setPageRole( localDiv );
- }
+ //if url is a string
+ if( url ){
+ to = jQuery( "[id='" + url + "']" );
+ }
+
+ // find the "to" page, either locally existing in the dom or by creating it through ajax
+ if ( to.length ) {
+ setBaseURL();
+ enhancePage();
+ transitionPages();
+ } else {
+
+ pageLoading();
+
+ if ( url.match( '&' + jQuery.mobile.subPageUrlKey ) ) {
+ fileUrl = url.split( '&' + jQuery.mobile.subPageUrlKey )[0];
+ }
+
+ $.ajax({
+ url: fileUrl,
+ success: function( html ) {
setBaseURL();
- localDiv.page();
- changePage( active, localDiv, transition, back );
+ var all = jQuery("
");
+ //workaround to allow scripts to execute when included in page divs
+ all.get(0).innerHTML = html;
+ to = all.find('[data-role="page"]');
- } else { //ajax it in
- pageLoading();
-
- if ( url.match( '&' + jQuery.mobile.subPageUrlKey ) ) {
- fileUrl = url.split( '&' + jQuery.mobile.subPageUrlKey )[0];
+ //preserve ID on a retrieved page
+ if ( to.attr('id') ) {
+ to = wrapNewPage( to );
}
- $.ajax({
- url: fileUrl,
- success: function( html ) {
- var all = jQuery("
");
- //workaround to allow scripts to execute when included in page divs
- all.get(0).innerHTML = html;
- var page = all.find('[data-role="page"]');
+ to
+ .attr( "id", fileUrl )
+ .appendTo( $pageContainer );
+
+ enhancePage();
+ transitionPages();
+ },
+ error: function() {
+ pageLoading( true );
- if ( page.attr('id') ) {
- page = wrapNewPage( page );
- }
+ jQuery("
Error Loading Page
")
+ .css({ "display": "block", "opacity": 0.96 })
+ .appendTo( $pageContainer )
+ .delay( 800 )
+ .fadeOut( 400, function(){
+ $(this).remove();
+ });
- page
- .attr( "id", fileUrl )
- .appendTo( $pageContainer );
+ preventLoad = true;
+ history.back();
+ }
+ });
+ }
- setPageRole( page );
- page.page();
- changePage( active, page, transition, back );
- },
- error: function() {
- pageLoading( true );
+ };
- jQuery("
Error Loading Page
")
- .css({ "display": "block", "opacity": 0.96 })
- .appendTo( $pageContainer )
- .delay( 800 )
- .fadeOut( 400, function(){
- $(this).remove();
- });
+
+ jQuery(function() {
- preventLoad = true;
- history.back();
- }
- });
-
- setBaseURL();
- }
- } else {
- // either we've backed up to the root page url
- // or it's the first page load with no hash present
- var currentPage = jQuery( ".ui-page-active" );
- if ( currentPage.length && !$startPage.is( ".ui-page-active" ) ) {
- changePage( currentPage, $startPage, transition, back );
- } else {
- $startPage.trigger("pagebeforeshow", {prevPage: $('')});
- $startPage.addClass( activePageClass );
- pageLoading( true );
-
- if( $startPage.trigger("pageshow", {prevPage: $('')}) !== false ){
- reFocus($startPage);
- }
+ $body = jQuery( "body" );
+ pageLoading();
+
+ // needs to be bound at domready (for IE6)
+ // find or load content, make it active
+ $window.bind( "hashchange", function(e, extras) {
+ var to = location.hash,
+ transition = (extras && extras.manuallyTriggered) ? false : undefined;
+
+ // either we've backed up to the root page url
+ // or it's the first page load with no hash present
+ //there's a hash and it wasn't manually triggered
+ // > probably a new page, "back" will be figured out by changePage
+ if ( to ){
+ changePage( to, transition);
+ }
+ //there's no hash, the active page is not the start page, and it's not manually triggered hashchange
+ // > probably backed out to the first page visited
+ else if( $activePage.length && !$startPage.is( $activePage ) && !(extras && extras.manuallyTriggered) ) {
+ changePage( $startPage, transition, true );
+ }
+ else{
+ $startPage.trigger("pagebeforeshow", {prevPage: $('')});
+ $startPage.addClass( activePageClass );
+ pageLoading( true );
+
+ if( $startPage.trigger("pageshow", {prevPage: $('')}) !== false ){
+ reFocus($startPage);
}
}
+
});
});
@@ -368,7 +393,7 @@
jQuery(function(){
//set up active page
- $startPage = jQuery('[data-role="page"]:first');
+ $startPage = $activePage = jQuery('[data-role="page"]:first');
//set page container
$pageContainer = $startPage.parent();
From cb13c2f84a2492c8e4448836c0225a8f4d9aeaca Mon Sep 17 00:00:00 2001
From: scottjehl
Date: Thu, 21 Oct 2010 13:12:25 -0400
Subject: [PATCH 02/13] updated to use new changePage function, which no longer
has a "from" arg
---
docs/_assets/js/_viewsource.js | 4 ++--
js/jquery.mobile.dialog.js | 8 ++++++++
js/jquery.mobile.forms.select.js | 4 ++--
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/docs/_assets/js/_viewsource.js b/docs/_assets/js/_viewsource.js
index 38af785cf9f..bb5925e66d3 100644
--- a/docs/_assets/js/_viewsource.js
+++ b/docs/_assets/js/_viewsource.js
@@ -26,9 +26,9 @@ $.fn.addSourceLink = function(style){
var activePage = $(this).parents('.ui-page-active');
page.find('.ui-content').append(codeblock);
- $.changePage(activePage, page, 'slideup',false);
+ $.changePage(page, 'slideup',false);
page.find('.ui-btn-left').click(function(){
- $.changePage(page, activepage, 'slideup',true);
+ $.changePage(activepage, 'slideup',true);
return false;
});
})
diff --git a/js/jquery.mobile.dialog.js b/js/jquery.mobile.dialog.js
index af7a38f34e6..0fad55834d2 100644
--- a/js/jquery.mobile.dialog.js
+++ b/js/jquery.mobile.dialog.js
@@ -13,6 +13,14 @@ $.fn.dialog = function(options){
.addClass('ui-page ui-dialog ui-body-a')
.find('[data-role=header]')
.addClass('ui-corner-top ui-overlay-shadow')
+ .find('.ui-btn-left').tap(function(){
+ $.changePage()
+ return false;
+ })
+ .click(function(){
+ return false;
+ })
+ .end()
.end()
.find('.ui-content,[data-role=footer]')
.last()
diff --git a/js/jquery.mobile.forms.select.js b/js/jquery.mobile.forms.select.js
index 5d832f4bf2f..4761ec22096 100644
--- a/js/jquery.mobile.forms.select.js
+++ b/js/jquery.mobile.forms.select.js
@@ -95,7 +95,7 @@ $.fn.customSelect = function(options){
if( menuHeight > window.innerHeight - 80 || !$.support.scrollTop ){
menuType = "page";
menuPageContent.append( list );
- $.changePage(thisPage, menuPage, false, false);
+ $.changePage(menuPage, false, false);
}
else {
menuType = "overlay";
@@ -119,7 +119,7 @@ $.fn.customSelect = function(options){
function hidemenu(){
if(menuType == "page"){
- $.changePage(menuPage, thisPage, false, true);
+ $.changePage(thisPage, false, true);
}
else{
screen.addClass( "ui-screen-hidden" );
From b8cf201a88e129db898a400a8cdc85c0b7111d73 Mon Sep 17 00:00:00 2001
From: scottjehl
Date: Thu, 21 Oct 2010 13:16:48 -0400
Subject: [PATCH 03/13] ajaxClick only updates the hash if the clicked element
doesn't match the new unHashedSelectors var. So far, this only includes
[data-rel=dialog]
---
js/jquery.mobile.js | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/js/jquery.mobile.js b/js/jquery.mobile.js
index 1899844665b..5ff0707be9c 100644
--- a/js/jquery.mobile.js
+++ b/js/jquery.mobile.js
@@ -58,7 +58,8 @@
} ],
focusable = "[tabindex],a,button:visible,select:visible,input",
nextPageRole = null,
- preventLoad = false;
+ preventLoad = false,
+ unHashedSelectors = '[data-rel=dialog]';
// TODO: don't expose (temporary during code reorg)
$.mobile.urlStack = urlStack;
@@ -129,8 +130,13 @@
location = href
}
else{
- // let the hashchange event handler take care of requesting the page via ajax
- location.hash = href;
+ changePage(href, pageTransition);
+
+ if( !$(this).is(unHashedSelectors) ){
+ // let the hashchange event handler take care of requesting the page via ajax
+ location.hash = href;
+ }
+
}
return this;
};
From 06e6ceb519aabf0944c1f584d284a118c2f76cd8 Mon Sep 17 00:00:00 2001
From: scottjehl
Date: Thu, 21 Oct 2010 14:04:47 -0400
Subject: [PATCH 04/13] moved $activePage to $.activePage, so it's exposed for
external plugins
---
js/jquery.mobile.js | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/js/jquery.mobile.js b/js/jquery.mobile.js
index 5ff0707be9c..eba1fa164cc 100644
--- a/js/jquery.mobile.js
+++ b/js/jquery.mobile.js
@@ -46,7 +46,6 @@
$pageContainer,
startPageId = 'ui-page-start',
activePageClass = 'ui-page-active',
- $activePage,
pageTransition,
forceBack,
transitions = 'slide slideup slidedown pop flip fade',
@@ -200,7 +199,7 @@
}
//from is always the currently viewed page
- var from = $activePage,
+ var from = $.activePage,
url = fileUrl = $.type(to) === "string" ? to.replace( /^#/, "" ) : null,
back = forceBack || ( urlStack.length > 1 && urlStack[ urlStack.length - 2 ].url === url ),
transition = (transition !== undefined) ? transition : ( pageTransition || "slide" );
@@ -233,7 +232,7 @@
pageLoading( true );
//trigger show/hide events, allow preventing focus change through return false
if( from.trigger("pagehide", {nextPage: to}) !== false && to.trigger("pageshow", {prevPage: from}) !== false ){
- $activePage = to;
+ $.activePage = to;
reFocus( to );
}
}
@@ -344,7 +343,7 @@
}
//there's no hash, the active page is not the start page, and it's not manually triggered hashchange
// > probably backed out to the first page visited
- else if( $activePage.length && !$startPage.is( $activePage ) && !(extras && extras.manuallyTriggered) ) {
+ else if( $.activePage.length && !$startPage.is( $.activePage ) && !(extras && extras.manuallyTriggered) ) {
changePage( $startPage, transition, true );
}
else{
@@ -399,7 +398,7 @@
jQuery(function(){
//set up active page
- $startPage = $activePage = jQuery('[data-role="page"]:first');
+ $startPage = $.activePage = jQuery('[data-role="page"]:first');
//set page container
$pageContainer = $startPage.parent();
From 6f90c3aa176864a2b32daa250d3d393a38ec05aa Mon Sep 17 00:00:00 2001
From: scottjehl
Date: Thu, 21 Oct 2010 15:59:44 -0400
Subject: [PATCH 05/13] changed to use click event.
---
js/jquery.mobile.page.js | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/js/jquery.mobile.page.js b/js/jquery.mobile.page.js
index 15ef708fd7e..cfe335d80e2 100644
--- a/js/jquery.mobile.page.js
+++ b/js/jquery.mobile.page.js
@@ -52,11 +52,8 @@ $.widget( "mobile.page", $.mobile.widget, {
//auto-add back btn on pages beyond first view
if ( $.mobile.addBackBtn && role === "header" && ($.mobile.urlStack.length > 1 || $('.ui-page').length > 1) && !leftbtn && !$this.data( "noBackBtn" ) ) {
$( "Back" )
- .tap(function() {
- history.back();
- return false;
- })
.click(function() {
+ history.back();
return false;
})
.prependTo( $this );
From 5ad3d040848dac91ab84486ea56b87ebe77bc5ce Mon Sep 17 00:00:00 2001
From: scottjehl
Date: Thu, 21 Oct 2010 16:28:17 -0400
Subject: [PATCH 06/13] several changes that allow for changing pages without
hash changes: - allowed prevention of hash listening during a particular hash
change - allowed $.activePage to remain set on previous page when an
untracked page is open (return pageshow event false to use this feature) -
moved setting and resetting to base urls and made sure they update at the
right moment for both new pages and those previously visited. - changePage
now accepts an array as first argument, allowing you to specify both
[from,to] pages, whereas non-array types would refer to the "to" page,
assuming "from" should be the currently viewed page - error requests never
generate a hash change now - edited the ajax error to appear in the right
location when scrolled
Essentially, plugins can now create page changes that are not tracked in history, which is a dialog critical bug.
---
js/jquery.mobile.js | 83 ++++++++++++++++++++++++++-------------------
1 file changed, 48 insertions(+), 35 deletions(-)
diff --git a/js/jquery.mobile.js b/js/jquery.mobile.js
index eba1fa164cc..0cf73e963e9 100644
--- a/js/jquery.mobile.js
+++ b/js/jquery.mobile.js
@@ -57,7 +57,7 @@
} ],
focusable = "[tabindex],a,button:visible,select:visible,input",
nextPageRole = null,
- preventLoad = false,
+ hashListener = true,
unHashedSelectors = '[data-rel=dialog]';
// TODO: don't expose (temporary during code reorg)
@@ -94,9 +94,9 @@
return newBaseURL;
}
- function setBaseURL(){
+ function setBaseURL( nonHashPath ){
//set base url for new page assets
- $('#ui-base').attr('href', getBaseURL());
+ $('#ui-base').attr('href', getBaseURL( nonHashPath ));
}
function resetBaseURL(){
@@ -128,12 +128,12 @@
if ( ( /^[^#]/.test(href) && !jQuery.support.ajax ) || ( /https?:\/\//.test(href) && !!!href.match(location.hostname) ) ) {
location = href
}
- else{
- changePage(href, pageTransition);
-
- if( !$(this).is(unHashedSelectors) ){
- // let the hashchange event handler take care of requesting the page via ajax
- location.hash = href;
+ else{
+ if( $(this).is(unHashedSelectors) ){
+ changePage(href, pageTransition, undefined);
+ }
+ else{
+ changePage(href, pageTransition, undefined, true);
}
}
@@ -191,17 +191,14 @@
//for getting or creating a new page
- function changePage( to, transition, back ){
- //if an error occurred, preventLoad will be true
- if ( preventLoad ) {
- preventLoad = false;
- return;
- }
-
+ function changePage( to, transition, back, changeHash){
+
//from is always the currently viewed page
- var from = $.activePage,
+ var toIsArray = $.type(to) === "array",
+ from = toIsArray ? to[0] : $.activePage,
+ to = toIsArray ? to[1] : to,
url = fileUrl = $.type(to) === "string" ? to.replace( /^#/, "" ) : null,
- back = forceBack || ( urlStack.length > 1 && urlStack[ urlStack.length - 2 ].url === url ),
+ back = (back !== undefined) ? back : (forceBack || ( urlStack.length > 1 && urlStack[ urlStack.length - 2 ].url === url )),
transition = (transition !== undefined) ? transition : ( pageTransition || "slide" );
//unset pageTransition, forceBack
@@ -225,15 +222,22 @@
jQuery( document.activeElement ).blur();
//trigger before show/hide events
- from.trigger("pagebeforehide", {nextPage: to});
- to.trigger("pagebeforeshow", {prevPage: from});
+ from.data("page")._trigger("beforehide", {nextPage: to});
+ to.data("page")._trigger("beforeshow", {prevPage: from});
function loadComplete(){
pageLoading( true );
//trigger show/hide events, allow preventing focus change through return false
- if( from.trigger("pagehide", {nextPage: to}) !== false && to.trigger("pageshow", {prevPage: from}) !== false ){
+ if( from.data("page")._trigger("hide", null, {nextPage: to}) !== false && to.data("page")._trigger("show", null, {prevPage: from}) !== false ){
$.activePage = to;
- reFocus( to );
+ }
+ reFocus( to );
+ if( changeHash && url ){
+ hashListener = false;
+ location.hash = url;
+ setTimeout(function(){
+ hashListener = true;
+ }, 500);
}
}
@@ -257,35 +261,46 @@
}
};
- //
+ //shared page enhancements
function enhancePage(){
setPageRole( to );
to.page();
}
-
+
+ //get the actual file in a jq-mobile nested url
+ function getFileURL( url ){
+ return url.match( '&' + jQuery.mobile.subPageUrlKey ) ? url.split( '&' + jQuery.mobile.subPageUrlKey )[0] : url;
+ }
//if url is a string
if( url ){
- to = jQuery( "[id='" + url + "']" );
+ to = jQuery( "[id='" + url + "']" ),
+ fileUrl = getFileURL(url);
+ }
+ else{ //find base url of element, if avail
+ var toID = to.attr('id'),
+ toIDfileurl = getFileURL(toID);
+
+ if(toID != toIDfileurl){
+ fileUrl = toIDfileurl;
+ }
}
// find the "to" page, either locally existing in the dom or by creating it through ajax
if ( to.length ) {
- setBaseURL();
+ if( fileUrl ){
+ setBaseURL(fileUrl);
+ }
enhancePage();
transitionPages();
} else {
pageLoading();
- if ( url.match( '&' + jQuery.mobile.subPageUrlKey ) ) {
- fileUrl = url.split( '&' + jQuery.mobile.subPageUrlKey )[0];
- }
-
$.ajax({
url: fileUrl,
success: function( html ) {
- setBaseURL();
+ setBaseURL(fileUrl);
var all = jQuery("");
//workaround to allow scripts to execute when included in page divs
all.get(0).innerHTML = html;
@@ -307,15 +322,12 @@
pageLoading( true );
jQuery("Error Loading Page
")
- .css({ "display": "block", "opacity": 0.96 })
+ .css({ "display": "block", "opacity": 0.96, "top": $(window).scrollTop() + 100 })
.appendTo( $pageContainer )
.delay( 800 )
.fadeOut( 400, function(){
$(this).remove();
});
-
- preventLoad = true;
- history.back();
}
});
}
@@ -331,6 +343,7 @@
// needs to be bound at domready (for IE6)
// find or load content, make it active
$window.bind( "hashchange", function(e, extras) {
+ if( !hashListener ){ return; }
var to = location.hash,
transition = (extras && extras.manuallyTriggered) ? false : undefined;
From ef3fd116dca8be147bac6057ff84e21895c25380 Mon Sep 17 00:00:00 2001
From: scottjehl
Date: Thu, 21 Oct 2010 16:29:05 -0400
Subject: [PATCH 07/13] refactored to use widget factory and not be tracked via
hash/history. Fixes #176
---
js/jquery.mobile.dialog.js | 35 ++++++++++++++++++++---------------
1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/js/jquery.mobile.dialog.js b/js/jquery.mobile.dialog.js
index 0fad55834d2..2e0c266f244 100644
--- a/js/jquery.mobile.dialog.js
+++ b/js/jquery.mobile.dialog.js
@@ -4,27 +4,32 @@
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
* Note: Code is in draft form and is subject to change
*/
-(function($){
-$.fn.dialog = function(options){
- return $(this).each(function(){
- $(this)
+(function ( $ ) {
+$.widget( "mobile.dialog", $.mobile.widget, {
+ options: {},
+ _create: function(){
+ var $el = this.element,
+ $closeBtn = $('Close')
+ .click(function(){
+ $.changePage([$el, $.activePage], undefined, true );
+ return false;
+ });
+
+ this.element
+ .bind("pageshow",function(){
+ return false;
+ })
//add ARIA role
.attr("role","dialog")
.addClass('ui-page ui-dialog ui-body-a')
.find('[data-role=header]')
.addClass('ui-corner-top ui-overlay-shadow')
- .find('.ui-btn-left').tap(function(){
- $.changePage()
- return false;
- })
- .click(function(){
- return false;
- })
- .end()
+ .prepend( $closeBtn )
.end()
.find('.ui-content,[data-role=footer]')
.last()
.addClass('ui-corner-bottom ui-overlay-shadow');
- });
-};
-})(jQuery);
\ No newline at end of file
+
+ }
+});
+})( jQuery );
\ No newline at end of file
From 21a7b0a2baca47d79093e13a53601f7243b4cbe3 Mon Sep 17 00:00:00 2001
From: scottjehl
Date: Thu, 21 Oct 2010 17:02:59 -0400
Subject: [PATCH 08/13] updated to reflect new changes in pageChange function
and dialog behavior
---
js/jquery.mobile.forms.select.js | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/js/jquery.mobile.forms.select.js b/js/jquery.mobile.forms.select.js
index 4761ec22096..10249d061a4 100644
--- a/js/jquery.mobile.forms.select.js
+++ b/js/jquery.mobile.forms.select.js
@@ -16,7 +16,6 @@ $.fn.customSelect = function(options){
//extendable options
o = $.extend({
- closeText: "close",
chooseText: label.text(),
theme: select.data("theme")
}, options),
@@ -43,7 +42,6 @@ $.fn.customSelect = function(options){
}),
menuPage = $( "" +
"
"+
"
"+
@@ -95,7 +93,7 @@ $.fn.customSelect = function(options){
if( menuHeight > window.innerHeight - 80 || !$.support.scrollTop ){
menuType = "page";
menuPageContent.append( list );
- $.changePage(menuPage, false, false);
+ $.changePage(menuPage, undefined);
}
else {
menuType = "overlay";
@@ -119,7 +117,7 @@ $.fn.customSelect = function(options){
function hidemenu(){
if(menuType == "page"){
- $.changePage(thisPage, false, true);
+ $.changePage([menuPage,thisPage], undefined, true);
}
else{
screen.addClass( "ui-screen-hidden" );
@@ -189,12 +187,6 @@ $.fn.customSelect = function(options){
hidemenu();
return false;
});
-
- //menu page back button
- menuPage.find( ".ui-btn-left" ).click(function(){
- hidemenu();
- return false;
- });
//hide on outside click
screen.click(function(){
From f91b2523ff176044caa531cb7a323e6bd728a5a0 Mon Sep 17 00:00:00 2001
From: John Resig
Date: Thu, 21 Oct 2010 17:18:59 -0400
Subject: [PATCH 09/13] Merge clickable into buttonMarkup. Improve performance
of the Button Markup plugin.
---
Makefile | 1 -
js/jquery.mobile.buttonMarkup.js | 107 +++++++++++++++++--------------
js/jquery.mobile.clickable.js | 28 --------
js/jquery.mobile.listview.js | 9 ++-
js/manifest.php | 1 -
5 files changed, 63 insertions(+), 83 deletions(-)
delete mode 100644 js/jquery.mobile.clickable.js
diff --git a/Makefile b/Makefile
index db9bb0674ae..a693ac13426 100755
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,6 @@ FILES = js/jquery.ui.widget.js \
js/jquery.mobile.event.js \
js/jquery.mobile.hashchange.js \
js/jquery.mobile.page.js \
- js/jquery.mobile.clickable.js \
js/jquery.mobile.fixHeaderFooter.js \
js/jquery.mobile.forms.checkboxradio.js \
js/jquery.mobile.forms.textinput.js \
diff --git a/js/jquery.mobile.buttonMarkup.js b/js/jquery.mobile.buttonMarkup.js
index 69fffcc08a9..98976f6e7fe 100644
--- a/js/jquery.mobile.buttonMarkup.js
+++ b/js/jquery.mobile.buttonMarkup.js
@@ -4,91 +4,102 @@
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
* Note: Code is in draft form and is subject to change
*/
-(function($){
+(function( jQuery ) {
-$.fn.buttonMarkup = function( options ){
+jQuery.fn.buttonMarkup = function( options ){
return this.each( function() {
- var el = $( this ),
- o = $.extend( {}, {
- theme: (function(){
- //if data-theme attr is present
- if(el.is('[data-theme]')){
- return el.attr('data-theme');
- }
- //if not, try to find closest theme container
- else if( el.parents('body').length ) {
- var themedParent = el.closest('[class*=ui-bar-],[class*=ui-body-]');
- return themedParent.length ? themedParent.attr('class').match(/ui-(bar|body)-([a-z])/)[2] : 'c';
- }
- else{
- return 'c';
- }
- })(),
- iconpos: el.data('iconpos'),
- icon: el.data('icon'),
- inline: el.data('inline')
- }, $.fn.buttonMarkup.defaults, options),
+ var el = jQuery( this ),
+ o = jQuery.extend( {}, jQuery.fn.buttonMarkup.defaults, el.data(), options),
// Classes Defined
buttonClass = "ui-btn ui-btn-up-" + o.theme,
innerClass = "ui-btn-inner",
iconClass;
+
+ if ( attachEvents ) {
+ attachEvents();
+ }
+
+ // if not, try to find closest theme container
+ if ( !o.theme ) {
+ var themedParent = el.closest("[class*='ui-bar-'],[class*='ui-body-']");
+ return themedParent.length ?
+ /ui-(bar|body)-([a-z])/.exec( themedParent.attr("class") )[2] :
+ "c";
+ }
- if( o.inline ){
+ if ( o.inline ) {
buttonClass += " ui-btn-inline";
}
- if (o.icon) {
- o.icon = 'ui-icon-' + o.icon;
+ if ( o.icon ) {
+ o.icon = "ui-icon-" + o.icon;
+ o.iconpos = o.iconpos || "left";
iconClass = "ui-icon " + o.icon;
- if (o.shadow) { iconClass += " ui-icon-shadow" }
- o.iconpos = o.iconpos || 'left';
+ if ( o.shadow ) {
+ iconClass += " ui-icon-shadow"
+ }
}
- if (o.iconpos){
+ if ( o.iconpos ) {
buttonClass += " ui-btn-icon-" + o.iconpos;
- if( o.iconpos == 'notext' && !el.attr('title') ){
- el.attr('title', el.text() );
+ if ( o.iconpos == "notext" && !el.attr("title") ) {
+ el.attr( "title", el.text() );
}
-
}
-
-
-
- if (o.corners) {
+ if ( o.corners ) {
buttonClass += " ui-btn-corner-all";
innerClass += " ui-btn-corner-all";
}
- if (o.shadow) {
+ if ( o.shadow ) {
buttonClass += " ui-shadow";
}
el
- .attr( 'data-theme', o.theme )
- .addClass( buttonClass )
- .wrapInner( $( '<' + o.wrapperEls + '>', { className: "ui-btn-text" } ) );
-
- if (o.icon) {
- el.prepend( $( '', { className: iconClass } ) );
- }
+ .attr( "data-theme", o.theme )
+ .addClass( buttonClass );
- el.wrapInner( $('<' + o.wrapperEls + '>', { className: innerClass }) );
+ var wrap = ("" +
+ ( o.icon ? "" : "" ) +
+ "").replace(/D/g, o.wrapperEls);
- el.clickable();
+ el.wrapInner( wrap );
});
};
-$.fn.buttonMarkup.defaults = {
+jQuery.fn.buttonMarkup.defaults = {
corners: true,
shadow: true,
iconshadow: true,
- wrapperEls: 'span'
+ wrapperEls: "span"
};
-})(jQuery);
+var attachEvents = function() {
+ jQuery(".ui-btn").live({
+ mousedown: function() {
+ var theme = jQuery(this).attr( "data-theme" );
+ jQuery(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-down-" + theme );
+ },
+ mouseup: function() {
+ var theme = jQuery(this).attr( "data-theme" );
+ jQuery(this).removeClass( "ui-btn-down-" + theme ).addClass( "ui-btn-up-" + theme );
+ },
+ "mouseover focus": function() {
+ var theme = jQuery(this).attr( "data-theme" );
+ jQuery(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-hover-" + theme );
+ },
+ "mouseout blur": function() {
+ var theme = jQuery(this).attr( "data-theme" );
+ jQuery(this).removeClass( "ui-btn-hover-" + theme ).addClass( "ui-btn-up-" + theme );
+ }
+ });
+
+ attachEvents = null;
+}
+})(jQuery);
diff --git a/js/jquery.mobile.clickable.js b/js/jquery.mobile.clickable.js
deleted file mode 100644
index e66a36edf9a..00000000000
--- a/js/jquery.mobile.clickable.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-* jQuery Mobile Framework : sample scripting for manipulating themed interaction states
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
-* Note: Code is in draft form and is subject to change
-*/
-(function($){
-$.fn.clickable = function(){
- return $(this).each(function(){
- var theme = $(this).attr('data-theme');
- $(this)
- .mousedown(function(){
- $(this).removeClass('ui-btn-up-'+theme).addClass('ui-btn-down-'+theme);
- })
- .mouseup(function(){
- $(this).removeClass('ui-btn-down-'+theme).addClass('ui-btn-up-'+theme);
- })
- .bind('mouseover focus',function(){
- $(this).removeClass('ui-btn-up-'+theme).addClass('ui-btn-hover-'+theme);
- })
- .bind('mouseout blur',function(){
- $(this).removeClass('ui-btn-hover-'+theme).addClass('ui-btn-up-'+theme);
- });
- });
-};
-})(jQuery);
-
-
diff --git a/js/jquery.mobile.listview.js b/js/jquery.mobile.listview.js
index 58f0b5e648e..a6d26a4e956 100644
--- a/js/jquery.mobile.listview.js
+++ b/js/jquery.mobile.listview.js
@@ -27,7 +27,7 @@ $.widget( "mobile.listview", $.mobile.widget, {
this.element.addClass( "ui-listview-inset ui-corner-all ui-shadow" );
}
- this.element.delegate("ui-li", "focusin", function() {
+ this.element.delegate(".ui-li", "focusin", function() {
jQuery(this).attr( "tabindex", "0" );
});
@@ -126,10 +126,7 @@ $.widget( "mobile.listview", $.mobile.widget, {
$list.find( ".ui-li-dec" ).remove();
}
- li
- .addClass( "ui-li" )
- .attr( "role", "option" )
- .attr( "tabindex", "-1" )
+ li.attr({ "role": "option", "tabindex": "-1" });
li.first().attr( "tabindex", "0" );
@@ -141,6 +138,8 @@ $.widget( "mobile.listview", $.mobile.widget, {
return;
}
+ item.addClass( "ui-li" );
+
var a = item.find( "a" );
if ( a.length ) {
diff --git a/js/manifest.php b/js/manifest.php
index a8440c98907..a5f8a182132 100644
--- a/js/manifest.php
+++ b/js/manifest.php
@@ -7,7 +7,6 @@
'jquery.mobile.event.js',
'jquery.mobile.hashchange.js',
'jquery.mobile.page.js',
- 'jquery.mobile.clickable.js',
'jquery.mobile.fixHeaderFooter.js',
'jquery.mobile.forms.checkboxradio.js',
'jquery.mobile.forms.textinput.js',
From c7003aac9593b83eaa5aa15412d13ff4e630b98b Mon Sep 17 00:00:00 2001
From: Jeffrey Way
Date: Thu, 21 Oct 2010 18:06:08 -0400
Subject: [PATCH 10/13] Querystrings containing "http" in the middle will
incorrectly load synchronously
---
js/jquery.mobile.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/js/jquery.mobile.js b/js/jquery.mobile.js
index 6b9ad04ce48..4592236a12e 100644
--- a/js/jquery.mobile.js
+++ b/js/jquery.mobile.js
@@ -115,17 +115,17 @@
var newBaseURL = getBaseURL();
//if href is absolute but local, or a local ID, no base needed
- if( /^\//.test(href) || (/https?:\/\//.test(href) && !!(href).match(location.hostname)) || /^#/.test(href) ){
+ if( /^\//.test(href) || (/^https?:\/\//.test(href) && !!(href).match(location.hostname)) || /^#/.test(href) ){
newBaseURL = '';
}
// set href to relative path using baseURL and
- if( !/https?:\/\//.test(href) ){
+ if( !/^https?:\/\//.test(href) ){
href = newBaseURL + href;
}
//if it's a non-local-anchor and Ajax is not supported, or if it's an external link, go to page without ajax
- if ( ( /^[^#]/.test(href) && !jQuery.support.ajax ) || ( /https?:\/\//.test(href) && !!!href.match(location.hostname) ) ) {
+ if ( ( /^[^#]/.test(href) && !jQuery.support.ajax ) || ( /^https?:\/\//.test(href) && !!!href.match(location.hostname) ) ) {
location = href
}
else{
From 562126cae2b2cf7c9e3e5e6f213a04a35a0b6122 Mon Sep 17 00:00:00 2001
From: Jeffrey Way
Date: Sat, 23 Oct 2010 02:15:23 -0400
Subject: [PATCH 11/13] Rewrote ajaxClick method to clean-up and use less
regexes
---
js/jquery.mobile.js | 56 ++++++++++++++++++++++-----------------------
1 file changed, 27 insertions(+), 29 deletions(-)
diff --git a/js/jquery.mobile.js b/js/jquery.mobile.js
index 4592236a12e..447a6c3adf2 100644
--- a/js/jquery.mobile.js
+++ b/js/jquery.mobile.js
@@ -106,38 +106,36 @@
// send a link through hash tracking
jQuery.fn.ajaxClick = function() {
- var href = jQuery( this ).attr( "href" );
- pageTransition = jQuery( this ).data( "transition" ) || "slide";
- forceBack = jQuery( this ).data( "back" ) || undefined;
- nextPageRole = jQuery( this ).attr( "data-rel" );
-
- //find new base for url building
- var newBaseURL = getBaseURL();
-
- //if href is absolute but local, or a local ID, no base needed
- if( /^\//.test(href) || (/^https?:\/\//.test(href) && !!(href).match(location.hostname)) || /^#/.test(href) ){
- newBaseURL = '';
- }
-
- // set href to relative path using baseURL and
- if( !/^https?:\/\//.test(href) ){
- href = newBaseURL + href;
- }
-
- //if it's a non-local-anchor and Ajax is not supported, or if it's an external link, go to page without ajax
- if ( ( /^[^#]/.test(href) && !jQuery.support.ajax ) || ( /^https?:\/\//.test(href) && !!!href.match(location.hostname) ) ) {
- location = href
- }
- else{
- if( $(this).is(unHashedSelectors) ){
+ var $this = jQuery( this ),
+ href = $this.attr( "href" ),
+ // If href begins with a slash or hash, or it doesn't contain http, or the hostname is within the href, must be local.
+ isLocal = ( /^(\/|#)/.test(href) ) || ( href.indexOf('http') === -1 ) || ( href.indexOf(location.hostname) > -1 ),
+ //find new base for url building
+ newBaseURL = getBaseURL();
+
+ pageTransition = $this.data( "transition" ) || "slide";
+ forceBack = $this.data( "back" ) || undefined;
+ nextPageRole = $this.attr( "data-rel" );
+
+ //if href is absolute but local, no base needed
+ if ( isLocal && href.indexOf('http') > -1 ) {
+ newBaseURL = '';
+ } else {
+ // set href to relative path using baseURL
+ href = newBaseURL + href;
+ }
+
+ //if it's a non-local-anchor and Ajax is not supported, go to page without ajax
+ if ( !isLocal || !jQuery.support.ajax ) {
+ location = href;
+ } else {
+ if( $this.is(unHashedSelectors) ) {
changePage(href, pageTransition, undefined);
- }
- else{
+ } else {
changePage(href, pageTransition, undefined, true);
}
-
- }
- return this;
+ }
+ return this;
};
// ajaxify all navigable links
From 7d0a069ed08375abfdd8afff959ef6cb5b650eb5 Mon Sep 17 00:00:00 2001
From: Jeffrey Way
Date: Fri, 22 Oct 2010 23:47:36 -0700
Subject: [PATCH 12/13] Added fix for hrefs which direct to parent directories,
with ../
---
js/jquery.mobile.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/js/jquery.mobile.js b/js/jquery.mobile.js
index 447a6c3adf2..e67bf1bd7ea 100644
--- a/js/jquery.mobile.js
+++ b/js/jquery.mobile.js
@@ -108,8 +108,8 @@
jQuery.fn.ajaxClick = function() {
var $this = jQuery( this ),
href = $this.attr( "href" ),
- // If href begins with a slash or hash, or it doesn't contain http, or the hostname is within the href, must be local.
- isLocal = ( /^(\/|#)/.test(href) ) || ( href.indexOf('http') === -1 ) || ( href.indexOf(location.hostname) > -1 ),
+ // If href doesn't contain "http", or it begins with a slash, hash, or period, or the hostname is within the href... must be local.
+ isLocal = ( href.indexOf('http') === -1 ) || ( /^(\/|\.|#)/.test(href) ) || ( href.indexOf(location.hostname) > -1 ),
//find new base for url building
newBaseURL = getBaseURL();
From 7b613ca85e2a005931faaf75c8193d4cf51dc6c7 Mon Sep 17 00:00:00 2001
From: Jeffrey Way
Date: Sat, 23 Oct 2010 12:38:51 -0700
Subject: [PATCH 13/13] Updated `isLocal` variable to be more precise.
---
js/jquery.mobile.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/jquery.mobile.js b/js/jquery.mobile.js
index e67bf1bd7ea..a324f57f35d 100644
--- a/js/jquery.mobile.js
+++ b/js/jquery.mobile.js
@@ -109,7 +109,7 @@
var $this = jQuery( this ),
href = $this.attr( "href" ),
// If href doesn't contain "http", or it begins with a slash, hash, or period, or the hostname is within the href... must be local.
- isLocal = ( href.indexOf('http') === -1 ) || ( /^(\/|\.|#)/.test(href) ) || ( href.indexOf(location.hostname) > -1 ),
+ isLocal = ( !/^(http)/.test(href) ) || ( href.indexOf(location.hostname) > -1 ),
//find new base for url building
newBaseURL = getBaseURL();