AMG: Problem display div mittels klick durch Javaskript

Guten Tag, Das hier ist mein erster Beitrag, falls ich irgend was falsch mache bitte ich um Nachsicht...

Hier mein html file:

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Amatic+SC:400,700|Bungee+Shade|Creepster|Lobster|Open+Sans+Condensed:300,300i,700|Poiret+One">
    <link rel="stylesheet" href="/css/uns.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <script src="../js/menu.js" type="text/javascript"></script>
    <title>Startseite</title>  
  </head>

  <body>
      <div id="backr">
          <br style="text-size: 1px ;">
          <table id="navi">
              <tr>
                  <th>
                      <a href="../index.html" style="text-decoration: none ; color: inherit ; "><i class="fa fa-university" aria-hidden="true"></i>Startseite<i class="fa fa-university" aria-hidden="true"></i></a></th>
                  <th>
                      <i class="fa fa-users" aria-hidden="true"></i> Über die Crew <i class="fa fa-users" aria-hidden="true"></i></th>
                  <th>
                      <div class="dropdown" onclick="showmen()">
                          <button class="dropbtn"><i class="fa fa-camera" aria-hidden="true"></i> Bilder <i class="fa fa-camera" aria-hidden="true"></i></button>
                          <div class="dropdown-content">
                            <a href="#">Link 1</a>
                            <a href="#">Link 2</a>
                            <a href="#">Link 3</a>
                          </div>
                      
                      </div>
                </th>
              </tr>
          </table>
          <table id="headdie">
              <tr id="logo">
                  <th><span id="bigline1">Tranny Huntaz Crew<i class="fa fa-copyright " aria-hidden="true" style="font-size: .5em  ; vertical-align: middle ; margin-left: 4px ;"></i></span></th>
                  <th style="width: 15em ; "><h1>-Über Uns-</h1></th>
                  <th><span id="bigline1">Tranny Huntaz Crew<i class="fa fa-copyright " aria-hidden="true" style="font-size: .5em  ; vertical-align: middle ; margin-left: 4px ;"></i></span></th>
              </tr>
          </table>
          <p id="footr">est. 2016</p>
      </div>
  </body>

Hier mein css file:

h1 {
    text-align: center ; 
    font-family: Lobster ; 
    font-size: 3em ; 
    font-weight: 600 ;
}

html, body {
    background-color: #d2cdb2 ;
    margin: 0;
    padding: 0;
    height: 100%;
}

#navi th {
    font-family: "Open Sans Condensed" ;
    font-size: 1.3em ;
    font-weight: 300 ;
}

#navi  {
    color: aliceblue; 
    border-radius: 25px;
    border: 3px solid aqua;
    padding: 5px;
    background-color: black ; 
    width: 99%;
    table-layout: fixed ;
    margin: auto;
    
}

#navi th:hover {
    background-color: aliceblue;
    color: black ;
    border-radius: 25px ;
}

#bigline1 {
    font-family: "Creepster" ;
    font-size: 2.5em ;
    border: 10px solid red ;
    border-radius: 100% ;
    background-color: white ; 
    padding: .5em
}

#logo {
    text-align: center ;
}

#backr {
    width: 90% ;
    background-color: aliceblue ;
    margin: auto ;
    border: 2px solid aqua;
    border-radius: 10px;
    position: inherit ;
    min-height: 100%;
    position: relative ;
}

#footr {
    text-align: center ;
    font-family: "Bungee Shade" ;
    font-size: 1.5em ;
    background-color: #ffffcc ;
    padding-bottom:  0.5em ;
    padding-top: 0.5em ;
    bottom: 0 ;
    position: absolute;
    width: 100%;
    border-bottom-left-radius: 10px ;
    border-bottom-right-radius: 10px ;
    border-top: 2px solid black ;
    margin-bottom: 0 ;
}

#headdie {
    width: 99%;
    table-layout: fixed ;
    margin: auto ;
    margin-top: 3em ;
}



.dropbtn {
    background: none;
    color: inherit;
    padding: inherit ;
    font-family: inherit ;
    font-size: inherit ;
    border: none;
    cursor: pointer;
}

.dropdown {
    display: inline-block;
}

