複数のテキスト入力といくつかのselect2要素を持つフォームがあります。キーボードを使用してフィールド間をタブで移動すると正常に動作します-Select2要素はフォーム要素のように動作し、タブ移動時にフォーカスを受け取ります。 Select2要素がフォーカスを取得したときにドロップダウンを開くことが可能かどうか疑問に思っていました。
これまでに試したことは次のとおりです。
$("#myid").select2().on('select2-focus', function(){
$(this).select2('open');
});
ただし、このコードを使用すると、選択後にドロップダウンが再び開きます。
次のコードは、initialフォーカスでメニューを開きますが、メニューが閉じた後に選択が再びフォーカスされると、無限ループに陥りません。
_// 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
イベントは2回発生
フォーカスイベントのタイプ間の違いを探すことで、無限ループを防ぐことができます。コントロールへの最初のフォーカスでのみメニューを開きたいので、次の発生したイベントを何らかの方法で区別する必要があります。
ブラウザーが異なるイベントとともに異なる情報を送信し、Select2が以前のフローを中断するイベントの内部起動に多くの小さな変更を加えたため、クロスブラウザーフレンドリーな方法でこれを行うのは困難です。
動作するように思われる1つの方法は、メニューの closing
イベント中にイベントハンドラーをアタッチし、それを使用して差し迫ったfocus
イベントをキャプチャし、バブリングを防ぐことです。 DOMをアップします。次に、委任されたリスナーを使用して、focus
イベントがdocument
に達するまでのみ、実際のフォーカス->オープンコードを呼び出します。
このgithubの問題 #4025-タブフォーカスでドロップダウンが開かない で述べたように、次のような_'open'
_ select要素で_: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を開くと2回起動していましたが、 Issue#35 で修正され、ジャンクを防ぐ必要がありました
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でテスト済み
現在の回答は、select2が起動したバージョン3.5.4以前にのみ適用されます。この場合、 ぼかしイベントとフォーカスイベント (select2-focus
&select2-blur
)。 $.one
を使用して1回限りの使用ハンドラーをアタッチし、最初のフォーカスをキャッチし、その後の使用のためにぼかし中に再アタッチします。
$('.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の回答を両方試してみましたが、両方の問題に遭遇しました(ドロップダウンを2回クリックする必要があり、Firefoxは「イベントが定義されていません」をスローします)。
2つの問題を解決するようで、まだ他の問題に遭遇していない解決策を見つけました。これは@ 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>
ページ上のすべてのselect2インスタンスで動作する簡単なもの。
$(document).on('focus', '.select2', function() {
$(this).siblings('select').select2('open');
});
PDATE:上記のコードはIE11/Select2 4.0.で適切に動作しないようです。
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');
});
}
おそらく選択が行われた後、select2-focus
イベントがトリガーされます。
私が見つけた唯一の方法は、select2-focus
およびselect2-blur
イベントとjQuery one
イベントハンドラ。
そのため、要素が最初にフォーカスを取得すると、select2が1回(1つのため)開かれ、要素がぼやけると、1つのイベントハンドラーが再びアタッチされます。
コード:
$('#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');
}
少し遅れていますが、select2 4.0.0を使用してコードを共有します
$("#my_id").select2();
$("#my_id").next(".select2").find(".select2-selection").focus(function() {
$("#my_id").select2("open");
});
Select2のバージョン4.xの代替ソリューションを次に示します。リスナーを使用してフォーカスイベントをキャッチし、選択を開くことができます。
$('#test').select2({
// Initialisation here
}).data('select2').listeners['*'].Push(function(name, target) {
if(name == 'focus') {
$(this.$element).select2("open");
}
});
実際の例を見つける here @tonywchenによって作成された例
問題は、内部フォーカスイベントが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
KyleMitの答えは私にとってはうまくいきました(ありがとう!)ドロップダウンが閉じているとき、メインの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');
});
}
});
Select2.full.jsバージョン4.0.3を使用している私にとっては、上記のソリューションはどれも本来の方法で動作していませんでした。そこで、上記のソリューションの組み合わせを作成しました。まず、Select2.full.jsを修正して、「Thomas Molnar」が答えたように、内部フォーカスとぼかしイベントをjqueryイベントに転送しました。
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);
}
これらの多くを試してみて、最終的にSelect2 4.0.1で動作する次のものを思いつきました。要素は<select>
要素。
$.data(element).select2.on("focus", function (e) {
$(element).select2("open");
});
重要なことは、複数選択を常に開いたままにすることです。最も簡単な方法は、コードの「条件」でopenイベントを起動することです。
<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");
これは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/
私には2つの問題がありました:
1。複数のselect2要素があるフォームでは、ドロップダウンはタブで開かず、スペースキーを押して開く必要があります
2。選択を行った後、tabindexは尊重されず、次の入力フィールドを手動でクリックする必要があります
通常の提案は機能していましたが、ライブラリスクリプトが通常のselectからselect2への変換を行っていたため、この初期化を制御できなかったため、独自のバージョンを思いつきました。
ここに私のために働いたコードがあります。
タブを開く
$(document).on("focus", ".select2", function() {
$(this).siblings("select").select2("open");
});
選択時にnextに移動
var 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
});
お役に立てれば。
どういうわけか、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')
私はかなりい解決策を試みましたが、それは私の問題を修正しました。
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');
}
});
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)
})