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

Commit da816e7

Browse files
author
Gabriel Schulhof
committed
Toolbar: Back button correctly appears/disappears on external toolbar
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
1 parent ea0533f commit da816e7

File tree

3 files changed

+160
-22
lines changed

3 files changed

+160
-22
lines changed

js/widgets/toolbar.js

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,7 @@ define( [
4646
},
4747
_setOptions: function( o ) {
4848
if ( o.addBackBtn !== undefined ) {
49-
if ( this.options.addBackBtn &&
50-
this.role === "header" &&
51-
$( ".ui-page" ).length > 1 &&
52-
this.page[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) !== $.mobile.path.stripHash( location.hash ) &&
53-
!this.leftbtn ) {
54-
this._addBackButton();
55-
} else {
56-
this.element.find( ".ui-toolbar-back-btn" ).remove();
57-
}
49+
this._updateBackButton();
5850
}
5951
if ( o.backBtnTheme != null ) {
6052
this.element
@@ -81,6 +73,8 @@ define( [
8173
this._setRelative();
8274
if ( this.role === "footer" ) {
8375
this.element.appendTo( "body" );
76+
} else if ( this.role === "header" ) {
77+
this._updateBackButton();
8478
}
8579
}
8680
this._addHeadingClasses();
@@ -102,25 +96,71 @@ define( [
10296
},
10397
// Deprecated in 1.4. As from 1.5 ui-btn-left/right classes have to be present in the markup.
10498
_addHeaderButtonClasses: function() {
105-
var $headeranchors = this.element.children( "a, button" );
106-
this.leftbtn = $headeranchors.hasClass( "ui-btn-left" );
107-
this.rightbtn = $headeranchors.hasClass( "ui-btn-right" );
99+
var headerAnchors = this.element.children( "a, button" );
100+
101+
// Do not mistake a back button for a left toolbar button
102+
this.leftbtn = headerAnchors.hasClass( "ui-btn-left" ) &&
103+
!headerAnchors.hasClass( "ui-toolbar-back-btn" );
108104

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

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

114+
this.rightbtn = this.rightbtn || headerAnchors.eq( 1 ).addClass( "ui-btn-right" ).length;
113115
},
114-
_addBackButton: function() {
115-
var options = this.options,
116+
_updateBackButton: function() {
117+
var backButton,
118+
options = this.options,
116119
theme = options.backBtnTheme || options.theme;
117120

118-
$( "<a role='button' href='javascript:void(0);' " +
119-
"class='ui-btn ui-corner-all ui-shadow ui-btn-left " +
120-
( theme ? "ui-btn-" + theme + " " : "" ) +
121-
"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' " +
122-
"data-" + $.mobile.ns + "rel='back'>" + options.backBtnText + "</a>" )
123-
.prependTo( this.element );
121+
// Retrieve the back button or create a new, empty one
122+
backButton = this._backButton = ( this._backButton || {} );
123+
124+
// We add a back button only if the option to do so is on
125+
if ( this.options.addBackBtn &&
126+
127+
// This must also be a header toolbar
128+
this.role === "header" &&
129+
130+
// There must be multiple pages in the DOM
131+
$( ".ui-page" ).length > 1 &&
132+
( this.page ?
133+
134+
// If the toolbar is internal the page's URL must differ from the hash
135+
( this.page[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) !==
136+
$.mobile.path.stripHash( location.hash ) ) :
137+
138+
// Otherwise, if the toolbar is external there must be at least one
139+
// history item to which one can go back
140+
( $.mobile.navigate && $.mobile.navigate.history &&
141+
$.mobile.navigate.history.activeIndex > 0 ) ) &&
142+
143+
// The toolbar does not have a left button
144+
!this.leftbtn ) {
145+
146+
// Skip back button creation if one is already present
147+
if ( !backButton.attached ) {
148+
backButton.element = ( backButton.element ||
149+
$( "<a role='button' href='javascript:void(0);' " +
150+
"class='ui-btn ui-corner-all ui-shadow ui-btn-left " +
151+
( theme ? "ui-btn-" + theme + " " : "" ) +
152+
"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' " +
153+
"data-" + $.mobile.ns + "rel='back'>" + options.backBtnText +
154+
"</a>" ) )
155+
.prependTo( this.element );
156+
backButton.attached = true;
157+
}
158+
159+
// If we are not adding a back button, then remove the one present, if any
160+
} else if ( backButton.element ) {
161+
backButton.element.detach();
162+
backButton.attached = false;
163+
}
124164
},
125165
_addHeadingClasses: function() {
126166
this.element.children( "h1, h2, h3, h4, h5, h6" )
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<!doctype html>
2+
3+
<html lang="en">
4+
<head>
5+
<meta charset="UTF-8" />
6+
<title>jQuery Mobile Toolbar Test Suite</title>
7+
8+
<script src="../../../external/requirejs/require.js"></script>
9+
<script src="../../../js/requirejs.config.js"></script>
10+
<script src="../../../js/jquery.tag.inserter.js"></script>
11+
<script src="../../jquery.setNameSpace.js"></script>
12+
<script src="../../../tests/jquery.testHelper.js"></script>
13+
<script src="../../../external/qunit/qunit.js"></script>
14+
<script>
15+
$.testHelper.asyncLoad([
16+
[
17+
"widgets/toolbar",
18+
"jquery.mobile.buttonMarkup"
19+
],
20+
[ "jquery.mobile.init" ],
21+
[ "external_toolbar_core.js" ]
22+
]);
23+
</script>
24+
25+
<link rel="stylesheet" href="../../../css/themes/default/jquery.mobile.css"/>
26+
<link rel="stylesheet" href="../../../external/qunit/qunit.css"/>
27+
<link rel="stylesheet" href="../../jqm-tests.css"/>
28+
29+
<script src="../../swarminject.js"></script>
30+
</head>
31+
<body>
32+
33+
<div id="qunit"></div>
34+
35+
<div id="header" data-nstest-role="header" data-nstest-add-back-btn="true">
36+
<h1>Header</h1>
37+
</div>
38+
<div data-nstest-role="page">
39+
<div class="ui-content" role="main">
40+
<a href="#page2" id="go-to-page-2">Go to page 2</a>
41+
</div>
42+
</div>
43+
<div data-nstest-role="page" id="page2">
44+
<div data-nstest-role="content">
45+
<a href="#page3" id="go-to-page-3">Go to page 3</a>
46+
<p>Content</p>
47+
</div>
48+
</div>
49+
<div data-nstest-role="page" id="page3">
50+
<div data-nstest-role="content">
51+
<p>Content</p>
52+
</div>
53+
</div>
54+
</body>
55+
</html>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
asyncTest( "Back button added to external toolbar", function() {
2+
$( "#header" ).toolbar();
3+
$.testHelper.pageSequence([
4+
function() {
5+
$( "#go-to-page-2" ).click();
6+
},
7+
function() {
8+
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 1,
9+
"After navigating to page 2 exactly one back button " +
10+
"appears on the external toolbar" );
11+
$.mobile.back();
12+
},
13+
function() {
14+
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 0,
15+
"After going back from page 2 no back button appears on the external toolbar" );
16+
$( "#go-to-page-2" ).click();
17+
},
18+
function() {
19+
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 1,
20+
"After navigating to page 2 again exactly one back button " +
21+
"appears on the external toolbar" );
22+
$( "#go-to-page-3" ).click();
23+
},
24+
function() {
25+
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 1,
26+
"After navigating to page 3 exactly one back button " +
27+
"appears on the external toolbar" );
28+
$.mobile.back();
29+
},
30+
function() {
31+
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 1,
32+
"After navigating back to page 2 exactly one back button " +
33+
"appears on the external toolbar" );
34+
$.mobile.back();
35+
},
36+
function() {
37+
deepEqual( $( "#header" ).find( ".ui-toolbar-back-btn" ).length, 0,
38+
"After navigating back from page 2 no back button " +
39+
"appears on the external toolbar" );
40+
start();
41+
},
42+
]);
43+
});

0 commit comments

Comments
 (0)