Подтвердить что ты не робот

Выделить раскрывающееся меню Select2

У меня есть форма с несколькими текстовыми вводами и некоторыми элементами select2. Использование клавиатуры для вкладок между полями отлично работает - элемент Select2 ведет себя как элемент формы и получает фокус при табуляции. Мне было интересно, можно ли открыть раскрывающийся список, когда элемент Select2 получает фокус.

Вот что я пробовал до сих пор:

$("#myid").select2().on('select2-focus', function(){
     $(this).select2('open');
});

Но с помощью этого кода выпадающее меню открывается снова после выбора.

4b9b3361

Ответ 1

Окончательное решение

Вы должны использовать следующий код, чтобы открыть контейнер select2 для всех событий фокуса (tab + click):

$(document).on('focus', '.select2.select2-container', function (e) {

  var isOriginalEvent = e.originalEvent // don't re-open on closing focus event
  var isSingleSelect = $(this).find(".select2-selection--single").length > 0

  if (isOriginalEvent && isSingleSelect) {
    $(this).siblings('select:enabled').select2('open');
  } 

});

Вот почему

Предотвратить бесконечный фокус

Событие focus запускается дважды

  1. Один раз, когда вкладка в поле
  2. Снова при вкладке с открытым раскрывающимся списком, чтобы восстановить фокус

Мы можем предотвратить бесконечный цикл, ища различия между типами событий фокуса. Мы можем использовать наличие originalEvent чтобы идентифицировать начальное событие фокуса.

Таким образом, мы можем изменить оригинальный код rain01 следующим образом:

$(document).on('focus', '.select2', function (e) {
  if (e.originalEvent) { $(this).siblings('select').select2('open'); } 
});

Предотвратить открытие отключено Выбирает

Как отмечалось в этом выпуске github № 4025 - Раскрывающийся список не открывается в фокусе вкладки, мы должны убедиться, что мы вызываем только 'open' on :enabled элементы select вроде этого:

$(this).siblings('select:enabled').select2('open');

Обновление до 4.0.5

Вот некоторые из соответствующих разделов кода в игре

