Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

Commit

Permalink
Toolbar: Back button correctly appears/disappears on external toolbar
Browse files Browse the repository at this point in the history
This commit makes the following modifications:
1. Rename _addBackButton() to _updateBackButton() and move the decision making
   as to whether to add or remove a back button from _setOptions() into
   _updateBackButton().

2. Call _updateBackButton() from refresh() as well. This will cause the back
   button to be updated whenever the page changes, because the "pageshow"
   handler is hooked up to refresh().

3. Modify _addHeaderButtonClasses to not recognize the back button as a left
   button.

4. Modify the preconditions for adding a button to include an alternative to
   checking the page's URL for instances where there is no page present - i.e.
   when the toolbar is external. In such cases one must add a back button if
   the active item on the history stack is not the first item.

(cherry picked from commit b0685b3)

Closes gh-7188
Fixes gh-6950
  • Loading branch information
Gabriel Schulhof committed Jun 6, 2014
1 parent ea0533f commit da816e7
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 22 deletions.
84 changes: 62 additions & 22 deletions js/widgets/toolbar.js
Expand Up @@ -46,15 +46,7 @@ define( [
},
_setOptions: function( o ) {
if ( o.addBackBtn !== undefined ) {
if ( this.options.addBackBtn &&
this.role === "header" &&
$( ".ui-page" ).length > 1 &&
this.page[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) !== $.mobile.path.stripHash( location.hash ) &&
!this.leftbtn ) {
this._addBackButton();
} else {
this.element.find( ".ui-toolbar-back-btn" ).remove();
}
this._updateBackButton();
}
if ( o.backBtnTheme != null ) {
this.element
Expand All @@ -81,6 +73,8 @@ define( [
this._setRelative();
if ( this.role === "footer" ) {
this.element.appendTo( "body" );
} else if ( this.role === "header" ) {
this._updateBackButton();
}
}
this._addHeadingClasses();
Expand All @@ -102,25 +96,71 @@ define( [
},
// Deprecated in 1.4. As from 1.5 ui-btn-left/right classes have to be present in the markup.
_addHeaderButtonClasses: function() {
var $headeranchors = this.element.children( "a, button" );
this.leftbtn = $headeranchors.hasClass( "ui-btn-left" );
this.rightbtn = $headeranchors.hasClass( "ui-btn-right" );
var headerAnchors = this.element.children( "a, button" );

// Do not mistake a back button for a left toolbar button
this.leftbtn = headerAnchors.hasClass( "ui-btn-left" ) &&
!headerAnchors.hasClass( "ui-toolbar-back-btn" );

this.leftbtn = this.leftbtn || $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
this.rightbtn = headerAnchors.hasClass( "ui-btn-right" );

this.rightbtn = this.rightbtn || $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
// Filter out right buttons and back buttons
this.leftbtn = this.leftbtn ||
headerAnchors.eq( 0 )
.not( ".ui-btn-right,.ui-toolbar-back-btn" )
.addClass( "ui-btn-left" )
.length;

this.rightbtn = this.rightbtn || headerAnchors.eq( 1 ).addClass( "ui-btn-right" ).length;
},
_addBackButton: function() {
var options = this.options,
_updateBackButton: function() {
var backButton,
options = this.options,
theme = options.backBtnTheme || options.theme;

$( "<a role='button' href='javascript:void(0);' " +
"class='ui-btn ui-corner-all ui-shadow ui-btn-left " +
( theme ? "ui-btn-" + theme + " " : "" ) +
"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' " +
"data-" + $.mobile.ns + "rel='back'>" + options.backBtnText + "</a>" )
.prependTo( this.element );
// Retrieve the back button or create a new, empty one
backButton = this._backButton = ( this._backButton || {} );

// We add a back button only if the option to do so is on
if ( this.options.addBackBtn &&

// This must also be a header toolbar
this.role === "header" &&

// There must be multiple pages in the DOM
$( ".ui-page" ).length > 1 &&
( this.page ?

// If the toolbar is internal the page's URL must differ from the hash
( this.page[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) !==
$.mobile.path.stripHash( location.hash ) ) :

// Otherwise, if the toolbar is external there must be at least one
// history item to which one can go back
( $.mobile.navigate && $.mobile.navigate.history &&
$.mobile.navigate.history.activeIndex > 0 ) ) &&

// The toolbar does not have a left button
!this.leftbtn ) {

// Skip back button creation if one is already present
if ( !backButton.attached ) {
backButton.element = ( backButton.element ||
$( "<a role='button' href='javascript:void(0);' " +
"class='ui-btn ui-corner-all ui-shadow ui-btn-left " +
( theme ? "ui-btn-" + theme + " " : "" ) +
"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' " +
"data-" + $.mobile.ns + "rel='back'>" + options.backBtnText +
"</a>" ) )
.prependTo( this.element );
backButton.attached = true;
}

// If we are not adding a back button, then remove the one present, if any
} else if ( backButton.element ) {
backButton.element.detach();
backButton.attached = false;
}
},
_addHeadingClasses: function() {
this.element.children( "h1, h2, h3, h4, h5, h6" )
Expand Down
55 changes: 55 additions & 0 deletions tests/integration/toolbar/external-toolbar-tests.html
@@ -0,0 +1,55 @@
<!doctype html>

<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery Mobile Toolbar Test Suite</title>

<script src="../../../external/requirejs/require.js"></script>
<script src="../../../js/requirejs.config.js"></script>
<script src="../../../js/jquery.tag.inserter.js"></script>
<script src="../../jquery.setNameSpace.js"></script>
<script src="../../../tests/jquery.testHelper.js"></script>
<script src="../../../external/qunit/qunit.js"></script>
<script>
$.testHelper.asyncLoad([
[
"widgets/toolbar",
"jquery.mobile.buttonMarkup"
],
[ "jquery.mobile.init" ],
[ "external_toolbar_core.js" ]
]);
</script>

<link rel="stylesheet" href="../../../css/themes/default/jquery.mobile.css"/>
<link rel="stylesheet" href="../../../external/qunit/qunit.css"/>
<link rel="stylesheet" href="../../jqm-tests.css"/>

<script src="../../swarminject.js"></script>
</head>
<body>

<div id="qunit"></div>

<div id="header" data-nstest-role="header" data-nstest-add-back-btn="true">
<h1>Header</h1>
</div>
<div data-nstest-role="page">
<div class="ui-content" role="main">
<a href="#page2" id="go-to-page-2">Go to page 2</a>
</div>
</div>
<div data-nstest-role="page" id="page2">
<div data-nstest-role="content">
<a href="#page3" id="go-to-page-3">Go to page 3</a>
<p>Content</p>
</div>
</div>
<div data-nstest-role="page" id="page3">
<div data-nstest-role="content">
<p>Content</p>
</div>
</div>
</body>
</html>
43 changes: 43 additions & 0 deletions tests/integration/toolbar/external_toolbar_core.js
@@ -0,0 +1,43 @@
asyncTest( "Back button added to external toolbar", function() {
$( "#header" ).toolbar();
$.testHelper.pageSequence([
function() {
$( "#go-to-page-2" ).click();
},
function() {
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 1,
"After navigating to page 2 exactly one back button " +
"appears on the external toolbar" );
$.mobile.back();
},
function() {
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 0,
"After going back from page 2 no back button appears on the external toolbar" );
$( "#go-to-page-2" ).click();
},
function() {
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 1,
"After navigating to page 2 again exactly one back button " +
"appears on the external toolbar" );
$( "#go-to-page-3" ).click();
},
function() {
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 1,
"After navigating to page 3 exactly one back button " +
"appears on the external toolbar" );
$.mobile.back();
},
function() {
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 1,
"After navigating back to page 2 exactly one back button " +
"appears on the external toolbar" );
$.mobile.back();
},
function() {
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 0,
"After navigating back from page 2 no back button " +
"appears on the external toolbar" );
start();
},
]);
});

0 comments on commit da816e7

Please sign in to comment.