Запретить диалогу jQuery UI устанавливать фокус на первое текстовое поле
Я настроил модальное диалоговое окно jQuery UI, которое отображается, когда пользователь нажимает на ссылку. В этом теге div диалога есть два текстовых поля (для краткости я показываю только код 1), и оно заменено на текстовое поле 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 не был реализован, но вместо этого использовался каскадный поиск различных элементов. Из билета:
Расширение автофокуса, начиная с [автофокус], затем: содержимое с вкладками, затем панель кнопок, затем кнопка закрытия, затем диалоговое окно
Итак, отметьте элемент с autofocus
атрибут, и это элемент, который должен получить фокус:
<input autofocus>
В документации объясняется логика фокуса (только под оглавлением, под заголовком "Фокус"):
При открытии диалога фокус автоматически перемещается на первый элемент, который соответствует следующему:
- Первый элемент в диалоге с
autofocus
атрибут- Первый
:tabbable
элемент в содержании диалога- Первый
:tabbable
элемент в панели кнопок диалога- Кнопка закрытия диалога
- Сам диалог
Добавьте скрытый диапазон над ним, используйте ui-helper-hidden-available, чтобы сделать его скрытым путем абсолютного позиционирования. Я знаю, что у вас есть этот класс, потому что вы используете диалог из 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;
Это повлияет на все dialog
на странице без необходимости редактировать каждый вручную.
Оригинальная функция не делает ничего, кроме установки фокуса на первый элемент с помощью autofocus
атрибут / tabbable
элемент / или отступление к самому диалогу. Поскольку его использование - просто установка фокуса на элементе, не должно быть проблем с его заменой noop
,
Начиная с 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
Я нашел следующий код функции диалога 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 работает как обходной путь.
Просто понял это во время игры.
С этими решениями я обнаружил, что смещение фокуса привело к тому, что клавиша ESC перестала работать (т.е. закрывался диалог) при первом входе в диалог.
Если диалоговое окно открывается и вы сразу нажимаете ESC, оно не закрывает диалоговое окно (если оно включено), потому что фокус находится на каком-то скрытом поле или чем-то еще, и оно не получает события нажатия клавиши.
Я исправил это, добавив это к событию open, чтобы вместо этого убрать фокус с первого поля:
$('#myDialog').dialog({
open: function(event,ui) {
$(this).parent().focus();
}
});
Это устанавливает фокус на диалоговое окно, которое не отображается, и затем ключ ESC работает.
Мой обходной путь:
open: function(){
jQuery('input:first').blur();
jQuery('#ui-datepicker-div').hide();
},
Установите 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");
}
});
});
Простой обходной путь:
Просто создайте невидимый элемент с tabindex=1 ... Это не будет фокусировать средство выбора даты...
например.:
<a href="" tabindex="1"></a>
...
Here comes the input element
У меня был контент, который был длиннее, чем диалог. При открытии диалоговое окно переходит к первому: вкладка, которая находится внизу. Здесь было мое исправление.
$("#myDialog").dialog({
...
open: function(event, ui) { $(this).scrollTop(0); }
});
Вы можете предоставить эту опцию, вместо этого сфокусировать кнопку закрытия.
.dialog({
open: function () {
$(".ui-dialog-titlebar-close").focus();
}
});
Вот решение, которое я реализовал после прочтения билета 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;
}
Я искал другую проблему, но ту же причину. Проблема в том, что диалог установил фокус на первый <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>
получает фокус, но затем скрывается. Так что общий эффект - это желаемый эффект.
Я знаю, что это старая ветка, но что касается документации по пользовательскому интерфейсу, это не исправить. Это не требует размытия или фокусировки для работы. Не уверен, что это самый элегантный. Но это просто имеет смысл и легко объяснить кому угодно.
На мой взгляд, это решение очень приятно:
$("#dialog").dialog({
open: function(event, ui) {
$("input").blur();
}
});
Найдено здесь: невозможно удалить автофокус-в-UI-диалоге
Если у вас есть только одно поле в форме диалога Jquery, и именно оно требует Datepicker, в качестве альтернативы, вы можете просто установить фокус на диалоговом окне Закрыть (крестик) в строке заголовка диалога:
$('.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>
Это может быть поведение браузера, а не проблема с плагином jQuery. Вы пытались удалить фокус программно после открытия всплывающего окна.
$('#lnkAddReservation').click(function () {
dlg.dialog('open');
// you may want to change the selector below
$('input,textarea,select').blur();
return false;
});
Не проверял это, но должно работать хорошо.
У меня похожая проблема. Я открываю диалоговое окно с ошибкой, когда проверка не проходит, и она захватывает фокус, как это показывает Флуган в своем ответе. Проблема в том, что даже если ни один элемент внутри диалога не является вкладочным, само диалоговое окно все еще находится в фокусе. Вот оригинальный унифицированный код из 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);
};
Я бы применил ту же проблему и решил ее, вставив пустой ввод перед указателем даты, который захватывает фокус при каждом открытии диалога. Этот вход скрыт при каждом открытии диалога и снова отображается при закрытии.
Что ж, это круто, что пока никто не нашел решения, но, похоже, у меня есть кое-что для тебя. Плохая новость заключается в том, что диалог захватывает фокус в любом случае, даже если внутри нет входных данных и ссылок. Я использую диалог в качестве всплывающей подсказки, и определенно нужно, чтобы фокус оставался в исходном элементе. Вот мое решение:
используйте опцию [autoOpen: false]
$toolTip.dialog("widget").css("visibility", "hidden");
$toolTip.dialog("open");
$toolTip.dialog("widget").css("visibility", "visible");
Пока диалог невидим, фокус нигде не установлен и остается на прежнем месте. Он работает для всплывающих подсказок с простым текстом, но не тестируется для более функциональных диалогов, где может быть важно, чтобы диалог был виден в момент открытия. Вероятно, будет работать нормально в любом случае.
Я понимаю, что оригинальная публикация была просто для того, чтобы не фокусироваться на первом элементе, но вы можете легко решить, где должен быть фокус после открытия диалога (после моего кода).
Проверено в IE, FF и Chrome.
Надеюсь, это кому-нибудь поможет.
У меня та же проблема.
Обходной путь, который я сделал, это добавление пустого текстового поля в верхней части диалогового контейнера.
<input type="text" style="width: 1px; height: 1px; border: 0px;" />
У меня была похожая проблема, и я решил ее, сосредоточившись на диалоге после открытия:
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?)
Но в моем случае первый элемент - это якорь, поэтому я не знаю, если в вашем случае это оставит открытым указатель даты.
РЕДАКТИРОВАТЬ: работает только на IE
Выпущена jQuery 1.9, и, похоже, нет исправления. Попытка предотвратить фокусировку первого текстового поля некоторыми из предложенных методов не работает в 1.9. Я думаю, потому что методы пытаются размыть фокус или переместить фокус, ПОСЛЕ того, как текстовое поле в диалоге уже получило фокус и сделало свою грязную работу.
Я не вижу ничего в документации API, которая заставляет меня думать, что что-то изменилось с точки зрения ожидаемой функциональности. Выкл, чтобы добавить кнопку открывания...
У меня была похожая проблема. На моей странице первым вводом является текстовое поле с календарем пользовательского интерфейса 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();
});
Чтобы расширить некоторые из предыдущих ответов (и игнорировать вспомогательный аспект выбора даты), если вы хотите предотвратить focus()
событие от фокусировки первого поля ввода, когда ваш диалог открывается, попробуйте это:
$('#myDialog').dialog(
{ 'open': function() { $('input:first-child', $(this)).blur(); }
});
Это действительно важно для смартфонов и планшетов, потому что клавиатура появляется, когда фокус ввода находится в фокусе. Это то, что я сделал, добавьте этот ввод в начале div:
<input type="image" width="1px" height="1px"/>
Не работает с размером 0px
, Я думаю, что это даже лучше с реальным прозрачным изображением, либо .png
или же .gif
но я не пробовал
Работает нормально до сих пор в iPad.
Как уже упоминалось, это известная ошибка в jQuery UI, которая должна быть исправлена относительно скоро. До тех пор...
Вот еще один вариант, так что вам не нужно связываться с tabindex:
Временно отключите средство выбора даты, пока не откроется диалоговое окно:
dialog.find(".datepicker").datepicker("disable");
dialog.dialog({
"open": function() {$(this).find(".datepicker").datepicker("enable");},
});
Работает для меня.
Двойной вопрос: как размыть первый ввод формы при открытии диалога
найти в 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();
Вы можете добавить это:
...
dlg.dialog({ autoOpen:false,
modal: true,
width: 400,
open: function(){ // There is new line
$("#txtStartDate").focus();
}
});
...
В качестве первого ввода: <input type="text" style="position:absolute;top:-200px" />