.dropdown-content {
    display: none;
    position: middle;
    background-color: #f9f9f9;
    min-width: 8em;
    box-shadow: 0px 10px 20px  #595959;
    margin-bottom: 0.5em;
    margin-top: 0.25em;
}

.dropdown-content a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
}

.dropdown-content a:hover {
    background-color: #f1f1f1
}

.dropdown:hover .dropdown-content {
    display: block;
}

Hier mein JavaSkript:

function showmen() {
    if (document.getElementsByClassName('dropdown-content').style.display === 'none') {
        document.getElementsByClassName('dropdown-content').style.display = 'block';
    } 
    else {
        document.getElementsByClassName('dropdown-content').style.display = 'none';
    }
}

Ich möchte, dass sich der 'droptdown-content' nicht nur über hover in dem CSS file öffnet, sondern auch bei einem Klick öffnet (falls man einen Touchscreen verwendet) daher hab ich das Skript geschrieben. Villeicht ist der Fehler ja offensichtlich und ich seh ihn nicht, doch ich probier das jetzt schon seit zwei Tagen und hänge einfach fest... Das ist meine erste HTML seite, ich bringe mir das gerade selber bei... Danke im Vorraus und außerdem riesen Lob an die Selfhtml seite und an alle Leute die hier aktiv sind. Es gibt nur wenige Communities mit solchem wissen und solcher Hilfe! Danke!

P.S.: die ordner Struktur meines Html ist Folgende (wegen der eventuell verwirrenden bezüge auf css und js file): /html/ueber_uns.html ; /css/uns.css ; /js/menu.js ; /index.html /main.css

Das Simikolon trennt neue Pfade, irgendwie funtioniert der Zeilenumbruch nicht...

