Запретить jQuery UI dialog устанавливать фокус на первое текстовое поле

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

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

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

<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 ответов


jQuery UI 1.10.0 журнал изменений списки билет 4731 как быть исправлена.

похоже, focusSelector не был реализован, но вместо этого использовался каскадный поиск различных элементов. Из билета:

расширьте автофокус, начиная с [автофокус], затем: tabbable content, затем buttonpane, затем close button, затем dialog

Итак, отметьте элемент с помощью autofocus атрибут, и это элемент, который должен получить фокус:

<input autofocus>

на документация, логика фокусировки объясняется (только под оглавлением, под заголовком "фокус"):

при открытии диалогового окна, фокус автоматически перемещается на первый элемент это соответствует следующему:

  1. первый элемент в диалоговом окне с autofocus атрибут
  2. первый :tabbable элемент в содержимом диалогового окна
  3. первый :tabbable элемент в buttonpane диалогового окна
  4. кнопка "Закрыть" диалогового окна
  5. сам диалог

добавьте скрытый промежуток над ним, используйте ui-helper-hidden-accessible, чтобы сделать его скрытым абсолютным позиционированием. Я знаю, что у вас есть этот класс, потому что вы используете диалог из jquery-ui, и он находится в jquery-ui.

<span class="ui-helper-hidden-accessible"><input type="text"/></span>

в jQuery UI > = 1.10.2 вы можете заменить _focusTabbable метод прототипа функцией плацебо:

$.ui.dialog.prototype._focusTabbable = $.noop;

Скрипка

это повлияет на все dialogs на странице без необходимости редактировать каждый из них вручную.

исходная функция не делает ничего, кроме установки фокуса на первый элемент с autofocus атрибут / tabbable элемент / или возврат к самому диалогу. По мере того как своя польза как раз установка сосредоточьтесь на элементе, не должно быть никаких проблем с заменой его на noop.


Я нашел следующий код диалоговой функции jQuery UI для open.

c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();

вы можете либо обойти поведение jQuery, либо изменить поведение.

tabindex -1 работает как обходной путь.


начиная с jQuery UI 1.10.0, вы можете выбрать на каком входном элементе сосредоточиться с помощью атрибута HTML5 автофокус.

все, что вам нужно сделать, это создать фиктивный элемент в качестве первого ввода в диалоговом окне. Он поглотит фокус для вас.

<input type="hidden" autofocus="autofocus" />

Это было протестировано в Chrome, Firefox и Internet Explorer (все последние версии) 7 февраля 2013 года.

http://jqueryui.com/upgrade-guide/1.10/#added-ability-to-specify-which-element-to-focus-on-open


просто понял это, играя вокруг.

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

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

кстати я исправил это чтобы добавить это в событие open, чтобы удалить фокус из первого поля:

$('#myDialog').dialog({
    open: function(event,ui) {
        $(this).parent().focus();
    }
});

это устанавливает фокус на диалоговое окно, которое не отображается, а затем ESC ключ работает.


установите tabindex входных данных в -1, а затем установите диалоговое окно.откройте для восстановления tabindex, если вам это нужно позже:

$(function() {
    $( "#dialog-message" ).dialog({
        modal: true,
        width: 500,
        autoOpen: false,
        resizable: false,
        open: function()
        {
            $( "#datepicker1" ).attr("tabindex","1");
            $( "#datepicker2" ).attr("tabindex","2");
        }
    });
});

мое решение:

open: function(){
  jQuery('input:first').blur();
  jQuery('#ui-datepicker-div').hide();
},  

простой обходной путь:

просто создайте невидимый элемент с tabindex=1 ... Это не будет фокусировать datepicker ...

например.:

<a href="" tabindex="1"></a>
...
Here comes the input element

У меня был контент, который был больше, чем диалог. При открытии диалог будет расширяться до первого: tabbable, который был внизу. Здесь был мой исправить.

$("#myDialog").dialog({
   ...
   open: function(event, ui) { $(this).scrollTop(0); }
});

вот решение, которое я реализовал после прочтения 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 UI "select" и добавляем дополнительный код, чтобы textElement не терял фокус в IE 8 После выбора.

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

$.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;
}

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

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

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

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

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

    return false;
});

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


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


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

использовать опцию [autoOpen: false]

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

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

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

протестировано в IE, FF и Chrome.

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


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

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

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


