Element zÃská fokus tehdy, když na nÄj uživatel buÄ klikne, nebo použije klávesu Tab na klávesnici. Existuje také HTML atribut autofocus, který standardnÄ umÃstà fokus na element, když se stránka naÄte, a jsou i jiné způsoby zÃskánà fokusu.
PÅesun fokusu na element obecnÄ znamená: âpÅiprav se pÅijÃmat dataâ, takže to je chvÃle, kdy můžeme spustit kód, abychom inicializovali požadovanou funkcionalitu.
JeÅ¡tÄ důležitÄjšà může být okamžik ztráty fokusu (âblurâ). Ten nastane, když uživatel klikne nÄkam jinam nebo stiskne Tab, aby se pÅesunul na dalšà pole ve formuláÅi. Jsou i jiné způsoby ztráty fokusu.
Ztráta fokusu obecnÄ znamená: âdata byla zadánaâ, takže můžeme spustit kód, který je zkontroluje, nebo je dokonce uložà na server a podobnÄ.
Práce s fokusovými událostmi má důležité zvláštnosti. Budeme se je dále snažit co nejlépe vysvÄtlit.
Události focus/blur
Událost focus je volána, když element zÃská fokus, a blur, když jej ztratÃ.
Využijme je ke kontrole vstupnÃho pole.
V následujÃcÃm pÅÃkladu:
- Handler
blurzkontroluje, zda byl do pole zadán e-mail, a pokud ne, zobrazà chybu. - Handler
focusskryje chybovou zprávu (pÅi událostiblurbude kontrola provedena znovu):
<style>
.vadný { border-color: red; }
#chyba { color: red }
</style>
Váš e-mail, prosÃm: <input type="email" id="input">
<div id="chyba"></div>
<script>
input.onblur = function() {
if (!input.value.includes('@')) { // to nenà e-mail
input.classList.add('vadný');
chyba.innerHTML = 'Zadejte prosÃm platný e-mail.'
}
};
input.onfocus = function() {
if (this.classList.contains('vadný')) {
// odstranÃme indikaci "chyba", protože uživatel chce znovu nÄco zadat
this.classList.remove('vadný');
chyba.innerHTML = "";
}
};
</script>
Modernà HTML nám umožÅuje provádÄt mnoho kontrol pomocà vstupnÃch atributů: required, pattern a podobnÄ. NÄkdy je to pÅesnÄ to, co potÅebujeme. Chceme-li vÃce flexibility, můžeme použÃt JavaScript. Můžeme také automaticky odeslat zmÄnÄnou hodnotu na server, pokud je korektnÃ.
Metody focus/blur
Metoda elem.focus() nastavà fokus na element, metoda elem.blur() odebere fokus z elementu.
NapÅÃklad zakažme návÅ¡tÄvnÃkovi opustit vstupnà pole, pokud je jeho hodnota neplatná:
<style>
.chyba {
background: red;
}
</style>
Váš e-mail, prosÃm: <input type="email" id="input">
<input type="text" style="width:300px" placeholder="zadejte neplatný e-mail a zkuste sem vstoupit">
<script>
input.onblur = function() {
if (!this.value.includes('@')) { // to nenà e-mail
// zobrazà se chyba
this.classList.add("chyba");
// ...a fokus se vrátà zpÄt
input.focus();
} else {
this.classList.remove("chyba");
}
};
</script>
Funguje to ve vÅ¡ech prohlÞeÄÃch kromÄ Firefoxu (v důsledku chyby).
Jestliže do vstupnÃho pole nÄco zadáme a pak se pokusÃme použÃt Tab nebo klikneme mimo <input>, pak onblur vrátà fokus zpÄt.
ProsÃme vÅ¡imnÄte si, že nemůžeme âzakázat ztrátu fokusuâ volánÃm událost.preventDefault() v onblur, protože onblur se spustà až poté, co element ztratil fokus.
V praxi bychom si vÅ¡ak mÄli dobÅe rozmyslet, zda budeme nÄco takového implementovat, protože obecnÄ bychom mÄli uživateli zobrazovat chyby, ale nemÄli bychom mu bránit pokraÄovat ve vyplÅovánà formuláÅe. Může chtÃt napÅed vyplnit ostatnà pole.
Ke ztrátÄ fokusu může dojÃt z mnoha důvodů.
Jeden z nich je situace, kdy návÅ¡tÄvnÃk klikne nÄkam jinam. Ale ztrátu může způsobit i samotný JavaScript, napÅÃklad:
alertstrhne fokus na sebe, takže způsobà ztrátu fokusu na elementu (událostblur), a kdyžalertzmizÃ, fokus se vrátà zpÄt (událostfocus).- Pokud je element odstranÄn z DOMu, dojde také ke ztrátÄ fokusu. Pokud je pozdÄji znovu vložen, fokus se na nÄj nevrátÃ.
Tyto vlastnosti mohou nÄkdy způsobit, že se handlery focus/blur nechovajà správnÄ â spustà se, když nejsou zapotÅebÃ.
NejlepÅ¡Ãm receptem je dávat si pÅi použÃvánà tÄchto událostà pozor. Chceme-li sledovat ztrátu fokusu iniciovanou uživatelem, mÄli bychom se vyhnout tomu, že ji způsobÃme sami.
Povolenà fokusu na kterýkoli element: tabindex
Mnoho elementů standardnÄ fokus nepodporuje.
Jejich seznam se mezi jednotlivými prohlÞeÄi mÃrnÄ liÅ¡Ã, ale jedno platà vždy: podpora focus/blur je zaruÄena u elementů, s nimiž může návÅ¡tÄvnÃk interagovat: <button>, <input>, <select>, <a> a podobnÄ.
Naproti tomu elementy, jejichž úÄelem je nÄco formátovat, napÅ. <div>, <span>, <table>, standardnÄ nemohou fokus zÃskat. Metoda elem.focus() na nich nefunguje a události focus/blur se nikdy nespustÃ.
To můžeme zmÄnit použitÃm HTML atributu tabindex.
Každý element, který má tabindex, může zÃskat fokus. Hodnotou tohoto atributu je poÅadové ÄÃslo elementu, když je použita klávesa Tab (nebo nÄco podobného) k pÅepÃnánà mezi elementy.
To znamená, že máme-li dva elementy, prvnà má tabindex="1" a druhý tabindex="2", pak když jsme v prvnÃm elementu a stiskneme Tab, fokus se pÅesune na druhý.
PoÅadà pÅepÃnánà je následujÃcÃ: napÅed jdou elementy s tabindex od 1 a vyššÃm (v poÅadà podle tabindex), pak elementy bez tabindex (napÅ. obvyklý <input>).
Elementy bez odpovÃdajÃcÃho tabindex se pÅepÃnajà v poÅadÃ, v jakém jsou ve zdrojovém kódu dokumentu (standardnà poÅadÃ).
DvÄ hodnoty jsou speciálnÃ:
-
tabindex="0"umÃstà element mezi ty, které nemajÃtabindex. To znamená, že když pÅepÃnáme mezi elementy, elementy stabindex=0následujà až po elementech stabindex ⥠1.To se obvykle použÃvá k tomu, abychom umožnili elementu zÃskat fokus, ale zachovali standardnà poÅadà pÅepÃnánÃ. Abychom element uÄinili souÄástà formuláÅe na stejné úrovni, jako
<input>. -
tabindex="-1"umožÅuje nastavit fokus na element pouze programovÄ. Klávesa Tab takové elementy pÅeskakuje, ale metodaelem.focus()na nich funguje.
NapÅÃklad zde máme seznam. KliknÄte na prvnà položku a stisknÄte Tab:
KliknÄte na prvnà položku a stisknÄte Tab. Sledujte poÅadà pÅesunu fokusu. ProsÃme vÅ¡imnÄte si, že mnoho následujÃcÃch stisknutà Tab může v tomto pÅÃkladu pÅesunout fokus mimo iframe.
<ul>
<li tabindex="1">Jedna</li>
<li tabindex="0">Nula</li>
<li tabindex="2">DvÄ</li>
<li tabindex="-1">Minus jedna</li>
</ul>
<style>
li { cursor: pointer; }
:focus { outline: 1px dashed green; }
</style>
PoÅadà je následujÃcÃ: 1 - 2 - 0. BÄžnÄ <li> nepodporuje fokus, ale tabindex jej umožnà vÄetnÄ vlastnostà a nastavenà stylů pomocà :focus.
elem.tabIndexV JavaScriptu můžeme pÅidat tabindex pomocà vlastnosti elem.tabIndex, která má stejný efekt.
DelegovánÃ: focusin/focusout
Události focus a blur nebublajÃ.
Nemůžeme napÅÃklad umÃstit onfocus na <form>, abychom jej zvýraznili, tÅeba takto:
<!-- pÅi fokusu na formuláŠ-- pÅidáme tÅÃdu -->
<form onfocus="this.className='focused'">
<input type="text" name="jméno" value="Jméno">
<input type="text" name="pÅÃjmenÃ" value="PÅÃjmenÃ">
</form>
<style> .focused { outline: 1px solid red; } </style>
Uvedený pÅÃklad nefunguje, protože když uživatel nastavà fokus na <input>, událost focus se spustà jen na tomto vstupu a neprobublá výš. Proto se form.onfocus nikdy nespustÃ.
Má to dvÄ ÅeÅ¡enÃ.
Za prvé, focus/blur majà jednu veselou historickou vlastnost: nebublajÃ, ale propadajà se dolů ve fázi zachytávánÃ.
Tohle bude fungovat:
<form id="form">
<input type="text" name="jméno" value="Jméno">
<input type="text" name="pÅÃjmenÃ" value="PÅÃjmenÃ">
</form>
<style> .focused { outline: 1px solid red; } </style>
<script>
// umÃstÃme handler ve fázi zachytávánà (poslednà argument je true)
form.addEventListener("focus", () => form.classList.add('focused'), true);
form.addEventListener("blur", () => form.classList.remove('focused'), true);
</script>
Za druhé, existujà vlastnosti focusin a focusout â jsou pÅesnÄ stejné jako focus/blur, ale bublajÃ.
VÅ¡imnÄte si, že musejà být pÅiÅazeny pomocà elem.addEventListener, ne pomocà on<událost>.
Zde je tedy jiná fungujÃcà varianta:
<form id="form">
<input type="text" name="jméno" value="Jméno">
<input type="text" name="pÅÃjmenÃ" value="PÅÃjmenÃ">
</form>
<style> .focused { outline: 1px solid red; } </style>
<script>
form.addEventListener("focusin", () => form.classList.add('focused'));
form.addEventListener("focusout", () => form.classList.remove('focused'));
</script>
ShrnutÃ
Události focus a blur se spouÅ¡tÄjà na elementech, když zÃskávajÃ/ztrácejà fokus.
Majà následujÃcà zvláštnosti:
- NebublajÃ. Můžeme vÅ¡ak použÃt fázi zachytávánà nebo události
focusin/focusout. - VÄtÅ¡ina elementů standardnÄ fokus nepodporuje. Abyste umožnili elementu zÃskávat fokus, použijte
tabindex.
Element, který má aktuálnÄ fokus, je k dispozici jako document.activeElement.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)