akzeptierte Antworten

  1. Hallo,

    Wahrscheinliche Fehlerquelle:

    • getElementsByClassName gibt dir ein Array von Elementen zurück nicht das Element selbst. Deshalb bewirkt document.getElementsByClassName('dropdown-content').style.display nichts. Wahrscheinlich müsste es document.getElementsByClassName('dropdown-content')[0].style.display heißen.

    Du kannst das mit console.log(document.getElementsByClassName('dropdown-content').style.display); überprüfen. Die Entwickler-Tools öffnest du im Browser mit CTRL+SHIFT+I.

    Sonstiges:

    • vermeide inline-Styles. Stichwort: Separation of concerns.

    • vermeide inline Javascript (onclick="showmen()"). Verwende addEventListener, wenn du klick-Events abfragen möchtest.

    • Du lädst jede Menge Schriftarten. Überlege, ob du die wirklich alle benötigst. Weniger ist manchmal mehr.

    • Verwende für einen Footer das HTML5 <footer>-Element, für die Navigation das <nav>-Element.

    • Verwende keine Tabellen, für Inhalte, die semantisch keine Tabellen sind.

    • Bedenke, dass deine mit aria-hidden gekennzeichneten Elemente Leute mit Screenreadern nicht lesen können. Du versteckst beispielsweise einen Link auf deine Homepage.

    • gib Fallbacks für die Eigenschaft font-family an.

    Ich habe meine Aussagen und Empfehlungen nicht begründet, oder weiter ausgeführt. Ich hoffe das hilft dir trotzdem weiter.

    lg mark

    1. @@mark

      • getElementsByClassName gibt dir ein Array von Elementen zurück

      Nein, das gibt eine Collection von Elementen zurück. Der Unterschied zwischen Collection und Array ist manchmal zu vernachlässigen; in anderen Fällen aber bedeutsam.

      • Bedenke, dass deine mit aria-hidden gekennzeichneten Elemente Leute mit Screenreadern nicht lesen können. Du versteckst beispielsweise einen Link auf deine Homepage.

      Du meinst <a href="../index.html" style="text-decoration: none ; color: inherit ; "><i class="fa fa-university" aria-hidden="true"></i>Startseite<i class="fa fa-university" aria-hidden="true"></i></a>?

      Beachte, dass die i-Elemente aria-hidden-Attribute tragen, nicht das a-Element; der Text „Startseite“ davon also nicht erfasst wird.

      Was jetzt aber den Missbrauch von i-Elementen zur Einbindung von Icons nicht besser macht. (Vermutlich eine Unsitte des verwendeten Frameworks. Bootcrap?)

      LLAP 🖖

      --
      „Wenn du eine weise Antwort verlangst, musst du vernünftig fragen.“ —Johann Wolfgang von Goethe
    2. Hi Mark,

      Danke für die super Antwort!

      Kannst du mir kurz mal sagen was die [0] genau bedeuten soll, außerdem wie genau funktioniert der addEventListener und auch dein Tipp mit "console.log(document.getElementsByClassName('dropdown-content').style.display);" verstehe ich nicht wirklich... Deine anderen Tipps werde ich versuchen später einzuarbeiten das ist mir alles schlüssig, bin aber grad noch in der Uni. Leider ist jetzt ein weiteres Problem aufgetaucht. Mit hover in css wird der 'dropdown-content' noch geöffnet, aber nur so lange nicht geklickt wird. Sobald ich einmal klicke funktioniert die Öffnung per hover nicht mehr nurnoch per click. Danke im Vorraus!

      Liebe grüße Josh

      1. [Vollzitat entfernt]

        Hab jetzt nochmal einiges umgeschrieben, ich ersetzte das hover einfach durch mouseover und mouseout... Außerdem hab ich die Classen durch id's ersetzt (der Einfachheit halber, ich versteh die [0] nämlich einfach nicht). Aber irgendwie funktioniert der addEventListener einfach nicht, die Funktionen lassen sich aber über onclick im HTML file aufrufen?!?!?

        hier der Code:

        		      <div id="dropdown">
                                  <Button id="dropbtn">
                                      <i class="fa fa-camera"></i> Bilder <i class="fa fa-camera"></i>
                                  </Button>
                                  <div id="dropdown-content">
                                    <a href="#">Link 1</a>
                                    <a href="#">Link 2</a>
                                    <a href="#">Link 3</a>
                                  </div>
                              
                              </div>
        
        document.getElementById('dropdown').addEventListener('click', showmen);
        document.getElementById('dropdown').addEventListener('mouseover', showmen1)
        document.getElementById('dropdown').addEventListener('mouseout', showmen2)
        
        function showmen() {
            if (document.getElementById('dropdown-content').style.display == 'none') {
                document.getElementById('dropdown-content').style.display = 'block';
            } 
            else {
                document.getElementById('dropdown-content').style.display = 'none';
            }
        }
        
        function showmen1() {
            document.getElementById('dropdown-content').style.display = 'block';   
        }
        
        function showmen2() {
            document.getElementById('dropdown-content').style.display = 'none';    
        }
        
        1. @@AMG

          document.getElementById('dropdown').addEventListener('click', showmen);
          document.getElementById('dropdown').addEventListener('mouseover', showmen1)
          document.getElementById('dropdown').addEventListener('mouseout', showmen2)
          

          Wenn du die Referenz zu einem Objekt öfter brauchst, muss du nicht jedesmal erneut das DOM danach durchsuchen. Besser die einmal gefundene Referenz in einer Variablen merken:

          var dropdownElement = document.getElementById('dropdown');
          dropdownElement.addEventListener('click', showmen);
          dropdownElement.addEventListener('mouseover', showmen1);
          dropdownElement.addEventListener('mouseout', showmen2);
          

          Und auch hier:

          function showmen() {
              if (document.getElementById('dropdown-content').style.display == 'none') {
                  document.getElementById('dropdown-content').style.display = 'block';
              } 
              else {
                  document.getElementById('dropdown-content').style.display = 'none';
              }
          }
          

          Dito.

          var dropdownContentElement = document.getElementById('dropdown-content');
          
          function showmen() {
              if (dropdownContentElement.style.display == 'none') {}
          }
          

          Oder du übergibst das Element als Parameter:

          function showmen(element) {
              if (element.style.display == 'none') {}
          }
          

          Aufruf dann mit showmen(dropdownContentElement).

          function showmen2() {
              document.getElementById('dropdown-content').style.display = 'none';    
          }
          

          Eine Funktion, die etwas ausblendet, heißt „show…“?

          Passende Namen für die Funktionen wären „toggle“, „show“, „hide“.

          Und die Funktionen sollten auch besser nicht die CSS-Eigenschaft display direkt ändern. Sondern das HTML-Attribut hidden setzen bzw. löschen.

          LLAP 🖖

          --
          „Wenn du eine weise Antwort verlangst, musst du vernünftig fragen.“ —Johann Wolfgang von Goethe
      2. @@AMG

        Kannst du mir kurz mal sagen was die [0] genau bedeuten soll

        [0] liefert dir das erste (in JavaScript-Zählweise das nullte) Element einer Collection bzw. eines Arrays. Bsp:

        var a = ['foo', 'bar'];
        console.log(a[0]); // "foo"
        

        In deinem Fall liefert das das erste (möglicherweise das einzige) Element der Klasse 'dropdown-content'.

        LLAP 🖖

        --
        „Wenn du eine weise Antwort verlangst, musst du vernünftig fragen.“ —Johann Wolfgang von Goethe
      3. Kannst du mir kurz mal sagen was die [0] genau bedeuten soll,

        Es gilt zu verstehen, was ein Array ist. Du kannst dir das zu Beginn, vorstellen wie ein Schrank mit Schubladen. Später wirst du erkennen, dass dieser Vergleich hinkt, aber zu Beginn geht das mMn recht gut.

        Mit variablenName[0] selektierst du die erste Schublade und liest deren Inhalt. Mit variablenName[1] selektierst du die zweite Schublade und liest deren Inhalt usw.

        Es wäre möglich, dass sich in deinem HTML-Dokument mehrere Elemente mit dem class-Attribut dropdown-content befinden. document.getElementsByClassName('dropdown-content') liefert dir einen Schrank und packt in jede Schublade ein 'dropdown-content'-Element.

        Auf deiner Seite befindet sich nur ein Element mit dem class-Attribut 'dropdown-content' deshalb hat dein Schrank nur eine Schublade.

        document.getElementsByClassName('dropdown-content') ist der Schrank. document.getElementsByClassName('dropdown-content')[0] ist die erste Schublade des Schrankes in der sich dein Element befindet.

        Und das ist ja genau das, was du möchtest. Du möchtest nicht den Schrank display = "block" zuweisen, sondern dem Inhalt deiner Schublade, sprich: dem 'dropdown-content'-Element.

        Nur am Rande: Gunnar hat vollkommen recht, dass es sich beim Rückgabewert von getElementsByClassName um eine Collection handelt. Also genau genommen nicht um ein Array. Darauf einzugehen würde mMn zu Beginn zu weit führen. Aber behalt dir das im Hinterkopf.

        außerdem wie genau funktioniert der addEventListener

        Darauf mag/kann ich nicht zufriedenstellend Antworten. Probiers aus und frag nach, wenn Probleme auftreten. https://wiki.selfhtml.org/wiki/AddEventListener

        Beispiele dafür gibt es zu hauf.

        el.addEventListener("click", deineFunktion );
        

        und auch dein Tipp mit "console.log(document.getElementsByClassName('dropdown-content').style.display);" verstehe ich nicht wirklich...

        a) Füge den Code console.log('HELLO WORLD'); in dein Javascript ein. b) Öffne deine Seite c) Öffne die Browser Konsole (Konsole: CTRL+SHIFT+C) d) Du solltest nun "HELLO WORLD" in deiner Konsole überprüfen können.

        Das ist ein Weg, von vielen Möglichen, um zu überprüfen, ob dein Code so funktioniert, wie du dir das vorgestellt hast.

        Als nächstes kannst du auf deiner Seite folgendes probieren: console.log(document.getElementsByClassName('dropdown-content')); console.log(document.getElementsByClassName('dropdown-content')[0]);

        Deine anderen Tipps werde ich versuchen später einzuarbeiten das ist mir alles schlüssig, bin aber grad noch in der Uni.

        Ja, eins nach dem anderen. Es hat sicherlich Priorität, dass du das mit dem Menue hinbekommst.

        Leider ist jetzt ein weiteres Problem aufgetaucht. Mit hover in css wird der 'dropdown-content' noch geöffnet, aber nur so lange nicht geklickt wird. Sobald ich einmal klicke funktioniert die Öffnung per hover nicht mehr nurnoch per click.

        Ja. Das hätte ich vorhersehen können/müssen. Du versteckst das Element mit document.getElementsByClassName('dropdown-content')[0].style.display = 'none'; Da erzeugst du einen inline Style der von deinem css nicht mehr überschrieben wird.

        Als Lösung könntest du anstatt style.display = 'none'; document.getElementsByClassName('dropdown-content')[0].removeAttribute('style') probieren. Das entfernt sämtliche von javascript gesetzten Styles. Dein Menue ist per default display: none, also sollte das reichen. Du musst das mit Javascript nicht extra nochmal setzen.

        Oder nur um dein Verständnis für die Materie zu schärfen könntest du auch in deinem css, im :hover-Selector ein display: block !important; probieren, dann würde dein css den von Javascript gesetzten inline-Style überschreiben. Von dieser Vorgehensweise ist aber sonst generell abzusehen.

        lg

        1. @mark @Gunnar

          Ich danke euch beiden für die ausführliche Hilfe! Echt toll dieses Forum hier! Allerdings habe ich habe mich nocheinmal ein wenig umgeschaut und eine Alternative, die wie ich finde deutlich simpler ist, gefunden:

                                <div id="dropdown">
                                    <button id="dropbtn" onclick="menudrop()">
                                        <i class="fa fa-camera"></i> Bilder <i class="fa fa-camera"></i>
                                    </button>
                                    <div class="mydrop" id="dropdown-content">
                                      <a href="#">Link 1</a>
                                      <a href="#">Link 2</a>
                                      <a href="#">Link 3</a>
                                    </div>
                                
                                </div>
          
          #dropbtn {
              background: none;
              color: inherit;
              padding: inherit ;
              font-family: inherit ;
              font-size: inherit ;
              border: none;
              cursor: pointer;
          }
          
          #dropdown {
              display: inline-block;
          }
          
          .mydrop {
              display: none;
              position: middle;
              overflow: auto;
              background-color: #f9f9f9;
              min-width: 8em;
              box-shadow: 0px 10px 20px  #595959;
              margin-bottom: 0.5em;
              margin-top: 0.25em;
          }
          
          #dropdown-content a {
              color: black;
              padding: 12px 16px;
              text-decoration: none;
              display: block;
          }
          
          #dropdown-content a:hover {
              background-color: #f1f1f1
          }
          
          #dropdown:hover .mydrop {
              display: block;
          }
          
          .show {
              display: block;
          }
          
          
          function menudrop() {
              document.getElementById("dropdown-content").classList.toggle('show');
          }
          
          window.onclick = function(event) {
            if (!event.target.matches('#dropbtn')) {
          
              var dropdowns = document.getElementsByClassName('mydrop');
              var i;
              for (i = 0; i < dropdowns.length; i++) {
                var openDropdown = dropdowns[i];
                if (openDropdown.classList.contains('show')) {
                  openDropdown.classList.remove('show');
                }
              }
            }
          }
          

          Dabei funktioniert auch das :hover im css und das menü schließt automatisch beim zweiten click. Aber trotzdem habe ich viel gelernt und möchte euch beiden nochmal danken! So ausführliche Antworten habe ich noch nie in Foren bekommen. Tolle Community hier!

          grüße Josh

          1. Freut mich!

            Nur am Rande: Bei Verwendung von classlist bekommst du u.U. Probleme im IE (Version 9, 10, 11). Siehe http://caniuse.com/#feat=classlist.

            Wenn du das Abwärtskompatibel machen willst solltest du className verwenden.

            lg

            mark

            1. @@mark

              Nur am Rande: Bei Verwendung von classlist bekommst du u.U. Probleme im IE (Version 9, 10, 11). Siehe http://caniuse.com/#feat=classlist.

              Die Umstande sind: SVG und mehrere Parameter, also irrelevant (für IE 10 und 11). IE 9 ist an sich schon irrelevant.

              Wenn du das Abwärtskompatibel machen willst solltest du className verwenden.

              Insbesondere remove() ist recht aufwändig nachzuimplementieren.

              LLAP 🖖

              --
              „Wenn du eine weise Antwort verlangst, musst du vernünftig fragen.“ —Johann Wolfgang von Goethe