Запретить диалогу jQuery UI устанавливать фокус на первое текстовое поле - PullRequest
150 голосов
/ 29 июля 2009

Я установил модальное диалоговое окно jQuery UI, которое отображается, когда пользователь нажимает на ссылку. В этом теге div диалога есть два текстовых поля (для краткости я показываю только код 1), и оно заменено текстовым полем jQuery UI DatePicker, которое реагирует на фокус.

Проблема в том, что диалоговое окно jQuery UI («open») каким-то образом вызывает фокусировку в первом текстовом поле, а затем немедленно запускает календарь средства выбора даты.

Поэтому я ищу способ предотвратить автоматическую фокусировку.

<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>

Ответы [ 30 ]

3 голосов
/ 04 июня 2013

Вот решение, которое я реализовал после прочтения тикета jQuery UI # 4731 , первоначально отправленного slolife как ответ на другой ответ. (Билет был также создан им.)

Во-первых, любым методом, который вы используете для автозаполнения страницы, добавьте следующую строку кода:

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

Это отключает поведение автофокуса в jQuery. Чтобы обеспечить доступность вашего сайта, оберните методы создания диалогов, чтобы можно было добавить дополнительный код, и добавьте вызов для фокусировки на первом элементе ввода:

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();

}

Чтобы дополнительно обеспечить доступность при выборе параметров автозаполнения с помощью клавиатуры, мы переопределяем обратный вызов автозаполнения в пользовательском интерфейсе jQuery и добавляем дополнительный код, чтобы гарантировать, что textElement не потеряет фокус в IE 8 после выбора.

Вот код, который мы используем для применения автозаполнения к элементам:

$.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;
}
2 голосов
/ 23 февраля 2017

Вы можете предоставить эту опцию, чтобы вместо этого сфокусировать кнопку закрытия.

.dialog({
      open: function () {
              $(".ui-dialog-titlebar-close").focus();
            }
   });
1 голос
/ 24 февраля 2012

Что ж, круто, что пока никто не нашел решение, но похоже, у меня есть кое-что для тебя. Плохая новость заключается в том, что диалог захватывает фокус в любом случае, даже если внутри нет входных данных и ссылок. Я использую диалог в качестве всплывающей подсказки, и определенно нужно, чтобы фокус оставался в исходном элементе. Вот мое решение:

используйте параметр [autoOpen: false]

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

Пока диалог невидим, фокус нигде не установлен и остается на прежнем месте. Он работает для всплывающих подсказок с простым текстом, но не тестируется для более функциональных диалогов, где может быть важно, чтобы диалог был виден в момент открытия. Вероятно, будет работать нормально в любом случае.

Я понимаю, что исходное сообщение было сделано только для того, чтобы не фокусироваться на первом элементе, но вы можете легко решить, где должен быть фокус после открытия диалога (после моего кода).

Проверено в IE, FF и Chrome.

Надеюсь, это кому-нибудь поможет.

1 голос
/ 12 марта 2011

Я бы применил ту же проблему и решил ее, вставив пустой ввод перед указателем даты, который крадет фокус при каждом открытии диалога. Этот вход скрыт при каждом открытии диалога и снова отображается при закрытии.

1 голос
/ 29 июля 2009

Это может быть поведение браузера, а не проблема с плагином jQuery. Вы пытались удалить фокус программно после открытия всплывающего окна.

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

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

    return false;
});

Не проверял, но должен работать нормально.

1 голос
/ 16 июня 2016

Если вы используете диалоговые кнопки, просто установите атрибут autofocus на одну из кнопок:

$('#dialog').dialog({
  buttons: [
    {
      text: 'OK',
      autofocus: 'autofocus'
    },
    {
      text: 'Cancel'
    }
  ]
});
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<link href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>

<div id="dialog" title="Basic dialog">
  This is some text.
  <br/>
  <a href="www.google.com">This is a link.</a>
  <br/>
  <input value="This is a textbox.">
</div>
1 голос
/ 14 сентября 2012

Я искал другую проблему, но ту же причину. Проблема состоит в том, что диалог устанавливает фокус на первое <a href="">.</a>, которое он находит. Поэтому, если в вашем диалоговом окне много текста и появляются полосы прокрутки, может возникнуть ситуация, когда полоса прокрутки будет прокручена вниз. Я считаю, что это также решает вопрос от первого лица. Хотя остальные так же.

Простое, легкое для понимания, исправление. <a id="someid" href="#">.</a> в качестве первой строки в вашем диалоге div.

Пример:

 <div id="dialogdiv" title="some title">
    <a id="someid" href="#">.</a>
    <p>
        //the rest of your stuff
    </p>
</div>

Где ваш диалог начинается

$(somediv).dialog({
        modal: true,
        open: function () { $("#someid").hide(); otherstuff or function },
        close: function () { $("#someid").show(); otherstuff or function }
    });

Выше не будет ничего сфокусировано, и полосы прокрутки останутся наверху, где он принадлежит. <a> получает фокус, но затем скрывается. Так что общий эффект - это желаемый эффект.

Я знаю, что это старая ветка, но что касается документации по пользовательскому интерфейсу, это не исправить. Это не требует размытия или фокусировки для работы. Не уверен, что это самый элегантный. Но это просто имеет смысл и легко объяснить кому-либо.

1 голос
/ 25 июня 2013

Если у вас есть только одно поле в форме диалога Jquery, и именно оно требует Datepicker, в качестве альтернативы, вы можете просто установить фокус на диалоге Закрыть (крест) кнопку в строке заголовка диалога:

$('.ui-dialog-titlebar-close').focus();

Вызов этого ПОСЛЕ диалогового окна был инициализирован, например ::1006

$('#yourDialogId').dialog();
$('.ui-dialog-titlebar-close').focus();

Поскольку кнопка закрытия отображается после вызова .dialog().

1 голос
/ 03 сентября 2012

У меня похожая проблема. Я открываю диалоговое окно с сообщением об ошибке, когда проверка завершается неудачей, и она захватывает фокус, как это показывает Флуган в своем ответе . Проблема в том, что даже если ни один элемент внутри диалога не является вкладкой, само диалоговое окно все еще находится в фокусе. Вот оригинальный унифицированный код из jquery-ui-1.8.23 \ js \ jquery.ui.dialog.js:

// set focus to the first tabbable element in the content area or the first button
// if there are no tabbable elements, set focus on the dialog itself
$(self.element.find(':tabbable').get().concat(
  uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
    uiDialog.get()))).eq(0).focus();

Комментарий их!

Это действительно плохо для меня по нескольким причинам. Самое неприятное, что первая реакция пользователя - нажать клавишу «Backspace», чтобы удалить последний символ, но вместо этого ему предлагается покинуть страницу, потому что «Backspace» попадает за пределы элемента управления вводом.

Я обнаружил, что следующий обходной путь работает для меня очень хорошо:

jqueryFocus = $.fn.focus;
$.fn.focus = function (delay, fn) {
  jqueryFocus.apply(this.filter(':not(.ui-dialog)'), arguments);
};
1 голос
/ 16 августа 2012

На мой взгляд, это решение очень приятно:

$("#dialog").dialog({
    open: function(event, ui) {
        $("input").blur();
    }
});

Найдено здесь: Невозможно удалить автофокус-в-диалоговом окне

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...