contras_t: Link mit mehreren JS-Funktionen verknüpfen

Hej!

Ich versuche gerade einen Link zu einem Anker mit zwei JS-funktionen zu koppeln.

Wenn man auf den Link klickt soll zuerst eine funktion (einblenden eines DIV) ausgeführt werden, danach soll zu dem Anker gescrollt (befindet sich innerhalb des engeblendeten DIV) - und anschließend eine zweite funktion (ausblenden eines DIV) ausgeführt werden.

HTML Beispiellink:

  
<a onClick="show('ring'); hide('hej','chair','uon','iron','baglight','clip','gridbook','stuff','vita','kontakt'); return false;" href="#ring">ring</a>

JS zum ein- & ausblenden (im Header extern verlinkt):

  
function hide(div) {  
with(document.getElementById(div).style){  
if(display=="inline-block"){  
display="none";  
}  
}  
}  
  
function show(div) {  
with(document.getElementById(div).style){  
if(display=="none"){  
display="inline-block";  
}  
}  
}

Das ganze findet Ihr auf dieser Seite.

Das scrollen zum Anker ist per smoothscroll dynamisch gelöst. Ich müsste das Ausblenden also um die Zeit des scrollens verzögern.
Also meine erste Frage: An welche stelle des JS muss ich einen delay setzen? (Bei den Beispielen die ich im Netz gefunden habe waren die scripte anders aufgebaut)

