我有一个包含多个文本输入和一些select2元素的表单。 使用键盘在字段之间切换工作正常 - Select2元素的行为类似于表单元素,并在Tab键时获得焦点。 我想知道当Select2元素获得焦点时是否可以打开下拉列表。
这是我到目前为止所尝试的内容:
$("#myid").select2().on('select2-focus', function(){
$(this).select2('open');
});
但是使用此代码会在选择后再次打开下拉列表。
答案 0 :(得分:26)
目前的答案仅适用于版本3.5.4及之前,其中select2已解雇blur and focus events(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中。
$('.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>
答案 1 :(得分:21)
以下代码将打开初始焦点上的菜单,但在菜单关闭后选择重新聚焦时不会陷入无限循环。
// 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。然后,使用委托的侦听器,我们将调用实际焦点 - &gt;仅当focus
事件一直到document
正如此github问题#4025 - Dropdown does not open on tab focus中所述,我们应该检查以确保我们只在'open'
上选择:enabled
这样的选择元素:
$(this).siblings('select:enabled').select2('open');
我们必须稍微遍历DOM,所以这里是Select2生成的HTML结构的地图
以下是一些相关的代码部分:
.on('mousedown'
... .trigger('toggle')
.on('toggle'
... .toggleDropdown()
.toggleDropdown
... .open()
.on('focus'
... .trigger('focus'
.on('close'
... $selection.focus()
曾经是打开select2两次开火的情况,但它已在Issue #3503中修复,这应该会阻止一些jank
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上测试
答案 2 :(得分:20)
对于页面上的所有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');
});
}
答案 3 :(得分:17)
选择完成后,可能会触发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/
要让鼠标点击工作,您必须检查触发处理程序的事件,它必须仅在事件为open
时触发focus
方法
代码:
function select2Focus() {
if (/^focus/.test(event.type)) {
$(this).select2('open');
}
}
演示:http://jsfiddle.net/IrvinDominin/fnjNb/4/
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');
}
答案 4 :(得分:9)
有点晚了......但是要使用select2 4.0.0分享我的代码
$("#my_id").select2();
$("#my_id").next(".select2").find(".select2-selection").focus(function() {
$("#my_id").select2("open");
});
答案 5 :(得分:6)
这是Select2版本4.x的替代解决方案。您可以使用侦听器捕获焦点事件,然后打开选择。
$('#test').select2({
// Initialisation here
}).data('select2').listeners['*'].push(function(name, target) {
if(name == 'focus') {
$(this.$element).select2("open");
}
});
根据@tonywchen
创建的示例找到工作示例here答案 6 :(得分:4)
问题是,内部焦点事件没有转换为jQuery事件,所以我修改了插件并将焦点事件添加到Select2 4.0.3第2063行的EventRelay:
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
答案 7 :(得分:4)
KyleMit的回答对我有用(谢谢!),但是我注意到使用select2元素允许搜索,尝试Tab键到下一个元素将无法工作(Tab键顺序有效丢失) ,所以我添加了代码,以便在下拉列表关闭时将焦点设置回主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');
});
}
});
答案 8 :(得分:3)
我尝试了其中一些,最后提出了以下适合我的Select2 4.0.1。 element是<select>
元素。
$.data(element).select2.on("focus", function (e) {
$(element).select2("open");
});
答案 9 :(得分:3)
对于我使用Select2.full.js版本4.0.3,以上解决方案都没有按照应有的方式工作。 所以我写了上面的解决方案的组合。 首先,我修改了Select2.full.js以将内部焦点和模糊事件转移到jquery事件,如#34; Thomas Molnar&#34;在他的回答中做了。
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);
}
答案 10 :(得分:2)
重要的是要始终保持多选的开放状态。最简单的方法是在代码中的'条件'上触发打开事件:
<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");
答案 11 :(得分:1)
这对我使用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的演示分析:http://jsfiddle.net/163cwdrw/
答案 12 :(得分:1)
我遇到了双管齐下的问题:
1.在具有多个select2元素的表单中,下拉菜单不会在选项卡上打开,您需要按空格键才能打开它
2.完成选择后,tabindex不会被尊重,您必须手动点击下一个输入字段
虽然通常的建议有效,但我提出了自己的版本,因为库脚本正在将普通选择转换为select2,因此我无法控制此初始化。
这是适用于我的代码。
要打开的标签
$(document).on("focus", ".select2", function() {
$(this).siblings("select").select2("open");
});
在选择
上移至 nextvar 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's a select
next.select2("open");
}
}, 500); //The delay is required to allow default events to occur
});
希望这有帮助。
答案 13 :(得分:0)
我尝试过一个非常难看的解决方案,但它解决了我的问题。
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');
}
});
答案 14 :(得分:0)
不知何故,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')
答案 15 :(得分:0)
我使用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)
})
答案 16 :(得分:0)
你可以使用这个:
sys.argv