Рабочий код для v4.0 + * (включая 4.0.7)
Следующий код откроет меню в начальном фокусе, но не застрянет в бесконечном цикле, когда выделение перефокусируется после закрытия меню.
// on first focus (bubbles up to document), open the menu
$(document).on('focus', '.select2-selection.select2-selection--single', function (e) {
$(this).closest(".select2-container").siblings('select:enabled').select2('open');
});
// steal focus during close - only capture once and stop propogation
$('select.select2').on('select2:closing', function (e) {
$(e.target).data("select2").$selection.one('focus focusin', function (e) {
e.stopPropagation();
});
});
Объяснение
Предотвратить бесконечную петлю фокуса
Примечание: событие focus
запускается дважды.
- Один раз при переходе в поле
- Опять же при переходе на табуляцию с открытым раскрывающимся списком для восстановления фокуса
Мы можем предотвратить бесконечный цикл, ища различия между типами событий фокуса. Поскольку мы хотим открыть меню только при начальном фокусе на элементе управления, мы должны как-то различать следующие вызванные события:
Сделать это кроссбраузерным способом сложно, потому что браузеры отправляют разную информацию вместе с разными событиями, а также в Select2 было внесено множество незначительных изменений в их внутреннюю активацию событий, которые прерывают предыдущие потоки.
Один из способов, который кажется работающим, - это прикрепить обработчик событий во время события closing
для меню и использовать он предназначен для захвата надвигающегося focus
события и предотвращения его всплытия в DOM. Затем, используя делегированного слушателя, мы вызовем фактический фокус -> открытый код только тогда, когда событие focus
всплывает полностью до document
Запретить открытие отключенных элементов
Как отмечалось в этой проблеме с github # 4025 - Выпадающий список не открывается при фокусе вкладки, мы должны убедитесь, что мы вызываем 'open'
только для таких :enabled
элементов select:
$(this).siblings('select:enabled').select2('open');
Select2 обход DOM
Нам нужно немного пройти по DOM, поэтому вот карта структуры HTML, созданная Select2
Исходный код на GitHub
Вот некоторые из соответствующих разделов кода в игре:
.on('mousedown'
... _11 _ a>
.on('toggle'
... .toggleDropdown()
.toggleDropdown
... .open()
_ 16_ ... .trigger('focus'
_ 18_ ... $selection.focus()
Раньше открытие select2 срабатывало дважды, но это было исправлено в проблеме №3503 и это должно предотвратить некоторую дрянь
Похоже, что PR # 5357 нарушил предыдущий код фокуса, который работал в 4.05.
$('.select2').select2({});
// on first focus (bubbles up to document), open the menu
$(document).on('focus', '.select2-selection.select2-selection--single', function (e) {
$(this).closest(".select2-container").siblings('select:enabled').select2('open');
});
// steal focus during close - only capture once and stop propogation
$('select.select2').on('select2:closing', function (e) {
$(e.target).data("select2").$selection.one('focus focusin', function (e) {
e.stopPropagation();
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/css/select2.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.7/js/select2.js"></script>
<select class="select2" style="width:200px" >
<option value="1">Apple</option>
<option value="2">Banana</option>
<option value="3">Carrot</option>
<option value="4">Donut</option>
</select>
Протестировано в Chrome, FF, Edge, IE11
person
KyleMit
schedule
13.03.2018