Hertel_JavaScript Hilfe es wuchert
Transcrição
Hertel_JavaScript Hilfe es wuchert
JavaScript - Hilfe es wuchert! Komponenten in JavaScript Matthias Hertel, http://www.mathertel.de 0 Zielsetzung • Wiederverwendbarkeit von JavaScript Programmen ermöglichen • Lösungsmöglichkeit möglichst nahe an HTML und JavaScript (keine Meta-Ebene oder Ableitung aus Hochsprachen) • Clientseitige Komponenten für Web Anwendungen bauen. • Kapselung, Strukturierung und Wiederverwendbarkeit von clientseitiger Logik. • Vortrag wendet sich insbesondere an diejenigen, die selbst ein JavaScript-Framework bauen oder erweitern. 1 Agenda • • • • • • • • „Das Problem“ – oder „Die Motivation“ Was sind Behaviors Wie funktionieren JavaScript Behaviors Wir bauen ein Behavior – Schritt für Schritt Wie funktioniert das ? Browser Kompatibilität Memory Leaks Das Projekt Fragen ? – Bitte auch zwischendurch ! 2 Über mich Studium der Informatik an der Universität Karlsruhe (TH), Abschluss als DiplomInformatiker Ab 1991: Realisierung eines Fertigungssteuerungs Systems, Firma ADI Ab 1993: Realisierung eines Client-Server basierte PPS Systems (P2) unter Windows Ab 1999: Aufbau der Architektur und Realisierung eines auf Internet-, XML Technologien und WebServices basierten ERP Systems (P2plus), Firma AP. 2002 Gewinner des weltweiten Awards „.NET Application of the Year“ http://www.microsoft.com/presspass/press/2002/jul02/07132002FusionAwardsPR.mspx 2003, 2004 weitere Auszeichnungen der Software http://www.microsoft.com/germany/partner/isv/dotnetaward/default.mspx seit Oktober 2005: Leiter Anwendungsentwicklung Technologie bei der Deutschen Bank Bauspar AG, Frankfurt Weitere Tätigkeiten Veröffentlichungen in der Fachpresse und Vorträge auf Konferenzen Mitglied in der OpenAjax Alliance Kontakt: [email protected], http://www.mathertel.de 3 Was man so alles falsch machen kann. Die Motivation 4 Was ist hier „falsch“ ? <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN"> <html> <head> <!–- see Wuerfel_0.htm --> <title>Ein Würfel</title> </head> <body> <div id="Wuerfel" unselectable="on" style="border: solid 2px blue; cursor:pointer; width:40px; height:40px; background-color:#EEEEFF; font-size: 30px; padding:20px; text-align:center; overflow:hidden" onclick="Wuerfel.innerText = Math.floor(Math.random()*6)+1" >click</div> </body> </html> 5 Die Motivation JavaScript in Attributen: onclick="..." onselect="..." • Wird erst beim Ausführen kompiliert => keine Syntaxprüfung beim Laden der Seite • Script wird typischerweise durch Kopieren von einer anderen Stelle übernommen => Wildwuchs, nicht mehr wartbare Sourcen • Kompatibilitätsprobleme der Browser (noch immer) • Eigene Tag-Libraries "helfen" das Chaos zu vermeiden 6 Die Motivation JavaScript in <script> Blöcken: body.onload="..." function numberCheck() {...} http://www.google.de/search?hl=de&q=body+onload+conflict • Es kann nur Einen (Event-Funktion) geben. • Beim Laden der Seite werden keine Konflikte angezeigt. • Code Fragmente dieser Art werden typischerweise durch Kopieren von einer anderen Stelle übernommen => Wildwuchs, nicht mehr wartbare Sourcen • Eigene Tag-Libraries "helfen" nicht. – Das Problem ist JavaScript nicht HTML – JavaScript muss übergreifend organisiert werden. 7 Die Motivation JavaScript in Include-Dateien (*.js): • Der globale Namensraum existiert nur einmal. • Erweiterung des window Objekts. • Globale JavaScript Dateien wachsen ständig… – Ein Grab für "veraltete" Funktionen – Verwendungsnachweis ? – Keiner will da was ändern (Seiteneffekte) • Der große Vorteil: Der Browser kann diese Dateien cachen ! • Vorsicht auch bei Erweiterungen von JavaScript Objekten http://weblogs.asp.net/mschwarz/archive/2006/04/05/RemovedObject.prototype.extend-for-third_2D00_party-libraries.aspx 8 Die Motivation • Bilden von Komponenten auf dem richtigen Level • Parametrierbare Komponenten • Wiederverwendbarkeit, Unabhängigkeit, keine Namenskonflikte • Typische Situation in der Web 2.0 Ära 9 Woher die Vorgehensweise kommt. Proprietäre Behaviors 10 Proprietäre Behaviors • Lange bekannter Wunsch bei Entwicklern • Lösung im Internet Explorer: *.htc-Dateien http://msdn.microsoft.com/workshop/components/htc/reference/htcref.asp • Lösung im Firefox/Mozilla: *.xbl-Dateien http://www.mozilla.org/projects/xbl/xbl.html • Beide Lösungen liegen dem w3c vor (seit 1999 von Netscape und Microsoft) • keine Einigung, keine Recommendation :-( 11 Beispiel *.htc <event name="onFadeDone" id="FadeDone" /> <property name="duration" /> <property name="offStart" /> <method name="fadeo" /> <method name="doFade" /> <attach event="ondocumentready" handler="startOnLoad" /> <script> function startOnLoad() { if (offStart != null) { if (offStart == "") offStart = 0; fadeo(offStart); } } function fadeo(internalPause) { ... } function doFade() { ... } } </script> 12 Aus der XBL Spezifikation This specification describes the ability to map elements to script, event handlers, CSS, and more complex content models. This can be used to re-order and wrap content so that, for instance, simple HTML or XHTML markup can have complex CSS styles applied without requiring that the markup be polluted with multiple semantically neutral div elements. It can also be used to implement new DOM interfaces, and, in conjunction with other specifications, enables arbitrary tag sets to be implemented as widgets. For example, XBL could in theory be used to implement XForms. 13 Beispiel *.xbl (1) <binding id="slideshow"> <content> <xul:vbox flex="1"> <xul:deck xbl:inherits="selectedIndex" selectedIndex="0" flex="1"> <children/> </xul:deck> <xul:hbox> <xul:button xbl:inherits="label=previoustext" oncommand="parentNode.parentNode.parentNode.page--;"/> <xul:description flex="1"/> <xul:button xbl:inherits="label=nexttext" oncommand="parentNode.parentNode.parentNode.page++;"/> </xul:hbox> </xul:vbox> </content> <implementation> <constructor> var totalpages=this.childNodes.length; document.getAnonymousNodes(this)[0].childNodes[1].childNodes[1] .setAttribute("value",(this.page+1)+" of "+totalpages); </constructor> ... 14 Beispiel *.xbl (2) <property name="page" onget="return parseInt(document.getAnonymousNodes(this)[0].childNodes[0].getAttribute('selectedIndex' ));" onset="return this.setPage(val);"/> <method name="setPage"> <parameter name="newidx"/> <body> <![CDATA[ var thedeck=document.getAnonymousNodes(this)[0].childNodes[0]; var totalpages=this.childNodes.length; if (newidx<0) return 0; if (newidx>=totalpages) return totalpages; thedeck.setAttribute("selectedIndex",newidx); document.getAnonymousNodes(this)[0].childNodes[1].childNodes[1] .setAttribute("value",(newidx+1)+" of "+totalpages); return newidx; ]]> </body> </method> </implementation> </binding> 15 Anbindung über CSS • Anbindung von xbl: style="-moz-binding: url(notes.xml#default)" • Anbindung von htc: style="behavior: url(over.htc)“ • Problem: Cascadierung von orthogonalen Technologien • Auch möglich mit JavaScript Behaviors: http://bennolan.com/behaviour/ 16 Was der Behavior Ansatz löst (und was nicht). Behaviors - Definition 17 Was machen Behaviors • XML basierte, deklarative Erweiterung von Elementen • Attributen: Spezifikation von Default-Werten und Zugriffsmethoden • Methoden: JavaScript Funktionen • Events: JavaScript Event Handler • Content: weitere (innere HTML-) Elemente • Anbindung über CSS: -moz-binding: behavior: • nicht kompatibel ! 18 Was machen Behaviors Behaviors in JavaScript • JavaScript Behaviors definieren die Funktionalität einer Komponente • Diese wird an existierende HTML Objekte angebunden • JavaScript / HTML DOM bietet dafür die notwendigen Features: – Dynamic object extensibility (expando) – Function objects 19 JavaScript basierte Behaviors • JSON statt XML • Attribute, Methoden und Events • Laden von Behaviors in JavaScript implementiert • Keine inneren HTML Objekte • Einige Namenskonventionen • Keine globale Variablen 20 Innovation in HTML ? • Es ist keine eigene Innovation in HTML zu erwarten, denn XML hat (fast) eine Antwort auf diese Probleme: • Die Modularisierung von HTML. • Vision XHTML: XHTML = HTML (incl. Einhaltung der XML Regeln) • + namespaces + CSS + XForms + SVG • + weitere XML Standards (XLink, XML Events, ...) Die Mehrheit der installierten Browser können das heute nicht. 21 Schritt für Schritt Behavior Beispiel 22 Wir bauen ein Behavior (1) • Beispiel1: • Ein Würfel, ein Quadrat mit einer Zahl (1-6) id="Wuerfel" unselectable="on" style="border: solid 2px •<div bei neue Zahl blue;Klick: cursor: zufällige pointer; width:40px; height:40px; backgroundcolor:#EEEEFF; font-size: 40px; padding:20px 10px; text-align: center" onclick="Wuerfel.innerText = Math.floor(Math.random()*6)+1" ></div> 23 Wir bauen ein Behavior (1) • CSS auslagern • JSON Objekt zur Beschreibung der Funktionalität var WuerfelBehaviour = { onclick: function(evt) { evt = evt || window.event; evt.srcElement.innerText = Math.floor(Math.random()*6)+1; } } // WuerfelBehaviour • Kein Objektverweis ! • Laden / Anbinden des Behaviors an das HTML Objekt jcl.LoadBehaviour("Wuerfel1", WuerfelBehaviour); 24 Exkurs: JSON (JavaScript Object Notation) • Die Syntax (kurz): Primitive Datentypen: null "a" 12 34.56 true Arrays: ["a", "b", "c"] assoziative Objekte: { name1: value1, name2: value2, name3: value3 } • Mehr unter http://www.json.org/ und http://de.wikipedia.org/wiki/JSON andere Objekte: new Date() new Array(44) anonyme Funktionen: function (p) { return (p+1); } Kein Komma ! Der IE akzeptiert das an dieser Stelle nicht. 25 Wie JavaScript und HTML zusammengebunden werden. Oder Was jcl.LoadBehaviour macht . Behaviors an HTML 26 LoadBehaviour • Einfache Werte -> Vorbelegte Attribute • Namenskonvention: on___ -> Events • Funktionen -> Methoden von zu HTMLObjekten • Laufzeitunterstützung • Liste aller geladenen Behaviors aufbauen • Vererbung zwischen Behaviors Siehe auch prototype.extend, jQuery.extend 27 Attribute und Properties • Default-Werte im Behavior • Konkrete Werte im HTML-Objekt • FF macht einen Unterschied zwischen neuen HTML Attributen und durch JavaScript angehängte (expando) Properties! for (var n = 0; n < obj.attributes.length; n++) if (obj[obj.attributes[n].name] == null) obj[obj.attributes[n].name] = obj.attributes[n].value; 28 Methoden und Events • Im Prinzip sind Methoden und Events JavaScript Funktionen (Objekte) • Einfache Funktionen werden mit dem Objekt im Kontext aufgerufen • Event Funktionen müssen den Kontext des Objektes zugewiesen bekommen. • Events haben ein standardisiertes Argument (Event Objekt) Siehe auch prototype.bind 29 Events • Problem der Einbindung von Event Handlern: – <body onload="initKeys()"> – <script>body.onload=initMouse;</script> • Es kann nur Einen (solchen Handler) geben ! • Erkannte Design Schwäche von HTML+JavaScript • Lösung: – attachEvent() im IE – addEventListener() im Firefox • Namenskonvention: on{event} 30 Events • Das jeweilige Event Objekt ist inkompatibel – Siehe X-Browser Kompatibilitätslayer • Die Event-Objekt Übergabe ist unterschiedlich implementiert: – Als Parameter im Mozilla/Firefox – Als globales Element im Microsoft IE • Beim Laden von Behaviors wird das onclick: function(evt) { vereinheitlicht. evt = evt || window.event; ... } 31 Globale Events • Einige Events werden nur vom Dokument erzeugt oder sind nur dort sinnvoll abgreifbar • Beispiel: Mausbewegungen, Tastatureingaben • Lösung: Attach in init(), Detach in term() 32 Wir bauen ein Behavior (2) • Beispiel2: 2 Spalten mit einstellbarer Breite • Drag & Drop Mouse Events <div id="vboxtest" class="VBox" style="width: 608px; backgroundcolor: Yellow; padding: 1px; border: solid 1px navy"> <div style="float: left; width: 400px;"> <p>...</p> </div> <div style="float: left; width: 4px; margin-left: 1px; margin-right: 1px; cursor: e-resize;"> </div> <div style="float: left;> <p>...</p> </div> </div> 33 Wir bauen ein Behavior (2) • Problem: Mouse-Events passen nicht immer zum Objekt • Lösung: – jcl.AttachEvent(document, ... ) – evt.cancelBubble, evt.returnValue Emulationen • Saubere Trennung von event und objekt bezogenen Funktionen • Siehe VBoxDemo.htm und VBox.js in den Beispielen 34 Initialisierung/Terminierung • Die Initialisierung eines Behaviors kann erst dann durchgeführt werden, wenn die Attribute des HTML Objektes übertragen wurden. • Deshalb werden keine JavaScript-OO Klassen und Objekte verwendet. • .init() wird erst nach dem Laden der kompletten Seite aufgerufen. • .afterinit() wird erst dann aufgerufen wenn alle Komponenten funktionsfähig sind. • .term() vor dem Entladen der Seite 35 JavaScript: this • Die Referenz auf den aktuellen Kontext • obj.function() -> obj wird zum aktuellen Kontext • function() -> der Kontext bleibt. • In Events wird der Kontext anhand von bind() gesetzt. Siehe auch: • http://digitalweb.com/articles/scope_in_javascript/ • Buch „Ajax in Practice“ (Dave Crane, …) 36 JavaScript Controls 37 JavaScript Controls • Behaviors sind statisch – Können in ein *.js ausgelagert werden – Der Browser kann diese Dateien cachen – Wiederverwendbarkeit • Tag Libraries können serverseitig die immer noch komplexe HTML Erstellung abnehmen. – Komplex für Tag-Library Entwickler – Einfach für Web Seiten Entwickler 38 Schritt für Schritt 1. CSS auslagern 2. Grundlegene Funktionalität einbinden – <script src="jcl.js"></script> 3. Behavior programmieren 4. Behavior auslagern – Wiederverwendbarkeit ist erreicht 5. Tag Library oder User Control als Wrapper verwenden 39 Tipps und Tricks Browser Kompatibilität 40 Browser Kompatibilität Standards verwenden so gut es geht • getElementById() statt form.elementId • getElementsByTagName() statt window.all bzw. window.tags • parentNode statt parentElement • firstChild liefert auch #text nodes im FF • childNodes statt children • nie document.all (Performance Killer) • Alle Seiten im strict Modus • utf-8 Codierung für alle Dateien. 41 Browser Kompatibilität • Mozilla/Firefox und Safari bietet einen Mechanismus an um Property Zugriffe auf Objekte zu kontrollieren: String.prototype.__defineGetter__(propName, function) • HTML und JavaScript Objekte im Mozilla/Firefox haben eine gemeinsame Implementierung; HTMLElement.prototype ist verfügbar • Mächtiger Mechanismus um den Mozilla/Firefox zum IE kompatibel zu machen. Mehr unter • http://www.codeproject.com/jscript/crossbrowserjavasc ript.asp • und jcl.js in den Beispiel-Sourcen 42 Browser Kompatibilität • Beispiele: – – – – HTMLElement innerText (textContent) Eigenschaft von Objekten Event-Objekt XMLDocument • Besser ist es kompatible Funktionen zu verwenden ! • Einige proprietäre Erweiterungen sind sehr sinnvoll ! 43 Memory Leaks • Im Browser sind 2 unterschiedliche Objektverwaltungen aktiv: HTML-DOM und JavaScript • Circular References • Gegenmittel: Alle Referenzen zu HTML Objekten in der term() Funktion auf null setzen • Bis IE 6.0 ein echtes Problem http://www.codeproject.com/jscript/leakpatterns.asp http://msdn.microsoft.com/library/en-us/IETechCol/dnwebgen/ie_leak_patterns.asp http://outofhanwell.com/ieleak/index.php?title=Main_Page http://www.squarefree.com/2006/01/13/memory-leak-detection-tool/ 44 Wiederverwendbarkeit / Standardisierung • JavaScript Framework definieren – Selbst realisieren, zusammensuchen – Open Source – Kommerziell • Funktionsreiche, zur Applikation passende Elemente / Tags bauen. • Kommerzielle Libraries bieten eine Vielzahl (konkret unnötiger) Parameter an. • Nicht notwendig für einmal verwendete Objekte 45 Was man beim Einführen von AJAX berücksichtigen sollte. Das Projekt 46 Das Projekt • • • • • Wie mache ich mein Team AJAX fähig? Architekt als Vorreiter Entwickler müssen früh geschult werden Reduzierung der Komplexität bei Entwicklern Das Management muss früh überzeugt werden – No Deployment – Zeigen Sie Web 2.0 Applikationen • Die Zeit arbeitet für Sie • Die Phase der “Ernüchterung” kommt noch ! 47 Das Projekt • Was wollen wir erreichen – Mehr Funktionalität im Browser ohne RoundTrips – Komfort bei der Eingabe – Lokale Prüfungen (DatenTypen, Muss-Felder) – PopUps, Menues, ... • • • • Klärung von Nutzen mit den Fachbereichen Implementieren von Prototypen Definieren von eigenen Standard Tags Implementieren von Tag-Libraries 48 Andere JavaScript Behavior Implementierungen: • Beispiele: http://bennolan.com/behaviour/ http://www.ccs.neu.edu/home/dherman/javascript/behavi or/ http://prototype.conio.net/ http://jquery.com/ – Einbindung von Funktionalität über CSS ähnliche Rules – i.A. keine Einbindung in ein Server-Side Framework • Professionelle Frameworks verwenden diese Techniken. 49 Ressourcen • • • • Foliensatz Beispiel-Dateien jcl.js Aspects of AJAX Book Online http://www.mathertel.de/2007/aia 50 51