Das Ziel, ein- und ausblenden sind ja eigentlich definiert, leider funktioniert jedoch keines der drei Ereignisse. Die .js Datei scheint vollkommen ignoriert zu werden.
Deshalb meine zweite Frage:
wie kann ich dem Link sagen, dass er die obigen Schritte in der richtigen Reihenfolge ausführen soll und habe ich irgendwo einen Fehler den ich nicht finde, wegen dessen meine .js-datei ignoriert wird?

  1. Om nah hoo pez nyeetz, contras_t!

    Ich versuche gerade einen Link zu einem Anker mit zwei JS-funktionen zu koppeln.

    Wenn man auf den Link klickt soll zuerst eine funktion (einblenden eines DIV) ausgeführt werden, danach soll zu dem Anker gescrollt (befindet sich innerhalb des engeblendeten DIV) - und anschließend eine zweite funktion (ausblenden eines DIV) ausgeführt werden.

    Mach doch eine Funktion draus.

    Matthias

    --
    Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Mozart und Mozartkugeln.

    1. Das ist ja eine nette Begrüßung :)

      Mach doch eine Funktion draus.

      Dafür reichen meine JS-Kenntnisse leider noch nicht aus.

  2. Hallo,

    An welche stelle des JS muss ich einen delay setzen? (Bei den Beispielen die ich im Netz gefunden habe waren die scripte anders aufgebaut)

    Funktionen definieren:
    http://de.selfhtml.org/javascript/sprache/funktionen.htm

    Timeout setzen:
    http://de.selfhtml.org/javascript/objekte/window.htm#set_timeout

    Die Logik ließe sich vereinfachen, indem du alle fraglichen IDs in eine Liste schreibst. Mit zwei Funktionen wird das Zeigen und Verstecken gesteuert:

    // Liste mit allen Bereichen  
    var ids = ['ring', 'hej', 'chair', 'uon', 'iron', 'baglight', 'clip', 'gridbook', 'stuff', 'vita', 'kontakt'];  
      
    // Versteckt alle Elemente außer der angegebenen ID  
    var hideAllExcept = function(id) {  
      for (var i = 0, l = ids.length; i < l; i++) {  
        var otherId = ids[i];  
        if (id != otherId) {  
          hide(otherId);  
        }  
      }  
    };  
      
    // Zeigt ein Element, versteckt andere nach Wartezeit  
    var showAndHide = function(aElement) {  
      // Hole die ID aus dem href-Attribut  
      var id = aElement.hash.substring(1);  
      show(id);  
      // Verzögerung von einer Sekunde (1000ms)  
      setTimeout(function() {  
        // Verstecke alle anderen Elemente  
        hideAllExcept(id);  
      }, 1000);  
    };
    

    Das HTML kann dann so aussehen:

    <a href="#ring" onclick="showAndHide(this)">ring</a>  
    <a href="#chair" onclick="showAndHide(this)">chair</a>
    

    usw.

    this ist hier das angeklickte a-Element, es wird an die Funktion übergeben, damit sie die ID aus dem href-Attribut lesen kann. Damit spart man sich, es zweimal im Code anzugeben.

    (Ungetesteter Beispielcode.)

    Das lässt sich noch weiter verbessern und verallgemeinern, z.B. indem du Klassen anstatt IDs verwendest und die Elemente mit document.querySelector ansprichst. Dann musst du im JavaScript keine Liste von IDs pflegen, sondern durchläufst mit einer Schleife die gefundenen Elemente.

    Auch das Event-Handling ließe sich mit JavaScript lösen, sodass die vielen gleichen onclick-Attribute im HTML überflüssig werden. Siehe dazu:
    http://molily.de/js/event-handling-grundlagen.html
    http://molily.de/js/event-handling-effizient.html

    wie kann ich dem Link sagen, dass er die obigen Schritte in der richtigen Reihenfolge ausführen soll und habe ich irgendwo einen Fehler den ich nicht finde, wegen dessen meine .js-datei ignoriert wird?

    Die Funktionen show und hide werden korrekt aufgerufen.
    hide() nimmt aber nur eine ID als Parameter entgegen, nicht mehrere. Du müsstest also dutzende hide()-Aufrufe tätigen, oder hide so umschreiben, dass es eine variable Anzahl von Parametern entgegennimmt. Das ist sehr umständlich und der Wartungsaufwand hoch. Daher habe ich in meinem Beispiel oben die Funktion hideAllExcept definiert, die mit einer for-Schleife über eine einmal definierte Liste läuft.

    Grüße,
    Mathias

    1. Das ganze über ein Script zu lösen, welches automatisch die ID des Links ausliest und weiterverarbeitet habe ich auch überlegt, habe aber vermutet, dass ich hier niemanden gewinnen könnte, der mir ein solches script schreibt. Danke, dass ich mich geirrt habe ;)

      Das lässt sich noch weiter verbessern und verallgemeinern, z.B. indem du Klassen anstatt IDs verwendest und die Elemente mit document.querySelector ansprichst. Dann musst du im JavaScript keine Liste von IDs pflegen, sondern durchläufst mit einer Schleife die gefundenen Elemente.

      Die entsprechenden Container gehören alle der class .container an.
      Ich habe dein Script dementsprechend abgeändert und die JS-Datei sieht jetzt so aus:

      function hide(div) {  
      with(document.getElementById(div).style){  
      if(display=="inline-block"){  
      display="none";  
      }  
      }  
      };  
        
      function show(div) {  
      with(document.getElementById(div).style){  
      if(display=="none"){  
      display="inline-block";  
      }  
      }  
      };  
        
      // Versteckt alle Elemente der class .container außer der angegebenen ID  
      var hideAllExcept = function(id) {  
        for (var i = 0; i < document.querySelectorAll(".container").length; i++) {  
          var otherId = document.querySelectorAll[i];  
          if (id != otherId) {  
            hide(otherId);  
          }  
        }  
      };  
        
      // Zeigt ein Element, versteckt andere nach Wartezeit  
      var showAndHide = function(aElement) {  
        // Hole die ID aus dem href-Attribut  
        var id = aElement.hash.substring(1);  
        show(id);  
        // Verzögerung von einer halben Sekunde (500ms)  
        setTimeout(function() {  
          // Verstecke alle anderen Elemente  
          hideAllExcept(id);  
        }, 500);  
      };  
      
      

      Leider funktioniert es trotzdem noch nicht.
      Chrome gibt als Fehlermeldung "Uncaught TypeError: Cannot read property 'style' of null" aus, mit dem Verweis auf Zeile 2 der oben angefügten JS-Datei, was wohl darauf hinweist, dass ein Befehl ausgeführt werden soll, bevor der Inhalt geladen ist. (Quelle)

      Weiß jemand Rat?

      Danke schonmal für den großartigen Ansatz über this