Felix Riesterer: getElementsByClassName als Methode von document?

Liebe JS-Könner,

ich brauche manchmal die Funktion document.getElementsByClassName(), die jedoch nicht im bisherigen Javascript-Sprachumfang implementiert ist.

Ich habe mir einfach eine solche Funktion geschrieben:

function getElementsByClassName(className) {  
    var muster = new RegExp("(^| )" + className + "($| )");  
    var alles = document.getElementsByTagName("*");  
    var gefunden = new Array();  
    var i;  
  
    for (i=0; i < alles.length; i++) {  
        if (alles[i] && alles[i].className && alles[i].className != "") {  
            if (alles[i].className.match(muster))  
                gefunden[gefunden.length] = alles[i];  
        }  
    }  
  
    return gefunden;  
}

Nun möchte ich diese Funktion als Methode des document-Objektes haben. Wie bekomme ich jetzt meine Funktion dazu, dass sie sich auf das document bezieht? Einfach ein document.getElementsByClassName = function (className) {...} reicht ja nicht, da in meinem Funktionscode das document-Objekt fest benutzt wird. Durch die Schreibweise "document.getElementsByClassName" soll aber genau dieser Zusammenghang klar werden, ohne dass ich in meinem Code "document.xyz" notieren muss.

Wie geht das? Brauche ich etwas wie "prototype"?

Liebe Grüße aus Ellwangen,

Felix Riesterer.

