11

Whenever I type something in the following Insert Hyperlink text input, all the words are going to textarea behind it. OK and Cancel buttons are working fine but I cannot focus to text input.

We'are using jQuery UI 1.10.1. It was working nicely with previous version of jQuery which was 1.8.x.

enter image description here

I've checked code behind of jQuery and it has the following methods called when opening a Modal Dialog:

_focusTabbable: function () {
    // Set focus to the first match:
    // 1. First element inside the dialog matching [autofocus]
    // 2. Tabbable element inside the content element
    // 3. Tabbable element inside the buttonpane
    // 4. The close button
    // 5. The dialog itself
    var hasFocus = this.element.find("[autofocus]");
    if (!hasFocus.length) {
        hasFocus = this.element.find(":tabbable");
    }
    if (!hasFocus.length) {
        hasFocus = this.uiDialogButtonPane.find(":tabbable");
    }
    if (!hasFocus.length) {
        hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
    }
    if (!hasFocus.length) {
        hasFocus = this.uiDialog;
    }
    hasFocus.eq(0).focus();
},

_keepFocus: function (event) {
    function checkFocus() {
        var activeElement = this.document[0].activeElement,
            isActive = this.uiDialog[0] === activeElement ||
                $.contains(this.uiDialog[0], activeElement);
        if (!isActive) {
            this._focusTabbable();
        }
    }
    event.preventDefault();
    checkFocus.call(this);
    // support: IE
    // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
    // so we check again later
    this._delay(checkFocus);
},

that is taken from here: http://code.jquery.com/ui/1.10.1/jquery-ui.js

Tarik
  • 79,711
  • 83
  • 236
  • 349
  • Interesting... I'm having a similar issue with anchor tags in a dialog box with a scrollbar for vertical content. If I scroll down and click anywhere in the dialog box, the focus scrolls back to the topmost anchor tag in the dialog box. I've traced it down to the code you're referencing, but I don't feel comfortable commenting out that code... nor should I have to... and I feel like unbinding is dirty. – incutonez May 10 '13 at 13:02
  • This is a bug in jQuery UI: http://bugs.jqueryui.com/ticket/9101 . Should be fixed in the next version. – Noyo Mar 14 '14 at 11:27
  • That bug is fixed in jQuery UI 1.11.0. That's the version I'm running but I still observe this problem. – Sam Kauffman Mar 17 '16 at 16:33

5 Answers5

11

Second answer I've found is that in the following code jQuery binds document to dialog. So when I unbind this when I click on the desired button's onclick event (or whatever event you're handling):

 if (window.jQuery && window.jQuery.ui.dialog) {
   $(document).unbind("focusin.dialog");
 }

This is where jQuery UI binds it _focusTabble() method to focusin.dialog event of document.

if ( !$.ui.dialog.overlayInstances ) {
            // Prevent use of anchors and inputs.
            // We use a delay in case the overlay is created from an
            // event that we're going to be cancelling. (#2804)
            this._delay(function() {
                // Handle .dialog().dialog("close") (#4065)
                if ( $.ui.dialog.overlayInstances ) {
                    this.document.bind( "focusin.dialog", function( event ) {
                        if ( !$( event.target ).closest(".ui-dialog").length &&
                                // TODO: Remove hack when datepicker implements
                                // the .ui-front logic (#8989)
                                !$( event.target ).closest(".ui-datepicker").length ) {
                            event.preventDefault();
                            $(".ui-dialog:visible:last .ui-dialog-content")
                                .data("ui-dialog")._focusTabbable();
                        }
                    });
                }
            });
        }
Tarik
  • 79,711
  • 83
  • 236
  • 349
  • This worked well for me. I execute that little block of code you posted up at the top, immediately before opening up a JavaScript SpellChecker... and now the focus is working correctly. Before the jquery dialog was stealing the focus. However, I only wonder if by removing this jQuery placed event handler we will cause something to break! – Jason Parker Sep 09 '13 at 20:38
  • Should be fixed in jQuery UI 1.11.0 when it's out: http://bugs.jqueryui.com/ticket/9101 . – Noyo Mar 14 '14 at 11:26
1

What I did to solve this problem is to comment out this $(".ui-dialog:visible:last .ui-dialog-content").data("ui-dialog")._focusTabbable();

You can find the complete code below:

    if ( !$.ui.dialog.overlayInstances ) {
        // Prevent use of anchors and inputs.
        // We use a delay in case the overlay is created from an
        // event that we're going to be cancelling. (#2804)
        this._delay(function() {
            // Handle .dialog().dialog("close") (#4065)
            if ( $.ui.dialog.overlayInstances ) {
                this.document.bind( "focusin.dialog", function( event ) {
                    if ( !$( event.target ).closest(".ui-dialog").length &&
                            // TODO: Remove hack when datepicker implements
                            // the .ui-front logic (#8989)
                            !$( event.target ).closest(".ui-datepicker").length ) {
                        event.preventDefault();
                        //$(".ui-dialog:visible:last .ui-dialog-content")
                            //.data("ui-dialog")._focusTabbable();
                    }
                });
            }
        });
    }
Tarik
  • 79,711
  • 83
  • 236
  • 349
1

Another way to stop blocking focus from jquery dialog

$.widget("ui.dialog", $.ui.dialog, {
    _allowInteraction: function (event) {
        return !!$(event.target).closest(".input-container").length || this._super(event);
    }
});

Where .input-container is container which contains controls that should receive focus.

YuriyP
  • 4,210
  • 4
  • 25
  • 35
1

thats because jquery prevents focus outside of dialog child, jquery has this method you can read, that will whitelist which other elements you want to allow focus.

"_allowInteraction( event )Returns: Boolean Modal dialogs do not allow users to interact with elements behind the dialog. This can be problematic for elements that are not children of the dialog, but are absolutely positioned to appear as though they are. The _allowInteraction() method determines whether the user should be allowed to interact with a given target element; therefore, it can be used to whitelist elements that are not children of the dialog but you want users to be able to use."

https://api.jqueryui.com/dialog/#method-_allowInteraction

So what i do to disable this "block focus" to some items with class .other-popups is add this line in the code

$.widget( "ui.dialog", $.ui.dialog, {
    _allowInteraction: function( event ) {
        return !!$( event.target ).closest( ".other-popups" ).length || this._super( event );
    }
});

Or to disable completly

 $.widget( "ui.dialog", $.ui.dialog, {
        _allowInteraction: function( event ) {
            return true ;
        }
    });
Miguel
  • 3,349
  • 2
  • 32
  • 28
0

I had a similar issue where I needed the focus to be within the content of my dialog box (for WCAG). Using focus() alone failed, so what my end solution was in the dialog instantiation I added:

focus: function(event, ui) {
                    setTimeout(function(){ 
                        $('#element').blur().focus().css({'color': '#000', 'text-decoration' : 'none', 'cursor' : 'default'});
                    }, 500);
                }

I used the timeout to ensure compatibility. *Note, I made the '#element' an anchor tag (interactive element) so the focus would take. That is the reason for the styling.

This code should be able to be added into the "open" function of the jQuery Dialog as well.

Bren1818
  • 2,612
  • 1
  • 23
  • 28