.on('mousedown'... .trigger('toggle')
.on('toggle'... .toggleDropdown()
.toggleDropdown... .open()

Раньше случалось так, что открытие select2 сработало дважды, но это было исправлено в выпуске # 3503, и это должно предотвратить некоторый рывок

Рабочая демонстрация в jsFiddle & Stack Snippets:

$('.select2').select2({});

$(document).on('focus', '.select2.select2-container', function (e) {
  
  var isOriginalEvent = e.originalEvent // don't re-open on closing focus event
  var isSingleSelect = $(this).find(".select2-selection--single").length > 0 // multi-select will pass focus to input

  if (isOriginalEvent && isSingleSelect) {
    $(this).siblings('select:enabled').select2('open');
  } 

});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/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.5/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>

Ответ 2

Для версии 3.5.4 (30 августа 2015 г. и ранее)

Текущий ответ применим только к версиям 3.5.4 и более ранним, где select2 срабатывает размытие и фокусировка (select2-focus & select2-blur). Он прикрепляет обработчик одноразового использования, используя $.one чтобы поймать начальный фокус, а затем повторно присоединяет его во время размытия для последующих применений.

$('.select2').select2({})
  .one('select2-focus', OpenSelect2)
  .on("select2-blur", function (e) {
    $(this).one('select2-focus', OpenSelect2)
  })

function OpenSelect2() {
  var $select2 = $(this).data('select2');
  setTimeout(function() {
    if (!$select2.opened()) { $select2.open(); }
  }, 0);  
}

Я попробовал оба ответа @irvin-dominin-aka-edward, но также столкнулся с обеими проблемами (необходимость дважды щелкнуть раскрывающийся список, и Firefox выдает "событие не определено").

Я нашел решение, которое, кажется, решает две проблемы и еще не сталкивалось с другой проблемой. Это основано на ответах @irvin-dominin-aka-edward, изменив функцию select2Focus, чтобы вместо выполнения остального кода сразу обернуть его в setTimeout.

Демо в jsFiddle & Stack Snippets

$('.select2').select2({})
  .one('select2-focus', OpenSelect2)
  .on("select2-blur", function (e) {
    $(this).one('select2-focus', OpenSelect2)
  })

function OpenSelect2() {
  var $select2 = $(this).data('select2');
  setTimeout(function() {
    if (!$select2.opened()) { $select2.open(); }
  }, 0);  
}
body {
  margin: 2em;
}

.form-control {
  width: 200px;  
  margin-bottom: 1em;
  padding: 5px;
  display: flex;
  flex-direction: column;
}

select {
  border: 1px solid #aaa;
  border-radius: 4px;
  height: 28px;
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.js"></script>

  
  <div class="form-control">
    <label for="foods1" >Normal</label>
    <select id="foods1" >
      <option value=""></option>
      <option value="1">Apple</option>
      <option value="2">Banana</option>
      <option value="3">Carrot</option>
      <option value="4">Donut</option>
    </select>
</div>

<div class="form-control">
  <label for="foods2" >Select2</label>
  <select id="foods2" class="select2" >
    <option value=""></option>
    <option value="1">Apple</option>
    <option value="2">Banana</option>
      <option value="3">Carrot</option>
      <option value="4">Donut</option>
    </select>
  </div>

Ответ 3

Что-то легкое, что будет работать на всех экземплярах select2 на странице.

$(document).on('focus', '.select2', function() {
    $(this).siblings('select').select2('open');
});

ОБНОВЛЕНИЕ: Приведенный выше код не работает должным образом в IE11/Select2 4.0.3

PS: также добавлен фильтр для выбора только single полей выбора. Выбрать с помощью атрибута multiple не нужно, и он, вероятно, сломается, если применяется.

var select2_open;
// open select2 dropdown on focus
$(document).on('focus', '.select2-selection--single', function(e) {
    select2_open = $(this).parent().parent().siblings('select');
    select2_open.select2('open');
});

// fix for ie11
if (/rv:11.0/i.test(navigator.userAgent)) {
    $(document).on('blur', '.select2-search__field', function (e) {
        select2_open.select2('close');
    });
}

Ответ 4

Вероятно, после того, как выбор сделан, срабатывает событие select2-focus.

Единственный способ, которым я нашел, - это комбинация событий select2-focus и select2-blur и обработчик событий jQuery one.

Итак, в первый раз, когда элемент получает фокус, select2 открывается один раз (из-за одного), когда элемент размыт, один обработчик событий снова подключен и т.д.

код:

$('#test').select2({
    data: [{
        id: 0,
        text: "enhancement"
    }, {
        id: 1,
        text: "bug"
    }, {
        id: 2,
        text: "duplicate"
    }, {
        id: 3,
        text: "invalid"
    }, {
        id: 4,
        text: "wontfix"
    }],
    width: "300px"
}).one('select2-focus', select2Focus).on("select2-blur", function () {
    $(this).one('select2-focus', select2Focus)
})

function select2Focus() {
    $(this).select2('open');
}

Демо: http://jsfiddle.net/IrvinDominin/fnjNb/

UPDATE

Чтобы щелкнуть мышью, вы должны проверить событие, которое запускает обработчик, оно должно запускать метод open только в том случае, если событие focus

код:

function select2Focus() {
    if (/^focus/.test(event.type)) {
        $(this).select2('open');
    }
}

Демо: http://jsfiddle.net/IrvinDominin/fnjNb/4/

ОБНОВЛЕНИЕ ДЛЯ SELECT2 V 4.0

select2 v 4.0 изменил свой API и сбросил пользовательские события (см. https://github.com/select2/select2/issues/1908). Поэтому необходимо изменить способ обнаружения фокуса на нем.

код:

$('.js-select').select2({
    placeholder: "Select",
    width: "100%"
})

$('.js-select').next('.select2').find('.select2-selection').one('focus', select2Focus).on('blur', function () {
    $(this).one('focus', select2Focus)
})

function select2Focus() {
    $(this).closest('.select2').prev('select').select2('open');
}

Демо: http://jsfiddle.net/IrvinDominin/xfmgte70/

Ответ 5

немного поздно... но поделиться своим кодом с помощью select2 4.0.0

$("#my_id").select2();
$("#my_id").next(".select2").find(".select2-selection").focus(function() {
    $("#my_id").select2("open");
});

Ответ 6

Вот альтернативное решение для версии 4.x Select2. Вы можете использовать слушатели, чтобы поймать фокусное событие, а затем откройте выбор.

$('#test').select2({
    // Initialisation here
}).data('select2').listeners['*'].push(function(name, target) { 
    if(name == 'focus') {
        $(this.$element).select2("open");
    }
});

Найдите рабочий пример здесь на основе примера, созданного @tonywchen

Ответ 7

Проблема заключается в том, что внутреннее фокусное событие не преобразуется в событие jQuery, поэтому я модифицировал плагин и добавил событие focus в EventRelay в строке 2063 Select2 4.0.3:

EventRelay.prototype.bind = function (decorated, container, $container) {
    var self = this;
    var relayEvents = [
      'open', 'opening',
      'close', 'closing',
      'select', 'selecting',
      'unselect', 'unselecting',
      'focus'
    ];

Тогда достаточно открыть select2, когда происходит фокус:

$('#select2').on('select2:focus', function(evt){
    $(this).select2('open');
});

Хорошо работает на Chrome 54, IE 11, FF 49, Opera 40

Ответ 8

Ответ KyleMit работал для меня (спасибо!), Но я заметил, что с элементами select2, которые позволяют искать, попытка перехода к следующему элементу не будет работать (порядок вкладок был фактически потерян), поэтому я добавил код, чтобы вернуть фокус обратно к основному элементу select2 при закрытии выпадающего меню:

$(document).on('focus', '.select2', function (e) {
    if (e.originalEvent) {
        var s2element = $(this).siblings('select');
        s2element.select2('open');

        // Set focus back to select2 element on closing.
        s2element.on('select2:closing', function (e) {
            s2element.select2('focus');
        });
    }
});

Ответ 9

Я попробовал несколько из них и, наконец, придумал следующее, что работает для меня с Select2 4.0.1. Элемент - это элемент <select>.

$.data(element).select2.on("focus", function (e) {
    $(element).select2("open");
});

Ответ 10

Для меня, используя Select2.full.js Версия 4.0.3, ни одно из вышеперечисленных решений не работало так, как должно быть. Поэтому я написал комбинацию решений выше. Прежде всего, я изменил Select2.full.js, чтобы перенести события внутреннего фокуса и размытия на события jquery, как это сделал "Thomas Molnar" в своем ответе.

EventRelay.prototype.bind = function (decorated, container, $container) {
    var self = this;
    var relayEvents = [
      'open', 'opening',
      'close', 'closing',
      'select', 'selecting',
      'unselect', 'unselecting',
      'focus', 'blur'
    ];

И затем я добавил следующий код для обработки фокуса и размытия и фокусировки следующего элемента

$("#myId").select2(   ...   ).one("select2:focus", select2Focus).on("select2:blur", function ()
{
    var select2 = $(this).data('select2');
    if (select2.isOpen() == false)
    {
        $(this).one("select2:focus", select2Focus);
    }
}).on("select2:close", function ()
{
    setTimeout(function ()
    {
        // Find the next element and set focus on it.
        $(":focus").closest("tr").next("tr").find("select:visible,input:visible").focus();            
    }, 0);
});
function select2Focus()
{
    var select2 = $(this).data('select2');
    setTimeout(function() {
        if (!select2.isOpen()) {
            select2.open();
        }
    }, 0);  
}

Ответ 11

важная вещь состоит в том, чтобы постоянно держать мультиселект открытым. Самый простой способ - запустить событие open в "условиях" в вашем коде:

<select data-placeholder="Choose a Country..." multiple class="select2-select" id="myList">
    <option value="United States">United States</option>
    <option value="United Kingdom">United Kingdom</option>
    <option value="Afghanistan">Afghanistan</option>
    <option value="Aland Islands">Aland Islands</option>
    <option value="Albania">Albania</option>
    <option value="Algeria">Algeria</option>
</select>

JavaScript:

$(".select2-select").select2({closeOnSelect:false});
$("#myList").select2("open");

скрипка: http://jsfiddle.net/xpvt214o/153442/

Ответ 12

Это работало для меня с помощью Select2 v4.0.3

//Initialize Select2
 jQuery('.js-select').select2();

// Make Select2 respect tab focus
function select2Focus(){
    jQuery(window).keyup(function (e) {
        var code = (e.keyCode ? e.keyCode : e.which);
        if (code == 9 && jQuery('.select2-search__field:focus').length) {
            jQuery('.js-select').select2('open');
        }
    });
}

select2Focus();

Вилка Irvin Dominin demo: http://jsfiddle.net/163cwdrw/

Ответ 13

У меня была проблема, которая была двухсторонней:
 1. В форме с несколькими элементами select2 выпадающий список не открывается на вкладке, и вам нужно нажать клавишу пробела, чтобы открыть его
 2. После того, как вы сделали выбор, tabindex не будет выполняться, и вы должны вручную щелкнуть по следующему полю ввода

В то время как обычные рекомендации работали, я придумал свою собственную версию, так как библиотека script выполняла преобразование нормального выбора в select2, и, следовательно, я не контролировал эту инициализацию.

Вот код, который работал у меня.

вкладка для открытия

$(document).on("focus", ".select2", function() {
    $(this).siblings("select").select2("open");
});

Переход к следующему при выборе

var inputs = $("input,select"); // You can use other elements such as textarea, button etc. 
                                //depending on input field types you have used
$("select").on("select2:close",function(){
    var pos = $(inputs).index(this) + 1;
    var next = $(inputs).eq(pos);
    setTimeout( function() {
        next.focus();
        if (next.siblings(".select2").length) { //If it a select
            next.select2("open");
        }
    }, 500); //The delay is required to allow default events to occur
});

Надеюсь, что это поможет.

Ответ 14

Я пробовал эти решения с помощью select2 версии 3.4.8 и обнаружил, что когда вы делаете blur, select2 запускает сначала select2-close, затем select2-focus, а затем select2-blur, поэтому в конце мы в конечном итоге снова открываем select2.

Тогда мое решение таково:

$('#elemId').on('select2-focus', function(){
    var select2 = $(this).data('select2');
    if( $(this).data('select2-closed') ){
        $(this).data('select2-closed', false)
        return
    }
    if (!select2.opened()) {
        select2.open()
    }
}).on('select2-close', function(){
    $(this).data('select2-closed', true)
})

Ответ 15

Как-то select2Focus не работал здесь с пустым выбором, не мог понять проблему, поэтому я добавил ручное управление, когда после автоматического срабатывания автофокуса активизируется.

Здесь находится coffeescript:

$("#myid").select2()
  .on 'select2-blur', ->
    $(this).data('select2-auto-open', 'true')
  .on 'select2-focus', ->
    $(this).data('select2').open() if $(this).data('select2-auto-open') != 'false'
  .on 'select2-selecting', ->
    $(this).data('select2-auto-open', 'false')

Ответ 16

Я пробовал довольно уродливое решение, но оно исправило мою проблему.

    var tabPressed = false;

    $(document).keydown(function (e) {
        // Listening tab button.
        if (e.which == 9) {
            tabPressed = true;
        }
    });

    $(document).on('focus', '.select2', function() {
        if (tabPressed) {
            tabPressed = false;
            $(this).siblings('select').select2('open');
        }
    });