DOM Problem mit Opera

sadi

Mitglied
Hallo auch,
ich habe ein Problem mit einem Javascript für ein Menü. Soweit funktioniert es sehr gut in Firefox und dem IE6. Nur in Opera 9.02 gibt es Probleme. Das Menü besteht aus zwei Ebenen, welche jeweils in Divs gepackt sind. Beim Laden der Seite soll die zweite Ebene geschlossen werden und nur die Hauptmenüpunkte sollen angezeigt werden. Leider bleibt die Ebene 2 in Opera 9.02 geöffnet und die Fehlerkonsole spuckt folgende Meldung aus:

JavaScript - http://localhost/Menu/menu2.htm
Inline script thread
Error:
name: TypeError
message: Statement on line 9: Could not convert undefined or null to object
Backtrace:
Code:
  Line 9 of inline#1 script in http://localhost/Menu/menu2.htm
    hoehen[i] = parentTR[i].childNodes[1].childNodes[1].childNodes[3].clientHeight;
  Line 2 of inline#2 script in http://localhost/Menu/menu2.htm
    initialisieren();
Wenn ich das richtig verstehe, dann kann Opera den Ausdruck in der Scriptzeile 9 nicht in ein Objekt umwandeln. Aber warum nur, schließlich können es FF und IE. Ich habe auch schon verschiedene Varianten durch gespielt das Script zu initialisieren, aber ohne Erfolg. Interpretiert Opera vielleicht das DOM Modell etwas anders als FF oder IE? Die Seite mit dem Script findet ihr unter http://www.sascha-dietrich.com/menu2.htm.

Wäre echt super wenn mir jemand helfen könnte.

Gruß

Sascha
 
Hi,

bei mir funktioniert es auch im IE.

Grund für das Problem ist das Durchlaufen der Dokumentstruktur mit Hilfe der childNode-Kollektionen, denn hier
finden sich nicht nur HTML-Elemente, sondern auch einfache Zeichen (Leerzeichen, Text usw.).

Besser wäre das gezielte Ansprechen der gewünschten Elemente - z.B. über getElementsByTagName. Auf diese
Weise lassen sich alle DIVs innerhalb einer Tabellenzeile ermitteln. Das dritte DIV (Index = 2) ist dann das Menue,
das ein- bzw. ausgeblendet werden soll.

Die Funktionsaufrufe in den onclick-Events solltest Du ebenfalls an diese Vorgehensweise anpassen.
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Menutest</title>
<script type="text/javascript">
  <!--
var hoehen = new Array(); // definieren der globalen Variablen, welche die Höhe des Listendivs abspeichern soll
var parentTR;  // definieren der globalen Variablen, welche die TR Tags/Knoten abspeichern soll

function initialisieren(){
  // Alle Zeilen der Menuetabelle ermitteln
  parentTR = document.getElementById("menuTable").getElementsByTagName("tr");

  // Alle Zeilen durchlaufen
  for(var i=0; i<parentTR.length; i++){
    // Alle enthaltenen DIVs ermitteln
    var arrDiv = parentTR[i].getElementsByTagName("div");
    hoehen[i] = arrDiv[2].clientHeight;
    arrDiv[2].style.height = 0+"px";
    arrDiv[2].style.display = "none";
  }
}

function menuAnzeige(aktuellesMenu) { // wenn die Funktion aufgerufen wird der aktuelle Knoten übergeben
	if (aktuellesMenu.style.display == "block")
	{ // abfragen, ob das Div schon im Anzeigemodus Block ist
	  for (var i = 0; i < parentTR.length; i++) // hier beginnt eine Zählschleife, um zu bestimmen welcher Menupunkt/Listendiv gewählt wurde. Dazu wird bestimmt, mit welchem Knoten aus der Knotenliste parentTR der Aktuelle übereinstimmt
	  {
	      if (aktuellesMenu.parentNode.parentNode.parentNode == parentTR[i]) // hier findet die entsprechende Überprüfung des Knotens statt
	      {
	         var teile = hoehen[i]/10; // die Listendiv-Höhe in 10 gleich große Teile teilen
	         for (var i = 0; i < 10; i++)
	         { // das Listendiv auf 0 verkleinern
	             aktuellesMenu.style.height = aktuellesMenu.clientHeight - teile+"px";
	         } // for
	         if (i >= 10)
	         { // das Listendiv entgültig ausblenden
	            aktuellesMenu.style.display = "none";
	         } //if
	      } // if
	  } // for
	} else {
	 for (var i = 0; i < parentTR.length; i++) // gleiche Überprüfung wie oben
	 {
	     if (aktuellesMenu.parentNode.parentNode.parentNode == parentTR[i])
	     {
	        aktuellesMenu.style.display = "block"; // das Listendiv anzeigen lassen
	        var teile = hoehen[i]/10; // die Listendiv-Höhe in 10 gleich große Teile teilen
	        for (var i = 0; i < 10; i++) { // das Listendiv auf volle Größe vergrößern
	            aktuellesMenu.style.height = aktuellesMenu.clientHeight + teile+"px";
	        } // for
	     } //if
	 } //for
	} // if
}

window.onload=initialisieren;
 //-->
</script>
</head>

<body>
<table id="menuTable">
	<tr>
	  <td>
	    <div id="t1" style="width: 200px; border: 1px solid #000000;">
	      <div style="width: 200px; background-color: #DDDDDD; border-bottom: 1px solid #000000; cursor: pointer;" onclick="menuAnzeige(this.parentNode.getElementsByTagName('div')[1]);">
	      Überschrift 1 <!-- Der Nutzer kann hier seinen Hauptmenupunkt eintragen -->
	      </div>
	      <div style="width: 200px; background-color: #66CCFF; display: block">
	      Punkt 1 <br /> <!-- Hier werden die Untermenupunkte eingetragen -->
	      Punkt 2 <br />
	      Punkt 3
	      </div>
	    </div> <!-- Das gesamte Div kann beliebig mal kopiert werden19:31:3419:36:53 -->
	  </td>
	</tr>
	<tr>
	<td>
	  <div style="width: 200px; border: 1px solid #000000;">
	    <div style="width: 200px; background-color: #DDDDDD; border-bottom: 1px solid #000000; cursor: pointer;" onclick="menuAnzeige(this.parentNode.getElementsByTagName('div')[1]);">
	      Überschrift 2
	    </div>
	    <div style="width: 200px; background-color: #66CCFF; display: block;">
	      Punkt 1 <br />
	      Punkt 2
	    </div>
	  </div>
	</td>
	</tr>
</table>
</body>
</html>
Ciao
Quaese
 
Vielen Dank. An diesen Ansatz habe ich irgendwie gar nicht gedacht. Damit umgeht man natürlich einige Schwierigkeiten mit der childNode Struktur. Obwohl ich mir dennoch nicht so ganz im Klaren bin, wo Opera genau das Problem hat. Aber naja, es funktioniert jetzt.

Gruß

Sascha
 

Neue Beiträge

Zurück