154 votes

Empêcher la boîte de dialogue jQuery UI de mettre le focus sur la première zone de texte

J'ai configuré une boîte de dialogue modale jQuery UI qui s'affiche lorsqu'un utilisateur clique sur un lien. Il y a deux zones de texte (je ne montre que le code de la première pour des raisons de brièveté) dans la balise div dialog et elle est modifiée pour être une zone de texte DatePicker de jQuery UI qui réagit au focus.

Le problème est que la fonction dialog('open') de jQuery UI déclenche en quelque sorte la mise au point de la première zone de texte, ce qui déclenche l'ouverture immédiate du calendrier du sélecteur de date.

Je cherche donc un moyen d'empêcher la mise au point de se faire automatiquement.

<div><a id="lnkAddReservation" href="#">Add reservation</a></div>

<div id="divNewReservation" style="display:none" title="Add reservation">
    <table>
        <tr>
            <th><asp:Label AssociatedControlID="txtStartDate" runat="server" Text="Start date" /></th>
            <td>
                <asp:TextBox ID="txtStartDate" runat="server" CssClass="datepicker" />
            </td>
        </tr>
    </table>

    <div>
        <asp:Button ID="btnAddReservation" runat="server" OnClick="btnAddReservation_Click" Text="Add reservation" />
    </div>
</div>

<script type="text/javascript">
    $(document).ready(function() {
        var dlg = $('#divNewReservation');
        $('.datepicker').datepicker({ duration: '' });
        dlg.dialog({ autoOpen:false, modal: true, width:400 });
        $('#lnkAddReservation').click(function() { dlg.dialog('open'); return false; });
        dlg.parent().appendTo(jQuery("form:first"));
    });
</script>

3voto

Voici la solution que j'ai mise en œuvre après avoir lu le document ticket jQuery UI #4731 , initialement posté par slolife en réponse à une autre réponse. (Le ticket a également été créé par lui).

Tout d'abord, dans la méthode que vous utilisez pour appliquer les autocompléments à la page, ajoutez la ligne de code suivante :

$.ui.dialog.prototype._focusTabbable = function(){};

Cela désactive le comportement "auto-focus" de jQuery. Pour que votre site continue d'être largement accessible, enveloppez vos méthodes de création de boîtes de dialogue de manière à ce que du code supplémentaire puisse être ajouté, et ajoutez un appel à la mise au point du premier élément de saisie :

function openDialog(context) {

    // Open your dialog here

    // Usability for screen readers.  Focus on an element so that screen readers report it.
    $("input:first", $(context)).focus();

}

Pour améliorer l'accessibilité lorsque les options de la saisie semi-automatique sont sélectionnées au clavier, nous remplaçons la fonction de rappel "select" de la saisie semi-automatique de jQuery UI et ajoutons du code supplémentaire pour garantir que l'élément textElement ne perde pas le focus dans IE 8 après avoir effectué une sélection.

Voici le code que nous utilisons pour appliquer les autocompléments aux éléments :

$.fn.applyAutocomplete = function () {

    // Prevents jQuery dialog from auto-focusing on the first tabbable element.
    // Make sure to wrap your dialog opens and focus on the first input element
    // for screen readers.
    $.ui.dialog.prototype._focusTabbable = function () { };

    $(".autocomplete", this)
        .each(function (index) {

            var textElement = this;

            var onSelect = $(this).autocomplete("option", "select");
            $(this).autocomplete("option", {
                select: function (event, ui) {
                    // Call the original functionality first
                    onSelect(event, ui);

                    // We replace a lot of content via AJAX in our project.
                    // This ensures proper copying of values if the original element which jQuery UI pointed to
                    // is replaced.
                    var $hiddenValueElement = $("#" + $(textElement).attr('data-jqui-acomp-hiddenvalue'));
                    if ($hiddenValueElement.attr("value") != ui.item.value) {
                        $hiddenValueElement.attr("value", ui.item.value);
                    }

                    // Replace text element value with that indicated by "display" if any
                    if (ui.item.display)
                        textElement.value = ui.item.display;

                    // For usability purposes.  When using the keyboard to select from an autocomplete, this returns focus to the textElement.
                    $(textElement).focus();

                    if (ui.item.display)
                        return false;

                }
            });
        })
        // Set/clear data flag that can be checked, if necessary, to determine whether list is currently dropped down
        .on("autocompleteopen", function (event, ui) {
            $(event.target).data().autocompleteIsDroppedDown = true;
        })
        .on("autocompleteclose", function (event, ui) {
            $(event.target).data().autocompleteIsDroppedDown = false;
        });

    return this;
}

3voto

Jay Dubal Points 173

Vous pouvez proposer cette option, afin de mettre l'accent sur le bouton de fermeture à la place.

.dialog({
      open: function () {
              $(".ui-dialog-titlebar-close").focus();
            }
   });

1voto

RaYell Points 26761

Il peut s'agir d'un comportement du navigateur et non d'un problème de plugin jQuery. Avez-vous essayé d'enlever le focus programmatiquement après avoir ouvert la popup.

$('#lnkAddReservation').click(function () {
    dlg.dialog('open');

    // you may want to change the selector below
    $('input,textarea,select').blur();

    return false;
});

Je ne l'ai pas testé mais cela devrait fonctionner.

1voto

maenu Points 1617

J'ai eu le même problème et je l'ai résolu en insérant une entrée vide avant le sélecteur de date, qui vole le focus à chaque fois que le dialogue est ouvert. Cette entrée est cachée à chaque ouverture de la boîte de dialogue et réaffichée à la fermeture.

1voto

Roc Points 34

Eh bien, c'est cool que personne n'ait trouvé la solution pour le moment, mais il semble que j'ai quelque chose pour vous. La mauvaise nouvelle est que la boîte de dialogue prend le focus dans tous les cas, même si aucune entrée ou lien ne se trouve à l'intérieur. J'utilise la boîte de dialogue comme une infobulle et j'ai absolument besoin que le focus reste dans l'élément d'origine. Voici ma solution :

utiliser l'option [autoOpen : false]

$toolTip.dialog("widget").css("visibility", "hidden"); 
$toolTip.dialog("open");
$toolTip.dialog("widget").css("visibility", "visible");

Pendant que la boîte de dialogue est invisible, le focus n'est placé nulle part et reste à l'endroit initial. Cela fonctionne pour les infobulles avec juste un texte simple, mais n'a pas été testé pour des dialogues plus fonctionnels où il peut être important que le dialogue soit visible au moment de l'ouverture. Cela fonctionnera probablement bien dans tous les cas.

Je comprends que le post original était juste pour éviter d'avoir le focus sur le premier élément, mais vous pouvez facilement décider où le focus doit être après l'ouverture du dialogue (après mon code).

Testé dans IE, FF et Chrome.

J'espère que cela aidera quelqu'un.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X