Select2 4.0.0 AJAX - 使用Tab选择突出显示的选项

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Select2 4.0.0 AJAX - 使用Tab选择突出显示的选项相关的知识,希望对你有一定的参考价值。

我通过AJAX获取用户ID和名称,并使用Select2搜索它们,但是我的用户已经请求能够通过按Tab键从typeahead下拉列表中进行选择,有效地将其视为按Enter键。这是我的select2声明:

$("#user-select").select2(
    ajax: 
        url: "/api/User",
        method: "get",
        data: function (params) 
            return 
                search: params.term
            ;
        ,
        beforeSend: function () 
            $(".loading-results").text("Loading...");
        ,
        processResults: function (data) 
            return 
                results: data
            ;
        ,
        cache: true
    ,
    allowClear: true,
    placeholder: "Enter a User ID or Name",
    templateResult: function (data) 
        return "(" + data.id + ") " + data.name;
    ,
    templateSelection: function (data) 
        return "(" + data.id + ") " + data.name;
    

每当下拉列表可见时,“。select2-search__field”似乎都是焦点元素,突出显示的元素将获得类“select2-results__option - highlight”。

我已经尝试了一些解决方案,但似乎没有任何效果,特别是因为这个元素在下拉列表打开时出现并消失。不幸的是,我从我的尝试中丢失了代码,但它们主要包括在聚焦输入上触发Tab时执行preventDefault,然后在突出显示的元素上触发click事件或触发输入上的enter键。

我也试过调整selectOnClose选项,但是这看起来很麻烦,当我让它正常运行时会导致无限循环,更不用说根据按下的键来覆盖它了。

[编辑] 所选解决方案有效,但不考虑指定的templateResult,而是显示“()undefined”。因此,我调整它以将突出显示的答案添加为上覆选择的所选选项,然后在该选择上调用更改事件。

...(与初始select2相同)

).on('select2:close', function (evt) 
    var context = $(evt.target);

    $(document).on('keydown.select2', function (e) 
        if (e.which === 9)  // tab
            var highlighted = context.data('select2').$dropdown.find('.select2-results__option--highlighted');

            if (highlighted) 
                var data = highlighted.data('data');

                var id = data.id;
                var display = data.name;

                $("#user-select").html("<option value='" + id + "' selected='selected'>" + display + "</option>");
                $("#user-select").change();
            
            else 
                context.val("").change();
            
        
    );
答案

我一直试图找到解决这个问题的方法。 主要问题是select2事件没有提供关于按下哪个键的任何信息。

所以我想出了这个hack来访问select2上下文中的keydown事件。 我一直在尽我所能地测试它,它似乎完美无缺。

selectElement
.select2( options ... )
.on('select2:close', function(evt) 
    var context = $(evt.target);

    $(document).on('keydown.select2', function(e) 
        if (e.which === 9)  // tab
            var highlighted = context
                              .data('select2')
                              .$dropdown
                              .find('.select2-results__option--highlighted');
            if (highlighted) 
                var id = highlighted.data('data').id;
                context.val(id).trigger('change');
            
        
    );

    // unbind the event again to avoid binding multiple times
    setTimeout(function() 
        $(document).off('keydown.select2');
    , 1);
);
另一答案

selectOnClose功能似乎在4.0.3中是稳定的,并且是一个更简单的解决方案:

$("#user-select").select2(
  ...
  selectOnClose: true
);

模板的使用可能会干扰此功能,我没有使用它,所以我没有测试过。

另一答案

对于任何想要使用多选项进行选项卡选择的人来说,这对我有用:

$("#selected_ids").select2( multiple: true ).on('select2:open', function(e)  selectOnTab(e) );

function selectOnTab(event)

  var $selected_id_field = $(event.target);

  $(".select2-search__field").on('keydown', function (e) 
    if (e.which === 9) 
      var highlighted = $('.select2-results__option--highlighted');

      if (highlighted) 
        var data = highlighted.data('data');
        var vals = $selected_id_field.val();
        if (vals === null)
          vals = [];
        
        vals.push(data.id)
        $selected_id_field.val(vals).trigger("change")
      
    
  );

目前,这限制了我每页一个字段,但它正在完成这项工作。

感谢MikeOShay和Sniffdk深入研究这个问题。 目前有一个未解决的问题可能会解决这个问题:

https://github.com/select2/select2/issues/3359

另一答案

在使用所有这些解决方案后,这个解决方案似乎能够抓住大多数情况并为我做最好的工作。注意我使用的是select2 4.0.3,但不喜欢selectOnClose,如果你有多个select2盒子,它可能会造成严重破坏!

var fixSelect2MissingTab = function (event) 
    var $selected_id_field = $(event.target);

    var selectHighlighted = function (e) 
        if (e.which === 9) 
            var highlighted = $selected_id_field.data('select2').$dropdown.find('.select2-results__option--highlighted');

            if (highlighted) 
                var data = highlighted.data('data');
                if (data) 
                    var vals = $selected_id_field.val();
                    if (vals === null) 
                        vals = [];
                    
                    if (vals.constructor === Array) 
                        vals.push(data.id);
                     else 
                        vals = data.id;
                    
                    $selected_id_field.val(vals).trigger("change");
                
            
        
    ;

    $('.select2-search__field').on('keydown', selectHighlighted);       


$(document).on('select2:open', 'select', function (e)  fixSelect2MissingTab(e) );
$(document).on('select2:close', 'select', function (e) 
    //unbind to prevent multiple
    setTimeout(function () 
        $('.select2-search__field').off('keydown');
    , 10);
);

这个解决方案的优点是它是通用的,可以应用于框架代码,即使对于动态添加的select2框也是如此。

另一答案

您只需更改Select2控件的来源,只需一行:

否则如果(键=== KEYS.ENTER)

否则if(key === KEYS.ENTER || key === KEYS.TAB)

由此:

 this.on('keypress', function (evt) 
   var key = evt.which;

   if (self.isOpen()) 
     if (key === KEYS.ESC || key === KEYS.TAB ||
         (key === KEYS.UP && evt.altKey)) 
       self.close();

       evt.preventDefault();
      else if (key === KEYS.ENTER) 
       self.trigger('results:select', );

       evt.preventDefault();

对此

this.on('keypress', function (evt) 
  var key = evt.which;

  if (self.isOpen()) 
    if (key === KEYS.ESC || (key === KEYS.UP && evt.altKey)) 
      self.close();

      evt.preventDefault();
     else if (key === KEYS.ENTER || key === KEYS.TAB) 
      self.trigger('results:select', );

      evt.preventDefault();

可以在源文件src / js / select2 / core.js中或在编译版本中完成更改。当我应用此更改时,我已修改src / js / select2 / core.js并执行gruntfile.js以再次编译select2库。此解决方案不是解决方法,而是select2的一个很好的功能。

另一答案

我正在使用带有vue的select2版本4.0.6-rc.1,这是我保持绑定安全所做的:

selectElement
.select2( options ... )
.on("select2:close", function(evt) 
      var context = $(evt.target);

      $(document).on("keydown.select2", function(e) 
          if (e.which === 9) 
              var highlighted = context
                  .data("select2")
                  .$dropdown.find(".select2-results__option--highlighted");

              if (highlighted) 
                  $.fn.select2.amd.require(["select2/utils"], function(Utils) 
                      var data = Utils.__cache[highlighted.data().select2Id].data;
                      var $select2 = context.data('select2');
                      $select2.trigger("select", data: data);
                  );
              
          
      );

      setTimeout(function() 
        $(document).off("keydown.select2");
      , 1);
  );

对我来说,关键是Utils帮助器,它是库的一部分,从当前元素的缓存中检索列表,然后使用新值强制选择。

祝好运! :)

另一答案

类似于@Semen Shekhovtsov的解决方案,但如果您希望TAB实际上跳转到下一个字段以及进行选择(更像是正常的输入选择),那么会有所改变。如果是块,则将KEYS.ENTER和KEYS.TAB分离到自己的else中,并省略evt.preventDefaults()。如下所示在core.js或select2.full.js中(如果你不想重新编译它)。

if (key === KEYS.ESC || (key === KEYS.UP && evt.altKey)) 
  self.close();

  evt.preventDefault();
 else if (key === KEYS.ENTER)
  self.trigger('results:select', );
  evt.preventDefault();
 else if (key === KEYS.TAB)
  self.trigger('results:select', );
  // leave out the prevent default if you want it to go to the next form field after selection
  //evt.preventDefault();

另一答案

我混合了这里提出的一些解决方案,使用others在元素聚焦时打开select2下拉列表。

我还想要TAB键进行选择并立即聚焦下一个select2字段。相反,SHIFT-TAB将聚焦前一个select2字段。

这是我的最终代码(select2 4.0.5,在FF和Chrome上测试过)。我假设你的选择字段有“select2”类:

$('.select2').select2().on('select2:close', function (e) 
    var target = $(e.target);

    $(document).on('keydown.select2', function(e) 
        if (e.which === 9)  // tab
            var highlighted = target
                              .data('select2')
                              .$dropdown
                              .find('.select2-results__option--highlighted');
            if (highlighted) 
                // select the option
                var id = highlighted.data('data').id;
                target.val(id);
                target.trigger('change');
                // focus the next (or the previous) field with "select2" class
                var set = $('.select2');
                var current_index = set.index(target);
                var next_index = current_index + 1;
                if (e.shiftKey) 
                    next_index = current_index - 1;
                
                var next = set.eq(next_index)
                next.focus();
            
        
    );

    // unbind the event again to avoid binding multiple times
    setTimeout(function() 
        $(document).off('keydown.select2');
    , 1);

);

// on focus, open the menu
$(document).on('focus', '.select2-selection.select2-selection--single', function (e) 
    $(this).closest(".select2-contain

以上是关于Select2 4.0.0 AJAX - 使用Tab选择突出显示的选项的主要内容,如果未能解决你的问题,请参考以下文章

Select2:使用ajax数据源时添加和选择手动值

使用带有无限数据和过滤器的 SELECT2 4.0.0

用 Select2 换行选定的文本

select2 noresult 捕获输入

Select2 v4.0.0 性能问题

Select2 v4.0 使 optgroups 可选