Sebuah elemen menjadi fokus ketika user mengkliknya atau menggunakan tombol Tab pada keyboard. Ada juga atribut HTML autofocus
yang fokus pada sebuah element secara default ketika memuat sebuah halaman dan sebagainya untuk mendapatkan fokus.
Fokus pada sebuah elemen pada umumnya diartikan: ???bersiap untuk terima datanya disini???, jadi itu adalah momen ketika kita bisa menjalankan kode untuk di inisiasi kebutuhan fungsionalitas.
Momen ketika hilang fokus (???blur???) bahkan bisa lebih penting. Itu adalah dimana user klik disuatu tempat or menekan Tab untuk pindah ke kotak selanjutnya, atau dengan cara yang lain.
Kehilangan fokus pada umumnya diartikan: ???data telah di isi???, jadi kita bisa menjalankan kode untuk mengeceknya atau bahkan menyimpannya ke server dan sebagainya.
Ada beberapa keanehan saat bekerja dengan event fokus. Kami akan melakukan yang terbaik untuk membahasnya lebih lanjut.
Events focus/blur
Event focus
terpanggil/trigger saat sedang fokus, dan event blur
??? ketika elemen hilang fokus.
Mari gunakan mereka sebagai validasi sebuah kotak input.
Dalam contoh dibawah:
blur
cek jika kotak email telah terisi , dan jika tidak ??? tampilkan error.focus
menyembunyikan pesan error (padablur
itu akan di cek kembali):
<style>
.invalid {
border-color: red;
}
#error {
color: red;
}
</style>
Your email please: <input type="email" id="input" />
<div id="error"></div>
<script>
input.onblur = function() {
if (!input.value.includes('@')) { // not email
input.classList.add('invalid');
error.innerHTML = 'Please enter a correct email.'
}
};
input.onfocus = function() {
if (this.classList.contains('invalid')) {
// remove the "error" indication, because the user wants to re-enter something
this.classList.remove('invalid');
error.innerHTML = "";
}
};
</script>
Dengan HTML modern kita bisa melakukan beberapa validasi menggunakan atribut input: required
, pattern
dan lainnya. Dan terkadang hanya mereka yang kita butuhkan. Kita bisa menggunakan Javascricpt jika ingin fleksibelitas lebih. Juga kita bisa secara otomatis mengirim nilai yang diubah ke server jika nilainya benar.
Metode focus/blur
Metode elem.focus()
dan elem.blur()
set/unset fokus pada elemen.
Misalnya, mari buat pengunjung tidak bisa keluar dari input jika nilainya tidak valid:
<style>
.error {
background: red;
}
</style>
Your email please: <input type="email" id="input" />
<input
type="text"
style="width:220px"
placeholder="make email invalid and try to focus here"
/>
<script>
input.onblur = function() {
if (!this.value.includes('@')) { // not email
// show the error
this.classList.add("error");
// ...and put the focus back
input.focus();
} else {
this.classList.remove("error");
}
};
</script>
Itu bekerja pada semua browser kecuali Firefox (bug).
Jika kita sedang mengetik/memasukkan sesuatu ke input dan coba menggunakanTab atau klik diluar elemen <input>
, maka onblur
membuat fokus kembali ke input.
Perlu diingat bahwa kita tidak bisa ???mencegah hilangnya fokus??? dengan memanggil event.preventDefault()
pada onblur
, karena onblur
bekerja saat element hilang fokus.
Focus loss bisa terjadi untuk alasan tertentu.
Salah satu diantaranya adalah ketika pengunjung klik di tempat lain. Tetapi mungkin Javascript sendiri yang menyebabkannya, Misalya:
- Sebuah
alert
memindahkan fokus untuknya, jadi itu menyebabkan focus loss pada elemen (blur
event), dan ketikaalert
sudah tidak ada, fokus ada kembali (focus
event). - Jika sebuah elemen dihapus dari DOM, itu juga menyebabkan focus loss. Jika di isi lagi nanti, maka fokus tidak akan kembali.
Beberapa fitur ini membuat focus/blur
handler menjadi misbehave ??? trigger disaat mereka tidak diperlukan.
Resep yang baik adalah berhati-hati mengunakan event ini. Jika kita ingin melacak focus-loss yang dimulai oleh user, maka kita harus menghidari yang dapat menyebabkan pada kita sendiri.
Memungkinkan fokus pada elemen apapun: tabindex
Secara default banyak elemen yang tidak support focusing.
Daftarnya sedikit bervariasi dibeda browser, etapi satu hal yang pasti benar: focus/blur
dukungannya terjamin untuk elemen-elemen yang pengunjung bisa berinteraksi dengan: <button>
, <input>
, <select>
, <a>
dan lainnya.
Di lain sisi, elemen-elemen yang ada hanya untuk meformat sesuatu seperti <div>
, <span>
, <table>
??? adalah unfocusable secara default. Metode elem.focus()
tidak bekerja pada mereka, dan focus/blur
event tidak akan pernah ke trigger.
Ini bisa diubah dengan menggunakan HTML-attribute tabindex
.
Elemen apapun menjadi focusable jika ia memilkitabindex
. Nilai atributnya adalah dari urutan nomor elemen ketika Tab digunakan untuk berpindah diantara mereka.
Itu adalah: jika kita memilki 2 elemen, yang pertama memilki tabindex="1"
, dan yang kedua memilki tabindex="2"
, lalu menekan Tab pada saat masih di elemen pertama ??? fokus berpindah ke elemen kedua.
Urutuan pindahnya ialah: elemen dengan tabindex
dari 1
dan diatasnya menjadi yang pertama (pada urutantabindex
), dan baru kemudian elemen tanpa tabindex
(seperti <input>
input biasa).
Element dengan tabindex
yang sesuai berpindah pada urutan sumber dokumen (urutan default).
Disana ada dua nilai khusus:
-
tabindex="0"
menempatkan sebuah elemen diantara mereka tanpatabindex
. Itu ialah, ketika kita pindah elemen, elemen dengantabindex=0
berpindah setelah elemen dengantabindex ??? 1
.Biasanya itu digunakan agar sebuah elemen menjadi focusable, tapi tetap memerhatikan urutan perpindahan default. Untuk membuat sebuah elemen menjadi bagian dari form yang setara
<input>
. -
tabindex="-1"
hanya membolehkan programmatic focusing pada sebuah elemen. Kunci Tab mengabaikan elemen seperti itu, akan tetapi metodeelem.focus()
dapat berfungsi.
Misalnya, ada list elemen. Klik item pertama dan tekan Tab:
Klik pada elemen pertama dan tekan tab. Perhatikan pada urutan. Harap perhatikan
bahwa banyak Tab berikutnya yang dapat memindahkan fokus dari iframe dalam
contoh.
<ul>
<li tabindex="1">One</li>
<li tabindex="0">Zero</li>
<li tabindex="2">Two</li>
<li tabindex="-1">Minus one</li>
</ul>
<style>
li {
cursor: pointer;
}
:focus {
outline: 1px dashed green;
}
</style>
Urutannya sepeti ini: 1 - 2 - 0
. Normalnya, <li>
tidak support focusing, tetapi dengan tabindex
membuatnya focusable, berserta dengan eventnya dan styling :focus
.
elem.tabIndex
juga dapat bekerja
Delegation: focusin/focusout
Events focus
and blur
tidak mengelembung(bubble)./ Misalnya, kita tidak bisa letak onfocus
pada <form>
untuk menghighlight-nya, seperti ini:
<!-- on focusing in the form -- add the class -->
<form onfocus="this.className='focused'">
<input type="text" name="name" value="Name">
<input type="text" name="surname" value="Surname">
</form>
<style> .focused { outline: 1px solid red; } </style>
Contoh diatas tidak akan bekerja, karena ketika sedang fokus pada sebuah <input>
, event focus
akan trigger hanya pada input tersebut. Ia tidak mengelembung ke atas(bubble up). Jadi form.onfocus
tidak akan pernah trigger.
Hanya ada dua solusi.
Pertama, ada satu sejarah lucu dengan fitur: focus/blur
yang tidak mengelembung ke atas(bubble up), tetapi merambat ke bawah saat capturing phase.
Ini akan bekerja:
<form id="form">
<input type="text" name="name" value="Name" />
<input type="text" name="surname" value="Surname" />
</form>
<style>
.focused {
outline: 1px solid red;
}
</style>
<script>
// meletakkan handler pada capturing phase (argumenterakhir set menjadit true)
form.addEventListener("focus", () => form.classList.add('focused'), true);
form.addEventListener("blur", () => form.classList.remove('focused'), true);
</script>
Kedua, ada event focusin
dan focusout
??? persis sama denganfocus/blur
, tetapi mereka mengelembung(bubble). Ingat bahwa mereka perlu di definisi menggunakan elem.addEventListener
, bukan on<event>
.
Jadi ini adalah cara lain yang dapat bekerja:
<form id="form">
<input type="text" name="name" value="Name" />
<input type="text" name="surname" value="Surname" />
</form>
<style>
.focused {
outline: 1px solid red;
}
</style>
<script>
form.addEventListener("focusin", () => form.classList.add('focused'));
form.addEventListener("focusout", () => form.classList.remove('focused'));
</script>
Kesimpulan
Event focus
dan blur
trigger pada saat sebuah elemen fokus dan hilang fokus.
Keistimewaan mereka adalah:
- Mereka tidak mengelembung(bubble). Gantinya bisa menggunakan capturing state atau
focusin/focusout
. - Kebanyakan elemen tidak mendukung fokus secara default. Gunakan
tabindex
untuk membuat elemen manapapun menjadi focusable.
Elemen fokus saat ini tersedia sebagai document.activeElement
.