这是以下类似的 SO问题和几个github问题的主题,包括:
但建议的解决方案或问题同等地处理了所有模糊事件,无论它们是如何被调用的。大多数答案都会通过设置Automatic selection来充分利用selectOnClose
。
理想情况下,仅在鼠标悬停在选项上后单击下拉列表(转义)不应更改值:
如何更新tabout上的选择,而不是其他关闭事件?
$('.select2').select2({});

<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/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.0/js/select2.js"></script>
<div class="form-control">
<label for="foods2">Select2</label>
<select id="foods2" class="select2" >
<option value="1">Apple</option>
<option value="2">Banana</option>
<option value="3">Carrot</option>
<option value="4">Donut</option>
</select>
</div>
&#13;
答案 0 :(得分:1)
通过修改同样处理制表符和esc键的原始source code on line 323,可以轻松处理这个问题:
if (key === KEYS.ESC || key === KEYS.TAB || (key === KEYS.UP && evt.altKey)) {
self.close();
evt.preventDefault();
}
但理想情况下,第三方库应该使用拉取请求进行修改。因此,我们在为此创建包装器时遇到了一些问题。原则上,检测标签 keypress
事件 hard 。如果我们抓得太晚,另一个动作可能会取代它,或者可能会在另一个领域被解雇。
捕获标签事件和持久信息的前景似乎分为两个部分:
在任何一种情况下,我们都必须知道 tab 键是导致菜单关闭的违规项目。
如果我们使用标签来监听按键事件,则在开放输入中,如果没有搜索,它们将从.select2-selection
发出;如果启用了搜索,则会select2-search__field
。
$("body").on('keydown', e => { if (e.keyCode === 9) console.log(e.target) });
然而,如果我们设置为委托处理程序,如上所述,当事件一直冒泡到“正文”时,菜单已经关闭,从而清除了目前突出显示的项目,甚至是我们是否开始公开的指标。
我们可以在菜单关闭之前拦截,注册select2:closing
这样的事件:
$("body").on('select2:closing', e => { console.log(e,e.target) });
但是,选择2不会保留原始事件信息,而是创建自己的新jQueryEvent
,因此我们还不知道我们是否因为标签而关闭事件(body.keypress
事件随后触发)
我们将监控select2:closing
事件并捕获我们需要知道的内容。接下来,我们需要附加一个处理程序,该处理程序在事件管道完成时侦听后续触发初始单击或键击。我们需要为每个关闭选项触发一次 。为此,我们可以使用此扩展程序$.fn.once
。如果它是由选项卡引发的,它将更新在关闭期间检测到的任何值。如果没有,那个值和处理程序就会消失。
总而言之,它应该是这样的:
// monitor every time we're about to close a menu
$("body").on('select2:closing', function (e) {
// save in case we want it
var $sel2 = $(e.target).data("select2");
var $sel = $sel2.$element;
var $selDropdown = $sel2.$results.find(".select2-results__option--highlighted")
var newValue = $selDropdown.data("data").element.value;
// must be closed by a mouse or keyboard - listen when that event is finished
// this must fire once and only once for every possible menu close
// otherwise the handler will be sitting around with unintended side affects
$("html").once('keyup mouseup', function (e) {
// if close was due to a tab, use the highlighted value
var KEYS = { UP: 38, DOWN: 40, TAB: 9 }
if (e.keyCode === KEYS.TAB) {
if (newValue != undefined) {
$sel.val(newValue);
$sel.trigger('change');
}
}
});
});
$.fn.once = function (events, callback) {
return this.each(function () {
$(this).on(events, myCallback);
function myCallback(e) {
$(this).off(events, myCallback);
callback.call(this, e);
}
});
};
$('.select2').select2({});
// monitor every time we're about to close a menu
$("body").on('select2:closing', function (e) {
// save in case we want it
var $sel2 = $(e.target).data("select2");
var $sel = $sel2.$element;
var $selDropdown = $sel2.$results.find(".select2-results__option--highlighted")
var newValue = $selDropdown.data("data").element.value;
// must be closed by a mouse or keyboard - setup listener to see when that event is completely done
// this must fire once and only once for every possible menu close
// otherwise the handler will be sitting around with unintended side affects
$("html").once('keyup mouseup', function (e) {
// if close was due to a tab, use the highlighted value
var KEYS = { UP: 38, DOWN: 40, TAB: 9 }
if (e.keyCode === KEYS.TAB) {
if (newValue != undefined) {
$sel.val(newValue);
$sel.trigger('change');
}
}
});
});
$.fn.once = function (events, callback) {
return this.each(function () {
$(this).on(events, myCallback);
function myCallback(e) {
$(this).off(events, myCallback);
callback.call(this, e);
}
});
};
.form-control {
padding:10px;
display:inline-block;
}
select {
width: 100px;
border: 1px solid #aaa;
border-radius: 4px;
height: 28px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/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.0/js/select2.js"></script>
<div class="form-control">
<label for="foods2">Select2</label>
<select id="foods2" class="select2" >
<option value="1">Apple</option>
<option value="2">Banana</option>
<option value="3">Carrot</option>
<option value="4">Donut</option>
</select>
</div>