--
ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  1. if (alles[i] && alles[i].className && alles[i].className != "") {

    Der letzte Vergleich dürfte überflüssig sein

    Nun möchte ich diese Funktion als Methode des document-Objektes haben. Wie bekomme ich jetzt meine Funktion dazu, dass sie sich auf das document bezieht? Einfach ein document.getElementsByClassName = function (className) {...} reicht ja nicht, da in meinem Funktionscode das document-Objekt fest benutzt wird. Durch die Schreibweise "document.getElementsByClassName" soll aber genau dieser Zusammenghang klar werden, ohne dass ich in meinem Code "document.xyz" notieren muss.

    Das verstehe ich nicht, document.xyz ist der einzige Weg, den alle Browser verstehen.

    Struppi.

    --
    Javascript ist toll (Perl auch!)
    1. Lieber Struppi,

      erst einmal danke für Deine Antwort!

      Das verstehe ich nicht, document.xyz ist der einzige Weg, den alle Browser verstehen.

      Ich meinte das so, dass ich innerhalb meiner Funktion im Code das document-Objekt nicht erneut notieren muss, da der Bezug zu eben diesem Objekt ja schon durch den Funktionsaufruf document.xyz() klar ist. Irgendwie könnte das mit dem Schlüsselwort "this" geschehen, nur habe ich keine Ahnung, wie.

      Beispiel:
      document.getElementsByTagName("a") // Holt alle Anker aus document
      document.forms[0].getElementsByTagName("a") // Holt alle Anker aus dem ersten Formular (sonst keine!)

      Im obigen Beispiel ist der zweite Funktionsaufruf auf das erste Formular im Dokument beschränkt. Die Funktion "getElementsByTagName" bezieht sich hier nur auf das Formular-Objekt, nicht jedoch auf das ganze Dokument (vergleiche ersten Aufruf). Wie kann ich diesen Umstand im meiner Funktion von der Schreibweise her nachbilden?

      Ich glaube, ich brauche da etwas wie Konstruktor oder prototype, nur verstehe ich davon noch viel zu wenig. Daher meine Frage...

      Liebe Grüße aus Ellwangen,

      Felix Riesterer.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  2. Hallo,

    Durch die Schreibweise "document.getElementsByClassName" soll aber genau dieser Zusammenghang klar werden, ohne dass ich in meinem Code "document.xyz" notieren muss.

    this.getElementsByTagName

    this in einer Funktion verweist auf das Objekt, dessen Methode die Funktion ist (oder window, wenn die Funktion eine lokale Variable ist).

    document.func = function () {
     alert(this === document);
    };
    document.func();

    Voraussetzung ist die Aufrufweise »objekt.methode()«.

    Mathias

    1. Lieber Mathias,

      vielen Dank für Deinen Hinweis!

      this in einer Funktion verweist auf das Objekt, dessen Methode die Funktion ist (oder window, wenn die Funktion eine lokale Variable ist).

      document.func = function () {
      alert(this === document);
      };
      document.func();

      Damit kann ich nun tatsächlich "document.getElementsByClassName" verwenden. SUPER!

      Wie kann ich das ausweiten auf alle HTML-Elemente? Es wäre chic, wenn ich diese Funktion auf ein beliebiges HTML-Element anwenden könnte, um nur dessen Kindknoten zu erhalten, anstatt alle Knoten des gesamten Dokuments.

      Braucht es dazu prototype? Und wenn ja, wie definiere ich das so, dass es sich auf alle HTML-Objekte bezieht? Ich habe im Archiv gelesen, dass man streng zwischen Javascript und DOM trennen muss, und genau hier scheint sich diese Grenze aufzutun...

      Liebe Grüße aus Ellwangen,

      Felix Riesterer.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  3. Hallo Felix Riesterer,

    Wie geht das? Brauche ich etwas wie "prototype"?

    Hmm, scheint so. Auf anhieb schien das zu funktionieren:

      
       Object.prototype.getElementsByClassName = function(className){  
        var muster = new RegExp("(^| )" + className + "($| )");  
        var alles = document.getElementsByTagName("*");  
        var gefunden = new Array();  
        var i;  
      
        for (i=0; i < alles.length; i++)  
         if (alles[i] && alles[i].className && alles[i].className != "")  
          if (alles[i].className.match(muster))  
           gefunden[gefunden.length] = alles[i];  
      
        return gefunden;  
       }
    

    Wobei nun wahrscheinlich jedes Object diese Methode hat; es geht vermutlich besser...

    Mit freundlichem Gruß
    Micha

    1. Hallo,

      Wie geht das? Brauche ich etwas wie "prototype"?
      Hmm, scheint so.

      Kommt drauf an, was Felix will...

      Object.prototype.getElementsByClassName

      Wenn schon, dann HTMLElement.prototype, was aber IE bekanntlich auch nicht kann.

      Object.prototype zu erweitern ist nicht ohne und hat weitreichende Konsequenzen, daraufhin muss man jede for-in-Schleife mit einer hasOwnProperty-Abfrage versehen. Also lieber Finger weg davon, wenns auch anders geht.

      var alles = document.getElementsByTagName("*");

      Dann hier natürlich this, wie gesagt.

      Mathias

      1. Lieber Mathias,

        Wenn schon, dann HTMLElement.prototype, was aber IE bekanntlich auch nicht kann.

        Aha! Also in nicht-IEs wäre das eine Option? Und wie macht man dann den IE gefügig?

        Liebe Grüße aus Ellwangen,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
        1. hi,

          Wenn schon, dann HTMLElement.prototype, was aber IE bekanntlich auch nicht kann.

          Aha! Also in nicht-IEs wäre das eine Option? Und wie macht man dann den IE gefügig?

          Wenn's ein wenig von hinten durch die Brust ins Auge sein darf - dann vielleicht analog dazu, wie es Jason Karl Davis in DOM2 EventTarget in IE zeigt:

          Die Funktionalität wird in einem HTC untergebracht, und dann per Universal-Selektor * und behaviour im CSS an alle Elemente "drangehängt".
          (An document muss sie nach wie vor mit dem im Thread schon genannten Weg angehängt werden, denn document wird ja nicht durch CSS selektiert.)

          Ich habe allerdings keine Ahnung, wie performant das ist - und schwanke auch noch innerlich, ob ich diesen Ansatz eher als clever, oder als total meschugge ansehen soll :-)

          gruß,
          wahsaga

          --
          /voodoo.css:
          #GeorgeWBush { position:absolute; bottom:-6ft; }
          1. Lieber wahsaga,

            Die Funktionalität wird in einem HTC untergebracht

            [...]

            ob ich diesen Ansatz eher als clever, oder als total meschugge ansehen soll :-)

            danke Dir für diesen Hinweis. Das ist wirklich sehr verzwickt. :-)

            Ich bleibe lieber bei meiner ursprünglichen Version von meiner Funktion, der ich eben einen optionalen zweiten Parameter mitgebe, der dann das aktuelle HTML-Element referenziert, innerhalb dessen ich die Nachfahrenknoten ermitteln lasse.

            window.getElementsByClassName = function (className, element) {  
                var muster = new RegExp("(^| )" + className + "($| )");  
                var alles = element.getElementsByTagName("*");  
                var gefunden = new Array();  
                var i;  
              
                element = element ? element : document;  
              
                for (i=0; i < alles.length; i++) {  
                    if (alles[i] && alles[i].className && alles[i].className != "") {  
                        if (alles[i].className.match(muster))  
                            gefunden[gefunden.length] = alles[i];  
                    }  
                }  
              
                return gefunden;  
            }
            

            In dieser Art wurde eine solche Funktion ja im Forum schon öfter diskutiert - anscheinend geht es browser(krücken)übergreifend nicht besser...

            Liebe Grüße aus Ellwangen,

            Felix Riesterer.

            --
            ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
            1. hallo again Felix,

              Ich bleibe lieber bei meiner ursprünglichen Version von meiner Funktion,
              der ich eben einen optionalen zweiten Parameter mitgebe, der dann das
              aktuelle HTML-Element referenziert, innerhalb dessen ich die Nachfahrenknoten
              ermitteln lasse.

              eben, das ist durchaus der ansatz fuer schlankeren und uebersichlicheren code;
                 und fuer den fall dieser einen methode sowiso.

              window.getElementsByClassName = function (className, element) {

              var muster = new RegExp("(^| )" + className + "($| )");
                var alles = element.getElementsByTagName("*");
                var gefunden = new Array();
                var i;

              element = element ? element : document;

              
              >   
              >   ...  
                
                 hier muesstest Du die letzte pruefung aber ganz nach oben ziehen und etwas  
                 strikter pruefen, damit man Dir keinen mist unterjubeln kann; und auf das  
                 leerzeichen als einzigen \*whitespace\* wuerde ich mich an Deiner stelle auch  
                 nicht verlassen wollen.  
                
                 ~~~javascript
              window.getElementsByClassName = function (className, element) {  
                
                   var gefunden = [];  
                
                 //if ((typeof className == "string") || (className instanceof String)) {  
                   if (className) { // fliegt raus bei: [undefined], [null], [false], 0, "".  
                
                   //element = ((element && ((typeof element.getElementsByTagName == "function") || ((typeof element.getElementsByTagName == "object") && !obj))) ? (element) : (document));  
                     element = ((element && element.getElementsByTagName) ? (element) : (document));  
                
                     var muster = new RegExp("(^|\\s+)" + String(className) + "($|\\s+)"); // typecast wenn nur ueber >>if (className) {<< geprueft  
                     var alles = element.getElementsByTagName("*");  
                     var i;
              

              ...

              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,

                Ich bleibe lieber bei meiner ursprünglichen Version von meiner Funktion,
                der ich eben einen optionalen zweiten Parameter mitgebe, der dann das
                aktuelle HTML-Element referenziert, innerhalb dessen ich die Nachfahrenknoten
                ermitteln lasse.

                eben, das ist durchaus der ansatz fuer schlankeren

                Nö; Die Prototype-Variante ist - abgesehen von den IE-Würgarounds (die man am Besten in externe Dateien auslagert und per CCs nur dem IE zugänglich macht) - auch nicht viel umfangreicher:

                HTMLElement.prototype.getElementsByClassName = function(klasse){  
                var alles = this.getElementsByTagName("*");}
                

                uebersichlicheren code

                Da muss ich dir widersprechen.

                document.getElementById("foo").getElementsByClassName("bar")[0];

                ist IMHO um einiges übersichtlicher als

                getElementsByClassName("bar",document.getElementById("foo"))[0];

                …weil es die richtige Reihenfolge der Referenzierung wiedergibt. Das Mag bei diesem Beispiel noch nicht so stark in's Gewicht fallen, aber wenn die Schachtelungen immer tiefer werden, blickt man irgendwann nicht mehr durch.

                mfg. Daniel

                1. gruss Daniel,

                  eben, das ist durchaus der ansatz fuer schlankeren

                  Nö; Die Prototype-Variante ist - abgesehen von den IE-Würgarounds ...

                  davon laesst sich nicht absehen, denn darum geht es, um *genau einen*
                     *einheitlichen* code.

                  ... auch nicht viel umfangreicher:

                  HTMLElement.prototype.getElementsByClassName = function(klasse){

                  var alles = this.getElementsByTagName("*");

                  }

                    
                     das hat ja auch niemand in abrede gestellt. ich selbst habe seit jahren  
                     erweiterungen in meiner code-ramschkiste, die auf prototypischen  
                     erweiterungen von DOM elementen und/oder dem einsatz von \_\_getter\_\_,  
                     \_\_setter\_\_ beruhen (z.b. fuer listen, collections, dictionaries ...).  
                    
                     die realitaet sieht aber anders aus, und nicht nur der msie unterstuetzt  
                     diese features - denn das sind sie nunmal - nicht. kein browserhersteller  
                     ist verpflichtet, die elemente des DOM wie native, durch den standard  
                     ECMA-262, festgelegte JavaScript-objekte zu implementieren.  
                    
                     nachdem ich das endlich akzeptiert hatte, habe ich nach anderen  
                     loesungen und loesungsansaetzen gesucht.  
                    
                    
                  
                  > > ... uebersichlicheren code  
                  >   
                  > Da muss ich dir widersprechen.  
                  >   
                  > `document.getElementById("foo").getElementsByClassName("bar")[0];`{:.language-javascript}  
                  >   
                  > ist IMHO um einiges übersichtlicher als  
                  >   
                  > `getElementsByClassName("bar",document.getElementById("foo"))[0];`{:.language-javascript}  
                  >   
                  > …weil es die richtige Reihenfolge der Referenzierung wiedergibt.  
                    
                     volle zustimmung - ich arbeite auch lieber mit dem punkt-operator.  
                    
                  
                  > Das Mag bei diesem Beispiel noch nicht so stark in's Gewicht fallen,  
                  > aber wenn die Schachtelungen immer tiefer werden, blickt man  
                  > irgendwann nicht mehr durch.  
                    
                     richtig, aber das trifft auch auf den von Dir beschriebene idealfall  
                     zu, wo es ebenfalls oft angebracht ist, solch langen referenzen  
                     voruebergehend einer lokalen variablen aufzubuerden.  
                     im uebrigen schaffen die grossen bibliotheken das von Dir kritisierte  
                     stilistische merkmal ebenfalls nicht aus der welt; und einige nur dann,  
                     solange man nicht den jeweils spezifischen namensraum verlaesst bzw.  
                     die dort drinnen geltenden konventionen (und es sind immer andere)  
                     bricht.  
                    
                     und genau aus diesen gruenden, und weil Felix' werkzeug \*nur\* ein  
                     ordentlicher schraubendreher und kein profiwerkzeugkoffer sein wollte,  
                     ist der von ihm eingeschlagene weg der fuer ihn direkt ins ziel fuehrende.  
                    
                    
                     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](http://javascript.crockford.com/)  
                    
                  ie:( fl:) br:> va:( ls:& fo:) rl:| n3;} n4:} ss:} de:µ js:} mo:? zu:]
                  
              2. Lieber peterS.,

                ~~~javascript

                window.getElementsByClassName = function (className, element) {

                var gefunden = [];

                //if ((typeof className == "string") || (className instanceof String)) {
                     if (className) { // fliegt raus bei: [undefined], [null], [false], 0, "".

                //element = ((element && ((typeof element.getElementsByTagName == "function") || ((typeof element.getElementsByTagName == "object") && !obj))) ? (element) : (document));
                       element = ((element && element.getElementsByTagName) ? (element) : (document));

                var muster = new RegExp("(^|\s+)" + String(className) + "($|\s+)"); // typecast wenn nur ueber >>if (className) {<< geprueft
                       var alles = element.getElementsByTagName("*");
                       var i;

                  
                WOW! ich kapiere nichteinmal die Hälfte! Wenn [meine größten Sorgen mit den Browserunterschieden](https://forum.selfhtml.org/?t=152550&m=992304) bei meiner neuesten Spielerei beseitigt sind, dann werde ich mir das aus dem Archiv holen und gehörig reinziehen - versprochen!  
                  
                Liebe Grüße aus [Ellwangen](http://www.ellwangen.de/),  
                  
                Felix Riesterer.
                
                -- 
                ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
                
        2. Hallo,

          Und wie macht man dann den IE gefügig?

          In der Praxis gar nicht - man nutzt Frameworks, die alle Elementobjekte, mit denen man arbeitet, individuell statt zentral on-the-fly mit solchen Zusatzmethoden ausstatten (Prototype, jQuery etc.).

          Mathias

          1. Lieber Mathias,

            man nutzt Frameworks, die alle Elementobjekte, mit denen man arbeitet, individuell statt zentral on-the-fly mit solchen Zusatzmethoden ausstatten (Prototype, jQuery etc.).

            OK, jetzt reicht's! So einen Schwachsinn tue ich mir nicht an. Dann doch lieber mit meinObjekt.getElementsByClassName(className, element)...

            Vielen Dank für Deine Hinweise!

            Liebe Grüße aus Ellwangen,

            Felix Riesterer.

            --
            ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
            1. OK, jetzt reicht's! So einen Schwachsinn tue ich mir nicht an. Dann doch lieber mit meinObjekt.getElementsByClassName(className, element)...

              Der "Schwachsinn" ist aber eine durchaus übliche vorgehensweise bei komplexeren Anwendungen. Deshalb gibt es ja diese Bibliotheken, damit du dich nicht mehr um diesen "Schwachsinn" kümmern musst.

              Struppi.

              --
              Javascript ist toll (Perl auch!)
              1. Hallo,

                Der "Schwachsinn" ist aber eine durchaus übliche vorgehensweise bei komplexeren Anwendungen. Deshalb gibt es ja diese Bibliotheken, damit du dich nicht mehr um diesen "Schwachsinn" kümmern musst.

                Genau. Es sollte auch erwähnt werden, dass die Bibliotheken auf Geschwindigkeit optimiert sind. Das heißt konkret, dass sie, wenn es der Browser erlaubt, XPath oder die Selectors-API verwenden. Dadurch können sie Standardoperationen wie getElementsByClassName extrem schnell umsetzen, weil sie auf getElementsByTagName("*"), das manuelle Durchlaufen der Knotenliste und auf das Vergleichen von className mittels regulären Ausdrücken verzichten.

                Mathias

      2. Hallo molily,

        Object.prototype.getElementsByClassName

        Wenn schon, dann HTMLElement.prototype, was aber IE bekanntlich auch nicht kann.

        Hmm, stimmt, hatte ich nicht getestet.

        Object.prototype zu erweitern ist nicht ohne und hat weitreichende Konsequenzen, daraufhin muss man jede for-in-Schleife mit einer hasOwnProperty-Abfrage versehen.

        Nun, mit dieser Konsequenz könnte ich leben, da ich so gut wie nie diese Art von Schleife benötige - soll aber nicht heißen, das dies alle so machen ;-)

        Also lieber Finger weg davon, wenns auch anders geht.

        Ich merks mir ;-)

        Mit freundlichem Gruß
        Micha

  4. Hallo Felix.

    ich brauche manchmal die Funktion document.getElementsByClassName(), die jedoch nicht im bisherigen Javascript-Sprachumfang implementiert ist.

    Du solltest dir bei Gelegenheit dazu auch Peter Seligers JS-Bibliothek anschauen.

    Einen schönen Dienstag noch.

    Gruß, Mathias

    --
    ie:% fl:| br:< va:) ls:& fo:) rl:( n4:~ ss:) de:] js:| mo:| zu:)
    debian/rules
    1. Lieber Mathias,

      Du solltest dir bei Gelegenheit dazu auch Peter Seligers JS-Bibliothek anschauen.

      von der habe ich auch schon gelesen, aber ich hätte es gerne selbst verstanden und geschrieben. Peters Bibliothek zu verwenden (die ich nicht wirklich verstehe!) würde bedeuten, mich auf Code zu verlassen, den ich nicht selbst geschrieben habe, und den ich im Zweifelsfalle nicht selbst erfolgreich debuggen könnte.

      Ich hätte es gerne selbst gekonnt (und verstanden!), wenn Du verstehst, was ich meine. :-)

      Liebe Grüße aus Ellwangen,

      Felix Riesterer.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
      1. gruss Felix

        ... aber ich hätte es gerne selbst verstanden und geschrieben.

        das ehrt Dich. und damit ich von diesem lob auch etwas abbekomme,
           gestehe ich, dass dieses *selbst* auch der meinereinige antrieb ist.

        Peters Bibliothek zu verwenden (die ich nicht wirklich verstehe!)

        ach komm, so kompliziert ist das ding gar nicht.

        unter anderem werden dem [[Array]]-konstruktor sowohl statische als
           auch prototypische accessoren und iteratoren beigebracht, sofern er
           diese noch nicht kennen sollte bzw. sobald ich der meinung bin, dass
           meine auslegung besser ist als die der mozilla.org.

        falls die (nicht instanziierbaren) *DOM-klassen* [[NodeList]] bzw.
           [[Node]] nicht existieren - keine ahnung, wie ich das korrekt
           beschreiben soll - kurz und gut, falls also weder ein wie auch
           immer geartetes [NodeList]- bzw. [Node]-objekt existiert, werden in
           einem der ersten schritte einfache objektinstanzen auf den globalen
           variablen [NodeList] bzw. [Node] erzeugt.

        sowohl das [document]-objekt als auch die jetzt existierenden beiden
           oben genannten werden nun um jeweil gleichlautende DOM-methoden
           erweitert, das problem anerkennend, dass es einfach keine vernuenftige
           und browseruebergreifend performante loesung dafuer gibt, DOM-objekte
           im nachhinein fuer selbstgestrickte methoden zu erwaermen.

        und genau dieses problem erwartet dich ja auch, wenn Du Deine eigene,
           unkompliziert an das [document]-objekt getackerte methode jetzt auch
           noch jedem einzelnen DOM-Knoten angedeihen lassen moechtest.

        weiterhin finde ich es problematisch, dass die browseruebergreifenden
           loesungen, die so tun, als ob sie genau dies leisteten, dann eben doch
           keine echten [NodeList]s oder [HTMLCollection]s zurueckliefern.
           das problem wird dann mit einer armada von geschwindigkeitshemmenden
           und codeaufblaehenden wrapper-objekten erschlagen oder einfach gleich
           ignoriert.

        und das sind bei weitem nicht alle gruende dafuer, warum der von mir
           favorisierte loesungsansatz ein voellig anderer ist.

        würde bedeuten, mich auf Code zu verlassen, den ich nicht selbst
        geschrieben habe, und den ich im Zweifelsfalle nicht selbst
        erfolgreich debuggen könnte.

        richtig!

        Du solltest dir bei Gelegenheit dazu auch Peter Seligers JS-Bibliothek
        anschauen.

        @all:
           im uebrigen sind mir keine weiteren erfahrungsberichte ueber den
           einsatz dieser script-pakete zugeflossen - die welt sowiso und
           auch das forum koennen also ganz gut ohne solchen kram leben.

        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:]