bei Klick nächstes Element ausblenden
Matze
- javascript
Hallo,
ich habe eine Überschrift und darunter eine Liste.
<h3>Überschrift</h3>
<ul>
<li>foo</li>
<li>bar</li>
</ul>
Beim klick auf die Überschrift soll nun die Liste ausgeblendet werden.
An die Überschrift komm ich mit JS über target, aber ich weiß nicht wie ich die nachfolgende Liste ansprechen kann.
Ich habe es mit nextSibling versucht, aber da erhalte ich immer nur #text :(
function handleClicks(e){
var e=(window.event)?window.event:e;
var o=(window.event)?e.srcElement:e.target;
liste = o.nextSibling;
// dachte das funzt*
// liste.style.display = 'none';
// tut es aber nicht ;)
alert(liste);
}
window.document.addEventListener("click", handleClicks, false);
Könnte mir bitte jemand sagen wie ich an die <ul> komme?
Bin ich mit nextSibling auf dem richtigen Weg? Was mach ich falsch?
Danke und Grüße, Matze
Ich habe es mit nextSibling versucht, aber da erhalte ich immer nur #text :(
Works as desigend: Weil der nächste Knoten nach deinem h3-Element eindeutig ein Textknoten ist.
Bin ich mit nextSibling auf dem richtigen Weg? Was mach ich falsch?
Entweder du klebst du h3 und das ul-Element ohne Whitespace zusammen oder du prüst, welchen Knotentyp nextSibling hat: Eenn es ein Elementknoten ist, blendest du aus, wenn nicht nimmst du dessen nächsten Nachfolger (rekursiv).
Hallo suit!
Works as desigend: Weil der nächste Knoten nach deinem h3-Element eindeutig ein Textknoten ist.
Wieso? Nach meinem h3-Element kommt doch eindeutig eine Liste.
Bin ich mit nextSibling auf dem richtigen Weg? Was mach ich falsch?
Entweder du klebst du h3 und das ul-Element ohne Whitespace zusammen oder du prüst, welchen Knotentyp nextSibling hat: Eenn es ein Elementknoten ist, blendest du aus, wenn nicht nimmst du dessen nächsten Nachfolger (rekursiv).
Ich wusste nicht, dass die Whitespaces hier eine Rolle spielen.
Wenn ich </h3><ul>
direkt aneinander schreibe, komm ich an die Liste. Sieht aber nicht sehr schön aus.
So gefällt es mir besser:
liste = o.nextSibling;
while(liste.nodeName != 'UL'){
liste = liste.nextSibling;
}
liste.style.display = 'inline';
Es funktioniert soweit wie es soll. Ich frag trotzdem nochmal, ob ich einen Fehler gemacht habe.
Danke und Grüße, Matze
Hallo Matze,
liste = o.nextSibling;
while(liste.nodeName != 'UL'){
liste = liste.nextSibling;
}
liste.style.display = 'inline';
du solltest sicherstellen, das zumindestens am Ende der Seite ein UL steht,
Gruß, Jürgen
PS: [Elefantensuche](http://www.angelfire.com/moon/dotbrown/elefantensuche.htm)
Hallo Jürgen!
du solltest sicherstellen, das zumindestens am Ende der Seite ein UL steht,
Ähm sorry, aber wie mach ich das? Bzw. was passiert, wenn kein UL gefunden werden konnte? Dann bricht das Skript doch einfach irgendwann (spätestens am Ende des Dokuments) ab.
Danke und Grüße, Matze
Hallo Matze,
Ähm sorry, aber wie mach ich das? Bzw. was passiert, wenn kein UL gefunden werden konnte? Dann bricht das Skript doch einfach irgendwann (spätestens am Ende des Dokuments) ab.
ja, und zwar mit einen Fehler.
Sorge dafür, das
Gruß, Jürgen
Hallo Jürgen!
- das Script nicht die ganze Seite abklappert, aber auch nicht zu wenig, und prüfe, ob es nextSibling noch gibt.
Also prüfen ob nextSibling nicht null ist?!
Zu verhindern, dass das Skript nicht die komplette Seite durchwühlt, reicht ein Element um die Überschrift und Liste, oder? Durch nextSibling sollte dann nur innerhalb des Kontainers gesucht werden, oder?
Danke und Grüße, Matze
Hallo Matze,
Also prüfen ob nextSibling nicht null ist?!
Ja
Zu verhindern, dass das Skript nicht die komplette Seite durchwühlt, reicht ein Element um die Überschrift und Liste, oder?
Es ist deine Seite, du musst wissen, wie viele Elemente zwischen Überschrift und Liste sein können.
Durch nextSibling sollte dann nur innerhalb des Containers gesucht werden, oder?
gibt es einen Container?
Noch eine Idee:
Du bündelst Überschrift und Liste in einem Container, z.B. einem div. Dann kommst du per parentNode zum Containerelement und per parentNode.getElementsByTagName("ul")[0] zur 1. Liste im Container.
Noch eine weitere Idee:
du gibst Überschrift und Liste eine Klasse: class="...". Dann suchst du nach der Überschrift mit der entsprechenden Klasse und gibst ihr den onclick-Handler, der die Liste mit der gleichen Klasse aus- oder einblendet.
Beachte hierbei, dass du dir ein Browserübergreifendes "getElementsByClassName" selbst basteln oder suchen musst.
Beide Ideen ungetestet.
Gruß, Jürgen
Hallo Jürgen,
die fertige Version fehlerfrei getestet im aktuellen Firefox und Opera:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Unbenanntes Dokument</title>
<script type="text/javascript">
// bei aktiviertem JS die Submenüs ausblenden
window.onload = closeSubs;
function closeSubs() {
subMenues = document.getElementById('menu').getElementsByTagName('ul');
for(i = 0; i < subMenues.length; i++){
// offene Submenüs schließen
subMenues[i].style.display = 'none';
}
}
function handleClicks(e){
var e=(window.event)?window.event:e;
var o=(window.event)?e.srcElement:e.target;
if(o.className == 'submenuHeader'){
// gewählten Menüpunkt aufklappen
liste = o.nextSibling;
while(liste.nodeName != 'UL' || liste.nextSibling == null){
liste = liste.nextSibling;
}
status = liste.style.display;
closeSubs();
if(status == 'block'){
liste.style.display = 'none';
}else{
liste.style.display = 'block';
}
}
}
window.document.addEventListener("click", handleClicks, false);
</script>
<style type="text/css">
ul#menu {
list-style-type:none;
width:200px;
background:#CCC;
padding:0;
}
ul#menu li {
padding:2px 2px 2px 20px;
background:url(bottom.png) no-repeat left bottom;
}
ul#menu li.submenu {
padding-left:0;
padding-bottom:0;
/* anderer Unterstrich (Hintergrundbild) für Ende von Submenüs */
/* background:url(deinBild) no-repeat left bottom; */
}
ul#menu li.submenu h3 {
cursor:pointer;
padding:0 0 2px 20px;
margin:0;
font-size:1em;
font-weight:normal;
background:url(bottom.png) no-repeat left bottom;
}
.submenuList {
display:block;
}
ul#menu li.submenu ul {
list-style-type:none;
padding:0 0 0 20px;
}
ul#menu li.submenu ul li{
padding:2px 2px 2px 20px;
/* anderer Unterstrich (Hintergrundbild) für Submenüs */
/* background:url(deinBild) no-repeat left bottom; */
}
ul#menu li.submenu ul li.noBg {
background-image:none;
}
</style>
</head>
<body>
<ul id="menu">
<li>Startseite</li>
<li>Menüpunkt</li>
<li class="submenu">
<h3 class="submenuHeader">Menüpunkt mit Submenü</h3>
<ul class="submenuList">
<li>Menüpunkt</li>
<li class="noBg">Menüpunkt</li>
</ul>
</li>
<li>Menüpunkt</li>
<li class="submenu">
<h3 class="submenuHeader">Menüpunkt mit Submenü</h3>
<ul class="submenuList">
<li>Menüpunkt</li>
<li class="noBg">Menüpunkt</li>
</ul>
</li>
</ul>
</body>
</html>
bottom.png ist bei mir ein 1px hoher Streifen mit teilweiser Alpha-Transparenz.
Irgendwelche Einwände?
Grüße, Matze
Hallo Matze,
die fertige Version fehlerfrei getestet im aktuellen Firefox und Opera:
die anderen Browser aber nicht vergessen.
while(liste.nodeName != 'UL' || liste.nextSibling == null){
wenn ich das richtig verstehe, läuft die Schleife, wenn das Element kein UL ist, oder wenn du am Ende bist. Teste es mal, wenn kein UL im Dokument ist. Meiner Meinung nach müsste die Schleife so aussehen:
while(liste.nodeName != 'UL' && liste.nextSibling){
__________ __________ _______ ________
/ /
false bei UL false am Ende
Da bei UND beide Bedingungen true sein müssen, bricht die Schleife ab, wenn nodeName gleich UL ist oder das Ende des Dokuments erreicht ist.
Gruß, Jürgen
Hallo Jürgen,
while(liste.nodeName != 'UL' || liste.nextSibling == null){
while(liste.nodeName != 'UL' && liste.nextSibling){
ach Gott, was hab ich denn da gemacht. Ok, war auch schon spät.
Du hast natürlich völlig recht.
Danke, ich hätte nicht nochmal drüber geschaut.
Grüße, Matze
Hi,
Works as desigend: Weil der nächste Knoten nach deinem h3-Element eindeutig ein Textknoten ist.
Wieso? Nach meinem h3-Element kommt doch eindeutig eine Liste.
ja, aber nicht *direkt* danach. Erst kommt eine Text-Node.
Ich wusste nicht, dass die Whitespaces hier eine Rolle spielen.
Eswärefatal,siezuignorieren.Äußerstfatal.
Cheatah
Hallo Cheatah,
ja, aber nicht *direkt* danach. Erst kommt eine Text-Node.
also wird ein z.b. Leerzeichen bereits als Text erkannt?!
Ich wusste nicht, dass die Whitespaces hier eine Rolle spielen.
Eswärefatal,siezuignorieren.Äußerstfatal.
Hehe sehr treffend :)
Meine Annahme war eher die, dass ich mit JS DOM-Elemente bearbeite.
Was dazwischen an Whitespaces ist spielt wie im HTML keine (selten eine) Rolle.
Grüße, Matze
Hi,
ja, aber nicht *direkt* danach. Erst kommt eine Text-Node.
also wird ein z.b. Leerzeichen bereits als Text erkannt?!
natürlich. Außer in älteren IEs - die haben vermutlich den grauen Star.
Meine Annahme war eher die, dass ich mit JS DOM-Elemente bearbeite.
Korrekt. Wobei die Bezeichnung "DOM-Objekte" lauten muss. Zwar gibt es in DOM Element-Objekte, aber keine Elemente an sich.
Was dazwischen an Whitespaces ist spielt wie im HTML keine (selten eine) Rolle.
Es spielt in HTML eine Rolle, und es sind DOM-Objekte.
Cheatah
Meine Annahme war eher die, dass ich mit JS DOM-Elemente bearbeite.
Korrekt. Wobei die Bezeichnung "DOM-Objekte" lauten muss. Zwar gibt es in DOM Element-Objekte, aber keine Elemente an sich.
Afaik heisst es DOM-Knoten (Nodes), und die haben verschiedene Typen - Text, Kommentar, Element, Attribut usw.
Hi,
Afaik heisst es DOM-Knoten (Nodes),
richtig, in JavaScript werden sie repräsentiert durch Objekte.
Cheatah
was hältst du von CSS-Nachfahrenselektoren?
Was hilft das nun bei einem JavaScript-/DOM-Problem?
Eine Selektor-Engine (z.B. Sizzle) mit 8 KiB einrichten, damit man keine 5 Zeilen JS per Hand schreiben muss? :D
Om nah hoo pez nyeetz, suit!
Was hilft das nun bei einem JavaScript-/DOM-Problem?
Vielleicht habe ich es ja auch falsch verstanden, aber bei dieser Struktur
<h3>Überschrift</h3>
<ul>
<li>foo</li>
<li>bar</li>
</ul>
sollte das Ausblenden der Liste auch ohne JS möglich sein.
Matthias
sollte das Ausblenden der Liste auch ohne JS möglich sein.
Ja, aber nicht das dauerhafte ein und ausblenden.
Das ausblenden alle Elemente nach einer Überschrift und das gezielte Einblenden mittels ::target wäre eine Möglichkeit. Ist aber weit nicht so flexibel wie eine JavaScript-Lösung.
Hi,
was hältst du von CSS-Nachfahrenselektoren?
für das genannte Problem gar nichts.
Schließlich ist die ul ja kein Nachfahre der Überschrift, sondern nur ein Nachbar.
cu,
Andreas
Om nah hoo pez nyeetz, MudGuard!
Hi,
was hältst du von CSS-Nachfahrenselektoren?
für das genannte Problem gar nichts. Schließlich ist die ul ja kein Nachfahre der Überschrift, sondern nur ein Nachbar.
Wieder ein typisches Beispiel von unbedachtem Schreiben, aber der Link ist wenigstens richtig. h1 + ul selektiert die Liste.
Matthias