tab order for links in a simplemodal dialog

2019-05-07 19:12发布

问题:

I am using the excellent jquery.simplemodal dialog plugin to show a list of items. These items contain hyperlinks. It all works great except that the links in the modal dialog arent coming up as part of the tab order. I have tried setting tabindex explicitly, but for some reason only the input elements are in the tab order - if I tab through the dialog I just cycle through the 3 input elements and dont hit the anchors.

Am I doing something wrong with calling simplemodal plugin?

An example is at http://dev.andrewbucknell.com/basic/demo1.html

The code (with relative paths) for the demo is as follows

<!DOCTYPE html>  
<html>  
<head>  
<title> SimpleModal Basic Modal Dialog </title>  
<meta name='author' content='Eric Martin' />  
<meta name='copyright' content='2010 - Eric Martin' /> 
<!-- Page styles -->  
<link type='text/css' href='css/demo.css' rel='stylesheet' media='screen' /> 
<!-- Contact Form CSS files -->  
<link type='text/css' href='css/basic.css' rel='stylesheet' media='screen' /> 
<!-- IE6 "fix" for the close png image -->  
<!--[if lt IE 7]>  
<link type='text/css' href='css/basic_ie.css' rel='stylesheet' media='screen' />  
<![endif]--> 
<!-- JS files are loaded at the bottom of the page -->  
</head>  
<body>  
<div id='container'>  
        <div id='logo'>  
                <h1>Simple<span>Modal</span></h1>  
                <span class='title'>A Modal Dialog Framework Plugin for jQuery</span>  
        </div>  
        <div id='content'>  
                <div id='basic-modal'>  
                        <h3>Basic Modal Dialog</h3>  
                        <p>A basic modal dialog with minimal styling and no additional options. There 
are a few CSS properties set internally by SimpleModal, however, SimpleModal relies mostly 
on style options and/or external CSS for the look and feel.</p>
                        <input type='button' name='basic' value='Demo' class='basic'/> or <a 
href='#' class='basic'>Demo</a>
                </div>  
                <div id="funddialog">  
                        <div id="fundpickfilter">  
                                <div class="fundfilter">  
                                        <label style="font-weight: bold;" for="filtertext">Find: </label>  
                                        <input class="tfilter" type="text" id="filtertext" value=""/>  
                                </div>  
                                <div id="fundactions">  
                                                <button type="button" id="fundsearch" 
class="searchbutton">Search</button>
                                                <button type="button" id="fundreset" 
class="resetbutton">Reset</button>  
                                </div>  
                        </div>  
                        <div id="fundpicklist">  
                                <div class="fund"><a href="http://www.slashdot.org" >Item 
1</a></div>  
                                <div class="fund"><a href="http://www.arstechnica.com" >Item 
2</a></div>  
                                <div class="fund"><a href="http://www.techmeme.com" >Item 
3</a></div>  
                        </div>  
                </div>  
                <!-- modal content -->  
                <div id="basic-modal-content">  
                        <div id="funddialog">  
                                <div id="fundpickfilter">  
                                        <div class="fundfilter">  
                                                <label style="font-weight: bold;" for="filtertext">Find: </label>  
                                                <input class="tfilter" type="text" id="filtertext" value=""/>  
                                        </div>  
                                        <div id="fundactions">  
                                                        <button type="button" id="fundsearch" 
class="searchbutton">Search</button>
                                                        <button type="button" id="fundreset" 
class="resetbutton">Reset</button>
                                        </div>  
                                </div>  
                                <div id="fundpicklist">  
                                        <div class="fund"><a href="http://www.slashdot.org" >Item 
1</a></div>  
                                        <div class="fund"><a href="http://www.arstechnica.com" >Item 
2</a></div>  
                                        <div class="fund"><a href="http://www.techmeme.com" >Item 
3</a></div>  
                                </div>  
                        </div>  
                </div>  
        </div>  
</div>  
<!-- Load jQuery, SimpleModal and Basic JS files -->  
<script type='text/javascript' src='js/jquery.js'></script>  
<script type='text/javascript' src='js/jquery.simplemodal.js'></script>  
<script type='text/javascript' src='js/basic.js'></script>  
</body>  
</html> 

回答1:

I just ran into this problem myself. Here's what I worked out so far. Simplemodal has to add to tab navigation in the functions 'watchTab' and 'focus' in order to keep focus inside the modal. It achieves this by recording the first and last inputs and when you tab past them, focusing on the appropriate other one. Unfortunately, it is only looking at the inputs and not the links. This means that you can only tab to the links that are located between the first and last input elements. You can overwrite or modify these functions to get the desired behavior. Something like this:

replace line 473 with var input = $('#simplemodal-data :input:visible:enabled, #simplemodal-data a:visible')[p]();

replace line 592 with s.inputs = $('#simplemodal-data :input:visible:enabled, #simplemodal-data a:visible');

This is a simplistic solution which will probably break in the case of a browser which doesn't tab over links. I will try to come up with something better.



回答2:

I found an solution with SimpleModal 1.4.2

On line 609

Change this s.inputs = $(':input:enabled:visible:first, :input:enabled:visible:last', s.d.data[0]);

To this s.inputs = $('a:visible, :input:enabled:visible', s.d.data[0]).filter(':first,:last');



回答3:

s.d.data[0]s.d.data[0]note also that neither the existing implementation, with following selector:

s.inputs = $(':input:enabled:visible:first, :input:enabled:visible:last', s.d.data[0]);

nor the answer above, properly handle tabindexes - the switch after last element will be done the first element in dom, not the one with the least tabindex (and vice versa) to fix this, you must do sth like this:

s.inputs = $.merge(self.smallestTabindex(s.d.data[0]), self.biggestTabindex(s.d.data[0]));

where the functions smallest/biggestTabindex return the appropriate elements