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

145

Я установил модальный диалог jQuery UI для отображения, когда пользователь нажимает ссылку. Есть два текстовых поля (я только показываю код для 1 для краткости) в этом теге div div и он изменен как текстовое поле 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>
  • 0
    это установит фокус даже на изображение! как для обычных тегов <img>, так и для <input type = image>

30 ответов

69
Лучший ответ

jQuery UI 1.10.0 Список изменений содержит билет 4731 как фиксированный.

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

Расширьте автофокус, начиная с [автофокусировки], затем: tabbable content, затем кнопку, затем нажмите кнопку закрытия, затем диалог

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

<input autofocus>

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

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

  • Первый элемент в диалоге с атрибутом autofocus
  • Первый элемент :tabbable в содержимом диалога
  • Первый элемент :tabbable в панели кнопок диалога
  • Кнопка закрытия диалогового окна
  • Сам диалог
  • 0
    Для чего нужен понижающий голос? Если это произошло из-за того, что я указал версию 1.9 как исправленную версию, я обновил ее до 1.10, чтобы соответствовать заявке
  • 2
    Я, честно говоря, не помню.
Показать ещё 6 комментариев
64

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

<span class="ui-helper-hidden-accessible"><input type="text"/></span>
  • 0
    Отличная работа вокруг. Не требуется JS, не меняет макет, и JQuery UI поддерживает его изначально.
  • 0
    Согласитесь, отличная работа вокруг. Также приятно узнать о скрыто-доступном классе! Спасибо!!
Показать ещё 2 комментария
48

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

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

Fiddle

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

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

  • 7
    Часы и часы и часы и часы горели на этом. Мой клиент благодарит вас.
  • 0
    Спасибо приятель... !!!
Показать ещё 4 комментария
28

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

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 работает как обходной путь.

  • 1
    Разве tabindex = -1 не помешает мне перейти к текстовому полю?
  • 2
    Спасибо за исследование. Теперь я знаю, что это действительно код, который делает это. Я мог бы предложить команде jQuery UI добавить опцию, чтобы отключить эту автофокусировку.
Показать ещё 6 комментариев
24

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

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

<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

  • 0
    вы это помогли! благодарю вас
  • 6
    Это работает, только если ввод не скрыт. :-(
Показать ещё 1 комментарий
11

Просто подумал об этом во время игры.

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

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

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

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

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

  • 2
    Это кажется единственным работающим решением, которое не включает добавление бесполезного HTML, удаление tabindex или взлом ключа ESC.
10

Мое обходное решение:

open: function(){
  jQuery('input:first').blur();
  jQuery('#ui-datepicker-div').hide();
},  
  • 0
    +1. Работает как шарм, используя :first селектор или .first() в FF / Chrome / IE9. Бросок в dialogopen тоже работает.
  • 0
    Это тоже привело меня туда. Кроме меня, в моем диалоге вообще не было входных данных, и первая ссылка была в фокусе ... поэтому я добавил эту опцию в свой диалог jQuery: open: function(){ $('a').blur(); // no autofocus on links }
10

Установите tabindex ввода в -1, а затем установите dialog.open для восстановления tabindex, если вам это нужно позже:

$(function() {
    $( "#dialog-message" ).dialog({
        modal: true,
        width: 500,
        autoOpen: false,
        resizable: false,
        open: function()
        {
            $( "#datepicker1" ).attr("tabindex","1");
            $( "#datepicker2" ).attr("tabindex","2");
        }
    });
});
  • 4
    Разве tabindex = -1 не помешает мне перейти к текстовому полю?
  • 1
    Вы могли бы использовать setTimeout, чтобы установить tabindex обратно после показа диалога
8

Простой способ:

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

например:.

<a href="" tabindex="1"></a>
...
Here comes the input element
  • 0
    Не работает на Chrome. :-(
  • 0
    не работает :-(
Показать ещё 1 комментарий
7

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

$("#myDialog").dialog({
   ...
   open: function(event, ui) { $(this).scrollTop(0); }
});
  • 0
    Это сработало для меня, но я использовал $('...').blur(); вместо прокрутки.
  • 4
    Мое содержание тоже было очень длинным. Blur убрал выделение, но оставил диалоговое окно прокручиваться вниз. scrollTop прокручивал содержимое до самого верха, но оставлял выделение. В итоге я использовал $ ('...'). Blur (); $ (Это) .scrollTop (0); работал как чемпион.
3

Вот решение, которое я реализовал после прочтения jQuery UI ticket # 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 "выберите" автозавершение обратного вызова и добавим дополнительный код, чтобы гарантировать, что 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;
}
1

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

.dialog({
      open: function () {
              $(".ui-dialog-titlebar-close").focus();
            }
   });
  • 0
    это работает довольно хорошо
1

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

$('#dialog').dialog({
  buttons: [
    {
      text: 'OK',
      autofocus: 'autofocus'
    },
    {
      text: 'Cancel'
    }
  ]
});
<script src="/jquery-1.12.4.min.js"></script>
<script src="/jquery-ui.min.js"></script>
<link href="/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

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

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

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

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

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

1

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

У меня аналогичная проблема. Я открываю диалоговое окно с ошибкой, когда проверка не выполняется, и она захватывает фокус, точно так же, как Flugan показывает это в ответе . Проблема в том, что даже если ни один элемент внутри диалогового окна не является tabbable, само диалоговое окно все еще сфокусировано. Вот исходный unminified код из 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();

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

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

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

jqueryFocus = $.fn.focus;
$.fn.focus = function (delay, fn) {
  jqueryFocus.apply(this.filter(':not(.ui-dialog)'), arguments);
};
  • 0
    Это может быть расширено, чтобы влиять только на определенные диалоги, используя опцию 'dialogClass' в .dialog () и затем изменяя вышеупомянутое: не фильтровать, чтобы включить ваш класс. Например: нет (.ui-dialog.myDialogClass)
  • 0
    Больше не работает с jQuery UI 1.9.2.
1

По-моему, это решение очень приятно:

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

Найдено здесь: не удалось удалить-autofocus-in-ui-dialog

1

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

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

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

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

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

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

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

1

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

1

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

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

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

    return false;
});

Не тестировали, но должны работать нормально.

  • 1
    к сожалению, это не работает. не уверен, что это IE или JQuery UI. но даже если вы перемещаете фокус на что-то еще программно, календарь остается открытым.
  • 0
    у меня тоже не работает
0

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

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

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

Работает хорошо в iPad.

0

У меня была аналогичная проблема. На моей первой странице ввода находится текстовое поле с календарем пользовательского интерфейса jQuery. Второй элемент - это кнопка. Поскольку дата уже имеет значение, я устанавливаю фокус на кнопку, но сначала добавляю триггер для размытия в текстовом поле. Эта проблема разрешима во всех браузерах и, вероятно, во всех версиях 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();

});   

0

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

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

0

найти в jquery.ui.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();
0

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

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

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

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

0

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

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

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

Вот еще один вариант, поэтому вам не нужно связываться с tabindex:

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

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

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

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

0

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

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

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

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

...

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

...

  • 3
    Он спрашивает, как предотвратить фокус, а не добавить фокус.
-3

как первый вход: <input type="text" style="position:absolute;top:-200px" />

Ещё вопросы

Сообщество Overcoder
Наверх
Меню