Tabbing without breaking order when opening


#1

I can’t seem to quite get this to work. I tried this

field.select2(argArray).data('select2').listeners['*'].push(function(name, target) {
    if(name == 'focus') {
        $(this.$element).select2("open");
    }
});

and this

    field.data('select2').$selection.on('focus', function(e) {
    $(this).parent().parent().siblings('select');
    field.select2('open');
});

But in both cases they screwed up the tab order. Once the select2 opened if I tried to tab to the next one it reopened the first one. If I don’t auto open them then the tab through order is fine. How can I tab through with auto opening but not screw up the tab order?

I’m using version 4.0.7-rc


#2

Since your code snippets are out of context, it’s hard to troubleshoot from them. Can you put your code on jsfiddle.net or codepen.io so I can reproduce the problem you described?


#3

I have made a mock up of the issue here.

https://codepen.io/daemon-byte/pen/MdzGbW

when you press tab it moves into the first select and opens it. No issues. But then the tab order is broken because when you press tab again you go back to the first select and it opens. Basically you can’t tab past the first one.


#4

The reason you’re seeing this behavior is that you are forcing the Select2 open when focus is on the Select2. Select2 returns focus to this element when the dropdown closes, so your focus handler immediately forces it back open.

My suggestion is to remove your focus handler. Normal HTML <select> controls do not automatically open when they receive focus (especially via the keyboard), but rather when they are selected (i.e., clicked). Since Select2 already opens when it is clicked (or the keyboard equivalent—pressing Enter when the control has focus), you don’t need any special logic at all.

That said, if you really want to make the Select2 open on focus, then you need to add some extra logic to keep it from re-opening when focus returns to it after the dropdown has closed. This code works:

$(function() {
  $('select').each(function() {
    var field = $(this);
    var openOnFocus = true;
    field.select2({
      minimumResultsForSearch: 5,
      width: '7rem'
    });
    field.on("select2:closing", function () {
      openOnFocus = false;
    });
    field.data('select2').$selection.on('focus', function() {
      openOnFocus && field.select2('open');
      setTimeout(() => { openOnFocus = true; }, 500);
    });
  });
});

Note that I had to remove your closeOnSelect (or selectOnClose, I don’t recall which one), and put in a small delay before setting the openOnFocus flag back to true so the second focus event (after the dropdown closes) doesn’t trigger the Select2 open method.


#5

I completely agree with you but alas my arguments fell and it must be done. Thanks for the insight, I never considered that happening. I was to busy trying to fix a different problem that wasn’t my issue :slight_smile:


#6

Well I certainly understand having requirements from higher up the management chain, even if they’re not the most informed.

Good luck with your project.