2015-11-03 94 views
6

选择突出显示的选项我通过AJAX获取用户ID和名称,并使用Select2搜索它们,但我的用户已请求通过按Tab键从下拉菜单中进行选择的功能按Enter键处理它。这是我的选择2声明:Select2 4.0.0 AJAX - 通过标签

$("#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”似乎是每当下拉的可见的,突出显示的元素获取类聚焦元素‘选择2 - results__option - 突出’。

我试过一些解决方案,但似乎没有任何工作,特别是因为这个元素出现并随时打开下拉菜单消失。不幸的是,我从我的尝试中丢失了代码,但是他们主要是通过在焦点输入上点击Tab时执行preventDefault,然后在突出显示的元素上触发单击事件或触发输入上的Enter键。

我也尝试调整selectOnClose选项,但似乎越野车在一般情况下,导致无尽的循环,当我有它正常运行,更少尝试覆盖它基于什么键被按下。

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

...(同初始选择2)

}).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(); 
      } 
     } 
    }); 
+0

你有想过吗?遇到相同的问题。 – grant

+0

没有骰子,在我发布之前,我已经用尽了大部分的故障排除功能。如果你知道我应该在此标记以帮助人们找到可以回答的人,请告诉我,我会将其编辑到帖子中。 – MikeOShay

+1

非常感谢 - 我花了一些时间敲打它,也没有运气。我会让你知道如果我想出任何东西:) – grant

回答

9

我一直在试图找到一个解决这个问题为好。
主要问题是,select2事件不能提供任何关于哪个键被按下的信息。

所以我想出了这个黑客来访问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); 
}); 
+0

聪明!所以,当关闭事件正在进行时,您仍然捕获关键事件,然后以编程方式进行设置。您仍然需要手动设置templateresult的值(如果您对其进行模板化)。我会接受你的并更新问题以显示我的修改。 – MikeOShay

+0

是的,这是hacky地狱,但它现在的作品:) – Sniffdk

+0

OOF这是丑陋的,但似乎仍然是最好的选择(如果我知道更好)。非常感谢。 – neanderslob

2

对于任何人希望得到片选工作与多选,这个工作对我来说:

$("#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

+1

感谢您的解决方案。对于其他人而言,调用'trigger(“change”)'不会触发通常在选择选项时看到的DOM事件('select2:open','select2:close'等)。 – Marklar

+0

我看到一些iffy keydown行为,有时在按下按键时会调用五次,有时候根本不会。你有什么想法吗? – mmking

+0

@mmking有趣的是,从引用像[this]这样的讨论(https://stackoverflow.com/questions/9098168/jquery-keypress-event-fires-repeatedly-when-key-is-held-but-not-on-所有键)我相信这是keydown事件的正常行为。 –

7

的selectOnClose功能似乎是稳定的4.0.3,和更简单的解决方案:

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

这是可能的模板的使用干扰了这个功能,我没有使用它,所以我没有测试过。

+0

with selectOnClose,即使您单击页面正文中的其他位置(未单击select中的选项),也会选择该选项。如果这对你来说是个问题,你能找到解决办法吗? – Marklar

+0

在我的情况下,这不是一个问题,所以我没有看到解决方法。我的猜测是,你将不得不使用@Sniffdk的解决方案,以便只响应TAB,而不是关闭选择的其他方式。 –

+0

感谢您花时间回复。对于处于同一情况的其他人,Sniffdk的解决方案不适用于多选。 JP的解决方案,但通常的DOM事件不会被解雇。 – Marklar

0

您可以简单地改变选择二源头控制,只有一行:如果

其他(关键=== KEYS.ENTER)

否则,如果(键=== KEYS.ENTER | | 关键=== 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 /选择2/core.js中完成,或在编译的版本。当我应用此更改时,我修改了src/js/select2/core.js并执行gruntfile.js来再次编译select2库。这个解决方案不是一种解决方法,但是对于select2来说却是很好的功能。

+0

我相信这个解决方案是作为pull请求提交的,但select2的维护者说这是一个突破性变化,不会合并:https://github.com/select2/select2/pull/4325#issuecomment-229234605 – Marklar

+0

@Marklar ,所有的测试和一切似乎都没有问题,完全没有问题。我不知道是谁称之为“突变”,为什么。到目前为止,我一直在使用提出的解决方案没有任何问 –

+0

感谢您花时间回复并提供解决方案。如果你遇到任何不明原因的问题,我想这可能是一个突破性的变化是需要记住的。如果你看看我在上次评论中提供的链接,可以看到Kevin Brown(select2的维护者)表示这是一个突破性改变,而selectOnClose是他的推荐。 – Marklar

0

玩过所有这些解决方案后,这一个似乎赶上了大多数案件,并为我工作最好。注意我正在使用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); 
}); 

这个解决方案的好处是,它是通用的,可以在框架代码应用于将连工作动态添加选择2盒。