I have setup a jQuery UI modal dialog to display when a user clicks a link. There are two textboxes (I only show the code for 1 for brevity) in that dialog div tag and it is changed to be a jQuery UI DatePicker textbox that reacts on focus.
The problem is that the jQuery UI dialog('open') somehow triggers the first textbox to have focus, which then triggers the datepicker calendar to open immediately.
So I am looking for a way to prevent the focus from happening automatically.
<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>
-
it'll set focus even to an image! both to regular <img> tags - as well as <input type=image>Simon_Weaver– Simon_Weaver2011年02月17日 03:31:20 +00:00Commented Feb 17, 2011 at 3:31
30 Answers 30
Add a hidden span above it, use ui-helper-hidden-accessible to make it hidden by absolute positioning. I know you have that class because you are using dialog from jquery-ui and it's in jquery-ui.
<span class="ui-helper-hidden-accessible"><input type="text"/></span>
-
1Great work around. No js required, doesn't change the layout, and jquery ui support it natively.steampowered– steampowered2012年11月07日 18:33:20 +00:00Commented Nov 7, 2012 at 18:33
-
Agree, great work around. Also nice to know about hidden-accessible class! Thanks!!user1055761– user10557612012年11月24日 11:07:00 +00:00Commented Nov 24, 2012 at 11:07
-
4This causes problems for people using assistive technology (e.g. screen readers)rink.attendant.6– rink.attendant.62014年01月22日 04:33:10 +00:00Commented Jan 22, 2014 at 4:33
-
1@rink.attendant.6 which problems?oxfn– oxfn2015年04月11日 13:02:52 +00:00Commented Apr 11, 2015 at 13:02
-
amazing solutionPedro Coelho– Pedro Coelho2019年07月14日 01:42:43 +00:00Commented Jul 14, 2019 at 1:42
jQuery UI 1.10.0 Changelog lists ticket 4731 as being fixed.
Looks like focusSelector was not implemented, but a cascading search for various elements was used instead. From the ticket:
Extend autofocus, starting with [autofocus], then :tabbable content, then buttonpane, then close button, then dialog
So, mark an element with the autofocus
attribute and that is the element that should get the focus:
<input autofocus>
In the documentation, the focus logic is explained (just under the table of contents, under the title 'Focus'):
Upon opening a dialog, focus is automatically moved to the first item that matches the following:
- The first element within the dialog with the
autofocus
attribute- The first
:tabbable
element within the dialog's content- The first
:tabbable
element within the dialog's buttonpane- The dialog's close button
- The dialog itself
-
What's the downvote for? If it was because I listed 1.9 as the fix version, I have updated to 1.10 to match with the ticket.slolife– slolife2012年10月12日 20:37:38 +00:00Commented Oct 12, 2012 at 20:37
-
1I'm looking at the jquery-ui 1.10 documentation for Dialog, and I'm not seeing it. I searched for "focusSelector" in the api, and it's not there.Paul Tomblin– Paul Tomblin2013年03月26日 19:58:23 +00:00Commented Mar 26, 2013 at 19:58
-
3Setting focus to any element that is off screen scrolls the window up or down to that element, and this happens whenever the window gets focus, not only on dialog open. If I use Firebug to "inspect element" and then click back in the document window, my window scrolls up or down to whichever element jQuery-UI focused on. The question is not how to choose which element gets focus, but how to prevent focus. Choosing a different element to focus on would not solve the problem.Val Kornea– Val Kornea2014年11月17日 11:14:16 +00:00Commented Nov 17, 2014 at 11:14
-
5The idea that jQuery UI considers this 'fixed' is crazy. The fix is to remove any autofocusing logic altogether. I asked you to open a dialog, not focus on an input. So annoying.AJB– AJB2015年10月18日 07:17:05 +00:00Commented Oct 18, 2015 at 7:17
-
2fwiw, I added an input w/ type="hidden" above the first input and added autofocus attribute to it. It doesn't mean what you think it means, but it works for fixing this problem.jinglesthula– jinglesthula2016年01月13日 22:17:23 +00:00Commented Jan 13, 2016 at 22:17
In jQuery UI>= 1.10.2, you can replace the _focusTabbable
prototype method by a placebo function:
$.ui.dialog.prototype._focusTabbable = $.noop;
This will affect all dialog
s in the page without requiring to edit each one manually.
The original function does nothing but setting the focus to the first element with autofocus
attribute / tabbable
element / or falling back to the dialog itself. As its use is just setting focus on an element, there should be no problem replacing it by a noop
.
-
7Hours and hours and hours and hours burned on this. My client thanks you.lamarant– lamarant2014年03月24日 06:31:44 +00:00Commented Mar 24, 2014 at 6:31
-
2 days searched for this solutions... nothing else worked... Thanks a lot!Legionar– Legionar2015年09月30日 08:51:47 +00:00Commented Sep 30, 2015 at 8:51
-
1Warning: when the dialog pops up, pressing the Escape key won't close the dialog (until you focus the dialog).Robert– Robert2016年07月27日 07:38:51 +00:00Commented Jul 27, 2016 at 7:38
-
1@Robert, instead of replacing it with
$.noop
, replace it with a function that notes down the active dialog, then register a global key event handler that interceptsESC
and closes the 'active' dialog if there is one.Perkins– Perkins2016年09月15日 21:51:32 +00:00Commented Sep 15, 2016 at 21:51
Starting from jQuery UI 1.10.0, you can choose which input element to focus on by using the HTML5 attribute autofocus.
All you have to do is create a dummy element as your first input in the dialog box. It will absorb the focus for you.
<input type="hidden" autofocus="autofocus" />
This has been tested in Chrome, Firefox and Internet Explorer (all latest versions) on February 7, 2013.
http://jqueryui.com/upgrade-guide/1.10/#added-ability-to-specify-which-element-to-focus-on-open
I found the following code the jQuery UI dialog function for open.
c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();
You can either workaround the jQuery behaviour or change the behaviour.
tabindex -1 works as a workaround.
-
1Won't tabindex=-1 prevent me from tabbing to the textbox?slolife– slolife2009年07月29日 21:50:29 +00:00Commented Jul 29, 2009 at 21:50
-
2Thanks for the research. Now I know that it is actual code that is doing it. I might make a suggestion to the jQuery UI team to add an option to disable this auto-focus.slolife– slolife2009年07月29日 22:42:21 +00:00Commented Jul 29, 2009 at 22:42
-
3@slolife - Sorry to resurrect this really old thread, but that ticket says the fix (the
focusSelector
option) is supposed to be in jQueryUI 1.8, and we're now at 1.8.13 and I don't see it in the jQueryUI dialog docs. What happened to this?Tom Hamming– Tom Hamming2011年06月27日 20:07:00 +00:00Commented Jun 27, 2011 at 20:07 -
Never mind. I had seen "Milestone changed from TBD to 1.8" in the modification history, and had not noticed that it actually says 1.9 at the top.Tom Hamming– Tom Hamming2011年06月27日 21:09:34 +00:00Commented Jun 27, 2011 at 21:09
-
I have a similar problem, my workaround is described here - stackoverflow.com/a/12250193/80002mark– mark2012年09月03日 14:57:32 +00:00Commented Sep 3, 2012 at 14:57
Just figured this out while playing around.
I found with these solutions to remove focus, caused the ESC key to stop working (ie close the dialog) when first going into the Dialog.
If the dialog opens and you immediately press ESC, it won't close the dialog (if you have that enabled), because the focus is on some hidden field or something, and it is not getting keypress events.
The way I fixed it was to add this to the open event to remove the focus from the first field instead:
$('#myDialog').dialog({
open: function(event,ui) {
$(this).parent().focus();
}
});
This sets focus to the dialog box, which is not visible, and then the ESC key works.
-
3This seems the only working solution, that doesn't include adding useless HTML, removing tabindex or breaking the ESC key.Bojan Bedrač– Bojan Bedrač2016年12月16日 09:39:03 +00:00Commented Dec 16, 2016 at 9:39
Set the tabindex of the input to -1, and then set dialog.open to restore tabindex if you need it later:
$(function() {
$( "#dialog-message" ).dialog({
modal: true,
width: 500,
autoOpen: false,
resizable: false,
open: function()
{
$( "#datepicker1" ).attr("tabindex","1");
$( "#datepicker2" ).attr("tabindex","2");
}
});
});
My workaround:
open: function(){
jQuery('input:first').blur();
jQuery('#ui-datepicker-div').hide();
},
-
+1. Works like a charm using
:first
selector or.first()
in FF/Chrome/IE9. Throwing it into thedialogopen
binding works too.nickb– nickb2012年03月30日 03:06:50 +00:00Commented Mar 30, 2012 at 3:06 -
This one got me there, too. Except with me, my dialog had no inputs at all, and the first link was getting focus... so I added this option to my jQuery dialog:
open: function(){ $('a').blur(); // no autofocus on links }
Marcus– Marcus2013年04月08日 14:07:07 +00:00Commented Apr 8, 2013 at 14:07
I had content that was longer than the dialog. On open, the dialog would scoll to the first :tabbable which was at the bottom. Here was my fix.
$("#myDialog").dialog({
...
open: function(event, ui) { $(this).scrollTop(0); }
});
-
This worked for me, but I used
$('...').blur();
instead of scrolling.Jawa– Jawa2010年12月07日 08:41:43 +00:00Commented Dec 7, 2010 at 8:41 -
4My content was also very long. blur removed the selection, but left the dialog scrolled to the bottom. scrollTop scrolled the content to the top but left the selection. I ended up using $('...').blur(); $(this).scrollTop(0); worked like a champ.user82646– user826462011年01月28日 19:18:08 +00:00Commented Jan 28, 2011 at 19:18
Simple workaround:
Just create a invisible element with tabindex=1 ... This will not focus the datepicker ...
eg.:
<a href="" tabindex="1"></a>
...
Here comes the input element
-
Works fine in ie9 and firefox, but not safari/chrome.tuseau– tuseau2012年07月23日 14:25:41 +00:00Commented Jul 23, 2012 at 14:25
Here is the solution I implemented after reading through jQuery UI ticket #4731, originally posted by slolife as a response to another answer. (The ticket was also created by him.)
First, in whatever method you use to apply autocompletes to the page, add the following line of code:
$.ui.dialog.prototype._focusTabbable = function(){};
That disables jQuery's "auto-focus" behavior. To ensure that your site continues to be broadly accessible, wrap your dialog creation methods so that additional code can be added, and add a call to focus the first input element:
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();
}
To further address accessibility when autocomplete options are selected via keyboard, we override jQuery UI's "select" autocomplete callback and add some additional code to ensure the textElement does not lose focus in IE 8 after making a selection.
Here is the code we use to apply autocompletes to elements:
$.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;
}
You may provide this option, to focus the close button instead.
.dialog({
open: function () {
$(".ui-dialog-titlebar-close").focus();
}
});
This can be a browser behavior not jQuery plugin issue. Have you tried removing the focus programmatically after you open the popup.
$('#lnkAddReservation').click(function () {
dlg.dialog('open');
// you may want to change the selector below
$('input,textarea,select').blur();
return false;
});
Haven't tested that but should work ok.
-
1sadly this doesn't work. not sure if it's an IE thing, or a jquery UI thing. but even if you move the focus to something else programatically, the calendar stays open.Patricia– Patricia2010年09月17日 17:37:43 +00:00Commented Sep 17, 2010 at 17:37
I'd the same issue and solved it by inserting an empty input before the datepicker, that steals the focus every time the dialog is opened. This input is hidden on every opening of the dialog and shown again on closing.
Well, it is cool that nobody found the solution for now, but it looks like I have something for you. The bad news is that the dialog grabs focus in any case even if no inputs and links are inside. I use the dialog as a tooltip and definitely need focus stay in the original element. Here is my solution:
use option [autoOpen: false]
$toolTip.dialog("widget").css("visibility", "hidden");
$toolTip.dialog("open");
$toolTip.dialog("widget").css("visibility", "visible");
While the dialog invisible, the focus is not set anywhere and stay in the original place. It works for tooltips with just a plain text, but not tested for more functional dialogs where it may be important to have dialog visible on opening moment. Probably will work fine in any case.
I understand that the original post was just to avoid getting focus on the first element, but you can easily decide where the focus should be after the dialog is opened (after my code).
Tested in IE, FF and Chrome.
Hopefully this will help somebody.
In my opinion this solution is very nice:
$("#dialog").dialog({
open: function(event, ui) {
$("input").blur();
}
});
Found here: unable-to-remove-autofocus-in-ui-dialog
I have a similar problem. I open an error dialog when validation fails and it grabs the focus, just like Flugan shows it in his answer. The problem is that even if no element inside the dialog is tabbable, the dialog itself is still focused. Here is the original unminified code from 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();
The comment is theirs!
This is really bad for me for several reasons. The most annoying thing is that the first reaction of the user is to hit the backspace to delete the last character, but instead (s)he is prompted to leave the page, because the backspace is hit outside an input control.
I found that the following workaround works pretty good for me:
jqueryFocus = $.fn.focus;
$.fn.focus = function (delay, fn) {
jqueryFocus.apply(this.filter(':not(.ui-dialog)'), arguments);
};
-
This can be extended to only affect specific dialog's by using the 'dialogClass' option in .dialog() and then altering the above :not filter to include your class. e.g :not(.ui-dialog.myDialogClass)Andrew Martinez– Andrew Martinez2012年11月26日 18:45:19 +00:00Commented Nov 26, 2012 at 18:45
I was looking around for a different issue but same cause. The issue is that the dialog set focus to the first <a href="">.</a>
it finds. So if you have a lot of text in your dialog and scroll bars appear you could have the situation where the scroll bar will be scrolled to the bottom. I believe this also fixes the first persons question. Although the others do as well.
The simple easy to understand fix.
<a id="someid" href="#">.</a>
as the first line in your dialog div.
EXAMPLE:
<div id="dialogdiv" title="some title"> <a id="someid" href="#">.</a> <p> //the rest of your stuff </p> </div>
Where your dialog is initiated
$(somediv).dialog({ modal: true, open: function () { $("#someid").hide(); otherstuff or function }, close: function () { $("#someid").show(); otherstuff or function } });
The above will have nothing focused and the scroll bars will remain at the top where it belongs. The <a>
gets focus but is then hidden. So the overall effect is the desired effect.
I know this is an old thread but as for as the UI docs there is no fix to this. This does not require blur or focus to work. Not sure if it is the most elegant. But it just makes sense and easy to explain to anyone.
If you only have one field in the form of Jquery dialog and it is the one that needs Datepicker, alternatively, you can just set focus on dialog Close (cross) button in dialog's title bar:
$('.ui-dialog-titlebar-close').focus();
Call this AFTER dialog was initialized, e.g.:
$('#yourDialogId').dialog();
$('.ui-dialog-titlebar-close').focus();
Because close button is rendered after the .dialog()
is called.
If you're using dialog buttons, just set the autofocus
attribute on one of the buttons:
$('#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>
I got the same problem.
The workaround I did is add the dummy textbox at the top of the dialog container.
<input type="text" style="width: 1px; height: 1px; border: 0px;" />
As mentioned, this is a known bug with jQuery UI and should be fixed relatively soon. Until then...
Here's another option, so you don't have to mess with tabindex:
Disable the datepicker temporarily until the dialog box opens:
dialog.find(".datepicker").datepicker("disable");
dialog.dialog({
"open": function() {$(this).find(".datepicker").datepicker("enable");},
});
Works for me.
Duplicate question: How to blur the first form input at the dialog opening
To expand on some of the previous answers (and ignoring the ancillary datepicker aspect), if you want to prevent the focus()
event from focusing the first input field when your dialog opens, try this:
$('#myDialog').dialog(
{ 'open': function() { $('input:first-child', $(this)).blur(); }
});
I had a similar problem and solved it by focusing on the dialog after open:
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?)
But in my case the first element is an anchor, so I don't know if in your case that will leave the datepicker opened.
EDIT: only works on IE
find in jquery.ui.js
d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();
and replace with
d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(-1).focus();
jQuery 1.9 is released and there does not appear to be a fix. Attempting to prevent focus of the first text box by some of the suggested methods is not working in 1.9. I think beccause the methods attempt to blur focus or move focus occur AFTER the text box in the dialog has already gained focus and done its dirty work.
I can't see anything in the API documentation that makes me think that anything has changed in terms of expected functionality. Off to add an opener button...
-
The fix has now been pushed to 1.10 according to the jQuery ticket: bugs.jqueryui.com/ticket/4731slolife– slolife2012年10月11日 14:59:56 +00:00Commented Oct 11, 2012 at 14:59
I had similar problem. On my page first input is text box with jQuery UI calendar. Second element is button. As date already have value, I set focus on button, but first add trigger for blur on text box. This solve problem in all browsers and probably in all version of jQuery. Tested in version 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();
});
This is really important for smartphones and tablets because the keyboard comes up when an input has the focus. This is what I've done, add this input at the beginning of the div:
<input type="image" width="1px" height="1px"/>
Doesn't work with size 0px
. I guess it's even better with a real transparent image, either .png
or .gif
but I haven't tried.
Working fine so far in iPad.
You can Add this :
...
dlg.dialog({ autoOpen:false,
modal: true,
width: 400,
open: function(){ // There is new line
$("#txtStartDate").focus();
}
});
...
-
3He's asking how to prevent focus, not add focus.Chris Barr– Chris Barr2012年03月22日 14:56:30 +00:00Commented Mar 22, 2012 at 14:56
as first input : <input type="text" style="position:absolute;top:-200px" />