у меня аналогичная проблема. Я открываю диалоговое окно ошибки при сбое проверки, и он захватывает фокус, так же, как Flugan показывает его в своем ответ. Проблема в том, что даже если ни один элемент внутри диалог tabbable, сам диалог все-таки остановился. Вот исходный неминифицированный код из jquery-ui-1.8.23\js\jquery.пользовательский интерфейс.диалог.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);
};

Я искал другую проблему, но по той же причине. Проблема в том, что диалог устанавливает фокус на первый <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 }
    });

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

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


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

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

вызовите это после инициализации диалога, например:

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

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


Если вы используете диалоговые кнопки, просто установите 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>

У меня такая же проблема.

обходной путь, который я сделал, это добавить фиктивное текстовое поле в верхней части диалогового контейнера.

<input type="text" style="width: 1px; height: 1px; border: 0px;" />

Как уже упоминалось, это известная ошибка с jQuery UI и должна быть исправлена относительно скоро. До тех пор...

вот еще один вариант, так что вам не придется возиться с tabindex значение:

временно отключите datepicker, пока не откроется диалоговое окно:

dialog.find(".datepicker").datepicker("disable");
dialog.dialog({
    "open": function() {$(this).find(".datepicker").datepicker("enable");},
});

работает для меня.

дублирую вопрос: как размыть первый ввод формы при открытии диалога


чтобы расширить некоторые из предыдущих ответов (и игнорируя вспомогательный аспект datepicker), если вы хотите предотвратить focus() событие от фокусировки первого поля ввода при открытии диалогового окна попробуйте следующее:

$('#myDialog').dialog(
    { 'open': function() { $('input:first-child', $(this)).blur(); }
});

У меня была аналогичная проблема и я решил ее, сосредоточившись на диалоге после открытия:

var $dialog = $("#pnlFiltros")
    .dialog({
        autoOpen: false,
        hide: "puff",                   
        width: dWidth,
        height: 'auto',
        draggable: true,
        resizable: true,
        closeOnScape : true,
        position: [x,y]                    
    });
$dialog.dialog('open');
$("#pnlFiltros").focus(); //focus on the div being dialogued (is that a word?)

но в моем случае первый элемент является якорем, поэтому я не знаю, будет ли в вашем случае открыт datepicker.

EDIT: работает только на IE


найти в jquery.пользовательский интерфейс.js

d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(); 

и заменить на

d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(-1).focus();

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

Я не вижу ничего в документации API, что заставляет меня думать, что что-то изменилось с точки зрения ожидаемой функциональности. Чтобы добавить открывалка кнопка...


у меня была аналогичная проблема. На моей странице первый ввод-текстовое поле с календарем jQuery UI. Второй элемент-кнопка. Поскольку дата уже имеет значение, я устанавливаю фокус на кнопке, но сначала добавляю триггер для размытия в текстовое поле. Это решает проблему во всех браузерах и, вероятно, во всех версиях jQuery. Тестировался в версии 1.8.2.

<div style="padding-bottom: 30px; height: 40px; width: 100%;">
@using (Html.BeginForm("Statistics", "Admin", FormMethod.Post, new { id = "FormStatistics" }))
{
    <label style="float: left;">@Translation.StatisticsChooseDate</label>
    @Html.TextBoxFor(m => m.SelectDate, new { @class = "js-date-time",  @tabindex=1 })
    <input class="button gray-button button-large button-left-margin text-bold" style="position:relative; top:-5px;" type="submit" id="ButtonStatisticsSearchTrips" value="@Translation.StatisticsSearchTrips"  tabindex="2"/>
}

<script type="text/javascript">
$(document).ready(function () {        
    $("#SelectDate").blur(function () {
        $("#SelectDate").datepicker("hide");
    });
    $("#ButtonStatisticsSearchTrips").focus();

});   


Это очень важно для смартфонов и планшетов, потому что клавиатура при ввода имеет фокус. Вот что я сделал, добавьте этот ввод в начале div:

<input type="image" width="1px" height="1px"/>

не работает с размере 0px. Я думаю, что это даже лучше с реальным прозрачным изображением, либо .png или .gif но я не пробовал.

работает нормально до сих пор в iPad.


вы можете добавить это :

...

dlg.dialog({ autoOpen:false,
modal: true, 
width: 400,
open: function(){                  // There is new line
  $("#txtStartDate").focus();
  }
});

...


в качестве первого ввода:<input type="text" style="position:absolute;top:-200px" />