Permalink
Browse files

Flipswitch: Transfer tabindex to "on" button and make input unfocusable

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...
1 parent 126432e commit acea5f8c594b0909ca3c0b91597a5c9238587afe @gabrielschulhof gabrielschulhof committed Jan 17, 2014
@@ -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
@@ -61,6 +71,10 @@ $.widget( "mobile.flipswitch", $.extend({
});
},
+ _handleInputFocus: function() {
+ this.on.focus();
+ },
+
widget: function() {
return this.flipswitch;
},
@@ -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" ) ?
@@ -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();
@@ -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 );
@@ -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>
@@ -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.