Siri: Kapselung und Autostart

Hallo,

für ein kleines Framework hab ich mir folgende Grundstruktur (angelehnt an das Beispiel von Felix) überlegt:

var Test1 = (function () {	  
  
	var oldWinOnLoad = false;		  
  
	function init () {				  
		  
	};		  
  
	(function () {  
		oldWinOnLoad = window.onload;		  
		window.onload = function () {			  
			if( typeof (oldWinOnLoad) == 'function' ) {  
				oldWinOnLoad();  
			}			  
			init();			  
		}				  
	})();  
  
  
})();	

Das Ziel ist es, die Funktion "init" aufzurufen, wenn die Seite geladen ist. In init werden dann z.B. Eventhandler registriert, das funktioniert problemlos. Frage: Ist das state-of-the-art? Oder kann man das eleganter lösen?

Grüsse
Siri

  1. Hallo Siri,

    bei meinem Tabellensortierer habe ich das so gelöst:

      
    ( function() {  
      
      var tuwas = function() {  
        ...  
      }  
      
      ...  
      
      var JB_addEvent = function (obj, type, fn) {  
        if(type.search("on")==0) type = type.substr(2);  
        if (obj.addEventListener) {  
          obj.addEventListener(type, fn, false);  
        }  
        else if (obj.attachEvent) {  
          obj.attachEvent('on' + type, function () {  
            return fn.call(obj, window.event);  
          });  
        }  
      } // addEvent  
      
      JB_addEvent(window,"onload",function(e) {  
        ...  
        tu_was();  
        ...  
      });  
      
    })();  
    
    

    Ich "verstecke" also alles in einer anonymen sich selbst ausführenden Funktion, einschließlich des Notierens des Eventhandlers.

    Gruß, Jürgen

    1. Hallo,

      ( function() {

      var tuwas = function() {
          ...
        }

      ...

      var JB_addEvent = function (obj, type, fn) {
          if(type.search("on")==0) type = type.substr(2);
          if (obj.addEventListener) {
            obj.addEventListener(type, fn, false);
          }
          else if (obj.attachEvent) {
            obj.attachEvent('on' + type, function () {
              return fn.call(obj, window.event);
            });
          }
        } // addEvent

      JB_addEvent(window,"onload",function(e) {
          ...
          tu_was();
          ...
        });

      })();

      
      >   
        
      Du registrierst ein Eventhandler für das Ereignis "onload", wenn die Seite bereits geladen ist?  
        
      Grüße  
      Siri 
      
      1. Hallo Siri,

        Du registrierst ein Eventhandler für das Ereignis "onload", wenn die Seite bereits geladen ist?

        nein. Wie kommst du darauf?

        Gruß, Jürgen

        1. Hallo,

          Du registrierst ein Eventhandler für das Ereignis "onload", wenn die Seite bereits geladen ist?

          nein. Wie kommst du darauf?

          Vielleicht verstehe ich ja den zeitlichen Ablauf nicht...
          Das Script wird automatisch gestartet, während die Seite geladen wird. Das ist klar. Dabei wird der Eventhandler load am window registriert. Load wird "gefeuert", wenn window geladen ist. Was aber, wenn load schon durch ist, bevor der Eventhandler registriert wurde?

          Grüße
          Siri

          1. Hallo Siri,

            das Laden und Ausführen der Scripte blockiert das weitere Bearbeiten der Seite, sofern man die Scripte nicht asynchron laufen lässt bzw. asynchron einbindet.

            Wenn dir "window.onload" nicht geheuer ist, oder das Rendern der Seite nicht durch umfangreiche Scripte aufgehalten werden soll, kannst du die Scripte auch vom Head an das Ende des Body verschieben. Ziel ist ja eigentlich, sicherzustellen, das der DOM-Baum existiert, bevor das Script darauf zugreift.

            Gruß, Jürgen

  2. var Test1 = (function () {

    Die Variable Test1 macht hier keinen Sinn, deine Funktion gibt ja nichts zurück.

    (function () {
    oldWinOnLoad = window.onload;
    window.onload = function () {
    if( typeof (oldWinOnLoad) == 'function' ) {
    oldWinOnLoad();
    }
    init();
    }
    })();

    Was soll hier die zusätzliche Kapselung durch die anonyme Funktion bringen?

    1. Hallo,

      Die Variable Test1 macht hier keinen Sinn, deine Funktion gibt ja nichts zurück.
      Was soll hier die zusätzliche Kapselung durch die anonyme Funktion bringen?

      Ich wollte das Beispiel so übersichtlich wie möglich halten, da es mir in erster Linie darum geht, ob das Warten auf das Laden der Seite so optimal umgesetzt ist und die Struktur stimmt oder ob es was schickeres gibt.

      var Test1 = (function () {	  
        
      	var oldWinOnLoad = false;		  
        
      	function init () {				  
      	  // Eventhandler registrieren	  
      	};		  
        
      	(function () {  
      		oldWinOnLoad = window.onload;		  
      		window.onload = function () {			  
      			if( typeof (oldWinOnLoad) == 'function' ) {  
      				oldWinOnLoad();  
      			}			  
      			init();			  
      		}				  
      	})();  
        
              return {  
                public1: function() {  
                  alert("test");  
                }  
              }  
      })();	
      

      Grüße
      Siri

      1. da es mir in erster Linie darum geht, ob das Warten auf das Laden der Seite so optimal umgesetzt ist und die Struktur stimmt oder ob es was schickeres gibt.

        Ich habe zwar keine Ahnung, was du mit deinem Framework erreichen willst, aber eigentlich dürfte es doch keinen Grund geben überhaupt das Laden der Seite abzuwarten und schon Eventhandler zu registrieren, die vielleicht nicht mal alle genutzt werden.
        Ich würde die Eventhandler erst dann registrieren, wenn sie auch benötigt werden.

        1. Ich habe zwar keine Ahnung...

          Dazu kann ich Dir auch nur den Link empfehlen, der Dir oben schon ans Herz gelegt wurde.

          Ich würde die Eventhandler erst dann registrieren, wenn sie auch benötigt werden.

          Eventhandler können nur an Elementen registriert werden, die im DOM geladen sind, da die Eventhandler benötigt werden, wenn die Seite geladen ist muss man -ergo- wissen, wann das der Fall ist.

          1. Ich habe zwar keine Ahnung...
            Dazu kann ich Dir auch nur den Link empfehlen, der Dir oben schon ans Herz gelegt wurde.

            Du willst also einen Fader!

            Ich würde die Eventhandler erst dann registrieren, wenn sie auch benötigt werden.
            Eventhandler können nur an Elementen registriert werden, die im DOM geladen sind, da die Eventhandler benötigt werden, wenn die Seite geladen ist muss man -ergo- wissen, wann das der Fall ist.

            Und das sagt dir ja der Anwender, wenn er deiner Api das Element mit den gewünschten Parametern übergibt.

            1. Du willst also einen Fader!

              Ohh... Ich dachte du meinst den Link im Ausgangspost.
              Der Andere hat in beiden Fällen nichts mit meiner Frage zu tun.
              Die 2. Kapselung ist so, wie du sie gepostet hast überflüssig, da sie nichts kapselt und was du in deinem Framework vor hast, weiss ich immer noch nicht!

            2. Dazu kann ich Dir auch nur den Link empfehlen, der Dir oben schon ans Herz gelegt wurde.
              Du willst also einen Fader!

              Nein, will ich nicht, hinter dem Link ist kein Fader. Ich will ein Framework.

              Und das sagt dir ja der Anwender, wenn er deiner Api das Element mit den gewünschten Parametern übergibt.

              Und wie tut er das ohne registrierten Eventhandler? Auf zuruf? ;-)

              1. Und wie tut er das ohne registrierten Eventhandler? Auf zuruf? ;-)

                Genau!
                Framework.fade(Element, [von,] bis, inDieserZeit);

                1. Und wie tut er das ohne registrierten Eventhandler? Auf zuruf? ;-)
                  Genau!
                  Framework.fade(Element, [von,] bis, inDieserZeit);

                  Das ist aber nicht gottgegeben. Enweder ich arbeite i.w. mit onclick (ganz schlecht) oder mit dem Befehl im JS am Ende (besser) oder ich registriere einen Eventhandler myelement.addEventListener("click", Framework.fade, false)(gut!) und den kann ich erst registrieren, wenn "myelement" geladen ist.

                  1. Enweder ich arbeite i.w. mit onclick (ganz schlecht) oder mit dem Befehl im JS am Ende (besser) oder ich registriere einen Eventhandler myelement.addEventListener("click", Framework.fade, false)(gut!) und den kann ich erst registrieren, wenn "myelement" geladen ist.

                    Und das sagt dir wiederum der Anwender, wenn er mithilfe deiner Api den Eventhandler am Element registriert.
                    Du kennst das Element erst, wenn der Anwender es dir sagt.

                    1. Enweder ich arbeite i.w. mit onclick (ganz schlecht) oder mit dem Befehl im JS am Ende (besser) oder ich registriere einen Eventhandler myelement.addEventListener("click", Framework.fade, false)(gut!) und den kann ich erst registrieren, wenn "myelement" geladen ist.
                      Und das sagt dir wiederum der Anwender, wenn er mithilfe deiner Api den Eventhandler am Element registriert.
                      Du kennst das Element erst, wenn der Anwender es dir sagt.

                      Ich glaub wir reden von völlig verschiedenen Dingen! Ein Anwender ist für mich jemand, der vor dem Bildschirm sitzt und die Seite benutzen will, die er sieht. Und dann muss der Event registriert sein, damit er klicken kann.

                      Wenn jetzt jemand das Framework benutzen will ist das was anderes. Aber auch da gibts die Möglichkeit, dass zu "automatisieren" in dem Events an Element gehängt werden, die einer bestimmten Klasse angehören. Und DIESES anhängen erfolgt nach dem load-Event. Und DAS sollte ein Framework leisten.

                      1. Ich glaub wir reden von völlig verschiedenen Dingen! Ein Anwender ist für mich jemand, der vor dem Bildschirm sitzt und die Seite benutzen will, die er sieht. Und dann muss der Event registriert sein, damit er klicken kann.

                        Ich rede natürlich vom Anwender des Frameworks!

                        1. Ich rede natürlich vom Anwender des Frameworks!

                          Immerhin haben wirs rausgefunden ;-)

                    2. Hallo unknown,

                      schau dir mal dieses Beispiel an. In der HTML-Seite wirst du bis auf das Einbinden des Scripts kein Javascript finden. Das Script sucht sich nach dem Laden der Seite im HTML die entsprechenden Elemente und gibt ihnen dann die entsprechenden Eventhandler.

                      Gruß, Jürgen

                      1. schau dir mal dieses Beispiel an. In der HTML-Seite wirst du bis auf das Einbinden des Scripts kein Javascript finden. Das Script sucht sich nach dem Laden der Seite im HTML die entsprechenden Elemente und gibt ihnen dann die entsprechenden Eventhandler.

                        Und genau das finde ich nicht gut!

                        1. Hallo unknown,

                          Und genau das finde ich nicht gut!

                          warum nicht? Ich habe so eine strenge Trennung von Inhalt und Script. der Webautor muss nur das Script einbinden und die Tabellen entsprechend kennzeichnen.

                          Gruß, Jürgen

                          1. warum nicht?

                            Weil du z.B. keine Möglichkeit hast, Tabellen dynamisch zu erzeugen.
                            Du als Anbieter der Funktionalität schreibst mir als Nutzer auch die Klasse vor, das ist unnötig.

                            Ich habe so eine strenge Trennung von Inhalt und Script.

                            Dagegen spricht ja nichts, das ist Standard!

                            und die Tabellen entsprechend kennzeichnen.

                            Aber ich will selbst entscheiden wie ich sie kennzeichne!

                            1. Hallo unknown,

                              warum nicht?
                              Weil du z.B. keine Möglichkeit hast, Tabellen dynamisch zu erzeugen.

                              in der Anleitung steht, wie es geht. Dann ist der Sortierer allerdings nicht mehr anonym.

                              Du als Anbieter der Funktionalität schreibst mir als Nutzer auch die Klasse vor, das ist unnötig.

                              und die Tabellen entsprechend kennzeichnen.
                              Aber ich will selbst entscheiden wie ich sie kennzeichne!

                              dann bist du Profi und kannst das Script leicht anpassen.

                              Für mich sind das aber keine Gründe, die Vorteile der Anonymisierung aufzugeben.

                              Gruß, Jürgen

    2. Moin,

      Was soll hier die zusätzliche Kapselung durch die anonyme Funktion bringen?

      http://molily.de/js/organisation-module.html#scope

      Grüße Marco

  3. var Test1 = (function () {

    var oldWinOnLoad = false;

    function init () {

    };

    (function () {
    oldWinOnLoad = window.onload;
    window.onload = function () {
    if( typeof (oldWinOnLoad) == 'function' ) {
    oldWinOnLoad();
    }
    init();
    }
    })();

    })();

      
    onload wartet nicht nur bis der DOM-Baum erstellt wurde, sondern darüber hinaus bis alle Ressourcen geladen wurden. Außerdem hat deine Methode den Nachteil, dass ein später eingebundenes Skript den onload-Handler wieder überschreiben kann.  
      
    Ich benutze ein ähnliches Grundgerüst. Das hat den Vorteil, dass es Abhängigkeiten der Ladereihenfolge auflöst. Hat aber den Nachteil, dass es HTML5 ist und mit älteren Browser seine Probleme haben könnte. Demhingehen muss folgender Code also noch angepasst werden.  
      
    [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/)  
      
    ~~~javascript
      
      
    var Test1 = (function () {	  
      
     	function init () {				  
     		  
     	};		  
      
            document.addEventListener("DOMContentLoaded", init);  
      
    })();  
      
    
    
    1. Hallo,

      onload wartet nicht nur bis der DOM-Baum erstellt wurde, sondern darüber hinaus bis alle Ressourcen geladen wurden.

      Das ist ja erstmal nicht schlimm, oder? Es sei denn, die Seite läd so lang und der User versucht eine Aktion auszuführen, die noch nicht zur Verfügung steht?!

      Außerdem hat deine Methode den Nachteil, dass ein später eingebundenes Skript den onload-Handler wieder überschreiben kann.

      Wie könnte das ausschauen (reine Neugier)?

      DOM Level 3 Events

      var Test1 = (function () {

      function init () {

      };

      document.addEventListener("DOMContentLoaded", init);

      })();

      Das wär natürlich deutlisch schlanker und eleganter!  
        
      Grüße  
      Siri
      
      1. Hallo,

        onload wartet nicht nur bis der DOM-Baum erstellt wurde, sondern darüber hinaus bis alle Ressourcen geladen wurden.
        Das ist ja erstmal nicht schlimm, oder? Es sei denn, die Seite läd so lang und der User versucht eine Aktion auszuführen, die noch nicht zur Verfügung steht?!

        Genau das ist das Problem.

        Außerdem hat deine Methode den Nachteil, dass ein später eingebundenes Skript den onload-Handler wieder überschreiben kann.
        Wie könnte das ausschauen (reine Neugier)?

        Man könnte prüfen, ob der Browser html5 unterstützt und als Fallback

          
        document.addEventListener("load", init);  
        
        

        verwenden.

      2. Außerdem hat deine Methode den Nachteil, dass ein später eingebundenes Skript den onload-Handler wieder überschreiben kann.
        Wie könnte das ausschauen (reine Neugier)?

          
           window.onload = function(){ return; }  
        
        

        Wenn das Skript nun nach deinem eingebunden wird ist dein EventHandler einfach weg.

  4. Hallo,

      oldWinOnLoad = window.onload;		  
      window.onload = function () {			  
      	if( typeof (oldWinOnLoad) == 'function' ) {  
      		oldWinOnLoad();  
      	}			  
      	init();			  
      }				  
    

    Das ist traditionelles Event-Handling à la Netscape 2.

    Besser W3C-Event-Handling verwenden.

    Und anstelle des load-Ereignisses DOMContentLoaded verwenden.

    Letztlich ergibt es Sinn, ein Event-Bibliothek wie jQuery oder kleinere Bibliotheken wie bean zu verwenden. Siehe auch domready.

    Mathias