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

Documentos relacionados