这是以下类似的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>
这可以通过修改同样处理制表符和esc键的原始source code on line 323来轻松处理:
if (key === KEYS.ESC || key === KEYS.TAB || (key === KEYS.UP && evt.altKey)) {
self.close();
evt.preventDefault();
}
但理想情况下,第三方库应该使用pull请求进行修改。因此,我们在为此创建包装器时遇到了一些问题。原则上,检测标签keypress
事件很难。如果我们抓得太晚,另一个动作可能会取代它,或者可能会在另一个场上被解雇。
捕获标签事件和持久信息的前景似乎分为两个方面:
在任何一种情况下,我们都必须知道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) });
但是,select 2不会保留原始事件信息,而是自己创建新的jQueryEvent
,所以我们还不知道我们是否因为tab事件而关闭(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>