Anzahl von Kind-Elementen zählen
bearbeitet von
@@claus ginsel
> versteh ich dein JS richtig, dass der Eventhandler erst im Ereignisfall auf das auslösende Element gesetzt und zugleich ausgeführt wird?
Ich glaube nicht.
```js
const itemlist = document.querySelector('table');
itemlist.addEventListener('click', (event) => {
// …
});
```
ist ja im Wesentlichen das, was du auch hattest. Mit ein paar Unterschieden:
- Ich nenne das Ding nicht `table`, sondern `itemlist`. Ist ja keine richtige Datentabelle. Ich war auch schon geneigt, `<table role="presentation">`{:.language-html} zu setzen, wodurch Screenreader das nicht als Tabelle ansagen.
- Ich hab der Tabelle keine ID gegeben; ist ja in meinem Beispiel nicht nötig, weil die einzige. Bei dir ist das völlig richtig, das Ding über dessen ID anzusprechen (wobei `"tab"` kein sinnvoller Bezeichner ist). Ich würde das allerdings nicht mit `getElementById()` tun und auch nicht das von @Friedel ins Spiel gebrachte `getElementsByTagName()` verwenden, sondern `querySelector()` bzw. `querySelectorAll()` – ein einheitliches API für alle Fälle.
- Nicht `onclick`{:.bad}, sondern `addEventListener()`{:.good}.
- Die Eventhandlerfunktion bekommt `event` als Parameter. Wir werden gleich sehen, warum.
Es werden nicht Eventhandler für jedes einzelne interaktive Element registriert, sondern *ein* Eventhandler für deren gemeinsames Vorfahrenelement, wo alle `click`-Events durch Bubbling eintreffen. Also *event delegation*{:@en}.
Ich habe in meinem [Beispiel](https://codepen.io/gunnarbittersmann/pen/abKYEqx?editors=0011) (Link öffnet auch die Konsole) noch hinzugefügt:
```js
console.log(event.target.nodeName);
```
`event.target` liefert das Element, das der Nutzer geclickt hat. Beim Click auf den Button steht bei Tastaturbedienung `"BUTTON"` in der Konsole; bei Mausbedienung hingegen `"SPAN"`, weil ja auf das `span`-Element mit dem 🗑-Icon geclickt wird. Beim Mausclick außerhalb des Buttons wird `"TD"` ausgegeben.
(Die Codezeile ist nur zur Veranschauung und hat im Produktiv-Code nichts zu suchen.)
Als nächstes wird abgefragt, ob der bei `itemlist` ankommende `click`-Event von innerhalb eines Buttons kommt (d.h. vom `button` selbst (Tastaturbedienung) oder einem darin befindlichen Nachfahrenelement (Mausbedienung)):
```js
if (event.target.closest('button')) {
```
Die Aktion Löschen soll nur ausgeführt werden, wenn ein Löschen-Button betätigt wurde. Wenn man woanders hinclickt, soll nichts passieren.
(Das hattest du anders? Halte ich für einen Designfehler. Insbesondere, weil bei dir noch der ⤓ hinzukommt; und verschachtelte Clickflächen sind nicht die beste Idee.)
Wenn ein Löschen-Button betätigt wurde, wird dessen übergeornetes `tr`-Element ermittelt (es soll ja genau dieses gelöscht werden, nicht irgendein anderes):
```js
const item = event.target.closest('tr');
```
Bei dir passiert da natürlich noch was anderes. – Und bei jedem Item dasselbe, d.h. die letzte Abfrage in meinem Beispiel
```js
if (!item.querySelector('#unsere-liebe')) {
```
wirst du nicht haben. Die ist nur deshalb, weil unsere Liebe nicht bricht.
🖖 Живіть довго і процвітайте
{:@uk}
--
*„Im Vergleich mit Elon Musk bei Twitter ist ein Elefant im Porzellanladen eine Ballerina.“*
— @Grantscheam auf Twitter
Anzahl von Kind-Elementen zählen
bearbeitet von
@@claus ginsel
> versteh ich dein JS richtig, dass der Eventhandler erst im Ereignisfall auf das auslösende Element gesetzt und zugleich ausgeführt wird?
Ich glaube nicht.
```js
const itemlist = document.querySelector('table');
itemlist.addEventListener('click', (event) => {
// …
});
```
ist ja im Wesentlichen das, was du auch hattest. Mit ein paar Unterschieden:
- Ich nenne das Ding nicht `table`, sondern `itemlist`. Ist ja keine richtige Datentabelle. Ich war auch schon geneigt, `<table role="presentation">`{:.language-html} zu setzen, wodurch Screenreader das nicht als Tabelle ansagen.
- Ich hab der Tabelle keine ID gegeben; ist ja in meinem Beispiel nicht nötig, weil die einzige. Bei dir ist das völlig richtig, das Ding über dessen ID anzusprechen (wobei `"tab"` kein sinnvoller Bezeichner ist). Ich würde das allerdings nicht mit `getElementById()` tun und auch nicht das von @Friedel ins Spiel gebrachte `getElementsByTagName()` verwenden, sondern `querySelector()` bzw. `querySelectorAll()` – ein einheitliches API für alle Fälle.
- Nicht `onclick`{:.bad}, sondern `addEventListener()`{:.good}.
- Die Eventhandlerfunktion bekommt `event` als Parameter. Wir werden gleich sehen, warum.
Es werden nicht Eventhandler für jedes einzelne interaktive Element registriert, sondern *ein* Eventhandler für deren gemeinsames Vorfahrenelement, wo alle `click`-Events durch Bubbling eintreffen. Also *event delegation*{:@en}.
Ich habe in meinem [Beispiel](https://codepen.io/gunnarbittersmann/pen/abKYEqx?editors=0011) (Link öffnet auch die Konsole) noch hinzugefügt:
```js
console.log(event.target.nodeName);
```
`event.target` liefert das Element, das der Nutzer geclickt hat. Beim Click auf den Button steht bei Tastaturbedienung `"BUTTON"` in der Konsole; bei Mausbedienung hingegen `"SPAN"`, weil ja auf das `span`-Element mit dem 🗑-Icon geclickt wird. Beim Click außerhalb des Button wird `"TD"` ausgegeben.
(Die Codezeile ist nur zur Veranschauung und hat im Produktiv-Code nichts zu suchen.)
Als nächstes wird abgefragt, ob der bei `itemlist` ankommende `click`-Event von innerhalb eines Buttons kommt (d.h. vom `button` selbst (Tastaturbedienung) oder einem darin befindlichen Nachfahrenelement (Mausbedienung)):
```js
if (event.target.closest('button')) {
```
Die Aktion Löschen soll nur ausgeführt werden, wenn ein Löschen-Button betätigt wurde. Wenn man woanders hinclickt, soll nichts passieren.
(Das hattest du anders? Halte ich für einen Designfehler. Insbesondere, weil bei dir noch der ⤓ hinzukommt; und verschachtelte Clickflächen sind nicht die beste Idee.)
Wenn ein Löschen-Button betätigt wurde, wird dessen übergeornetes `tr`-Element ermittelt (es soll ja genau dieses gelöscht werden, nicht irgendein anderes):
```js
const item = event.target.closest('tr');
```
Bei dir passiert da natürlich noch was anderes. – Und bei jedem Item dasselbe, d.h. die letzte Abfrage in meinem Beispiel
```js
if (!item.querySelector('#unsere-liebe')) {
```
wirst du nicht haben. Die ist nur deshalb, weil unsere Liebe nicht bricht.
🖖 Живіть довго і процвітайте
{:@uk}
--
*„Im Vergleich mit Elon Musk bei Twitter ist ein Elefant im Porzellanladen eine Ballerina.“*
— @Grantscheam auf Twitter
Anzahl von Kind-Elementen zählen
bearbeitet von
@@claus ginsel
> versteh ich dein JS richtig, dass der Eventhandler erst im Ereignisfall auf das auslösende Element gesetzt und zugleich ausgeführt wird?
Ich glaube nicht.
```js
const itemlist = document.querySelector('table');
itemlist.addEventListener('click', (event) => {
// …
});
```
ist ja im Wesentlichen das, was du auch hattest. Mit ein paar Unterschieden:
- Ich nenne das Ding nicht `table`, sondern `itemlist`. Ist ja keine richtige Datentabelle. Ich war auch schon geneigt, `<table role="presentation">`{:.language-html} zu setzen, wodurch Screenreader das nicht als Tabelle ansagen.
- Ich hab der Tabelle keine ID gegeben; ist ja in meinem Beispiel nicht nötig, weil die einzige. Bei dir ist das völlig richtig, das Ding über dessen ID anzusprechen (wobei `"tab"` kein sinnvoller Bezeichner ist). Ich würde das allerdings nicht mit `getElementById()` tun und auch nicht das von @Friedel ins Spiel gebrachte `getElementsByTagName()` verwenden, sondern `querySelector()` bzw. `querySelectorAll()` – ein einheitliches API für alle Fälle.
- Nicht `onclick`{:.bad}, sondern `addEventListener()`{:.good}.
- Die Eventhandlerfunktion bekommt `event` als Parameter. Wir werden gleich sehen, warum.
Es werden nicht Eventhandler für jedes einzelne interaktive Element registriert, sondern *ein* Eventhandler für deren gemeinsames Vorfahrenelement, wo alle `click`-Events durch Bubbling eintreffen. Also *event delegation*{:@en}.
Ich habe in meinem [Beispiel](https://codepen.io/gunnarbittersmann/pen/abKYEqx?editors=0011) (Link öffnet auch die Konsole) noch hinzugefügt:
```js
console.log(event.target.nodeName);
```
`event.target` liefert das Element, das der Nutzer geclickt hat: bei Tastaturbedienung steht `"BUTTON"` in der Konsole; bei Mausbedienung hingegen `"SPAN"`, weil ja auf das `span`-Element mit dem 🗑-Icon geclickt wird.
(Die Codezeile ist nur zur Veranschauung und hat im Produktiv-Code nichts zu suchen.)
Als nächstes wird abgefragt, ob der bei `itemlist` ankommende `click`-Event von innerhalb eines Buttons kommt (d.h. vom `button` selbst (Tastaturbedienung) oder einem darin befindlichen Nachfahrenelement (Mausbedienung)):
```js
if (event.target.closest('button')) {
```
Die Aktion Löschen soll nur ausgeführt werden, wenn ein Löschen-Button betätigt wurde. Wenn man woanders hinclickt, soll nichts passieren.
(Das hattest du anders? Halte ich für einen Designfehler. Insbesondere, weil bei dir noch der ⤓ hinzukommt; und verschachtelte Clickflächen sind nicht die beste Idee.)
Wenn ein Löschen-Button betätigt wurde, wird dessen übergeornetes `tr`-Element ermittelt (es soll ja genau dieses gelöscht werden, nicht irgendein anderes):
```js
const item = event.target.closest('tr');
```
Bei dir passiert da natürlich noch was anderes. – Und bei jedem Item dasselbe, d.h. die letzte Abfrage in meinem Beispiel
```js
if (!item.querySelector('#unsere-liebe')) {
```
wirst du nicht haben. Die ist nur deshalb, weil unsere Liebe nicht bricht.
🖖 Живіть довго і процвітайте
{:@uk}
--
*„Im Vergleich mit Elon Musk bei Twitter ist ein Elefant im Porzellanladen eine Ballerina.“*
— @Grantscheam auf Twitter