Tabby – refactoring
Wir haben nun zwei Events für Tabby: eines lauscht auf einen Mausklick, eines auf die Pfeiltasten. Das lässt sich vereinfachen.
The click event
Section titled “The click event”Den Großteil des Codes für das Click-Event können wir in eine Funktion selectTab() auslagern:
/** * Selects a tab and the corresponding tab-content * @param {HTML-Element} tab | Tab that was clicked * @returns {}*/function selectTab() { const tab = e.target; const target = tab.dataset.target; const tabContent = tabby.querySelector('#' + target);
// Selects a tab tabs.forEach(t => { t.classList.remove('is-selected'); t.setAttribute('tabindex', '-1'); }); tab.classList.add('is-selected'); tab.removeAttribute('tabindex');
// Selects the corresponding tab content tabsContents.forEach(c => c.classList.remove('is-selected')); tabContent.classList.add('is-selected');}Folgende Variable brauchen wir:
tabtabstabContenttabsContents
Wir erhalten diese aus:
tabause.targettabsaus dem global scopetabContentaustab(bzw. daraus abgeleitettarget)tabsContentsaus dem global scope
Das bedeutet, dass wir der Funktion nur tab als Argument übergeben müssen:
function selectTab(tab) { const target = tab.dataset.target; const tabContent = tabby.querySelector('#' + target); // ...}Verwendung von selectTab() im EventListener:
tabsList.addEventListener('click', e => { const tab = e.target; selectTab(tab);});The keydown event
Section titled “The keydown event”In den ersten zwei Zeilen des EventListeners für das Keydown-Event entscheiden wir nur, ob wir auf den Event reagieren oder nicht. Dieser Teil kann nicht woanders hingeschoben werden.
In der dritten Zeile prüfen wir, welches Tab aktuell ausgewählt wurde bzw. im Fokus ist. Auch diese Zeile muss hier bleiben.
tabsList.addEventListener('keydown', e => { const { key } = e; if (key !== 'ArrowLeft' || key !== 'ArrowRight') return;
const index = tabs.findIndex(t => t.classList.contains('is-selected')); // ...});Die nächsten Zeilen werden dazu verwendet, den Zieltab zu finden, also:
- entscheiden, ob wir den vorhergehenden oder den nächsten Tab haben wollen
- den vorhergehenden oder den nächsten Tab finden
- ein Click-Event triggern
Um den Code zu vereinfachen, können wir zwei Funktionen getPreviousTab und getNextTab schreiben:
function getPreviousTab() { if (key === 'ArrowLeft' && index !== 0) targetTab = tabs[index - 1];}
function getNextTab() { if (key === 'ArrowRight' && index !== tabs.length - 1) targetTab = tabs[index + 1];}Welche Taste gedrückt wurde, ist innerhalb dieser Funktion eigentlich nicht relevant, daher können wir diesen Teil aus den Funktionen rausnehmen:
function getPreviousTab() { if (index !== 0) targetTab = tabs[index - 1];}
function getNextTab() { if (index !== tabs.length - 1) targetTab = tabs[index + 1];}Wir müssen aber den vorhergehden bzw. den nächsten Tab in der Funktion als Rückgabewert definieren:
function getPreviousTab() { if (index !== 0) { return tabs[index - 1]; }}
function getNextTab() { if (index !== tabs.length - 1) { return tabs[index + 1]; }}Wir brauchen zwei Variable für die beiden Funktionen:
tabsindex
tabs bekommen wir aus dem global scope, daher müssen wir nur index als Argument mitgeben:
/** * Selects the previous tab * @param {number} index | Index of the selected tab * @returns {number} index of the previous tab*/function getPreviousTab(index) { if (index !== 0) { return tabs[index - 1]; }}
/** * Selects the next tab * @param {number} index | Index of the selected tab * @returns {number} index of the next tab*/function getNextTab(index) { if (index !== tabs.length - 1) { return tabs[index + 1]; }}Verwendung von previousTab() und nextTab():
document.addEventListener('keydown', e => { // ... const index = tabs.findIndex(t => t.classList.contains('is-selected'));
let targetTab; if (key === 'ArrowLeft') targetTab = getPreviousTab(index); if (key === 'ArrowRight') targetTab = getNextTab(index);
// ...})Das macht mehr Sinn:
- Wenn Pfeil-nach-links-Taste, nehmen wir den vorhergehenden Tab
- Wenn Pfeil-nach-rechts-Taste, nehmen wir den nächsten Tab
Eine letzte Verbesserung geht auch noch: Wenn wir den targetTab gefunden haben, haben wir einen Klick drauf getriggert.
document.addEventListener('keydown', e => { // ... if (targetTab) { targetTab.click(); }});Wenn wir diesen Code lesen, verstehen wir, dass wir ein click Event getriggert haben, das den passenden Tab mit selectTab() auswählt.