]> source.dussan.org Git - jquery-ui.git/commitdiff
wrapping tab order for popup 338/head
authorHans Hillen <hans.hillen@gmail.com>
Wed, 25 May 2011 12:58:26 +0000 (14:58 +0200)
committerHans Hillen <hans.hillen@gmail.com>
Wed, 25 May 2011 12:58:26 +0000 (14:58 +0200)
demos/popup/default.html
ui/jquery.ui.popup.js

index 71b3c8dd2bd45cb67318152003fa3ffa3099cad6..ecfeaaf5bfcc93584df3bc1c0703dc8f0dc901d7 100644 (file)
 <body>
 
 <div class="demo">
-       <a href="#login-form">Log In</a>
-       <div id="login-form" class="ui-widget-content" tabIndex="0">
+       <a href="#login-form">Log In</a>        
+       <div class="ui-widget-content" id="login-form" aria-label="Login options">
                <form>
                        <div>
-                               <label>Username</label>
-                               <input type="username" />
+                               <label for="un">Username</label>
+                               <input type="text" id="un" />
                        </div>
                        <div>
-                               <label>Password</label>
-                               <input type="password" />
+                               <label for="pw">Password</label>
+                               <input type="password" id="pw" />
                        </div>
                        <div>
-                               <input type="submit" class="submit" value="Login" />
+                               <input type="submit" value="Login" class="submit" />
                        </div>
                </form>
        </div>
+       
+       
+       
+       
 </div>
 
 <div class="demo-description">
index 10361a35cacd3825748ce9672e71e16e7b9c6551..10e6931b8ed812f81746baa438c0c09c53000278 100644 (file)
@@ -35,7 +35,7 @@ $.widget( "ui.popup", {
                
                if ( !this.element.attr( "role" ) ) {
                        // TODO alternatives to tooltip are dialog and menu, all three aren't generic popups
-                       this.element.attr( "role", "tooltip" );
+                       this.element.attr( "role", "dialog" );
                        this.generatedRole = true;
                }
                
@@ -80,19 +80,22 @@ $.widget( "ui.popup", {
                });
                
                this._bind(this.element, {
-                       // TODO use focusout so that element itself doesn't need to be focussable
-                       blur: function( event ) {
+                       focusout: function( event ) {
                                var that = this;
                                // use a timer to allow click to clear it and letting that
                                // handle the closing instead of opening again
                                that.closeTimer = setTimeout( function() {
                                        that.close( event );
                                }, 100);
-                       }
+                       },
+                       focusin: function( event ) {
+                               var that = this;
+                               clearTimeout( that.closeTimer );
+                       }               
                });
 
                this._bind({
-                       // TODO only triggerd on element if it can receive focus
+                       // TODO only triggered on element if it can receive focus
                        // bind to document instead?
                        // either element itself or a child should be focusable
                        keyup: function( event ) {
@@ -141,14 +144,43 @@ $.widget( "ui.popup", {
                        .show()
                        .attr( "aria-hidden", false )
                        .attr( "aria-expanded", true )
-                       .position( position )
-                       // TODO find a focussable child, otherwise put focus on element, add tabIndex=0 if not focussable
-                       .focus();
-
-               if (this.element.is(":ui-menu")) {
+                       .position( position );          
+               
+               if (this.element.is(":ui-menu")) { //popup is a menu
+                       this.element.focus();
                        this.element.menu("focus", event, this.element.children( "li" ).first() );
+                       this.element.focus();
                }
-
+               // TODO add other special use cases that differ from the default dialog style keyboard mechanism
+               else {
+                       //default use case, popup could be anything (e.g. a form)
+                       this.element
+                               .bind( "keypress.ui-popup", function( event ) {
+                       if ( event.keyCode !== $.ui.keyCode.TAB ) {
+                           return;
+                       }
+                       var tabbables = $( ":tabbable", this ),
+                           first = tabbables.filter( ":first" ),
+                           last  = tabbables.filter( ":last" );
+                       if ( event.target === last[0] && !event.shiftKey ) {
+                           first.focus( 1 );
+                           return false;
+                       } else if ( event.target === first[0] && event.shiftKey ) {
+                           last.focus( 1 );
+                           return false;
+                       }
+                   });
+                       
+                       // set focus to the first tabbable element in the popup container
+               // if there are no tabbable elements, set focus on the popup itself
+               var tabbables = this.element.find( ":tabbable" );
+               if (!tabbables.length) {
+                       this.element.attr("tabindex", "0");
+                       tabbables.add(this.element);
+               }
+               tabbables.eq( 0 ).focus(1);
+               }
+               
                // take trigger out of tab order to allow shift-tab to skip trigger
                this.options.trigger.attr("tabindex", -1);
 
@@ -160,7 +192,8 @@ $.widget( "ui.popup", {
                this.element
                        .hide()
                        .attr( "aria-hidden", true )
-                       .attr( "aria-expanded", false );
+                       .attr( "aria-expanded", false )
+                       .unbind( "keypress.ui-popup");
 
                this.options.trigger.attr("tabindex", 0);