Ankündigung

Einklappen
Keine Ankündigung bisher.

JS: Einführung - Javascript im Schichtenmodell

Einklappen

Neue Werbung 2019

Einklappen
Dieses Thema ist geschlossen.
X
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • JS: Einführung - Javascript im Schichtenmodell

    Das nachfolgende Tutorial soll Euch anhand eines kleinen Beispiels die Verwendung von Javascript als behaviour layer näherbringen. Der Übersicht halber verzeiht mir bitte den aufs wesentliche reduzierten HTML Code. Zum Nachvollziehen bietet sich Firefox mit der Firebugerweiterung an, da sie auch nachträglich geänderte Attributwerte anzeigt.


    Empfohlene Grundlagen
    • HTML
      CSS
      Javascript Syntax
      JS Events + zugehörige HTML Attribute
      Dynamisches HTML über DOM Zugriff


    Aufgabenstellung

    Wir wollen als Beispiel ein einfaches Infofeld realisieren, das über ein Mausereignis an- und ausgeschaltet werden kann. Ein üblicher Ansatz wäre hier der folgende:

    toggleDiv.css:
    Code:
     .switcher {background-color:#bbb;
                margin:0;     }
     #Info     {display:none;
                background-color:#ff0;
                height:3em;width:20em;     }
    toggleDiv.js:
    Code:
    toggleDivArea = function (sID)
      {
      oElement = document.getElementById (sID);
      if (oElement.style.display=='none') oElement.style.display='block';
      else oElement.style.display='none';
      }
    Code:
    <html><head>
    <link rel="stylesheet" type="text/css" href="toggleDiv.css" />
    <script type="text/javascript" src="toggleDiv.js"></script>
    </head><body>
    
    <p class="switcher" onclick="toggleDivArea ('Info');">+ Schalter</p>
    <div id="Info">Unser Infofeld</div>
    
    </body></html>
    Das Schaltelement p ruft über ein onClick Ereignis die eigentliche Wechelfunktion auf. Dort wird auf das Infofeld über die ID zugegriffen und dann dessen CSS Eigenschaft 'display' geändert, was eine Sichtbar/Unsichtbarschaltung zur Folge hat. Der Übersicht halber wurde das An- und Ausschalten bereits in eine JS Funktion toggleDivArea ausgelagert. Die Schreibweise der Funktion weicht hier von dem Schema ab, das allgemein in JS (Einsteiger-)Lehrbüchern verwendet wird, wird uns aber später noch gute Dienste leisten.

    Die gezeigte Lösung weist einige Schwächen auf, die wir nachfolgend sukzessive auflösen wollen:
    • 1. Die verwendete Style Eigenschaft 'display' ist fest verdrahtet. Wollen wir das Infofeld später bspw. verkleinern statt ausblenden muß der Code der Funktion geändert werden. Die Funktion ist nicht mehr mehrfach verwendbar.
      2. Das onclick Ereignis bezieht sich auf eine feste ID, die bei Bedarf direkt im enthaltenen Javascript Code geändert werden muß.
      3. Das onclick Ereignis ist durch ein Attribut festgelegt. Wollen wir mehrere Infofenster gleichzeitig ändern, muß überall der Parameter angepaßt werden.


    Unser erklärtes Ziel

    Was mit CSS schon lange gang und gäbe ist, hält für Javascript erst langsam Einzug: die Abstraktion als eigene Ebene, den sogenannten 'behaviour layer'. Wie mit CSS die Formateigenschaften sollen über Attribute wie class und id mit Javascript funktionelle Eigenschaften definiert werden können. Unser obiges Beispiel könnte dann so aussehen:

    Code:
    <html><head>
    <link rel="stylesheet" type="text/css" href="toggleDiv.css">
    <script type="text/javascript" src="toggleDiv.js"></script>
    </head><body>
    
    <p class="switcher" tgg_target="Info">+ Schalter</p>
    <div id="Info">Unser Infofeld</div>
    
    </body></html>
    Der Unterschied erscheint zunächst subtil. Nehmen wir jedoch an, wir müßten die Daten in einer Datenbank speichern, so ist die Zuordnung Attribut-Wert bereits wesentlich einfacher geworden als die onClick Angabe im Ausgangsbeispiel. Noch ersichtlicher wird das ganze, wenn wir uns vorstellen, dass allein mit diesem Code auch mehrere Events eingerichtet werden könnten. Dazu aber später mehr.


    Schritt 1: Eine Grundlage

    Unser Ziel bietet schon mal die erste Hürde: JS stellt zwar die Funktionen getElementById, getElementsByName und getElementsByTagName bereit. Was wir jedoch gut gebrauchen könnten ist eine getElementsByClass Methode. Elements wohlgemerkt, denn das class Attribut kann und soll mehrfach vergeben werden. Und die bauen wir uns nun.

    Code:
    getElementsByClass = function (sClassName)
      {
      var aReturnElements = [];
    
      var oRegExpClass = new RegExp ('\\s*\\b' + sClassName + '\\b');
      var oElements = (document.all) 
                        ? document.all 
                        : document.getElementsByTagName ('*');
      for (var i = 0 ; i < oElements.length ; i++)
        {
        if (oRegExpClass.test (oElements[i].className)) aReturnElements.push (oElements[i]);
        }
    
      return (aReturnElements);
      }
    Die Funktion gibt eine Reihe von Referenzen auf Objekte zurück, die in einem Array gesammelt werden. Ausgangspunkt ist das document Objekt, dessen Unterobjekte in einer Schleife durchlaufen werden und dabei vermittels eines regulären Ausdrucks auf das Vorhandensein eines gegebenen Klassenattributwertes geprüft werden.
    Die Funktion ist übrigens eine abgeänderte Version von 'The Ultimate getElementsByClassName' [1], ist aber auch mannigfaltig anderswo im Netz zu finden.


    Schritt 2: Stil entwickeln

    Wir verabschieden uns von oElement.style.display='block' und abstrahieren. Wir führen statt dessen in unser bisheriges Stylesheet eine neue Formatklasse ein, die fortan von JS geschaltet wird. Für unser Beispiel reicht eine 'hidden' Klasse:

    toggleDiv.css:
    Code:
     .switcher {background-color:#bbb;
                margin:0;     }
     #Info     {background-color:#ff0;
                height:3em;width:20em;     }
     .hidden   {display:none;     }
    Natürlich muß dabei für #Info das display:none; entfernt werden, sonst würde unsere neu gesetzte Klassenformatierung keine Wirkung zeigen.
    An unserem HTML Code ändert sich nichts, JS muß jedoch angepaßt werden:

    toggleDiv.js:
    Code:
    toggleDivArea = function (sID , iStatus)
      {
      oElement = document.getElementById (sID);
      modifyClass (oElement , 'hidden');
      }
    
    modifyClass = function (oElement , sValue ,  iStatus)
      {
      var iStatus = iStatus || -1;
      var oRegExpClass = new RegExp ('\\s*\\b' + sValue + '\\b');
    
      if (-1 == iStatus) iStatus = ! oRegExpClass.test (oElement.className);
    
      switch (iStatus)
        {
        case true :
        case 1    :
        case '1'  :
          oElement.className += ' ' + sValue;
          break;
    
        default:
          oElement.className = oElement.className.replace (oRegExpClass , '');
          break;
        }
      }
    Wir führen eine neue Funktion modifyClass ein, die nichts weiter tut, als den Wert des class-Attributes eines via oElement referenzierten Objektes um einen String zu erweitern bzw. diesen wieder zu entfernen. Um die Funktion etwas praktischer zu gestalten, fügen wir noch den iStatus Parameter dazu, mit dem wir das Einfügen oder Entfernen über 1 bzw. 0 explizit setzen können. Ohne diese Angabe wird der Attributwert über einen regulären Ausdruck auf den entspr. String durchsucht und bei Nichtvorhandensein darum erweitert. Ist der String vorhanden, wird er dagegen aus der Attributangabe entfernt.


    Anregungen zur Erweiterung:
    • - modifyClass könnte einen weiteren String als Parameter erhalten, der anstelle des leeren Strings im default case eingesetzt wird.
      - toggleDivArea könnte einen zweiten modifyClass Aufruf enthalten, der je nach Ausgangslage (also nach gesetzten class Value bei Scriptaufruf) mit oder entgegengesetzt dem 'hidden' Wert gesetzt und entfernt wird.

    Schritt 3: Simon befiehlt

    Unser Grundgerüst steht. Nun geht es um die Layerfunktionalität des JS Codes. Bisher wurde die Aktion ja durch das onclick Attribut im HTML Code des p tags eingeleitet. Dazu muß man wissen, dass jedes dieser Events in JS auch so gesetzt werden kann: Objektbezug.Event = Funktion; also z.B.:
    Code:
    oElement.onclick = toggleDivArea;
    Die nächste Funktion entsteht:

    Code:
    addToggleEvent = function (oElement)
      {
      var sTargetIdentifier = 'tgg_target';
    
      var sTarget = oElement.getAttribute (sTargetIdentifier , false);
      oElement.removeAttribute (sTargetIdentifier , false);
    
      oElement.onclick = function ()  
        {
        toggleDivArea (sTarget);
        };
      }
    Über den Aufruf von addToggleEvent kann ich einen Elementbezug übergeben. Diesem Element wird dann die Eigenschaft onclick zugeordnet. Ein Mausklick auf das entspr. Element löst dann wie gewohnt den Div Wechsel aus. Genauso könnte man hier weitere Events zuordnen, bspw. onmouseover um eine Klasseneigenschaft für hover zu implementieren oder dergleichen.
    Da das noch nicht sehr komfortabel ist - schließlich muß ja vorher noch der Zugriff auf das Element erfolgen - erweitern wir unser JS um eine kleine Funktion, die diese Zuordnung einmalig für alle gewünschten Elemente übernimmt. Und hierbei kommt endlich unsere getElementsByClass Methode zum Einsatz. Wir werden unser Schalter-Element wahrscheinlich ohnehin später mit CSS formatieren, mit geeignetem Mauszeiger und einer Formatierung, die auf seine Funktion hinweist. Nichts liegt näher, als die dafür verwendete Klasse auch als Markierung für unsere JS Funktionalität einzusetzen. Es gilt also, alle Elemente mit der Klasseneigenschaft 'switcher' (siehe Ausgangsbeispiel) an die addToggleEvent Funktion zu übergeben. Und das geht so:

    Code:
    addToggleEvents = function ()
      {
      var sMarkUp  = 'switcher';
    
      var oElements = getElementsByClass (sMarkUp);
    
      var iLength = oElements.length;
      for(var iCnt = 0 ; iCnt < iLength ; iCnt++)
        {
        addToggleEvent (oElements[iCnt]);
        }
      }
    Thats it. Ein Aufruf von addToggleEvents erweitert unseren HTML Code um die gewünschte Wechsel-Funktionalität.

    Code:
    <html><head>
    <link rel="stylesheet" type="text/css" href="toggleDiv.css" />
    <script type="text/javascript" src="toggleDiv.js"></script>
    </head><body>
    
    <p class="switcher" tgg_target="Info">+ Schalter</p>
    <div id="Info">Unser Infofeld</div>
    
    <script type="text/javascript">
    
     addToggleEvents ();
    
    </script>
    
    </body></html>

    Anregungen zur Erweiterung:
    • - die fest zugewiesenen Attributbezeichner wie sTargetIdentifier können an einer zentralen Stelle des Scripts als globale Variablen außerhalb der Funktion gesetzt werden.
      - der Fall, dass ein tgg_target Attribut nicht gesetzt ist oder auf eine nicht existierende ID verweist, sollte mit einem return false abgefangen werden. Danach könnte das class Attribut um einen Bezeichner erweitert werden, der erst die CSS Formatierungen bereitstellt, die die Toggle Funktion signalisieren.
      - schließlich kann auch das auslösende Event selbst variabel gestaltet werden, z.B. auch über eine globale Variable oder sogar über einen Attribut-Wert im p Element. Hier verweise ich auf das zusammenfassende Scripting unten, wo ich das umgesetzt habe.


    Schritt 4: Viva Autonomia - Modularität

    Noch stört der Scriptaufruf am Ende. Schöner wäre doch, toggleDiv.js oben einzubinden und dabei schon automatisch die Toggle Funktion einzurichten. Das Problem ist dabei, dass alle Elemente bereits vorhanden sein müssen, die die onClick Event-Eigenschaft zugeordnet bekommen. Wir benötigen also einen Anstoß, wenn alle Elemente geladen sind. Genau das ermöglicht das window.onLoad Event. Eine Zeile in unserem toggleDiv.js genügt dafür:

    Code:
    window.onload = addToggleEvents;
    Toll oder? Und es geht noch besser.


    Schritt 5: Keine Streitigkeiten am Tisch!

    Die nächste und für dieses Tutorial letzte Frage wirft Drew McLellan in seinem Artikel Writing Responsible JavaScript[2] auf: JS als Layer - wunderbar, aber was passiert, wenn unser Konzept window.onload = addToggleEvents; auch in anderen JS 'Modulen' verfolgt wird? Jede Zuweisung a´la window.onload = ... wird die alte überschreiben und schließlich wird nur die Funktionalität des zuletzt eingebundenen JS Layers übrig bleiben.
    Gottlob gibts auch dafür eine Lösung. Als - man könnte sagen - Quasistandard hat sich folgendes Fragment von Simon Willison[3] herausgebildet, das ich lediglich in meine Variablenschreibweise umgemünzt habe:

    Code:
    addOnLoadEvent = function (mFunction)
      {
      var mOldOnLoad = window.onload;
      if (typeof window.onload != 'function' ) 
        {
        window.onload = mFunction;
        } 
      else 
        {
        window.onload = function () 
          {
          if (mOldOnLoad) mOldOnLoad ();
          mFunction ();
          }
        }
      }
    Kurz umrissen wird das zum Zeitpunkt gesetzte onLoad Ereignis ausgelesen. Ist es bisher undefiniert, wird es auf die neu gewünschte Funktion gesetzt, anderenfalls wird das Event einfach um die Funktion erweitert, indem die bisherige und die neu auszuführende Funktion in einem function Statement gekapselt und dem onLoad Event zugewiesen werden.

    Das macht unser Modul komplett. Statt egoistisch window.onload = addToggleEvents; zu benutzen, geben wir auch anderen Modulen die Freiheit window.onload zu nutzen und ändern den Aufruf in addOnLoadEvent (addToggleEvents); ab.


    Resultat (erweitert um einige Spirenzien)

    Code:
    <html><head>
    <link rel="stylesheet" type="text/css" href="toggleDiv.css" />
    <script type="text/javascript" src="toggleDiv.js"></script>
    </head><body>
    
    <p class="switcher" tgg_target="Info">+ Schalter</p>
    <div id="Info">Unser Infofeld</div>
    
    </body></html>
    toggleDiv.css:
    Code:
     .switcher {background-color:#bbb;
                margin:0;   }
     #Info     {background-color:#ff0;
                height:3em;width:20em;     }
     .hidden   {display:none;    }
    toggleDiv.js:
    Code:
    // onLoad Event hinzufügen - Funktion sollte als Core Methode in ein
    // separates externes JS
    
    addOnLoadEvent = function (mFunction)
      {
      var mOldOnLoad = window.onload;
      if (typeof window.onload != 'function' ) 
        {
        window.onload = mFunction;
        } 
      else 
        {
        window.onload = function () 
          {
          if (mOldOnLoad) mOldOnLoad ();
          mFunction ();
          }
        }
      }
    
    
    // Zugriff auf DOM Element über Klasseneigenschft - Funktion sollte als Core 
    // Methode in ein separates externes JS
    
    getElementsByClass = function (sClassName)
      {
      var aReturnElements = [];
    
      var oRegExpClass = new RegExp ('\\s*\\b' + sClassName + '\\b');
      var oElements = (document.all) 
                        ? document.all 
                        : document.getElementsByTagName ('*');
      for (var i = 0 ; i < oElements.length ; i++)
        {
        if (oRegExpClass.test (oElements[i].className)) aReturnElements.push (oElements[i]);
        }
    
      return (aReturnElements);
      }
    
    
    
    // Settings für die Umschaltfunktion
    
    sTgg_DefaultMarkUpAttribute  = 'switcher';
    sTgg_DefaultTargetIdentifier = 'tgg_target';
    sTgg_DefaultEvent            = 'click';
    
    
    
    toggleDivArea = function (sID , iStatus)
      {
      oElement = document.getElementById (sID);
      modifyClass (oElement , 'hidden');
      }
    
    
    modifyClass = function (oElement , sValue ,  iStatus)
      {
      var iStatus = iStatus || -1;
      var oRegExpClass = new RegExp ('\\s*\\b' + sValue + '\\b');
    
      if (-1 == iStatus) iStatus = ! oRegExpClass.test (oElement.className);
    
      switch (iStatus)
        {
        case true :
        case 1    :
        case '1'  :
          oElement.className += ' ' + sValue;
          break;
    
        default:
          oElement.className = oElement.className.replace (oRegExpClass , '');
          break;
        }
      }
    
    
    
    addToggleEvent = function (oElement , sTargetIdentifier)
      {
      var sTargetIdentifier = sTargetIdentifier || sTgg_DefaultTargetIdentifier;
    
      var sEvent  = sTgg_DefaultEvent;
      var sTarget = oElement.getAttribute (sTargetIdentifier , false);
      oElement.removeAttribute (sTargetIdentifier , false);
    
    
      if (oElement.addEventListener) 
        {
        oElement.addEventListener (sEvent.toLowerCase() , function ()  
          {
          toggleDivArea (sTarget);
          } , false);
        return (true);
        } 
      else 
        if (oElement.attachEvent) 
          {
          var mReturn = oElement.attachEvent('on' + sEvent.toLowerCase() , function ()  
            {
            toggleDivArea (sTarget);
            });
          return (mReturn);
          } 
        else 
          {
          return (false);
          }
      }
    
    
    addToggleEvents = function ()
      {
      var sMarkUp  = sMarkUp || sTgg_DefaultMarkUpAttribute;
    
      var oElements = getElementsByClass (sMarkUp);
    
      var iLength = oElements.length;
      for(var iCnt = 0 ; iCnt < iLength ; iCnt++)
        {
        addToggleEvent (oElements[iCnt]);
        }
      }
    
    
    // Funktionalität des Moduls einbinden
    
    addOnLoadEvent (addToggleEvents);

    Quellen

    [1] http://www.robertnyman.com/2005/11/0...tsbyclassname/
    [2] http://24ways.org/2006/writing-responsible-javascript
    [3] http://simonwillison.net/2004/May/26/addLoadEvent/

    Und jetzt seid ihr dran...
    --

    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


    --


  • #2
    Nachgereicht - das verbesserte addToggleEvent

    Im obigen Scripting zum Resultat wurde addToggleEvent im Vergleich zu den vorhergehenden Ausführungen stark verändert. Was dort veranstaltet wurde ähnelt dem Ziel, das wir schon für window.onload verfolgt haben: wie in addOnLoadEvent wurde hier allgemeingültig das mit sEvent bezeichnete Ereignis um eine weitere Funktion ergänzt, statt es einfach zu überschreiben. Die relativ aufwendige if Struktur dient - wie immer - der Befriedigung verschiedener Browser-Herangehensweisen an die Problemstellung; addEventListener bildet hier die von DOM Level 2 angebotene Zugriffsmethode, während der IE mittels attachEvent arbeitet.
    Die ganze Funktion entstand dann quasi aus einer Kombination aus der Funktionskapselung der addOnLoadEvent Methode und einem von Ulrike Häßler vorgestellten Scriptfragment 'Javascript: Event Listener' [4].


    Schritt 6: Eventzuweisung aufgebohrt

    Wenn man das eingangs beschrieben Modulkonzept für JS verwirklichen möchte, lässt sich schnell erkennen, dass die in addToggleEvent implementierte Verfahrensweise doch ruck zuck zu einem großen Overhead führt. Deshalb wollen wir hier noch einmal die Schere ansetzen und uns eine allgemeingültige Methode zum Erweitern der Eventeigenschaften eines Objektes schaffen.
    Hier können wir uns fast auf copy and paste beschränken: Unsere Funktion benötigt drei Parameter, eine Referenz auf das Objekt, den Bezeichner des einzurichtenden Events und die dabei auszuführende Funktion.

    Code:
    addEvent = function (oElement , sEvent , oFunction)
      {
      if (oElement.addEventListener) 
        {
        oElement.addEventListener (sEvent.toLowerCase() , function ()  
          {
          oFunction ();
          } , false);
        return (true);
        } 
      else 
        if (oElement.attachEvent) 
          {
          var mReturn = oElement.attachEvent('on' + sEvent.toLowerCase() , function ()  
            {
            oFunction ();
            });
          return (mReturn);
          } 
        else 
          {
          return (false);
          }
      }
    Die Funktion wird wieder als Parameter oFunction übergeben, dem vorher eine komplette Funktionsdefinition zugewiesen wurde. Diese Methodik haben wir weiter oben bei addOnLoadEvent (addToggleEvents); bereits gesehen.
    Eine Zuweisungsoperation sparen wir uns beim Aufruf, vielmehr schreiben wir gleich die gesamte Funktion als Parameter in addEvent's Parameterkette. Beispielhaft für addToggleEvent:

    Code:
    addToggleEvent = function (oElement , sTargetIdentifier)
      {
      var sTargetIdentifier = sTargetIdentifier || sTgg_DefaultTargetIdentifier;
    
      var sEvent  = sTgg_DefaultEvent;
      var sTarget = oElement.getAttribute (sTargetIdentifier , false);
      oElement.removeAttribute (sTargetIdentifier , false);
    
      addEvent (oElement , sEvent , function () 
        {
        toggleDivArea (sTarget);
        });
      }
    Schritt 7: 'Terminschwierigkeiten' - das Problem mit dem Event

    Bis jetzt klappt alles wunderbar. An die Grenzen stoßen wir, wenn wir das aktuell aufgetretene Eventobjekt auswerten möchten. Das wird dann notwendig, wenn wir auf bestimmte Tastaturereignisse reagieren wollen oder Mousekoordinaten ermitteln. Das Eventobjekt wird von JS wie von Zauberhand automatisch als Funktionsparameter übergeben. Das wirkt auf mich bis heute auch noch recht befremdlich. So kann ich ein per
    Code:
    oElement.onmousedown = trackMouse;
    zugewiesenes Eventereignis bei Auftreten in der trackMouse Funktion auswerten, indem ich in der Funktionsdefinition einfach den Parameter bereitstelle:

    Code:
    trackMouse = function (oEvent)
      {
      // non IE only
      alert (oEvent.layerX);
      }
    Defacto weiß ich bis dato nicht, wie ich oElement.onmousedown = ... hierbei z.B. einen eigenen Parameter mitgeben sollte.
    Glücklicherweise haben wir uns ja ohnehin für die oben beschriebene Auslagerung der Eventzuweisung entschieden und können dieses Problem so lösen:
    Code:
    addEvent (oElement , 'mousedown' , function (oEvent) { trackMouse (oEvent ,  'my Parameter'); });
    Auch innerhalb von addEvent müssen wir das Eventobjekt durchschleifen (man beachte die neu hinzugekommenen oEvent Parameter):

    Code:
    addEvent = function (oElement , sEvent , oFunction)
      {
      if (oElement.addEventListener) 
        {
        oElement.addEventListener (sEvent.toLowerCase() , function (oEvent)  
          {
          oFunction (oEvent);
          } , false);
        return (true);
        } 
      else 
        if (oElement.attachEvent) 
          {
          var mReturn = oElement.attachEvent('on' + sEvent.toLowerCase() , function (oEvent)  
            {
            oFunction (oEvent);
            });
          return (mReturn);
          } 
        else 
          {
          return (false);
          }
      }
    Wer dieses Tutorial aufmerksam gelesen hat und meine Ausführungen nachvollziehen kann, der sollte auch das letzte Fragment anwenden und sich damit recht einfach z.B. ein onmousemove Koordinatentracking zusammenbauen können.


    Quellen

    [4] http://www.mediaevent.de/javascript/event_listener.html
    .
    --

    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


    --

    Kommentar


    • #3
      Richtig gut, DANKE!
      "Nobody is as smart as everybody" - Kevin Kelly
      — The best things in life aren't things

      Kommentar


      • #4
        Warum nicht einfach mit jQuery uÄ?
        $('#Info').fadeOut();

        Kommentar


        • #5
          Damit man versteht was da eigentlich passiert.
          Ich muss zugegeben, dass ich mit Developer Version nicht allzu viel anfangen kann.
          Viele Zusammenhänge erschließen mir sich einfach nicht. Und
          Code:
          if (Statement)
              Expression;
          liest sich finde ich auch total schlecht.
          "Nobody is as smart as everybody" - Kevin Kelly
          — The best things in life aren't things

          Kommentar

          Lädt...
          X