Inhalte ausblenden
Meowsalot
- html
Guten Morgen,
besteht die Möglichkeit über ein data-attribut Inhalte auf meiner Webseite auszublenden? Es geht mir um folgende Option:
Ich habe eine Liste von Einträgen, jetzt möchte nur die angezeigt bekommen die mir zugeordnet wurden. Meine Idee war ich nutze ein data-attribut z.B.
data-name="meowsalot"
wenn ich jetzt eine Checkbox anklicke dann sollten alle anderen ausgeblendet werden die nicht mir zugeordnet wurden.
Ist dieses möglich?
Bis bald!
Meowsalot (Bernd)
Hallo,
ich habe hier bei Gunnar etwas gefunden, was in meine Richtung geht: https://codepen.io/gunnarbittersmann/pen/reRPJj
Jetzt müsste ich dieses nur irgendwie auf mein data-name und data-name-2 anwenden.
Und dazu kommt, dass ich eine Tabelle habe und keine Liste. Außerdem ist mir gerade aufgefallen dass das Beispiel nur mit CSS umgesetzt ist. Ist dieses wirklich so sinnvoll oder doch lieber mit jQuery (diese habe ich eh im Einsatz).
Bis bald!
Meowsalot (Bernd)
Hallo @Meowsalot,
Außerdem ist mir gerade aufgefallen dass das Beispiel nur mit CSS umgesetzt ist. Ist dieses wirklich so sinnvoll oder doch lieber mit jQuery (diese habe ich eh im Einsatz).
Warum umständlich (jquery), wenn es auch einfach und portabel (CSS) geht? Ich ziehe eine einfache und reine CSS-Lösung nach Möglichkeit immer irgendeinem JavaScript-Framework vor. Denn ersteres wird sehr viel wahrscheinlicher immer und überall funktionieren.
Viele Grüße
Robert
@@Meowsalot
besteht die Möglichkeit über ein data-attribut Inhalte auf meiner Webseite auszublenden? Es geht mir um folgende Option:
Ich habe eine Liste von Einträgen, jetzt möchte nur die angezeigt bekommen die mir zugeordnet wurden. Meine Idee war ich nutze ein data-attribut z.B.
data-name="meowsalot"
Die Idee ist gut.
wenn ich jetzt eine Checkbox anklicke
Diese weniger. Ein Toggle-Button ist die bessere Idee.
“The trouble with using form elements is their longstanding association with the collection of data. That is, checkboxes and radio buttons are established as controls for designating values. When a user checks a checkbox, they may just be switching a state, but they may suspect they are also choosing a value for submission.
“Whether you’re a sighted user looking at a checkbox, a screen reader user listening to its identity being announced, or both, its etymology is problematic. We expect toggle buttons to be buttons, but checkboxes and radio buttons are really inputs.”
dann sollten alle anderen ausgeblendet werden die nicht mir zugeordnet wurden.
also alle Items in der die Liste (bspw. <ul id="einträge">
) selektieren, die nicht data-name="meowsalot"
sind:
#einträge > li:not([data-name="meowsalot"])
Ist dieses möglich?
Klar. Nehmen wir solch einen Button (bspw. <button id="filter" aria-pressed="false">
), der sein aria-pressed
-Attribut zwischen "true"
und "false"
umschaltet.
Wenn die Liste (bspw. <ul id="einträge">
) ein nachfolgendes Geschwisterelement des Buttons ist, dann:
#filter[aria-pressed="true"] ~ #einträge > li:not([data-name="meowsalot"])
{
display: none;
}
Die robustere Variante (geht auch, wenn die Liste kein nachfolgendes Geschwisterelement des Buttons ist): per JavaScript nicht nur das aria-pressed
-Attribut umschalten, sondern auch noch ein data
-Attribut (oder class
-Attribut) für die Liste. Bspw. data-filtered="true"
und
#einträge[data-filtered="true"] > li:not([data-name="meowsalot"])
{
display: none;
}
LLAP 🖖
Hej Gunnar,
@@Meowsalot
besteht die Möglichkeit über ein data-attribut Inhalte auf meiner Webseite auszublenden?
dann sollten alle anderen ausgeblendet werden die nicht mir zugeordnet wurden.
Ist dieses möglich?
Klar. Nehmen wir solch einen Button (bspw.
<button id="filter" aria-pressed="false">
), der seinaria-pressed
-Attribut zwischen"true"
und"false"
umschaltet…
…und jedem li
ohne Meowsalot
ein hidden
mitgibt…
Marc
@@marctrix
…und jedem
li
ohneMeowsalot
einhidden
mitgibt…
Das würde ich in dem Fall nicht tun. Das macht das Script nur unnötig aufwendig – ohne erkennbaren Nutzen.
Wer hier ein hidden
mitkriegt, ist der Button, denn der macht ja im UI gar keinen Sinn, solange das JavaScript nicht geladen und ausgeführt wurde.
Also <button id="filter" aria-pressed="false" hidden="">
im Markup und im Script als erstes:
const filterButtonElement = document.querySelector('#filter');
filterButtonElement.hidden = false;
(Und wenn du jetzt einwendest, der Button macht auch keinen Sinn, wenn das Stylesheet nicht geladen und ausgeführt würde – ja, einen Tod muss man hier wohl sterben.)
LLAP 🖖
Hallo Gunnar,
vielen Dank für deine sehr ausführliche Erklärung und deinem Beispiel. Ich habe es etwas umgebaut: https://codepen.io/anon/pen/PRaLbB
Dieses funktioniert leider nicht
#einträge[data-filtered="true"] > tr:not([data-name-sender="User1"]),
#einträge[data-filtered="true"] > tr:not([data-name-empf="User1"]) {
display: none;
}
Ich nehme an, es liegt an diesem > tr: wie müsste dieses bei einer Tabelle heißen?
Bis bald!
Meowsalot (Bernd)
Hej Meowsalot,
Dieses funktioniert leider nicht
#einträge[data-filtered="true"] > tr:not([data-name-sender="User1"]), #einträge[data-filtered="true"] > tr:not([data-name-empf="User1"]) { display: none; }
Ich nehme an, es liegt an diesem > tr:
Nein, es liegt daran, dass du abfragst, ob es data-filtered="true"
gibt. Das setzt Dein Button aber nciht. Also wird auch nichts ausgeblendet…
Marc
Hallo marctrix,
Nein, es liegt daran, dass du abfragst, ob es
data-filtered="true"
gibt. Das setzt Dein Button aber nciht. Also wird auch nichts ausgeblendet…
dann habe ich dieses wohl falsch verstanden
Klar. Nehmen wir solch einen Button (bspw. <button id="filter" aria-pressed="false">), der sein aria-pressed-Attribut zwischen "true" und "false" umschaltet.
Wie kann ich den Button dazu bringen dass er auf true setzt?
EDIT: Ich habe jetzt das JavaScript eingefügt. Laut Entwicklertool wird auch umgeschaltet aber meine Einträge werden nicht ausgeblendet:
https://codepen.io/anon/pen/PRaLbB
Bis bald!
Meowsalot (Bernd)
@@Meowsalot
Nehmen wir solch einen Button (bspw. <button id="filter" aria-pressed="false">), der sein aria-pressed-Attribut zwischen "true" und "false" umschaltet.
Wie kann ich den Button dazu bringen dass er auf true setzt?
Das tut er.
BTW: const toggle = document.querySelector('[aria-pressed]');
würde ich so nicht verwenden. Das selektiert den ersten Toggle-Button auf der Seite, in deinem Fall also den einen. Was aber, wenn du mehrere davon hast?
Da dein Toggle-Button eine ID hat, kannst du ihn anhand derer selektieren. Und ich würde die Variable auch entsprechend benennen, bspw:
const filterButtonElement = document.querySelector('#filter');
Was er noch nicht tut: beim Element mit der ID "einträge" das data-filtered
-Attribut entsprechend setzen. Das müsstest du noch ergänzen.
EDIT: Ich habe jetzt das JavaScript eingefügt.
Das macht so keinen Sinn:
const button = document.querySelector('button');
Wozu? Du hast bereits eine Referenz auf das Button-Objekt. Wozu nochmal denselben Button selektieren und noch in einer anderen Variablen ablegen?
Außerdem macht die Änderung des Textes so keinen Sinn. Bis zum Abschnitt Changing Labels warst du nicht vorgedrungen? Darin beschreibt Heydon die Problematik.
LLAP 🖖
Hallo Gunnar,
const filterButtonElement = document.querySelector('#filter');
wenn ich dieses so nutze dann geht gar nichts mehr, schade:
https://codepen.io/anon/pen/PRaLbB
Kann man das nicht auch irgendwie mit jQuery umsetzten?
Was er noch nicht tut: beim Element mit der ID "einträge" das
data-filtered
-Attribut entsprechend setzen. Das müsstest du noch ergänzen.
Hmm, verstehe ich ehrlich gesagt nichts. Davon ist in deinem Beispiel auch nichts zu sehen.
Außerdem macht die Änderung des Textes so keinen Sinn. Bis zum Abschnitt Changing Labels warst du nicht vorgedrungen? Darin beschreibt Heydon die Problematik.
Ich denke schon dass es ein Sinn macht? Soll ich den User im dunklen lassen was gerade angezeigt wird? Da kommt er sich verarscht vor und ruf hier vielleicht ständig an, es geht nichts, die Einträge werden nicht mehr angezeigt usw.....
Bis bald!
Meowsalot (Bernd)
@@Meowsalot
const filterButtonElement = document.querySelector('#filter');
wenn ich dieses so nutze dann geht gar nichts mehr, schade:
Natürlich nicht …
const filterButtonElement = document.querySelector('#filter');
toggle.addEventListener(...
Du musst den EventListener schon für filterButtonElement
vorsehen.
Kann man das nicht auch irgendwie mit jQuery umsetzten?
Du kannst mit jQuery nicht mehr tun als mit reinem JavaScript.
Was er noch nicht tut: beim Element mit der ID "einträge" das
data-filtered
-Attribut entsprechend setzen. Das müsstest du noch ergänzen.Hmm, verstehe ich ehrlich gesagt nichts. Davon ist in deinem Beispiel auch nichts zu sehen.
Nein, das habe ich auch nicht eingebaut. Ich gehe davon aus, dass du das selbst schaffst.
Außerdem macht die Änderung des Textes so keinen Sinn. Bis zum Abschnitt Changing Labels warst du nicht vorgedrungen? Darin beschreibt Heydon die Problematik.
Ich denke schon dass es ein Sinn macht?
Ich habe dich nicht auf den Abschnitt hingewiesen, damit du ihm ungelesen widersprichst.
“As a rule of thumb, you should never change pressed state and label together.”
Soll ich den User im dunklen lassen was gerade angezeigt wird?
Heydon beschreibt eine Lösung des Problems mit aria-labelledby
. In deinem Fall sollte es mit aria-label
(worin der Text nicht geändert wird) gehen:
<button id="filter" aria-pressed="false" aria-label="Nur meine anzeigen" hidden="">
(zu hidden
siehe anderes Posting)
LLAP 🖖
Hallo Gunnar,
meine Idee war so: https://codepen.io/anon/pen/PRaLbB
const filterButtonElement = document.querySelector('#filter');
filterButtonElement.addEventListener('click', (e) => {
let pressed = e.target.getAttribute('aria-pressed') === 'true'
e.target.setAttribute('aria-pressed', String(!pressed));
let pressed = e.target.getAttribute('data-filtered') === 'true'
e.target.setAttribute('data-filtered', String(!pressed));
});
filterButtonElement.addEventListener('click', (e) => {
let text = e.target.textContent === 'Alle anzeigen' ? 'Nur meine anzeigen' : 'Alle anzeigen';
e.target.textContent = text;
});
Mein Problem ist, ich kenne mich mit JavaScript 0 aus. Jetzt reagiert nur noch das wechseln vom Text. Es wird nichts mehr auf true gesetzt.
Bis bald!
Meowsalot (Bernd)
Hallo Meowsalot,
ich habe es so hinbekommen: https://codepen.io/anon/pen/PRaLbB
const filterButtonElement = document.querySelector('#filter');
filterButtonElement.hidden = false;
filterButtonElement.addEventListener('click', (e) => {
let pressed = e.target.getAttribute('aria-pressed') === 'true'
e.target.setAttribute('aria-pressed', String(!pressed));
});
filterButtonElement.addEventListener('click', (e) => {
let pressed = e.target.getAttribute('data-filtered') === 'true'
document.getElementById('eintraege').setAttribute('data-filtered','true');
});
filterButtonElement.addEventListener('click', (e) => {
let text = e.target.textContent === 'Alle anzeigen' ? 'Nur meine anzeigen' : 'Alle anzeigen';
e.target.textContent = text;
});
Allerdings verschwinden meine Einträge noch immer nicht und das data-filtered verschwindet auch nicht wieder wenn ich wieder auf den Button klicke.
EDIT: OK, so kann ich auch das data-filterd anpassen
const filterButtonElement = document.querySelector('#filter');
filterButtonElement.hidden = false;
filterButtonElement.addEventListener('click', (e) => {
let pressed = e.target.getAttribute('aria-pressed') === 'true'
e.target.setAttribute('aria-pressed', String(!pressed));
});
filterButtonElement.addEventListener('click', (e) => {
let pressed1 = e.target.getAttribute('aria-pressed') === 'true'
console.log(pressed1);
if (pressed1 == true) {
document.getElementById('eintraege').setAttribute('data-filtered','true');
} else {
document.getElementById('eintraege').setAttribute('data-filtered','false');
}
});
filterButtonElement.addEventListener('click', (e) => {
let text = e.target.textContent === 'Alle anzeigen' ? 'Nur meine anzeigen' : 'Alle anzeigen';
e.target.textContent = text;
});
Ändern tut sich an meiner Liste dennoch nichts.
Bis bald!
Meowsalot (Bernd)
Hallo Meowsalot,
wenn ich dieses https://caniuse.com/#search=%3Anot richtig verstehe, dann funktioniert > tr:not im Google Chrome nicht? Rot soweit ich sehen kann.
Bis bald!
Meowsalot (Bernd)
Hallo
wenn ich dieses https://caniuse.com/#search=%3Anot richtig verstehe, dann funktioniert > tr:not im Google Chrome nicht? Rot soweit ich sehen kann.
Du hast auch die Erklärung oberhalb der Tabelle gelesen? Speziell in der ersten der aufgeführten Eigenschaften geht es nicht um :not
an sich, sondern darum, ob als Argument von :not
auch Listen von Selektoren erlaubt sind. Einfache Selektoren wie z.B. bla:not(p)
oder bla:not(last-child)
, darauf weist die Erklärung ebenfalls hin, funktionieren schon seit Längerem, wie sich zusätzlich durch herunterscrollen der verlinkten Seite ermitteln ließe. Da ist alles knallegrün.
Tschö, Auge
Hallo Auge,
dann verstehe ich es einfach nicht oder man kann keine Tabellenzeilen ausblenden.
Bis bald!
Meowsalot (Bernd)
@@Meowsalot
Hallo Meowsalot,
ich habe es so hinbekommen: https://codepen.io/anon/pen/PRaLbB
Sieht doch schon mal ganz gut aus. Der Button ändert sein aria-pressed
-Attribut und das data-filtered
-Attribut der Tabelle.
Noch eins, zwei Anmerkungen:
filterButtonElement.addEventListener('click', (e) => { let pressed = e.target.getAttribute('aria-pressed') === 'true' e.target.setAttribute('aria-pressed', String(!pressed)); });
Ich bin kein Freund von diesem e
-Dingens, sondern von sprechenden Variablen. Ich nenne das immer event
.
filterButtonElement.addEventListener('click', (e) => { let pressed = e.target.getAttribute('data-filtered') === 'true' document.getElementById('eintraege').setAttribute('data-filtered','true'); }); filterButtonElement.addEventListener('click', (e) => { let text = e.target.textContent === 'Alle anzeigen' ? 'Nur meine anzeigen' : 'Alle anzeigen'; e.target.textContent = text; });
Warum 2× EventListener? Das gehört doch alles zusammen, sollte also in einem Block stehen.
Allerdings verschwinden meine Einträge noch immer nicht
Das liegt daran, dass deine Selektoren im Stylesheet nicht greifen:
#eintraege [data-filtered="true"]
: Nicht ein Nachfahrenelement des Elements mit der ID "eintraege" (d.h. der Tabelle) hat das data-filtered
-Attribut, sondern die Tabelle selbst. Das Leerzeichen muss weg.
#eintraege[data-filtered="true"] > tr:not([data-name-sender="User1"])
geht immer noch nicht, weil tr
kein Kindelement von table
ist. >
ist aber der Kombinator für direkte Nachfahren.
(Das wäre auch so, wenn es keine <tbody>
-Tags im HTML-Code gäbe; kein Aprilscherz.)
Als Nachfahrenelement #eintraege[data-filtered="true"] tr:not([data-name-sender="User1"])
ohne >
selektiert ist wohl aber auch nicht das, was du willst, denn die Kopfzeile im thead
soll ja stehenbleiben.
Also nur die Zeilen im tbody
selektiert: #eintraege[data-filtered="true"] > tbody > tr:not([data-name-sender="User1"])
Das funktioniert dann schon mal:
#eintraege[data-filtered="true"] > tbody > tr:not([data-name-sender="User1"])
{
display: none;
}
Aber nicht die Kombination
#eintraege[data-filtered="true"] > tbody > tr:not([data-name-sender="User1"]),
#eintraege[data-filtered="true"] > tbody > tr:not([data-name-empf="User1"])
{
display: none;
}
Dann sind alle Zeilen weg, die kein data-name-sender="User1"
haben, also auch die Zeilen, die data-name-empf="User1"
haben. Und es sind alle Zeilen weg, die kein data-name-empf="User1"
haben, also auch die Zeilen, die data-name-sender="User1"
haben.
Du willst aber alle Zeilen weghaben, die weder data-name-sender="User1"
noch data-name-empf="User1"
haben:
#eintraege[data-filtered="true"] > tbody > tr:not([data-name-sender="User1"]):not([data-name-empf="User1"])
{
display: none;
}
LLAP 🖖
Hallo Gunnar,
vielen vielen vielen Dank, es hat funktioniert: https://codepen.io/anon/pen/PRaLbB
Warum 2× EventListener? Das gehört doch alles zusammen, sollte also in einem Block stehen.
Ich habe nun alles in einen gepackt
const filterButtonElement = document.querySelector('#filter');
filterButtonElement.hidden = false;
filterButtonElement.addEventListener('click', (event) => {
let pressed = event.target.getAttribute('aria-pressed') === 'true'
event.target.setAttribute('aria-pressed', String(!pressed));
let pressed1 = event.target.getAttribute('aria-pressed') === 'true'
if (pressed1 == true) {
document.getElementById('eintraege').setAttribute('data-filtered','true');
} else {
document.getElementById('eintraege').setAttribute('data-filtered','false');
}
let text = event.target.textContent === 'Alle anzeigen' ? 'Nur meine anzeigen' : 'Alle anzeigen';
event.target.textContent = text;
});
Meine erste Vermutung von vorhin war also doch gar nicht so falsch, dass es am > tr: liegt
https://forum.selfhtml.org/self/2018/apr/3/inhalte-ausblenden/1718131#m1718131
Dein CSS habe ich auch noch etwas auf meine Bedürfnisse angepasst:
#eintraege[data-filtered="true"] > tbody > tr:not([data-name-sender="User1"]):not([data-name-empf="User1"]):not([data-name-sender="alle"]):not([data-name-empf="alle"])
{
display: none;
}
Jetzt habe ich noch eine abschließende Frage, ist es möglich den Wert der gesetzt wurde (nur meine, oder alle) irgendwo zu speichern dass ich nicht nach jedem Reload oder nachdem ich etwas anderes angeklickt habe wieder wählen muss?
Bis bald!
Meowsalot (Bernd)
Hallo
Jetzt habe ich noch eine abschließende Frage, ist es möglich den Wert der gesetzt wurde (nur meine, oder alle) irgendwo zu speichern dass ich nicht nach jedem Reload oder nachdem ich etwas anderes angeklickt habe wieder wählen muss?
Geht es um die Speicherung einer Konfiguration? Wenn die Speicherung nur in dem einen Browser des Benutzers erfolgen soll, dann bietet sich „Local Storage“ an. Den kannst du mit JS schreiben und lesen.
Tschö, Auge
@@Meowsalot
Ein paar Anmerkungen hab ich noch:
let pressed = event.target.getAttribute('aria-pressed') === 'true' event.target.setAttribute('aria-pressed', String(!pressed)); let pressed1 = event.target.getAttribute('aria-pressed') === 'true'
Du hattest doch event.target.getAttribute('aria-pressed')
gerade vorher schon mal abgefragt, danach auf das Gegenteil !pressed
gesetzt, weißt also genau, was da jetzt drinsteht. Kein Grund, das nochmals abzufragen, du kannst genauso !pressed
verwenden; pressed1
brauchst du nicht.
BTW, pressed
ist kein besonders glücklich gewählter Bezeichner, da daraus nicht hervorgeht, ob das den Zustand vorher oder den neuen Zustand bezeichnet. Die Variable sollte umbenannt werden.
if (pressed1 == true) { document.getElementById('eintraege').setAttribute('data-filtered','true'); } else { document.getElementById('eintraege').setAttribute('data-filtered','false'); }
Du willst in beiden Zweigen dasselbe tun, nämlich dem data-filtered
-Attrubut einen booleschen Wert zuweisen. (Genauer gesagt: einen String, der einen booleschen Wert repräsentiert.)
Dafür brauchst du kein if
, das machst du analog wie oben beim aria-pressed
-Attribut. Deren Werte sollen ja immer übereinstimmen, also:
let pressed = event.target.getAttribute('aria-pressed') === 'true';
event.target.setAttribute('aria-pressed', String(!pressed));
document.getElementById('eintraege').setAttribute('data-filtered', String(!pressed));
Es muss auch nicht sein, das Element mit der ID "eintraege" jedesmal neu zu suchen. Das kannst du einmal am Anfang erledigen (also außerhalb des Eventhandlers):
const eintraegeTableElement = document.getElementById('eintraege');
oder
const eintraegeTableElement = document.querySelector('#eintraege');
Im Eventhandler dann
eintraegeTableElement.setAttribute('data-filtered', String(!pressed));
oder
eintraegeTableElement.dataset.filtered = String(!pressed);
let text = event.target.textContent === 'Alle anzeigen' ? 'Nur meine anzeigen' : 'Alle anzeigen'; event.target.textContent = text; });
Noch eine überflüssige Abfrage; die (sichtbare) Buttonbeschriftung hängt auch mit dem pressed
-Zustand zusammen:
let text = pressed ? 'Nur meine anzeigen' : 'Alle anzeigen';
event.target.textContent = text;
Wobei es hier keinen Sinn macht, da über eine Variable text
zu gehen. Gleich direkt:
event.target.textContent = pressed ? 'Nur meine anzeigen' : 'Alle anzeigen';
LLAP 🖖
Ich bin kein Freund von diesem
e
-Dingens, sondern von sprechenden Variablen. Ich nenne das immerevent
.
Du sprichst mir aus der Seele! Daher habe ich auch Probleme mit solchen Sachen:
Du willst aber alle Zeilen weghaben, die weder
data-name-sender="User1"
nochdata-name-empf="User1"
haben:#eintraege[data-filtered="true"] > tbody > tr:not([data-name-sender="User1"]):not([data-name-empf="User1"]) { display: none; }
Ja klar, kriegt man schon gedanklich noch auseinander gefriemelt, aber gut lesbar finde ich das nicht. Geht nicht gegen Dich und es gibt ja noch deutlich krassere Beispiele.