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

Commit

Permalink
Flipswitch: Transfer tabindex to "on" button and make input unfocusable
Browse files Browse the repository at this point in the history
The "on" button must be an anchor for it to be focusable just like an input even
when it does not have an explicitly set tabindex. Although the input becomes
unfocusable, a focus handler that transfers focus to the "on" button is
nevertheless attached to it in case third-party code focuses the input manually.

Fixes gh-6955
  • Loading branch information
Gabriel Schulhof committed Feb 6, 2014
1 parent 126432e commit acea5f8
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
25 changes: 24 additions & 1 deletion js/widgets/forms/flipswitch.js
Expand Up @@ -40,6 +40,16 @@ $.widget( "mobile.flipswitch", $.extend({

this._handleFormReset();

// Transfer tabindex to "on" element and make input unfocusable
this._originalTabIndex = this.element.attr( "tabindex" );
if ( this._originalTabIndex != null ) {
this.on.attr( "tabindex", this._originalTabIndex );
}
this.element.attr( "tabindex", "-1" );
this._on({
"focus" : "_handleInputFocus"
});

if ( this.element.is( ":disabled" ) ) {
this._setOptions({
"disabled": true
Expand All @@ -61,6 +71,10 @@ $.widget( "mobile.flipswitch", $.extend({
});
},

_handleInputFocus: function() {
this.on.focus();
},

widget: function() {
return this.flipswitch;
},
Expand Down Expand Up @@ -90,7 +104,11 @@ $.widget( "mobile.flipswitch", $.extend({
options = this.options,
element = this.element,
theme = options.theme ? options.theme : "inherit",
on = $( "<span></span>", { tabindex: 1 } ),

// The "on" button is an anchor so it's focusable
on = $( "<a></a>", {
"href": "#"
}),
off = $( "<span></span>" ),
type = element.get( 0 ).tagName,
onText = ( type === "INPUT" ) ?
Expand Down Expand Up @@ -200,6 +218,11 @@ $.widget( "mobile.flipswitch", $.extend({
if ( this.options.enhanced ) {
return;
}
if ( this._originalTabIndex != null ) {
this.element.attr( "tabindex", this._originalTabIndex );
} else {
this.element.removeAttr( "tabindex" );
}
this.on.remove();
this.off.remove();
this.element.unwrap();
Expand Down
36 changes: 36 additions & 0 deletions tests/integration/flipswitch/flipswitch_core.js
@@ -0,0 +1,36 @@
/*
* mobile flipswitch unit tests
*/
(function($){

var testFocusTransfer = function( element ) {
expect( 1 );
$.testHelper.detailedEventCascade([
function() {
element.focus();
},
{
focus: {
src: element.siblings( "a" ),
event: "focus.TransfersFocus1"
}
},
function( result ) {
deepEqual( result.focus.timedOut, false,
"'on' button received focus event" );
start();
}
]);
};

asyncTest( "select based flipswitch transfers focus to 'on' button",
function() {
testFocusTransfer( $( "#flip-select" ) );
});

asyncTest( "checkbox based flipswitch transfers focus to 'on' button",
function() {
testFocusTransfer( $( "#flip-checkbox" ) );
});

})( jQuery );
46 changes: 46 additions & 0 deletions tests/integration/flipswitch/index.html
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery Mobile Button 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>


<link rel="stylesheet" href="../../../css/themes/default/jquery.mobile.css"/>
<link rel="stylesheet" href="../../../external/qunit/qunit.css"/>
<script src="../../../external/qunit/qunit.js"></script>
<script>
$.testHelper.asyncLoad([
[ "widgets/page" ],
[
"widgets/forms/flipswitch",
],
[ "jquery.mobile.init" ],
[
"flipswitch_core.js"
]
]);
</script>

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

<div data-nstest-role="page" data-nstest-theme="a">
<div data-nstest-role="content" data-nstest-theme="b">
<input type="checkbox" data-nstest-role="flipswitch" name="flip-checkbox" id="flip-checkbox"/>
<select id="flip-select" name="flip-select" data-nstest-role="flipswitch">
<option>On</option>
<option>Off</option>
</select>
</div>
</div>
</body>
</html>
8 changes: 8 additions & 0 deletions tests/unit/flipswitch/flipswitch_core.js
Expand Up @@ -58,5 +58,13 @@
$("#flip-select").trigger("swiperight");
ok( $("#flip-select").parent().hasClass("ui-flipswitch-active"), "should not be active" );
});
test( "checkbox based flipswitch is untabbable", function() {
deepEqual( parseInt( $( "#flip-checkbox" ).attr( "tabindex" ) ), -1,
"tabindex is set to -1" );
});
test( "select based flipswitch is untabbable", function() {
deepEqual( parseInt( $( "#flip-select" ).attr( "tabindex" ) ), -1,
"tabindex is set to -1" );
});

})( jQuery );

0 comments on commit acea5f8

Please sign in to comment.