Prevent jQuery UI dialog from setting focus to first textbox

JavascriptJqueryJquery Ui

Javascript Problem Overview


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>

Javascript Solutions


Solution 1 - Javascript

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: > > 1. The first element within the dialog with the autofocus attribute > 2. The first :tabbable element within the dialog's content > 3. The first :tabbable element within the dialog's buttonpane > 4. The dialog's close button > 5. The dialog itself

Solution 2 - Javascript

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>

Solution 3 - Javascript

In jQuery UI >= 1.10.2, you can replace the _focusTabbable prototype method by a placebo function:

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

Fiddle

This will affect all dialogs 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.

Solution 4 - Javascript

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

Solution 5 - Javascript

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.

Solution 6 - Javascript

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.

Solution 7 - Javascript

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");
		}
	});
});

Solution 8 - Javascript

My workaround:

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

Solution 9 - Javascript

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

Solution 10 - Javascript

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

Solution 11 - Javascript

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

Solution 12 - Javascript

You may provide this option, to focus the close button instead.

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

Solution 13 - Javascript

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.

Solution 14 - Javascript

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.

Solution 15 - Javascript

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.

Solution 16 - Javascript

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

Solution 17 - Javascript

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

Solution 18 - Javascript

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:

>

> . >

> //the rest of your stuff >

>

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.

Solution 19 - Javascript

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.

Solution 20 - Javascript

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>

Solution 21 - Javascript

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;" />

Solution 22 - Javascript

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: https://stackoverflow.com/questions/5418138/how-to-blur-the-first-form-input-at-the-dialog-opening/5423943#5423943

Solution 23 - Javascript

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

Solution 24 - Javascript

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

Solution 25 - Javascript

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

Solution 26 - Javascript

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

Solution 27 - Javascript

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

Solution 28 - Javascript

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.

Solution 29 - Javascript

You can Add this :

...

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

...

Solution 30 - Javascript

as first input : <input type="text" style="position:absolute;top:-200px" />

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionslolifeView Question on Stackoverflow
Solution 1 - JavascriptslolifeView Answer on Stackoverflow
Solution 2 - JavascriptPatrick Lee ScottView Answer on Stackoverflow
Solution 3 - JavascriptFabrício MattéView Answer on Stackoverflow
Solution 4 - JavascriptsilkfireView Answer on Stackoverflow
Solution 5 - Javascriptuser53067View Answer on Stackoverflow
Solution 6 - JavascriptRob DonovanView Answer on Stackoverflow
Solution 7 - JavascriptredsquareView Answer on Stackoverflow
Solution 8 - JavascriptThomasView Answer on Stackoverflow
Solution 9 - JavascriptthetoolmanView Answer on Stackoverflow
Solution 10 - JavascriptAndyView Answer on Stackoverflow
Solution 11 - Javascriptuser1630889View Answer on Stackoverflow
Solution 12 - JavascriptJay DubalView Answer on Stackoverflow
Solution 13 - JavascriptRaYellView Answer on Stackoverflow
Solution 14 - JavascriptManuel LeuenbergerView Answer on Stackoverflow
Solution 15 - JavascriptRocView Answer on Stackoverflow
Solution 16 - JavascriptemolahView Answer on Stackoverflow
Solution 17 - JavascriptmarkView Answer on Stackoverflow
Solution 18 - JavascriptMikeFView Answer on Stackoverflow
Solution 19 - Javascriptmikhail-tView Answer on Stackoverflow
Solution 20 - JavascriptSamView Answer on Stackoverflow
Solution 21 - JavascriptTTCGView Answer on Stackoverflow
Solution 22 - JavascriptBMinerView Answer on Stackoverflow
Solution 23 - JavascriptnickbView Answer on Stackoverflow
Solution 24 - JavascriptdaniloquioView Answer on Stackoverflow
Solution 25 - Javascriptuser1443069View Answer on Stackoverflow
Solution 26 - JavascriptpixeldaView Answer on Stackoverflow
Solution 27 - Javascriptuser1698635View Answer on Stackoverflow
Solution 28 - JavascriptÁngel ArbetetaView Answer on Stackoverflow
Solution 29 - JavascriptKhofidin OfidView Answer on Stackoverflow
Solution 30 - Javascriptuser2816796View Answer on Stackoverflow