Fabulit: Mehrere Funktionsaufrufe an einem Event

Guten Morgen liebe Forums-Gemeinde,

nach einem längeren Disput mit meinem Freund Google, stehen wir kurz davor uns zu entzweien und hoffen auf ein versöhnliches Ende durch eure Hilfe.

Ich bin zwar ein Javascript-Frischling, schätze meine Problematik allerdings als alltägliche Aufgabe ein. Mir fehlen wohl die richtigen Suchbegriffe.

Meine Frage: Wie binde ich mehrere Funktions-Aufrufe an ein Event (ohne eine "Container"-Funktion welche alle Aufrufe beinhaltet)? Bzw. wie füge ich einen Aufruf hinzu ohne bestehende Aufrufe zu verlieren?

Hintergrund: Ich habe ein kleines Skript erstellt, welches Fieldsets "zuklappt" und wieder "entfaltet". Ich möchte, dass man dieses Skript integrieren kann, indem man die externe .js-Datei einbindet und sonst nichts weiter unternimmt. Ich habe also eine Initialisierungs-Funktion, welche ausgeführt werden soll wenn das Dokument geladen wurde. Momentan wird der Initialisierungs-Prozess per window.onload aufgerufen. Probleme entstehen dann, wenn an anderer Stelle auf gleiche Weise auf window.onload zugegriffen wird.

Der folgende Code gibt mein Problem in stark vereinfachter Form wieder:

  
<html>  
  <head>  
    <title></title>		  
  </head>  
  <body>  
    <span id="wort1">xxx</span> <span id="wort2">xxx</span>	  
    <script type="text/javascript">
~~~~~~javascript
  
      window.onload = function () {document.getElementById("wort1").innerHTML = "Hallo";};	  
      window.onload = function () {document.getElementById("wort2").innerHTML = "Welt!";};
~~~~~~html
  
    </script>  
  </body>  
</html>

Mir erschien es logisch, als Alternative, auf die addEventListener-Methode (im FF) zurückzugreifen. Versuche mit dieser Methode window.onload oder das onload-Event vom body mehrfach zu bestücken sind allerdings ebensfalls fehlgeschlagen. Mit der gleichen Symptomatik wie zuvor. Und selbst mit meinem neuen Lieblingswort "unobstrusive" konnte ich keine erkenntnisspendenden Suchergebnisse ernten.

Mittlerweile sehe ich vor lauter Bäumen den Holzweg nicht mehr.

Ich hoffe, ihr könnt mich von meiner Orientierungslosigkeit befreien und freue mich schon auf aufschlussreiche Antworten.

