cartman1984: Zugriff auf DOM-Elemente mit display:hidden;

Hallo Leute,

ihr habt mir letztens schon super geholfen mit dem Hinzufügen von EventHandlern, jetzt hakt es mit dem Verständnis schon wieder.

Ich habe auf vielen Seiten Icons mit Fragezeichen, denen ich ein Mouseover-Event verpassen will, das eine Popupbox öffnet mit einem Hilfe-Text.

Die Icons sehen so aus:

  
<div class="icon_help">  
  <div class="tooltip_text" style="display: none;">Dies ist der Hilfstext.</div>  
</div>  

Setzen will ich den Text für das Popup mit folgendm Code:

  
for (var i=0;i<tooltips.length;i++) {  
  if (tooltips[i].hasChildNodes()){  
    tooltip_text = tooltips[i].firstChildNode.innerHTML;  
  } else {  
    tooltip_text = "";  
  }  
...  

Obwohl das Array "tooltips" mit den richtigen Elementen gefüllt ist und mir Firebug die ChildNodes auch anzeigt, gibt die Funktion hasChildNodes() immer false zurück. Liegt es daran, dass der innere Div display:hidden als Eigenschaft hat?

Vielen Dank für eure Hilfe!!!

Cartman

  1. @@cartman1984:

    nuqneH

    tooltip_text = tooltips[i].firstChildNode.innerHTML;

    Eine Eigenschaft 'firstChildNode' gibt es nicht, wohl aber 'firstChild'. [http://de.selfhtml.org/javascript/objekte/node.htm@title=SELFHTML]

    display:hidden als Eigenschaft hat?

    "hidden" ist keine gültiger Wert für die 'display'-Eigenschaft, wohl aber "none". [CSS2 §9.2.5]

    Qapla'

    --
    Bildung lässt sich nicht downloaden. (Günther Jauch)
    1. Hallo hallo ihr beiden,

      ich war mit schreiben mal wieder zu schnell, sorry. Klar heißt es firstChild und display: none.

      So langsam komme ich weiter:

      Im Array tooltips stehen alle Elemente mit der Klasse "icon_help", richtig.
      Mit tooltips[i].getElementsByTagName('div')[0] greife ich auf das div "tooltip_text" zu, klappt auch.
      Die Abfrage tooltips[i].hasChildNodes() klappt dagegen nicht, ich weiß nicht wieso. Zur Abhilfe füge ich den DIV jetzt in jedes icon_help-Objekt ein.

      Dann gibt es aber noch ein großes Problem, das sich mir wahrscheinlich durch fehlendes Verständnis der JS-Vorgehensweise nicht erschließt:

      Die mouseover-Events füge ich per Funktion beim laden des Dokuments hinzu. Die Schleife sieht komplett jetzt so aus:

        
      for (var i=0;i<tooltips.length;i++) {  
        var tooltip_text = tooltips[i].getElementsByTagName('div').[0].innerHTML;  
        tooltips[i].addEventListener("mouseover", function(){showWMTT(tooltip_text), false);  
        tooltips[i].addEventListener("mouseout", function(){hideWMTT(), false);  
      }  
      
      

      Das funktioniert beim laden der Seite wunderbar. Jetzt das Problem: Sobald das mouseover-Event feuert, springt der Code in die Zeile mit dem addEventListener("mouseover"...) und führt die Anweisung nochmal aus. Natürlich steht die Variable i jetzt auf tooltips.length und tooltip_text ist leer. Der EventHandler sollte doch eigentlich schon längst erstellt sein, oder nicht?

      Ein verwirrter Cartman

      1. for (var i=0;i<tooltips.length;i++) {
          var tooltip_text = tooltips[i].getElementsByTagName('div').[0].innerHTML;
          tooltips[i].addEventListener("mouseover", function(){showWMTT(tooltip_text), false);
          tooltips[i].addEventListener("mouseout", function(){hideWMTT(), false);
        }

          
        Du verwendest eine [Closure](http://aktuell.de.selfhtml.org/artikel/javascript/organisation/#closures) (verschachtelte Funktion, die Zugriff auf die Variable der äußeren Funktion hat) in einer Schleife.  
        [Suche im Forumsarchiv](http://suche.de.selfhtml.org/?index_4=on&index_5=on&feld=alle&hits=alle&suchausdruck=closure+schleife)  
          
        Wenn die Handlerfunktion ausgeführt wird, ist der Wert der Variablen der vom letzten Schleifendurchlauf.  
          
        Einfache Lösung hier:  
        Speichere den Tooltip-Text in einer Eigenschaft an dem Element und greifst im Event-Handler über this auf das Element zu, um die Eigenschaft wieder auszulesen:  
          
        ~~~javascript
        for (var i = 0, t, length = tooltips.length; i < length; i++) {  
           t = tooltips[i];  
           t.tooltip_text = t.getElementsByTagName('div'][0].innerHTML;  
           t.addEventListener("mouseover", function () {  
              showWMTT(this.tooltip_text);  
           });  
        }
        

        Mathias

        1. Hallo Mathias,

          das ist eine super Idee!!! Ich danke dir vielmals. Auf diese Vorgehensweise und die Erklärung für das Problem wäre ich nicht gekommen. Ich bin halt einer der vielen Programmierer, die einfach drauf loslegen müssen, ohne einen fundierten Einstieg in die Sprache zu haben...

          Gruß
          Robin

  2. for (var i=0;i<tooltips.length;i++) {
      if (tooltips[i].hasChildNodes()){

    Welche Elemente stehen in tooltips? Die mit class=icon_help?

    tooltip_text = tooltips[i].firstChildNode.innerHTML;

    Es gibt keine Eigenschaft firstChildNode.
    Es gibt eine Eigenschaft namens firstChild. Aber der erste Kindknoten vom div mit class=icon_help ist höchstwahrscheinlich ein Textknoten mit dem Zeilenumbruch und Leerzeichen. Arbeite mit .getElementsByTagName("div"), wenn du das erste div-Kindelement brauchst.

    Obwohl das Array "tooltips" mit den richtigen Elementen gefüllt ist und mir Firebug die ChildNodes auch anzeigt, gibt die Funktion hasChildNodes() immer false zurück.

    Das kann ich nicht recht glauben.
    Lass dir mal tooltips[i] sowie tooltips[i].hasChildNodes() im Firebug ausgeben.

    Liegt es daran, dass der innere Div display:hidden als Eigenschaft hat?

    Nein.

    Mathias