[javascript] Prevent jQuery UI dialog from setting focus to first textbox

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>

This question is related to javascript jquery jquery-ui

The answer is


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.


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

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


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

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

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>

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

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.


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.


My workaround:

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

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


If you're using dialog buttons, just set the autofocus attribute on one of the buttons:

_x000D_
_x000D_
$('#dialog').dialog({_x000D_
  buttons: [_x000D_
    {_x000D_
      text: 'OK',_x000D_
      autofocus: 'autofocus'_x000D_
    },_x000D_
    {_x000D_
      text: 'Cancel'_x000D_
    }_x000D_
  ]_x000D_
});
_x000D_
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>_x000D_
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>_x000D_
<link href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet"/>_x000D_
_x000D_
<div id="dialog" title="Basic dialog">_x000D_
  This is some text._x000D_
  <br/>_x000D_
  <a href="www.google.com">This is a link.</a>_x000D_
  <br/>_x000D_
  <input value="This is a textbox.">_x000D_
</div>
_x000D_
_x000D_
_x000D_


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.


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

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

});   


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


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.


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

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

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.


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


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.


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


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.


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


You can Add this :

...

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

...


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

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

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

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to jquery-ui

How to auto adjust the div size for all mobile / tablet display formats? jQuery not working with IE 11 JavaScript Uncaught ReferenceError: jQuery is not defined; Uncaught ReferenceError: $ is not defined Best Practice to Organize Javascript Library & CSS Folder Structure Change table header color using bootstrap How to get HTML 5 input type="date" working in Firefox and/or IE 10 Form Submit jQuery does not work Disable future dates after today in Jquery Ui Datepicker How to Set Active Tab in jQuery Ui How to use source: function()... and AJAX in JQuery UI autocomplete