jQuery dialog losing focus on scrolling
Asked Answered
N

6

13

I have a jQuery dialog below. I'm using jQuery UI 1.11.

$("#contactContainer").dialog({
  closeOnEscape: false,
  modal: true,
  dialogClass: 'contactsFooter', 
  open: function(event, ui) {
    $(".ui-dialog-titlebar-close").show();
    $('#dialog_footer').remove();
    $(".contactsFooter").append('<div class="" id="dialog_footer"><div class="dialog-footer-buttons"><button type="button" id ="close" class="button-style-2" onclick="$(\'#hasChangedForm\').val(\'\');" style="margin-left: 5px;">Cancel</button></div></div>');
  },
  autoOpen: false,          
  width: 300,
  minHeight: 'auto',
  maxHeight: 400,
  position: { my: 'top', at: 'top+50' },
  close:function() {
    $('#contactContainer').dialog("option", "position", { my:"top", at:"top+50", of: window });
    $('#contactContainer').html('');
  }
}); 

$("#contactContainer").dialog('open');

Here is the Fiddle. In that fiddle,

  1. Click any of the textbox (means focus. In this example it is the one we have the value "test here").

  2. Now scroll the dialog by clicking the scrollbar of the dialog and drag it down / up and see what is happening. It is loosing the focus on the textbox we clicked. If I press tab, it is setting the focus to the first field again. This is weird.

If I use mouse scroll, the focus is still there on the same field. This is normal.

Frankly, I don't know why this is happening. Can someone help me for how do I prevent the dialog loosing focus when scrolling? I want the focus to be retained on the same field.

Nightjar answered 14/9, 2016 at 7:29 Comment(0)
S
6

Fixed. The problem is the tabindex.

I let you a fiddle working. The trick is removing the tabindex just after the initialization of the dialog, it can be done like this:

$(".ui-dialog.ui-widget").removeAttr("tabindex")

If you want this behaviour to be permanent you can edit the jQuery source code. If you reach the dialog section you are going to see a function called _createWrapper. Inside, you can see something like this:

.attr( {

            // Setting tabIndex makes the div focusable
            tabIndex: -1,
            role: "dialog"
        } )

Remove the tabindex from there, and that's all!

Salome answered 16/9, 2016 at 8:43 Comment(7)
This is interesting.. What was the issue with tabindex. Can you explain?Nightjar
I can remember the proper explanation because I had to deal with the problem months ago. But the scrollbar is placed on the $(".ui-dialog") padding, so, when you click on the scrollbar is the same as clicking on the container, and that cause you to lose your focus. Removing the tabindez makes the element non-focusable, so when you click on it, you don't lose focus on your input. Then, in some place I can't remember JQuery UI has a proper handler to re add the focusable property in the right way.Arnuad
Yes, you are right!!! The issue is with tabindex, but in my case I can't remove it because the default browser navigation actions (spacebar and shift+spacebar) will work on the popup only if we added tabindex. If we remove tabindex when you press the shift+spacebar in the dialog, it will scroll the background screen only not the dialogNightjar
sorry @linga. I haven't tested in all the browsers, but at least, in chrome, it works well. If you open my fiddle and you try the "space/shit+space" navigation the scroll works as expected.Arnuad
Yes. you are right. May be I missed something. Let me checkNightjar
The tabindex is the issue.. Thank youNightjar
Glad it helped!Arnuad
P
2

I think this might help you a bit.

$('#divWithTheScrollbar').scroll(function() {
    $('#elementLosingFocus').focus();
});
Parbuckle answered 14/9, 2016 at 8:38 Comment(1)
Good idea but, I don't want to use this for all dialog I have. Need to know why this is happening with JQuery dialog. No?Nightjar
S
0

From having looked around on the web it seems like the most viable option you have is the one @pritishvaidya added.

You have to realize that the focus event is triggered when anything gets clicked on your page. Meaning that if you click the scrollbar whilst having your textbox in focus you will put that the scrollbar in focus and lose the focus of the textbox.

I'd suggest you implement the solution by @pritishvaidya, but add some sort of validation around it where you know which one of the controls was in focus last and then force focus on that when the scrollbar's focus has been lost. That would put minimal strain on the client as well as allow you to progress with your use-case.

Happy coding!

Stealer answered 16/9, 2016 at 8:30 Comment(1)
You are correct the focus event is triggered when anything gets clicked on your page. Meaning that if you click the scrollbar whilst having your textbox in focus you will put that the scrollbar in focus and lose the focus of the textbox. But, here the focus is setting to the first field again when I press tab. That's weird. No?Nightjar
P
0

Try this; its working(Not necessary to add id or other selectors with the inpus)

var focused;
setInterval(function(){
        focused = $(':focus');
},500)

$("#contactContainer").scroll(function(){
       //console.log(focused[0]);
       $(focused).focus();
})
Prophase answered 16/9, 2016 at 8:32 Comment(1)
This isn't the ideal solution to the problemNightjar
G
0

This might be a general solution but it needs to be tested:

var lastFocus;

$(document)
  .on("focus", function(e) { lastFocus = e.target; })

$("#divWithTheScrollbar").scroll(function () {
  if (lastFocus) lastFocus.focus();
})

It generally saves which element had focus last and sets it again when you scroll the div. You need to extend it so an intentional blur event will still work without the element being focused again after scroll.

Gerita answered 16/9, 2016 at 8:33 Comment(0)
P
0

Please try with following JavaScript update.

https://jsfiddle.net/3q22xLhk/5/ You can check on fiddle

$("#contactContainer").dialog({
  closeOnEscape: false,
  modal: true,
  dialogClass: 'contactsFooter',
  open: function(event, ui) {
    $(".ui-dialog-titlebar-close").show();
    $('#dialog_footer').remove();
    $(".contactsFooter").append('<div class="" id="dialog_footer"><div class="dialog-footer-buttons"><button type="button" id ="close" class="button-style-2" onclick="$(\'#hasChangedForm\').val(\'\');" style="margin-left: 5px;">Cancel</button></div></div>');
  },
  autoOpen: false,
  width: 300,
  minHeight: 'auto',
  maxHeight: 400,
  position: {
    my: 'top',
    at: 'top+50'
  },
  close: function() {
    $('#contactContainer').dialog("option", "position", {
      my: "top",
      at: "top+50",
      of: window
    });
    $('#contactContainer').html('');
  }
});
var scrolling = false;
$("#contactContainer").dialog('open');
var lastFocusTextbox = null;
$("#contactContainer input").focus(function() {
  lastFocusTextbox = this;
});

$("#contactContainer").scroll(function(e) {
  scrolling = true;
});


$("#contactContainer").mouseup(function() {
  if (scrolling) {
    if (lastFocusTextbox != null) {
      $(lastFocusTextbox).focus();
    }
    scrolling = false;
  }
});
Paid answered 16/9, 2016 at 8:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.