Select2: Tabindex dan focus

Select2 yang digunakan adalah select2 Versi 4

Select2 adalah javascript library yang paling banyak digunakan untuk menampilkan daftar pilihan, dimana dengan select2 kita dapat mencari pilihan yang kita inginkan

Contoh html :

 

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.2/css/bootstrap.min.css" integrity="sha512-rt/SrQ4UNIaGfDyEXZtNcyWvQeOq0QLygHluFQcSjaGB04IxWhal71tKuzP6K8eYXYB6vJV4pHkXcmFGGQ1/0w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" integrity="sha512-nMNlpuaDPrqlEls3IX/Q56H36qvBASwb3ipuo3MxeWbsQB1881ox0cRv7UPTgBlriqoynt35KjEwgGUeUXIPnw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2-bootstrap-css/1.4.6/select2-bootstrap.min.css" integrity="sha512-3//o69LmXw00/DZikLz19AetZYntf4thXiGYJP6L49nziMIhp6DVrwhkaQ9ppMSy8NWXfocBwI3E8ixzHcpRzw==" crossorigin="anonymous" referrerpolicy="no-referrer" />

<div class="container-fluid">
	<div class="mb-npx collapse show">
		<fieldset class="form-group">
			<div class="row">
				<div class="col-12 pl-3">
					<div class="form-group">
						<label class="font-weight-bold" for="nama">Nama</label>
						<input type="text" id="nama" class="form-control" value="" tabindex="1"/>
					</div>
					<div class="form-group">
						<label class="font-weight-bold" for="pilihan">Pilihan</label>
						<select id="pilihan" class="form-control" tabindex="2"></select>
					</div>
					<div class="form-group">
						<button id="gantiKota" type="button" class="btn btn-success">Daftar Kota</button>
						<button id="gantiPropinsi" type="button" class="btn btn-success">Daftar Propinsi</button>
						<button id="kosongkan" type="button" class="btn btn-success">Kosongkan Daftar</button>
					</div>
				</div>
			</div>
		</fieldset>
	</div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js" integrity="sha512-aVKKRRi/Q/YV+4mjoKBsE4x3H+BkegoM/em46NNlCqNTmUYADjBbeNefNxYV7giUp0VxICtqdrbqU7iVaeZNXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.2/js/bootstrap.bundle.min.js" integrity="sha512-igl8WEUuas9k5dtnhKqyyld6TzzRjvMqLC79jkgT3z02FvJyHAuUtyemm/P/jYSne1xwFI06ezQxEwweaiV7VA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.full.min.js" integrity="sha512-RtZU3AyMVArmHLiW0suEZ9McadTdegwbgtiQl5Qqo9kunkVg1ofwueXD8/8wv3Af8jkME3DDe3yLfR8HSJfT2g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
	//tulis kode disini
</script>

Merujuk pada html diatas, input select dengan id “pilihan” diatas, akan kita deklarasikan menjadi select2

Setelah menjadi select2, structur html berubah, input select diatas akan menjadi hidden dan attribute tabindex menjadi -1, dibawah element tersebut akan ada tambahan element select 2 seperti berikut

....
<select id="pilihan" class="form-control select2-hidden-accessible" style="display:none" data-select2-id="pilihan" ....
<span class="select2 select2-container select2-container--bootstrap" dir="ltr" data-select2-id="1" ....
	<span class="selection">
		<span class="select2-selection select2-selection--single" role="combobox" ....
		
....

Lantas bagaimana dapat focus ke element “pilihan” jika element “pilihan” tersebut tersembunyi dan tabindex menjadi -1 ?

Untuk hal tersebut, select2 mengalihkan focus ke element span dengan class “select2-selection select2-selection–single” dalam struktur diatas. Span tersebut dapat focus karena mempunyai role “combobox”

Catatan : Jika opsi multiple dalam konfigurasi select2 adalah true, maka span tersebut mempunyai class “select2-selection select2-selection–multiple”

Jadi agar tabindex berjalan semestinya, ada 3 hal yang harus kita lakukan

  1. Set urutan tabindex kepada element span tersebut
  2. Mengubah event keydown tab pada element span tersebut
  3. Mengubah event klik pada select2 tersebut

Langkah 1 : Set urutan tabindex kepada element tersebut

Tujuannya adalah menambahkan attribut data-tab pada element span dengan class=”select2-selection select2-selection–single”

Bukan attribute tabindex, tapi data-tab, karena jika select2 di klik atau berubah nilai, tabindex element tersebut selalu menjadi -1

Berikut kodenya :

$("#pilihan").next(".select2-container").find(".select2-selection--single").attr("data-tab",2)  //di set 2 karena urutan tabindexnya adalah 2

Langkah 2 : Mengubah event keydown tab pada element span tersebut

Berikut kodenya :

$(document).on('keydown',"[data-tab]", function(e) { 
  var keyCode = e.keyCode || e.which; 
  if (keyCode == 9) { 
	var c=$(this).attr("data-tab");
	if(c>0){
		if(e.shiftKey){
			c--;	
		}else{
			c++;
		}
		if($("[data-tab='"+c+"']").length>0){
			e.preventDefault(); 
			$("[data-tab='"+c+"']").focus()
		}
	}
  } 
});

Langkah 3 : Mengubah event klik pada select2 tersebut

Hal ini perlu dilakukan karena apabila kita klik select2 maka dropdown list akan terbuka dan jika klik lagi maka dropdown list akan tertutup dan select2 kehilangan focus

Untuk menjaga agar select2 tetap focus, berikut kodenya :

$(document).on("click",".select2-container",function(){
	let selectorname=$(this).prev().attr("data-select2-id");
	if(!$("#"+selectorname).data('select2').isOpen()){
		$(this).find(".select2-selection--single").focus()
	}else{
		$(this).find(".select2-search__field").focus()
	}
});

Demikianlah salah satu cara agar tabindex dapat berjalan dengan memakai select2

Tambahan kode agar input search dapat focus saat dropdown select2 terbuka dengan cara menekan enter

$(document).on('select2:open',()=>{document.querySelector('.select2-search__field').focus()});