Gruß Fabulit

  1. Hallo Fabulit,

    wir haben folgenden Code in unserer Library:

      
    var General =  
    {  
      addEvent: function(element, eventName, function_)  
      {  
        if (typeof(function_) == 'undefined')  
          return false;  
        if (element.addEventListener)  
          element.addEventListener(eventName, function_, false);  
        else if (element.attachEvent)  
          element.attachEvent('on' + eventName, function_);  
        return true;  
      },  
      addOnLoad: function(function_)  
      {  
        if (document.readyState == 'loading')  
          General.addEvent(window, 'load', function_);  
        else  
          setTimeout(function_, 1);  
      }  
    }  
    
    

    Damit lässt sich über

    General.addOnLoad(function() {  
    ...  
    })
    

    browserübergreifend eine Funktion zum onLoad-Event hinzufügen.

    Gruß

    1. Vielen Dank Ver2felt, es klappt wunderbar. Und es hat mir sogar auf die Sprünge geholfen. Als ich mit addEventListener experimentiert habe, habe ich fälschlicherweise "onload" anstatt "load" angegeben.

      Die addEvent-Methode ist für mich nachvollziehbar. Aber das Drumherum bei der addOnLoad-Methode leuchtet mir noch nicht ganz ein. Meine Vermutung; wenn die Seite zum Zeitpunkt der Ausführung des Skripts noch geladen wird, wird window.onload angesprochen und wenn es schon "zu spät" sein sollte, wird die Funktion mit minimaler Verzögerung ausgeführt. Klingt logisch. Und wozu die minimale Verzögerung?

      1. Die addEvent-Methode ist für mich nachvollziehbar. Aber das Drumherum bei der addOnLoad-Methode leuchtet mir noch nicht ganz ein. Meine Vermutung; wenn die Seite zum Zeitpunkt der Ausführung des Skripts noch geladen wird, wird window.onload angesprochen und wenn es schon "zu spät" sein sollte, wird die Funktion mit minimaler Verzögerung ausgeführt. Klingt logisch. Und wozu die minimale Verzögerung?

        Das "Drumherum" ist vor allem einmal die Definition einer OO-ähnlichen Struktur. Die addEvent-Methode ist mächtiger und kann zu jedem möglichen Event Funktionen hinzufügen. addOnLoad ist ein Wrapper für addEvent, der speziell für die onLoad-Methode arbeitet. Da aber möglicherweise bei Ausführen dieses Befehls die Seite schon geladen ist, wird in dem Fall die Funktion einfach ausgeführt. Die "Verzögerung" um 1 Millisekunde ist nur dafür gut, dass die Funktion asynchron ausgeführt wird.

        1. Die "Verzögerung" um 1 Millisekunde ist nur dafür gut, dass die Funktion asynchron ausgeführt wird.

          Und welchen Nutzen ziehe ich aus der Asynchronität? Und wann bietet sich der Einsatz dieses Stilmittels an? Ein solches Konstrukt verwende ich ja sonst auch nicht, wenn ich eine Funktion aus der anderen heraus aufrufe. Fehlt mir da Grundlagenwissen, oder handelt sich hier um einen Spezialfall? Fragen über Fragen...

          Gruß

          1. Und welchen Nutzen ziehe ich aus der Asynchronität? Und wann bietet sich der Einsatz dieses Stilmittels an? Ein solches Konstrukt verwende ich ja sonst auch nicht, wenn ich eine Funktion aus der anderen heraus aufrufe. Fehlt mir da Grundlagenwissen, oder handelt sich hier um einen Spezialfall? Fragen über Fragen...

            Vor allem hast du erstmal auch keinen Nachteil. Wenn du aber weitere Befehle nach dem General.addOnLoad ausführst, werden zunächst diese Befehle ausgeführt und die Methode / Funktion beendet. Wenn die Funktion, die du eigentlich bei onLoad aufrufen wolltest, schnell ist fällt das gar nicht auf. Wenn diese aber aufwändige Berechnungen durchführt, einen AJAX-Aufruf oder eine Benutzereingabe ausführt, dann kann es vorteilhaft sein, zunächst mit dem restlichen Code weiterzumachen. Daher haben wir das so implementiert, kann aber natürlich auch durch einen einfachen Aufruf function_(); ersetzt werden.

            Gruß

            1. Sehr schön, vielen Dank. Da habe ich ja glatt noch einen Kniff gelernt, nach dem ich gar nicht gesucht hatte.

              Gruß Fabulit

  2. Befreit von der Last des Suchens bin ich nun zum Finden übergegangen und habe tatsächlich noch einen weiteren Ansatz entdeckt:
    Kompatibler Autostart

    Eine ähnliche Konstruktion habe ich in meiner Testphase nicht zu laufen bekommen, kann aber leider nicht mehr eruieren wo der Fehler lag.

    Gruß Fabulit

    1. gruss Fabulit,

      Befreit von der Last des Suchens bin ich nun zum Finden übergegangen
      und habe tatsächlich noch einen weiteren Ansatz entdeckt:
      Kompatibler Autostart

      Eine ähnliche Konstruktion habe ich in meiner Testphase nicht zu
      laufen bekommen, ...

      manchmal muss man tatsaechlich den unter obigen link beschriebenen
      weg einschlagen, um im nachhinein die [onload] scripte von dritten
      ein wenig besser steuern zu koennen.

      dieses "einschliessende ueberschreiben von methoden-referenzen" muss
      aber nicht immer wieder zu fuss erledigt werden.

      mit sogenannten »method modifiers« geht das auch eleganter/bequemer.

      hier Dein abgewandeltes bsp.:

      <html>  
        <head>  
          <title></title>  
        </head>  
        <body>  
          <span id="wort1">xxx</span> <span id="wort2">xxx</span>  
      <!--  
          [link:https://github.com/petsel/javascript-api-extensions/blob/master/core/Function/Function.modifiers.js@title=Function.modifiers] - [before], [after], [cover]:  
        
          [https://github.com/petsel/javascript-api-extensions/blob/master/core/Function/Function.modifiers.js]  
      //-->  
          <script type="text/javascript" src="https://github.com/petsel/javascript-api-extensions/raw/master/core/Function/Function.modifiers.min.js"></script>  
          <script type="text/javascript">
      ~~~~~~javascript
        
            if (typeof window.onload != "function") {  
              window.onload = function () {document.getElementById("wort1").innerHTML = "Hallo";};  
            } else {  
              window.onload = window.onload.after(function () {  
                document.getElementById("wort1").innerHTML = "Hallo";  
              });  
            }  
            window.onload = window.onload.after(function ()  
        
              {document.getElementById("wort2").innerHTML = "Welt!";  
        
            })/*.after(function () {  
        
            }).before(function () {  
        
            }).cover(function () {  
        
            })*/;
      ~~~~~~html
        
          </script>  
        </body>  
      </html>
      

      so long - peterS. - pseliger@gmx.net

      --
      »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
      Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
      ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
      1. Hallo Peter,

        das scheinen ja sehr komfortable Möglichkeiten zu sein, die deine Extension anbietet - vielen Dank. Für meine (noch) kleinen Übungsprojekte zwar überdimensioniert, zumal ich den Anspruch habe alles selbst zu erstellen und zu verstehen, aber bestimmt hilfreich in der Zukunft.

        Die Methode des self-Artikels empfinde zwar als vertraut, weil ich mit Strings ähnlich verfahren würde. Aber grundsätzlich finde ich die Methode mit addEventListener deutlich eleganter. Wäre das einer der von dir erwähnten Method Modifier?

        Ach, noch was; wenn ich die Methode von Ver2fehlt adaptiere, aber die Vorgabe/Einschränkung mache, dass das Skript immer im head liegt und die addOnLoad-Methode nur von diesem (im head befindlichen) Skript verwendet wird, ist dann sichergestellt dass sich die Seite noch im Lade-Status befindet? Oder anders gefragt; ist die if-Abfrage bezüglich document.readyState in der addOnLoad-Methode noch erforderlich, wenn sichergestellt ist, dass die addOnLoad-Methode nur dieses eine Mal aus dem head heraus verwendet wird? Du ahnst hoffentlich, worauf meine Frage abzielt.

        Gruß Fabulit

  3. Hallo,

    Wie binde ich mehrere Funktions-Aufrufe an ein Event (ohne eine "Container"-Funktion welche alle Aufrufe beinhaltet)? Bzw. wie füge ich einen Aufruf hinzu ohne bestehende Aufrufe zu verlieren?

    Siehe:
    JavaScript: Grundlagen zur Ereignisverarbeitung
    JavaScript: Fortgeschrittene Ereignisverarbeitung

    Mir erschien es logisch, als Alternative, auf die addEventListener-Methode (im FF) zurückzugreifen.

    Dessen Benutzung wird unter Event-Handling gemäß dem W3C-Standard DOM Events erklärt.

    Zudem solltest du dich mit DOMContentLoaded beschäftigen.

    Und selbst mit meinem neuen Lieblingswort "unobstrusive" konnte ich keine erkenntnisspendenden Suchergebnisse ernten.

    Es heißt ja auch »unobtrusive«. ;)

    Mathias

    1. Und selbst mit meinem neuen Lieblingswort "unobstrusive" konnte ich keine erkenntnisspendenden Suchergebnisse ernten.

      Es heißt ja auch »unobtrusive«. ;)

      Wenn das mal kein freud'scher Vertipper vom allerfeinsten ist :-)

      Vielen Dank für die Lese-Tipps. Ich war schon mal irgendwann über deine Doku gestolpert, allerdings zu dem Zeitpunkt noch nicht an JavaScript interessiert. Und nun stehe ich vor demselben Dilemma wie immer; man kann nicht einfach losspielen, sondern muss ich sich mit den Grundlagen beschäftigen. Ich hätte bei Lego bleiben sollen - das nenne ich mal intuitive Handhabe.

      Schönen Tag noch