Rolf B: Problem mit HTML+ CSS

Beitrag lesen

Hallo HTMLNOOB,

du weißt aber, dass es in HTML Tags gibt, die einen Bereich öffnen (z.B. <div>) , und andere, ähnlich aussehende, die diesen Bereich wieder schließen (</div>)?

Wenn nicht, fang hier an und schau Dich dann im Rest des Tutorials um.

Du hast beispielsweise geschrieben - und ich rücke das jetzt mal so ein wie es die Anfangs- und Ende-Tags nahelegen:

  <div class="menu" id="menu">
    <div class="item">
      <a href="#">
        <i class="material-icons">home</i>
      </a>
    </div>
  </div>
  <div class="item">
    <a href="#">
      <i class="material-icons">notifications</i>
    </a>
  </div>
  (... ein paar Zeilen lasse ich weg ...) 
  <div class="item">
    <a href="#">
      <i class="material-icons">search</i>
    </a>
  </div>
  <script...> (diesen Teil lasse ich auch weg) </script>
</body>

Was Du da hast, ist ein div Element mit Klasse und ID "menu" (was doppelt gemoppelt ist, sich aber jetzt nicht ändern lässt, wenn du noch nicht weißt was du tust)

Dieses menu-div beginnt in der ersten Beispielzeile und endet in der siebten. Es enthält ein weiteres div, diesmal mit Klasse "item" (von Zeile 2-6). In diesem div steht der Link (<a>...</a>) mit dem Home-Icon <i>...</i>. Das <i> Element wird hier falsch verwendet, es dient eigentlich anderen Zwecken, aber das machen viele Icon-Bibliotheken so.

DIVs sind generische Rahmen für fast beliebige Inhalte. Mit Hilfe von class oder id werden sie identifizierbar.

Genau das macht das Script. Da steht:

var i=document.getElementById("menu").childNodes;

document ist eine globale Variable in JavaScript. Sie enthält das Dokument-Objekt, das den Einstieg ins DOM (Document Object Model) bildet. document.getElementById ist eine so genannte Methode dieses Objekts. Unter Methoden versteht man kleine Funktionen, die zum Objekt gehören[1] und Daten zum Objekt liefern können, oder Werte darin verändern. getElementById ist eine Methode, die im Dokument ein HTML Element mit dieser ID sucht. Die Angabe ("menu") dahinter ist ein Parameter, vielleicht erinnerst Du Dich aus dem Matheunterricht an Funktionen und Parameter. document.getElementById("menu") sucht also im angezeigten Dokument ein Element mit der ID "menu". Dieses Element gibt es, das ist das <div>, von dem wir vorhin sprachen. Auch zu dem <div> gehört ein Objekt, auch in diesem Objekt gibt es Daten ("Eigenschaften" genannt) und Methoden. childNodes ist der Name einer bestimmten Datensammlung, die zum <div> gehört, und zwar findet sich darin eine Liste aller HTML Dinge, die dem <div> direkt untergeordnet sind. Weil dein menu-div bereits in Zeile 7 endet, ist da nur ein einziges Kind-Element drin: das item-div in Zeile 3. Diese childList ist nun das Ergebnis dieser Folge von Funktionsaufrufen, und sie wird in einer neuen Variablen namens i gespeichert.

Dummerweise besteht HTML aus mehr als nur Elementen. Der andere Bestandteil ist Text. Text ist alles, was nicht zwischen spitzen Klammern steht. Und darum enthält childList mehr als nur einen Eintrag. Es gibt noch zwei Textknoten, nämlich die beiden Leerräume vor und hinter dem item-div. Es wäre besser gewesen, hier statt childNodes die Eigenschaft children zu nehmen, die enthält die Textknoten nämlich nicht.

Wenn Du nun weiterschaust im JavaScript, dann wird da eine Funktion bereitstellt: expand. Diese Funktion wurde im HTML über das onclick-Attribut als Ereignisbehandler festgelegt, d.h. wenn Du auf das toggle klickst, wird expand aufgerufen.

Die Variable i ist zwar außerhalb der expand-Funktion erzeugt wurden, aber JavaScript-Programmteile sind ähnlich geschachtelt wie HTML Elemente. Dein Script erzeugt 3 Dinge: eine Variable j, eine Variable i und eine Funktion expand. Alle drei Dinge haben den gleichen Rahmen, in dem sie erzeugt wurden, und darum können die Befehle in der expand-Funktion die Variablen i und j sehen und benutzen. Das ist jetzt sehr vereinfacht, das Thema Sichtbarkeit und Lebensdauer von Werten ist kompliziert.

Jedenfalls greift die expand-Funktion auf i zu, und ergänzt i um eine Angabe in eckigen Klammern. So etwas macht man dann, wenn man eine Sammlung von Werten vorliegen hat. Die childList Variable von oben liefert eine Sammlung aller Kindobjekte, mit keinem, einem oder mehreren Einträgen drin. Die Zählung beginnt bei 0, d.h. i[1] bezeichnet das zweite Kind des menu-div. Das ist das, was ich eben erwähnte: Der Leerraum zwischen <div id="menu"> und <div class="item"> ist ein Textknoten und steht in der childList mit drin.

Dir wir auffallen, dass in Folge auf noch viel höhere Nummern zugegriffen wird. Und da ist das Problem, denn deine HTML Struktur gibt das nicht her. Das </div> in Zeile 7 beendet die Liste der Items viel zu früh. Du möchtest eigentlich, dass alle <div class="item">...</div> Gruppen Kinder des menu-div sind. Wenn Du das änderst, wird es besser.

Allerdings möchte ich Dich davor warnen, hier nun täglich mit neuen Fragen aufzukreuzen, ohne selbst etwas zu lernen. Damit erzeugst Du nur Frust, bei Dir uns uns. Ich habe jetzt eine Stunde lang für Dich geschrieben - nur aus Freundlichkeit. Beschäftige Dich mit den HTML- und CSS Texten in unserem WIKI, damit Du verstehst, was Du eigentlich tust. Du brauchst Geduld und Beharrlichkeit. HTML, CSS, JavaScript - das ist ein komplexes und umfangreiches Thema.

Rolf

--
sumpsi - posui - clusi

  1. Was unpräzise ist - sie gehören zur KLASSE des Objekts. Aber ich will jetzt nicht zu detailliert werden ↩︎