SlideShare uma empresa Scribd logo
1 de 73
Baixar para ler offline
und Notes
                                EntwicklerCamp
                                 09. März 2010

Innovative Software-Lösungen.
www.assono.de
Bernd Hort

Diplom-Informatiker, Universität Hamburg

seit 1995 entwickle ich Lotus Notes
Anwendungen

IBM Certified Application Developer,
System Administrator & Instructor

Sprecher auf diversen Konferenzen &
Lotusphere 2008
!
!   bhort@assono.de
!   http://www.assono.de/blog
!   040/73 44 28-315
www.assono.de
Agenda

- Motivation

- Einführung in dojo

- Core

- Dijit

- DojoX

- Dojo und Notes

- Dojo und XPages

- Fragen & Antworten


www.assono.de
Das Rad
                nicht
                neu
                erfinden!

www.assono.de
Motivation – Warum dojo?

    - Open Source


    - Browserunterstützung


    - Vielfältige UI Elemente


    - Internationalisierung


    - Verwendung in XPages


www.assono.de
Dojo besteht aus drei Teilen




www.assono.de
core - base

- Browser-Erkennung

- JSON encoding / decoding

- Laden von Packages

- Eventhandling

- Animation effects

- AJAX

- CSS Utilities

- OOP Unterstützung

- Firebug Integration
www.assono.de
core – Ergänzung

- Drag & Drop

- I18N Support

- Datumsformatierung

- Zahlenformatierung

- String Utils

- Cookie Handling

- Extended Animations

- Back Button Handling


www.assono.de
dijit

- Oberflächen Elemente
  (interface widgets)

- „Theme“ Unterstützung

- Internationalisierung

- Keyboard Unterstützung




www.assono.de
dojoX

- „quasi“ experimentell -
  „The future, today“

- Vieles stabil und produktiv einsetzbar

- Charts

- SVG Unterstützung

- DojoX Offline – Integration mit Gears

- DojoX Widgets




www.assono.de
«Page»
dojo-Hello World
       11
Hello World
<html>
  <head>
    <title>My First Dojo App</title>
    <link rel="StyleSheet" type="text/css"                   Basis CSS
       href="js/dojo/dojo/resources/dojo.css">
    <link rel="StyleSheet" type="text/css"
       href="js/dojo/dijit/themes/tundra/tundra.css">       Theme CSS

    <script type="text/javascript">
      var djConfig = {
                                                        Basis Konfiguration
         baseScriptUri : "js/dojo/",                    muss vor dem Laden
         parseOnLoad : true,                            von dojo.js erfolgen!
         extraLocale: ['en-us', 'zh-cn']
      };
    </script>                                             dojo.js (Base)

    <script type="text/javascript" src="js/dojo/dojo/dojo.js"></script>
    <script language="JavaScript" type="text/javascript">
      dojo.require("dojo.parser");
      dojo.require("dijit.form.Button");                   Nachladen
      dojo.require("dijit._Calendar");                    von Packages
    </script>

  </head>


www.assono.de
Hello World
  <body class="tundra">
    <div style="position:relative;top:10px;left:10px;width:80%;">
      <button dojoType="dijit.form.Button" id="myButton">
        Press me, NOW!
        <script type="dojo/method" event="onClick">          Button
           alert('You pressed the button');
        </script>
      </button>
      <br><br>
      <table border="0"><tr>
        <td valign="top">
           <input id="calEnglish" dojoType="dijit._Calendar" lang="en-us" />
        </td>
        <td width="25">&nbsp;</td>                         Calender US
        <td valign="top"
           <input id="calChinese" dojoType="dijit._Calendar" lang="zh-cn" />
        </td>
      </table>
    </div>
                                                          Calender CN
  </body>
</html>




www.assono.de
Hello World - Erklärung
<link rel="StyleSheet" type="text/css"
    href="js/dojo/dojo/resources/dojo.css">

- Simples Basis CSS – nur Abstände und Font-
  Definitionen
<link rel="StyleSheet" type="text/css"
      href="js/dojo/dijit/themes/tundra/tundra.css">

- Tundra ist eines der mit gelieferten Themes




www.assono.de
Hello World - Erklärung
<script type="text/javascript">
   var djConfig = {
   baseScriptUri : "js/dojo/",
   parseOnLoad : true,
   extraLocale: ['en-us', 'zh-cn']
   };
</script>

- Basis Konfiguration von dojo
   - Erzeugt ein djConfig Objekt
   - Das Objekt wird beim Laden von dojo.js ausgewertet
   - Eigenschaft baseScriptUri: Verzeichnis von dojo
   - Eigenschaft parseOnLoad: Analyse des HTML Codes
   - Eigenschaft extraLocale: zusätzliche Sprachen laden
   - Muss vor dem Laden von dojo.js definiert werden


 www.assono.de
Hello World - Erklärung
<script type="text/javascript" src="js/dojo/dojo/dojo.js"></script>

- Laden von „base“

<script language="JavaScript" type="text/javascript">
  dojo.require("dojo.parser");
  dojo.require("dijit.form.Button");
  dojo.require("dijit._Calendar");
</script>

- Steuern welche Packages nachgeladen werden
   - dojo.parser: Parst den HTML Code auf der Suche
     nach dojo relevanten Elementen
   - dijit.form.Button: Lädt das „Button“ Widget
   - dijit._Calendar: Lädt das „Calender“ Widget



www.assono.de
Kritikpunkt – Nachladen von Packages

- Nachladen von Packages (dojo.require) bedeutet
  viele kleine Serveraufrufe

- Aus Performancegründen eigentlich nicht so gut

- Dojo bietet die Möglichkeit sich eine Datei mit allen
  benötigten Dateien zusammenzustellen
  “Custom Dojo Build“

- Blog-Eintrag von Tim Tripcony „I still have one
  concern about Dojo“
  http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-7LLHQP

- Tim Tripcony hat ein Tool „JSFactory“
  http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-7FUSZF

www.assono.de
Hello World - Erklärung
<button dojoType="dijit.form.Button" id="myButton">
  Press me, NOW!
  <script type="dojo/method" event="onClick">
     alert('You pressed the button');
  </script>
</button>


- Erzeugt einen Button
   - Parser erkennt dojoType
   - „dijit.form.Button“ lädt das Button Widget

- Registriert das Event „onClick“
   - Parser erkennt type=“dojo/method“




 www.assono.de
Hello World - Erklärung
<table border="0"><tr>
  <td valign="top">
    <input id="calEnglish" dojoType="dijit._Calendar" lang="en-us" />
  </td>
  <td width="25">&nbsp;</td>
  <td valign="top"
    <input id="calChinese" dojoType="dijit._Calendar" lang="zh-cn" />
  </td>
</table>

- Erzeugt zwei Kalenderobjekte
   - Parser erkennt dojoType
   - „dijit._Calendar“ lädt das Kalender Widget
   - über die Sprachangabe „lang“ wird die
     Vorgabesprache übersteuert



 www.assono.de
base – dojo.addOnLoad()

- Registriert eine Funktion, die aufgerufen
  wird, sobald das DOM geladen ist und
  alle Widgets intialisiert sind
- dojo.addOnLoad(functionPointer);
  Einfacher Funktionsaufruf
- dojo.addOnLoad(object,
  "functionName");
  Aufruf einer Methode eines Objektes
- dojo.addOnLoad(object, function()
  { /* ... */});
  Definition einer neuen Methode in dem
  Objekt

www.assono.de
base – CSS Klassen

- dojo.addClass(DomNode|NodeId,
  ClassName)
  fügt dem DOM-Knoten eine CSS-Klasse
  hinzu
- dojo.removeClass(DomNode|NodeId,
  ClassName)
  entfernt eine CSS-Klasse von einem
  DOM-Knoten
- dojo.hasClass(DomNode|NodeId,
  ClassName)
  prüft einem DOM-Knoten eine CSS-
  Klasse zugewiesen wurde

www.assono.de
base – DOM Knoten

- dojo.byId(NodeId)
  liefert den DOM-Knoten mit der
  gegebenen Id zurück
- dojo.clone(Object)
  klont ein Objekt, auch DOM-Knoten,
  inklusive aller Kinder
- dojo.isDescendant(ChildDomNode,
  ParentDomNode)
  prüft einem DOM-Knoten Kind eines
  anderen DOM-Knoten ist




www.assono.de
base – dojo.query() (1)

- dojo.query(CSS3-Selector)
  liefert alle DOM-Knoten, die dem CSS3-
  Selektor entsprechen
   - Klassenname, z.B. „.foo“
   - HTML-Elemente, z.B. „span“
   - CSS Hierarchien, z.B. „table div“
   - Direkte Kindelemente (>), z.B.
     „#tabular_data > div“
   - Universal Selektor (*)
   - Unmittelbar vorangestellte
     Geschwisterknoten (~)
   - vorangestellte Geschwisterknoten (+)

www.assono.de
base – dojo.query() (2)

- dojo.query(CSS3-Selector)
  Abfrage nach Attributen
   - [foo] Attribut ist vorhanden
   - [foo='bar'] Attributwert stimmt genau
     überein
   - [foo~='bar'] Attributwert stimmt mit
     einem Eintrag in der Liste der Werte
     überein
   - [foo^='bar'] Attributwert beginnt mit
   - [foo$='bar'] Attributwert endet mit
   - [foo*='bar'] Attributwert enthält


www.assono.de
base – dojo.query() (3)

- dojo.query(CSS3-Selector)
  Pseudoklassen
   - :first-child – erstes Kind
   - :last-child – letztes Kind
   - :only-child – nur ein Kind
   - :empty – kein Kind
   - :checked – aktivierte Radiobuttons &
     Checkboxes
   -   :nth-child(n) – n-te Kind
   -   :nth-child(even) – alle „geraden“ Kinder
   -   :nth-child(odd) – alle „ungeraden“ Kinder
   -   :not(...) - Umkehrungen

www.assono.de
base – OOP – declare

- dojo.declare(className: String,
  superclass: Function|Function[],
  props: Object)
  Erzeugt eine neue Klasse, die von einer
  oder mehreren Klassen erben kann und
  die Eigenschaftes eines Objektes
  übernehmen kann




www.assono.de
base – OOP – declare - Beispiel
function MyClass1() {
   var firstName = "Mick";
   this.getFirstName = function() {
       return firstName;
   }
}
function MyClass2() {
   var lastName = "Foley";
   this.getLastName = function() {
       return lastName;
   }
}
dojo.declare("de.entwicklerCamp.AnotherClass", [ MyClass1, MyClass2],
   { middleName : "William",
       getMiddleName : function() {
          return this.middleName;
        }
     }
  );
var o = new de.entwicklerCamp.AnotherClass();
  alert(o.getFirstName() + " " + o.getMiddleName() + " " +
     o.getLastName());



www.assono.de
base – OOP – extend

- dojo.extend(constructor: Object,
  props: Object...);
  Fügt die Eigenschaften und Methoden
  einer oder mehrerer Klassen zu einer
  Klasse hinzu (Prototypische Vererbung)




www.assono.de
base – OOP – extend - Beispiel
function MyClass1() {
  var firstName = "Mick";
  this.getFirstName = function() {
    return firstName;
  }
}
function MyClass2() {
  var lastName = "Foley";
  this.getLastName = function() {
    return lastName;
  }
}
function MyClass3() {
  this.sayName = function() {
    alert("I am " + this.getFirstName() + " " + this.getLastName());
  }
}
dojo.extend(MyClass3, new MyClass1(), new MyClass2());
var mc3 = new MyClass3();
mc3.sayName();




www.assono.de
base – Aspektorientierte Programmierung – connect

- Ruft eine Methode / Funktion auf, sobald
  ein Event ausgelöst wurde oder eine
  Methode eines anderen Objektes
  aufgerufen wurde.
  dojo.connect(object: Object|null,
  event: String, context: Object|
  null, method: String|Function);

- Verknüpfung mit DOM-Knoten
  dojo.connect(dojo.byId(„foo“),
  „onmouseover“, function(evt)
  {console.log(evt)});



www.assono.de
base – Aspektorientierte Programmierung – connect

- Das Event kann auch einfach ein
  Methodenaufruf eines anderen Objektes
  sein.
  function MyClass(){
    this.sayHello = function(inName){
      alert("Hello, " + inName)}
  }
  function AnotherClass(){
    this.echo = function(message){
      alert(message + " has been greeted.")}
  }
  foo = new MyClass();
  bar = new AnotherClass();
  var handle = dojo.connect(foo, "sayHello", bar,
  "echo");
  foo.sayHello ("EntwicklerCamp");




www.assono.de
base – AJAX

- dojo.xhr(method: String,
  args: dojo.__XhrArgs,
  hasBody: Boolean?);
  Startet eine AJAX Anfrage
- Unterstützte Methoden:
  “DELETE“, „GET“, „POST“ & „PUT“

- Alternative
   - dojo.xhrDelete(args: dojo.__XhrArgs);
   - dojo.xhrGet(args: dojo.__XhrArgs);
   - dojo.xhrPost(args: dojo.__XhrArgs);
   - dojo.xhrPut(args: dojo.__XhrArgs);


www.assono.de
base – XhrArgs (1)

- url:String
  Die URL für den Aufruf

- handleAs:String
  Format der Serverantwort
   - text (default)
   - json
   - json-comment-optional
   - json-comment-filtered
   - javascript
   - xml



www.assono.de
base – XhrArgs (2)

- form:DOMNode
  Die Werte des Formulars werden
  in der Form feld1=wert1&feld2=wert2&....
  übertragen
- content:Object
  Die Eigenschaften des Objektes werden in der Form
  eigenschaft1=wert1&eigenschaft2=wert2&....
  übertragen
- headers:Object
  Zusätzlicher HTTP Header
  Die Eigenschaften des Objektes werden
  als Name-Wert-Paare übertragen

www.assono.de
base – XhrArgs (3)

- load:Function
  Funktionsreferenz, die bei erfolgreicher
  Serverantwort aufgerufen wird
- error:Function
  Funktionsreferenz, die bei fehlerhafter
  Serverantwort aufgerufen wird
- handle:Function
  Funktionsreferenz, die bei jeder
  Serverantwort aufgerufen wird




www.assono.de
base – XhrArgs (4)

- sync:Boolean
  Synchronisierter Aufruf
  (Browser blockiert bis zur Antwort)
   - Vorgabe ist false

- preventCache:Boolean
  Bei true wird der Browser daran gehindert die
  Anfrage zu cachen

- timeout:Integer
  Millisekunden, die auf die Antwort gewartet wird vor
  Aufrufen der Fehlerfunktion



www.assono.de
base – Basis Animation

- dojo.animateProperty(args:
  dojo.__AnimArgs);
  Basis für alle Animationseffekte
- dojo.animateProperty({ node: node, duration:
  2000,
    properties: {
      width: { start: '200', end: '400',
          unit:"px" },
      height: { start:'200', end: '400',
          unit:"px" },
      paddingTop: { start:'5', end:'50',
          unit:"px" }
      }
  }).play();

www.assono.de
base – fadeIn & fadeOut

- Einblenden und Ausblenden
- dojo.fadeOut({node : "myDiv",
  duration : 2000}).play();
- dojo.fadeIn({node : "myDiv",
  duration : 2000}).play();
- function doFading() {
  dojo.fadeOut({node : "myDiv", duration :
  2000, onEnd : function() {
     dojo.fadeIn({node : "myDiv", duration :
          2000}).play();
        }
     }).play();
  }

www.assono.de
dojo.fx – Weitere Animationseffekte

- dojo.require("dojo.fx");
  Nachladen des fx-Packages
- dojo.fx.slideTo({ node: node, left:"40",
  top:"50", unit:"px" }).play();
  Verschiebt den DOM-Knoten von seiner aktuellen
  Position auf die angegebene Position
- dojo.fx.wipeIn({ node: node, duration:
  200).play();
  DOM-Knoten in einem Wischeffekt erscheinen lassen
- dojo.fx.wipeOut({ node: node, duration:
  200).play();
  DOM-Knoten in einem Wischeffekt verschwinden
  lassen
www.assono.de
dojo.back – Handling des Back.Buttons

- Für die meisten Anwender ist der
  “Zurück-Knopf“ der wichtigste Knopf

- dojo.back erlaubt das Setzen von Referenzpunkten
- dojo.require("dojo.back");
- dojo.back.setInitialState(state);
- dojo.back.init();
- dojo.back.addToHistory(state);
- var state = {
      back: function() { alert("Back was
  clicked!"); },
      forward: function() { alert("Forward was
  clicked!"); }};
www.assono.de
dojo.behavior – Event Handling

- Registrieren von Eventhandlern an
  beliebigen DOM-Knoten

- DOM-Knoten werden anhand von CSS3-Selektoren
  identifiziert (siehe auch dojo.query())
-   dojo.require("dojo.behavior");
    dojo.behavior.add({"#myDiv" : {
         found : function (elem) {
            alert("Found the div: " + elem);
         },
         onmouseover: function (evt) {
            alert("onMouseOver fired");
         },
         onmouseout: function (evt) {
            alert("onMouseOut fired");
         }
      }
     });
    dojo.behavior.apply();


www.assono.de
dojo.dnd – Drag & Drop

- Zwei Ansätze
   - Einfaches Verschieben von
     HTML-Elementen auf dem Bildschirm
   - Container-Definitionen zum Bestimmen
     von Quelle und Ziel

- Beide Ansätze sind sehr einfach umgesetzt und bis
  ins kleinste steuerbar




www.assono.de
dojo.dnd.movable

- dojo.require("dojo.dnd.movable");
  Nachladen des Drag&Drop-Packages
- <div dojoType="dojo.dnd.Moveable">
  Some Content</div>
  Die Angabe des dojoTypes führt automatisch dazu,
  dass das HTML-Element beliebig auf dem Bildschirm
  verschoben werden kann.




www.assono.de
dojo.dnd.movable – mit „Handle“

- Ein Kindelement innerhalb des zu
  bewegenden HTML-Elementes kann als
  “Griffpunkt“ definiert werden.
- <div dojoType="dojo.dnd.Moveable"
  handle="dragHandle">
    <div id="dragHandle"></div>
    <textarea>Dieser Text kann editiert werden
     </textarea>
  </div>




www.assono.de
dojo.dnd.Source – Einfache Containerdefinition

- dojo.require("dojo.dnd.Source");
  Nachladen des Drag&Drop-Packages

- Definition der Liste
  <div dojoType="dojo.dnd.Source"
  class="container">
   <div class="dojoDndItem">Item X</div>
   <div class="dojoDndItem">Item Y</div>
   <div class="dojoDndItem">Item Z</div>
  </div>

- Mit dem richtigen Stylesheet verbunden
  ergibt sich auch eine visuelle
  Unterstützung beim Verschieben

www.assono.de
Weitere dojo core Packages

- dojo.cldr – Berücksichtigung von
  Länderunterschieden

- dojo.colors – Farben

- dojo.currency – Behandlung von Währungen

- dojo.date – Datumsfunktionen

- dojo.i18n – Übersetzungshilfen

- dojo.io – AJAX-ähnliche Funktionen ohne XmlHttpRequest

- dojo.number – Formartieren und Parsen von Zahlen

- dojo.regexp – Reguläre Ausdrücke

-www.assono.de
   dojo.string – Stringfunktionen
dijit - Einführung

- Dijit bezeichnet zwei Dinge
  - Das Widget Framework basierend
     auf den base und core Elementen
  - Ein einzelnes Widget wird auch als
     dijit bezeichnet

- Dijits sind voll „theme-able“ - können im Aussehen
  angepasst werden
   - Gewünschtes „Theme“ als CSS einbinden
   - <body class=“{Theme}“>
   - Beliebtestes „Theme“ ist „Tundra“



www.assono.de
Zwei Arten dijits einzubinden

- Dijits können auf zwei Arten
  eingebunden werden
   - Deklarativ
   - Programmatisch

- Beim deklarativen Ansatz wird der HTML-Code nach
  Attributen „dojoType“ abgesucht

- Gefundene Elemente werden automatisch um die
  notwendigen JavaScript-Aufrufe ergänzt

- Vorsicht! HTML Validierungs-Services melden den
  HTML-Code als nicht valide!


www.assono.de
Dijits deklarativ einbinden

- var djConfig = {
     baseScriptUri : "js/dojo/",
     parseOnLoad : true
  };
  Konfiguration zum Parsen des HTML-Codes
  beim Laden
- dojo.require("dojo.parser");
  Notwendiges Package zum Parsen
- dojo.require("dijit.form.Button");
  Das zum dijit gehörige Package laden
- <button dojoType="dijit.form.Button">ok</
  button>
  Dojo Attribute hinzufügen
www.assono.de
Dijit programmatisch einbinden

- dojo.require("dijit.form.Button");
  Das zum dijit gehörige Package laden
- var myDijit =
  new dijit.form.Button(
     {label : "Ok"}
  );
  dojo.byId("divButton").appendChild
  (myDijit.domNode);

- Der programmatische Ansatz ist der performantere
  Ansatz.
   - Nur bei großen HTML-Dokumenten wichtig
   - Oder bei hoch dynamischen Webseiten

www.assono.de
Zugriff auf dijits

- Jedes dijit wird vom dijit Manager
  verwaltet

- Jedes dijit hat eine eindeutige Id
   - Entweder manuell definiert
   - Oder automatisch generiert

- Die Methode dijit.byId(<someID>); liefert das dijit
  Objekt zurück

- Nicht zu verwechseln mit dojo.byId(<someID>);
   - Die Methode liefert den DOM-Knoten zurück



www.assono.de
dijit Methoden

Methode              Beschreibung

buildRendering       Konstruiert die visuelle Repräsentation
connect              Verbindet ein Object / Event mit
                     entsprechenden Methoden des dijit und
                     registriert für disconnect()

create               Startet den Lebenszyklus des dijits
destroy              Zerstört das dijit, lässt aber die
                     Kindelemente intakt
destroyDescendants   Zerstört alle Kindelemente rekursiv
destroyRecursive     Zerstört rekursiv das dijit und alle
                     Kindelemente

www.assono.de
dijit Methoden

Methode            Beschreibung

destroyRendering   Entfernt alle DOM-Knoten des dijit
disconnect         Löst die Verbindungen zu registrierten
                   Objekten / Events

getDescandants     Liefert alle Kindelemente
isFocusable        Ermittelt ob das dijit auswählbar ist
isLeftToRight      Ermittelt die Leserichtung
onBlur             Wird aufgerufen, wenn das dijit den Fokus
                   verliert

onClose            Wird aufgerufen, wenn das dijit zerstört
                   wird

www.assono.de
dijit Methoden

Methode              Beschreibung

onFocus              Wird aufgerufen, wenn das dijit den Fokus
                     erhält
postCreate           Wird aufgerufen, wenn die DOM-Knoten
                     des dijits erzeugt wurden

postMixInProperties Wird aufgerufen, nachdem alle Parameter
                    verarbeitet wurde, aber bevor die DOM-
                    Knoten erzeugt werden
setAttrbute          Setzt HTML Attribute direkt
startUp              Wird aufgerufen, nachdem alle dijit Kinder
                     erzeugt wurden, aber bevor sie dargestellt
                     werden


www.assono.de
dijit Attribute

Attribut          Beschreibung

attributeMap      Liste aller Attribute, vornehmlich HTML
                  Attribute
class             HTML Klassen Attribute
id                Die ID des dijit
lang              Die Sprache – erlaubt das Übersteuern
                  der automatisch bestimmten Sprache
srcNodeRef        Referenz auf den DOM-Knoten mit dem
                  dojoType Attribute
                  Der DOM-Knoten wird häufig ersetzt.
style             Die HTML Style Attribute


www.assono.de
dijit.form.NumberTextBox

- Widget für die Formatierung von
  Zahlenangaben

- Einbindung
  dojo.require
  ("dijit.form.NumberTextBox")
  <input dojoType="dijit.form.NumberTextBox" >

- Speichert Zahlenangabe mit „.“ als
  Dezimaltrennzeichen

- In der Standardausführung können die eingegebenen
  Werte nicht von Domino verarbeitet werden.
  => dijitDominoPatch.js

www.assono.de
dijit.form.CurrencyTextBox

- Widget für die Formatierung von
  Währungsangaben

- Einbindung
  dojo.require
  ("dijit.form.CurrencyTextBox")
  <input dojoType="dijit.form.CurrencyTextBox"
  currency="EUR">

- Speichert Zahlenangabe mit „.“ als
  Dezimaltrennzeichen

- In der Standardausführung können die eingegebenen
  Werte nicht von Domino verarbeitet werden.
  => dijitDominoPatch.js
www.assono.de
dijit.form.DateTextBox

- Widget für die Datumsauswahl

- Einbindung
  dojo.require
  ("dijit.form.DateTextBox")
  <input dojoType="dijit.form.DateTextBox" >

- Speichert Datumsangabe im Format
  [Jahr]-[Monat]-[Tag]

- In der Standardausführung können die eingegebenen
  Werte nicht von Domino verarbeitet werden.
  => dijitDominoPatch.js


www.assono.de
dijit.form.TimeTextBox

- Widget für die Zeitauswahl

- Einbindung
  dojo.require
  ("dijit.form.TimeTextBox")
  <input dojoType="dijit.form.TimeTextBox" >

- Speichert Zeitangabe im Format
  T[Stunden(24h-Basis)]:[Minuten]:[Sekunden]

- In der Standardausführung können die eingegebenen
  Werte nicht von Domino verarbeitet werden.
  => dijitDominoPatch.js


www.assono.de
dijitDominoPatch.js

- Patch im Entwicklungsstadium

- Wandelt Inputfelder vor der Initialisierung von dojo in
  das richtige Format um.

- Formatiert die Eingabe vor der Übertragung auf den
  Domino Server wieder in das von Domino erwartete
  Format um.

- Benutzung ohne Gewähr!




www.assono.de
dijitDominoPatch.js - Initailisierung

- Anpassung djConfig
  var djConfig = {
      afterOnLoad : true,
      parseOnLoad : false
  };

- Aufruf von
  onload="textBoxDominoLoadPatch();"

- Die Funktion untersucht alle Input-Elemente auf das
  Attribut „dojoType“

- Am Ende der Funktion wird mit
  dojo.parser.parse();
  der Parser manuell aufgerufen.
www.assono.de
dijitDominoPatch.js – Speichern (1)

- Mit dojo.connect mit dem onSubmit-Event verbinden
  dojo.connect(document.forms[0], "onsubmit",
  textBoxDominoSubmitPatch);

- Alle auf der Webseite registrierten Widgets
  untersuchen
  dijit.registry.forEach(function(widget,
  index, hash){...}

- Bei entsprechenden Widgets mit
  dojo.query(„input“, widget.domNode)
  die Input-Felder suchen.



www.assono.de
dijitDominoPatch.js – Speichern (2)

- Mit dojo.style() nach dem versteckten Input-Element
  suchen
  dojo.style(node, "display") == "none"

- Den Inhalt neu formatieren
  node.value = node.value.replace(/^(.*)-(.*)-
  (.*)$/g, "$3.$2.$1");




www.assono.de
dijit.form.ComboBox

- Widget für die Zeitauswahl

- Einbindung
  dojo.require
  ("dijit.form.ComboBox")
  <input dojoType="dijit.form.ComboBox" >

- Einfügen auch neuer Werte!

- Notesfeld „Dialogliste“
  Option „Neue Werte zulassen“ deaktivieren

- In der Auswahlliste „Formel verwenden“ und
  gespeicherten Wert hinzufügen
  @Trim(@Unique("Category A" : "Category B" : "Category C" :
  comboboxfield))

www.assono.de
dijit.form.Slider

- Widget für die Eingabe einer Zahl
  über einen Slider

- Beispiel, wo es sinnvoller ist das Widget
  über JavaScript einzubinden

- Platzhalter-Div mit ID an gewünschter Stelle
  positionieren

- Das Input-Element zur einfacheren
  Ansprache auch mit einer ID versehen




www.assono.de
dijit.form.Slider - Code(1)

- Zunächst den Vorgabewert bestimmen
  var defaultValue = 10;

- Dann den aktuellen Wert aus dem
  Input-Element bestimmen
  if (dojo.byId("horzsliderfield").value != ""){
    defaultValue =
      dojo.byId("horzsliderfield").
      value.replace(/,/g, ".");}

- Das value.replace ist notwendig, weil in dem Input-
  Element das Dezimaltrennzeichen ein Komma ist,
  aber ein Punkt erwartet wird.



www.assono.de
dijit.form.Slider - Code(2)

- Den Platzhalter-Knoten einer Variablen
  zuweisen
  var sliderNode = dojo.byId("slider");

- Neues Sliderobjekt erzeugen und an
  Platzhalter-Div anbinden
  var slider = new dijit.form.HorizontalSlider({
        name: "slider",
        value: defaultValue,
        minimum: 10,
        maximum: 60,
        intermediateChanges: true,
        style: "width:300px;",
        onChange: function(value){                 Funktion zum Aktualisieren
          var currentValue = value+"";             des Input-Elementes
          dojo.byId("horzsliderfield").value =
             currentValue.replace(/./g, ",");
        }
    }, sliderNode);

www.assono.de
dijit.form.Slider - Code(3)

- Neues Div erzeugen und an
  das Slider-Div als Kind anhängen
  var rulesNode = document.createElement('div');
  sliderNode.appendChild(rulesNode);


- Neues Sliderruler erzeugen und an neuen Dom-
  Knoten anbinden
  var sliderRules = new dijit.form.HorizontalRule({
          count:11,
          style:"width:5px;"
      }, rulesNode);




www.assono.de
DojoX - Charting

- Definition des Chart nur über
  JavaScript möglich

- Erwartet als Daten ein Array von Objekten
  mit den Werten

- Bestimmen der Werte über ein WebQueryOpen-
  Agent, der entsprechenden JavaScript-Code generiert
  und ein Feld „ComputedForDisplay“ speichert

- Im „HTML Head Content“ den Feldinhalt in
  JavaScript-Variable schreiben



www.assono.de
Ressourcen

  Offizielle Webseite
  http://www.dojotoolkit.org

  API Dokumentation
  http://api.dojotoolkit.org

  Demos
  http://demos.dojotoolkit.org

  DojoCampus
  http://dojocampus.org/

  Dojo Dokumentation
  http://docs.dojocampus.org/

  Alte Webseite
  http://o.dojotoolkit.org

www.assono.de
Ressourcen

- OpenNTF CodeBin - Dojo - Easy As 123
  http://www.openntf.org/Projects/codebin/codebin.nsf/0/
  A2A3F3DB69E21F2A8625740E005B8EC9

- Dojomino – Dojo Domino Framework
  http://dojomino.com/

- Sitepen Labs Dojo
  http://o.sitepen.com/labs/dojo.php

- Dojo Toolbox – Adobe AIR Anwendung mit Offline API
  http://o.sitepen.com/labs/toolbox/




www.assono.de
Bücher

- Frank W. Zammetti
  “Practical Dojo Projects“
  Apress Verlag




- Matthew A. Russell
  “Dojo – The Definitive Guide“
  O´Reilly Verlag




www.assono.de
Fragen?

jetzt stellen – oder später:

    bhort@assono.de
    http://www.assono.de/blog
    040/73 44 28-315


Folien & Beispieldatenbank unter
http://www.assono.de/blog/d6plinks/
EntwicklerCamp-2010-dojo



www.assono.de

Mais conteúdo relacionado

Destaque

Taking themes to the next level
Taking themes to the next levelTaking themes to the next level
Taking themes to the next leveldominion
 
Integrating Domino Data with DECS, DCRs, and LC/LSX
Integrating Domino Data with DECS, DCRs, and LC/LSXIntegrating Domino Data with DECS, DCRs, and LC/LSX
Integrating Domino Data with DECS, DCRs, and LC/LSXdominion
 
DXL: Working with Domino Data in XML
DXL: Working with Domino Data in XMLDXL: Working with Domino Data in XML
DXL: Working with Domino Data in XMLdominion
 
Advanced CSS for Domino Web
Advanced CSS for Domino WebAdvanced CSS for Domino Web
Advanced CSS for Domino Webdominion
 
H4 Lab 02 X Page Advanced
H4 Lab 02   X Page AdvancedH4 Lab 02   X Page Advanced
H4 Lab 02 X Page Advanceddominion
 
Aussie outback
Aussie outbackAussie outback
Aussie outbackdominion
 
Converting LotusScript Agents to Java Agents
Converting LotusScript Agents to Java AgentsConverting LotusScript Agents to Java Agents
Converting LotusScript Agents to Java Agentsdominion
 

Destaque (7)

Taking themes to the next level
Taking themes to the next levelTaking themes to the next level
Taking themes to the next level
 
Integrating Domino Data with DECS, DCRs, and LC/LSX
Integrating Domino Data with DECS, DCRs, and LC/LSXIntegrating Domino Data with DECS, DCRs, and LC/LSX
Integrating Domino Data with DECS, DCRs, and LC/LSX
 
DXL: Working with Domino Data in XML
DXL: Working with Domino Data in XMLDXL: Working with Domino Data in XML
DXL: Working with Domino Data in XML
 
Advanced CSS for Domino Web
Advanced CSS for Domino WebAdvanced CSS for Domino Web
Advanced CSS for Domino Web
 
H4 Lab 02 X Page Advanced
H4 Lab 02   X Page AdvancedH4 Lab 02   X Page Advanced
H4 Lab 02 X Page Advanced
 
Aussie outback
Aussie outbackAussie outback
Aussie outback
 
Converting LotusScript Agents to Java Agents
Converting LotusScript Agents to Java AgentsConverting LotusScript Agents to Java Agents
Converting LotusScript Agents to Java Agents
 

Semelhante a Dojo Und Notes

Javascript auf Client und Server mit node.js - webtech 2010
Javascript auf Client und Server mit node.js - webtech 2010Javascript auf Client und Server mit node.js - webtech 2010
Javascript auf Client und Server mit node.js - webtech 2010Dirk Ginader
 
Dokumentation schreiben kann spass machen
Dokumentation schreiben kann spass machenDokumentation schreiben kann spass machen
Dokumentation schreiben kann spass machenSebastian Hempel
 
Die Zukunft der Webstandards - Webinale 31.05.2010
Die Zukunft der Webstandards - Webinale 31.05.2010Die Zukunft der Webstandards - Webinale 31.05.2010
Die Zukunft der Webstandards - Webinale 31.05.2010Patrick Lauke
 
App Entwicklung mit Appcelerator Titanium - MTC 2014
App Entwicklung mit Appcelerator Titanium - MTC 2014App Entwicklung mit Appcelerator Titanium - MTC 2014
App Entwicklung mit Appcelerator Titanium - MTC 2014Marcel Pociot
 
Einführung in die webOS Programmierung
Einführung in die webOS ProgrammierungEinführung in die webOS Programmierung
Einführung in die webOS ProgrammierungMarkus Leutwyler
 
Mit jQTouch auf's iPhone & Android
Mit jQTouch auf's iPhone & AndroidMit jQTouch auf's iPhone & Android
Mit jQTouch auf's iPhone & AndroidBjörn Wibben
 
Web 2.0 Mit Der Yahoo User Interface Library
Web 2.0 Mit Der Yahoo User Interface LibraryWeb 2.0 Mit Der Yahoo User Interface Library
Web 2.0 Mit Der Yahoo User Interface LibraryStephan Schmidt
 
I thought you were my friend!
I thought you were my friend!I thought you were my friend!
I thought you were my friend!Mario Heiderich
 
Schnelle Winkel: 10x schnellere Webapps mit AngularJS und JEE
Schnelle Winkel: 10x schnellere Webapps mit AngularJS und JEESchnelle Winkel: 10x schnellere Webapps mit AngularJS und JEE
Schnelle Winkel: 10x schnellere Webapps mit AngularJS und JEEBenjamin Schmid
 
Microservices mit Rust
Microservices mit RustMicroservices mit Rust
Microservices mit RustJens Siebert
 
Mobile Webentwicklung mit HTML5
Mobile Webentwicklung mit HTML5Mobile Webentwicklung mit HTML5
Mobile Webentwicklung mit HTML5kkramhoeft
 
Christian heilmann html 5 - das web und der browser als platform
Christian heilmann   html 5 - das web und der browser als platformChristian heilmann   html 5 - das web und der browser als platform
Christian heilmann html 5 - das web und der browser als platformChristian Heilmann
 
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDBBack to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDBMongoDB
 
jQueryMobile mit Extbase/Fluid
jQueryMobile mit Extbase/FluidjQueryMobile mit Extbase/Fluid
jQueryMobile mit Extbase/FluidPeter Schuhmann
 
German: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptGerman: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptRalf Schwoebel
 
E2E Tests mit PHP
E2E Tests mit PHPE2E Tests mit PHP
E2E Tests mit PHPkmhusseini
 

Semelhante a Dojo Und Notes (20)

Javascript auf Client und Server mit node.js - webtech 2010
Javascript auf Client und Server mit node.js - webtech 2010Javascript auf Client und Server mit node.js - webtech 2010
Javascript auf Client und Server mit node.js - webtech 2010
 
Dokumentation schreiben kann spass machen
Dokumentation schreiben kann spass machenDokumentation schreiben kann spass machen
Dokumentation schreiben kann spass machen
 
Die Zukunft der Webstandards - Webinale 31.05.2010
Die Zukunft der Webstandards - Webinale 31.05.2010Die Zukunft der Webstandards - Webinale 31.05.2010
Die Zukunft der Webstandards - Webinale 31.05.2010
 
Hdc2012 cordova-präsi
Hdc2012 cordova-präsiHdc2012 cordova-präsi
Hdc2012 cordova-präsi
 
App Entwicklung mit Appcelerator Titanium - MTC 2014
App Entwicklung mit Appcelerator Titanium - MTC 2014App Entwicklung mit Appcelerator Titanium - MTC 2014
App Entwicklung mit Appcelerator Titanium - MTC 2014
 
Einführung in die webOS Programmierung
Einführung in die webOS ProgrammierungEinführung in die webOS Programmierung
Einführung in die webOS Programmierung
 
Einführung in React
Einführung in ReactEinführung in React
Einführung in React
 
Mit jQTouch auf's iPhone & Android
Mit jQTouch auf's iPhone & AndroidMit jQTouch auf's iPhone & Android
Mit jQTouch auf's iPhone & Android
 
HTML5
HTML5HTML5
HTML5
 
Web 2.0 Mit Der Yahoo User Interface Library
Web 2.0 Mit Der Yahoo User Interface LibraryWeb 2.0 Mit Der Yahoo User Interface Library
Web 2.0 Mit Der Yahoo User Interface Library
 
I thought you were my friend!
I thought you were my friend!I thought you were my friend!
I thought you were my friend!
 
Schnelle Winkel: 10x schnellere Webapps mit AngularJS und JEE
Schnelle Winkel: 10x schnellere Webapps mit AngularJS und JEESchnelle Winkel: 10x schnellere Webapps mit AngularJS und JEE
Schnelle Winkel: 10x schnellere Webapps mit AngularJS und JEE
 
Microservices mit Rust
Microservices mit RustMicroservices mit Rust
Microservices mit Rust
 
Mobile Webentwicklung mit HTML5
Mobile Webentwicklung mit HTML5Mobile Webentwicklung mit HTML5
Mobile Webentwicklung mit HTML5
 
Einfuehrung in ExtJS 4
Einfuehrung in ExtJS 4Einfuehrung in ExtJS 4
Einfuehrung in ExtJS 4
 
Christian heilmann html 5 - das web und der browser als platform
Christian heilmann   html 5 - das web und der browser als platformChristian heilmann   html 5 - das web und der browser als platform
Christian heilmann html 5 - das web und der browser als platform
 
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDBBack to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
Back to Basics German 2: Erstellen Sie Ihre erste Anwendung in MongoDB
 
jQueryMobile mit Extbase/Fluid
jQueryMobile mit Extbase/FluidjQueryMobile mit Extbase/Fluid
jQueryMobile mit Extbase/Fluid
 
German: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit JavascriptGerman: Softwareprodukte aus einem Source Code mit Javascript
German: Softwareprodukte aus einem Source Code mit Javascript
 
E2E Tests mit PHP
E2E Tests mit PHPE2E Tests mit PHP
E2E Tests mit PHP
 

Mais de dominion

What is a itil and how does it relate to your collaborative environment uklug
What is a itil and how does it relate to your collaborative environment   uklugWhat is a itil and how does it relate to your collaborative environment   uklug
What is a itil and how does it relate to your collaborative environment uklugdominion
 
iOS enterprise
iOS enterpriseiOS enterprise
iOS enterprisedominion
 
cloud session uklug
cloud session uklugcloud session uklug
cloud session uklugdominion
 
Uklug 2011 administrator development synergy
Uklug 2011 administrator development synergyUklug 2011 administrator development synergy
Uklug 2011 administrator development synergydominion
 
Uklug 2011 client management
Uklug 2011 client managementUklug 2011 client management
Uklug 2011 client managementdominion
 
JavaScript blast
JavaScript blastJavaScript blast
JavaScript blastdominion
 
Populating your domino directory or any domino database with tivoli directory...
Populating your domino directory or any domino database with tivoli directory...Populating your domino directory or any domino database with tivoli directory...
Populating your domino directory or any domino database with tivoli directory...dominion
 
Uklug2011 Know your Notes
Uklug2011 Know your NotesUklug2011 Know your Notes
Uklug2011 Know your Notesdominion
 
Supersize me
Supersize meSupersize me
Supersize medominion
 
Learning to run
Learning to runLearning to run
Learning to rundominion
 
Implementing xpages extension library
Implementing xpages extension libraryImplementing xpages extension library
Implementing xpages extension librarydominion
 
Abb presentation uklug
Abb presentation uklugAbb presentation uklug
Abb presentation uklugdominion
 
Uklug2011.lotus.on.linux.report.technical.edition.v1.0
Uklug2011.lotus.on.linux.report.technical.edition.v1.0Uklug2011.lotus.on.linux.report.technical.edition.v1.0
Uklug2011.lotus.on.linux.report.technical.edition.v1.0dominion
 
Domino testing presentation
Domino testing presentationDomino testing presentation
Domino testing presentationdominion
 
Composite applications tutorial
Composite applications tutorialComposite applications tutorial
Composite applications tutorialdominion
 
Maximizing application performance
Maximizing application performanceMaximizing application performance
Maximizing application performancedominion
 
Error handling in XPages
Error handling in XPagesError handling in XPages
Error handling in XPagesdominion
 
wcm domino
wcm dominowcm domino
wcm dominodominion
 
leverage dxl
leverage dxlleverage dxl
leverage dxldominion
 

Mais de dominion (20)

What is a itil and how does it relate to your collaborative environment uklug
What is a itil and how does it relate to your collaborative environment   uklugWhat is a itil and how does it relate to your collaborative environment   uklug
What is a itil and how does it relate to your collaborative environment uklug
 
iOS enterprise
iOS enterpriseiOS enterprise
iOS enterprise
 
cloud session uklug
cloud session uklugcloud session uklug
cloud session uklug
 
Uklug 2011 administrator development synergy
Uklug 2011 administrator development synergyUklug 2011 administrator development synergy
Uklug 2011 administrator development synergy
 
Uklug 2011 client management
Uklug 2011 client managementUklug 2011 client management
Uklug 2011 client management
 
JavaScript blast
JavaScript blastJavaScript blast
JavaScript blast
 
Populating your domino directory or any domino database with tivoli directory...
Populating your domino directory or any domino database with tivoli directory...Populating your domino directory or any domino database with tivoli directory...
Populating your domino directory or any domino database with tivoli directory...
 
Uklug2011 Know your Notes
Uklug2011 Know your NotesUklug2011 Know your Notes
Uklug2011 Know your Notes
 
Quickr
QuickrQuickr
Quickr
 
Supersize me
Supersize meSupersize me
Supersize me
 
Learning to run
Learning to runLearning to run
Learning to run
 
Implementing xpages extension library
Implementing xpages extension libraryImplementing xpages extension library
Implementing xpages extension library
 
Abb presentation uklug
Abb presentation uklugAbb presentation uklug
Abb presentation uklug
 
Uklug2011.lotus.on.linux.report.technical.edition.v1.0
Uklug2011.lotus.on.linux.report.technical.edition.v1.0Uklug2011.lotus.on.linux.report.technical.edition.v1.0
Uklug2011.lotus.on.linux.report.technical.edition.v1.0
 
Domino testing presentation
Domino testing presentationDomino testing presentation
Domino testing presentation
 
Composite applications tutorial
Composite applications tutorialComposite applications tutorial
Composite applications tutorial
 
Maximizing application performance
Maximizing application performanceMaximizing application performance
Maximizing application performance
 
Error handling in XPages
Error handling in XPagesError handling in XPages
Error handling in XPages
 
wcm domino
wcm dominowcm domino
wcm domino
 
leverage dxl
leverage dxlleverage dxl
leverage dxl
 

Dojo Und Notes

  • 1. und Notes EntwicklerCamp 09. März 2010 Innovative Software-Lösungen. www.assono.de
  • 2. Bernd Hort Diplom-Informatiker, Universität Hamburg seit 1995 entwickle ich Lotus Notes Anwendungen IBM Certified Application Developer, System Administrator & Instructor Sprecher auf diversen Konferenzen & Lotusphere 2008 ! ! bhort@assono.de ! http://www.assono.de/blog ! 040/73 44 28-315 www.assono.de
  • 3. Agenda - Motivation - Einführung in dojo - Core - Dijit - DojoX - Dojo und Notes - Dojo und XPages - Fragen & Antworten www.assono.de
  • 4. Das Rad nicht neu erfinden! www.assono.de
  • 5. Motivation – Warum dojo? - Open Source - Browserunterstützung - Vielfältige UI Elemente - Internationalisierung - Verwendung in XPages www.assono.de
  • 6. Dojo besteht aus drei Teilen www.assono.de
  • 7. core - base - Browser-Erkennung - JSON encoding / decoding - Laden von Packages - Eventhandling - Animation effects - AJAX - CSS Utilities - OOP Unterstützung - Firebug Integration www.assono.de
  • 8. core – Ergänzung - Drag & Drop - I18N Support - Datumsformatierung - Zahlenformatierung - String Utils - Cookie Handling - Extended Animations - Back Button Handling www.assono.de
  • 9. dijit - Oberflächen Elemente (interface widgets) - „Theme“ Unterstützung - Internationalisierung - Keyboard Unterstützung www.assono.de
  • 10. dojoX - „quasi“ experimentell - „The future, today“ - Vieles stabil und produktiv einsetzbar - Charts - SVG Unterstützung - DojoX Offline – Integration mit Gears - DojoX Widgets www.assono.de
  • 12. Hello World <html> <head> <title>My First Dojo App</title> <link rel="StyleSheet" type="text/css" Basis CSS href="js/dojo/dojo/resources/dojo.css"> <link rel="StyleSheet" type="text/css" href="js/dojo/dijit/themes/tundra/tundra.css"> Theme CSS <script type="text/javascript"> var djConfig = { Basis Konfiguration baseScriptUri : "js/dojo/", muss vor dem Laden parseOnLoad : true, von dojo.js erfolgen! extraLocale: ['en-us', 'zh-cn'] }; </script> dojo.js (Base) <script type="text/javascript" src="js/dojo/dojo/dojo.js"></script> <script language="JavaScript" type="text/javascript"> dojo.require("dojo.parser"); dojo.require("dijit.form.Button"); Nachladen dojo.require("dijit._Calendar"); von Packages </script> </head> www.assono.de
  • 13. Hello World <body class="tundra"> <div style="position:relative;top:10px;left:10px;width:80%;"> <button dojoType="dijit.form.Button" id="myButton"> Press me, NOW! <script type="dojo/method" event="onClick"> Button alert('You pressed the button'); </script> </button> <br><br> <table border="0"><tr> <td valign="top"> <input id="calEnglish" dojoType="dijit._Calendar" lang="en-us" /> </td> <td width="25">&nbsp;</td> Calender US <td valign="top" <input id="calChinese" dojoType="dijit._Calendar" lang="zh-cn" /> </td> </table> </div> Calender CN </body> </html> www.assono.de
  • 14. Hello World - Erklärung <link rel="StyleSheet" type="text/css" href="js/dojo/dojo/resources/dojo.css"> - Simples Basis CSS – nur Abstände und Font- Definitionen <link rel="StyleSheet" type="text/css" href="js/dojo/dijit/themes/tundra/tundra.css"> - Tundra ist eines der mit gelieferten Themes www.assono.de
  • 15. Hello World - Erklärung <script type="text/javascript"> var djConfig = { baseScriptUri : "js/dojo/", parseOnLoad : true, extraLocale: ['en-us', 'zh-cn'] }; </script> - Basis Konfiguration von dojo - Erzeugt ein djConfig Objekt - Das Objekt wird beim Laden von dojo.js ausgewertet - Eigenschaft baseScriptUri: Verzeichnis von dojo - Eigenschaft parseOnLoad: Analyse des HTML Codes - Eigenschaft extraLocale: zusätzliche Sprachen laden - Muss vor dem Laden von dojo.js definiert werden www.assono.de
  • 16. Hello World - Erklärung <script type="text/javascript" src="js/dojo/dojo/dojo.js"></script> - Laden von „base“ <script language="JavaScript" type="text/javascript"> dojo.require("dojo.parser"); dojo.require("dijit.form.Button"); dojo.require("dijit._Calendar"); </script> - Steuern welche Packages nachgeladen werden - dojo.parser: Parst den HTML Code auf der Suche nach dojo relevanten Elementen - dijit.form.Button: Lädt das „Button“ Widget - dijit._Calendar: Lädt das „Calender“ Widget www.assono.de
  • 17. Kritikpunkt – Nachladen von Packages - Nachladen von Packages (dojo.require) bedeutet viele kleine Serveraufrufe - Aus Performancegründen eigentlich nicht so gut - Dojo bietet die Möglichkeit sich eine Datei mit allen benötigten Dateien zusammenzustellen “Custom Dojo Build“ - Blog-Eintrag von Tim Tripcony „I still have one concern about Dojo“ http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-7LLHQP - Tim Tripcony hat ein Tool „JSFactory“ http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-7FUSZF www.assono.de
  • 18. Hello World - Erklärung <button dojoType="dijit.form.Button" id="myButton"> Press me, NOW! <script type="dojo/method" event="onClick"> alert('You pressed the button'); </script> </button> - Erzeugt einen Button - Parser erkennt dojoType - „dijit.form.Button“ lädt das Button Widget - Registriert das Event „onClick“ - Parser erkennt type=“dojo/method“ www.assono.de
  • 19. Hello World - Erklärung <table border="0"><tr> <td valign="top"> <input id="calEnglish" dojoType="dijit._Calendar" lang="en-us" /> </td> <td width="25">&nbsp;</td> <td valign="top" <input id="calChinese" dojoType="dijit._Calendar" lang="zh-cn" /> </td> </table> - Erzeugt zwei Kalenderobjekte - Parser erkennt dojoType - „dijit._Calendar“ lädt das Kalender Widget - über die Sprachangabe „lang“ wird die Vorgabesprache übersteuert www.assono.de
  • 20. base – dojo.addOnLoad() - Registriert eine Funktion, die aufgerufen wird, sobald das DOM geladen ist und alle Widgets intialisiert sind - dojo.addOnLoad(functionPointer); Einfacher Funktionsaufruf - dojo.addOnLoad(object, "functionName"); Aufruf einer Methode eines Objektes - dojo.addOnLoad(object, function() { /* ... */}); Definition einer neuen Methode in dem Objekt www.assono.de
  • 21. base – CSS Klassen - dojo.addClass(DomNode|NodeId, ClassName) fügt dem DOM-Knoten eine CSS-Klasse hinzu - dojo.removeClass(DomNode|NodeId, ClassName) entfernt eine CSS-Klasse von einem DOM-Knoten - dojo.hasClass(DomNode|NodeId, ClassName) prüft einem DOM-Knoten eine CSS- Klasse zugewiesen wurde www.assono.de
  • 22. base – DOM Knoten - dojo.byId(NodeId) liefert den DOM-Knoten mit der gegebenen Id zurück - dojo.clone(Object) klont ein Objekt, auch DOM-Knoten, inklusive aller Kinder - dojo.isDescendant(ChildDomNode, ParentDomNode) prüft einem DOM-Knoten Kind eines anderen DOM-Knoten ist www.assono.de
  • 23. base – dojo.query() (1) - dojo.query(CSS3-Selector) liefert alle DOM-Knoten, die dem CSS3- Selektor entsprechen - Klassenname, z.B. „.foo“ - HTML-Elemente, z.B. „span“ - CSS Hierarchien, z.B. „table div“ - Direkte Kindelemente (>), z.B. „#tabular_data > div“ - Universal Selektor (*) - Unmittelbar vorangestellte Geschwisterknoten (~) - vorangestellte Geschwisterknoten (+) www.assono.de
  • 24. base – dojo.query() (2) - dojo.query(CSS3-Selector) Abfrage nach Attributen - [foo] Attribut ist vorhanden - [foo='bar'] Attributwert stimmt genau überein - [foo~='bar'] Attributwert stimmt mit einem Eintrag in der Liste der Werte überein - [foo^='bar'] Attributwert beginnt mit - [foo$='bar'] Attributwert endet mit - [foo*='bar'] Attributwert enthält www.assono.de
  • 25. base – dojo.query() (3) - dojo.query(CSS3-Selector) Pseudoklassen - :first-child – erstes Kind - :last-child – letztes Kind - :only-child – nur ein Kind - :empty – kein Kind - :checked – aktivierte Radiobuttons & Checkboxes - :nth-child(n) – n-te Kind - :nth-child(even) – alle „geraden“ Kinder - :nth-child(odd) – alle „ungeraden“ Kinder - :not(...) - Umkehrungen www.assono.de
  • 26. base – OOP – declare - dojo.declare(className: String, superclass: Function|Function[], props: Object) Erzeugt eine neue Klasse, die von einer oder mehreren Klassen erben kann und die Eigenschaftes eines Objektes übernehmen kann www.assono.de
  • 27. base – OOP – declare - Beispiel function MyClass1() { var firstName = "Mick"; this.getFirstName = function() { return firstName; } } function MyClass2() { var lastName = "Foley"; this.getLastName = function() { return lastName; } } dojo.declare("de.entwicklerCamp.AnotherClass", [ MyClass1, MyClass2], { middleName : "William", getMiddleName : function() { return this.middleName; } } ); var o = new de.entwicklerCamp.AnotherClass(); alert(o.getFirstName() + " " + o.getMiddleName() + " " + o.getLastName()); www.assono.de
  • 28. base – OOP – extend - dojo.extend(constructor: Object, props: Object...); Fügt die Eigenschaften und Methoden einer oder mehrerer Klassen zu einer Klasse hinzu (Prototypische Vererbung) www.assono.de
  • 29. base – OOP – extend - Beispiel function MyClass1() { var firstName = "Mick"; this.getFirstName = function() { return firstName; } } function MyClass2() { var lastName = "Foley"; this.getLastName = function() { return lastName; } } function MyClass3() { this.sayName = function() { alert("I am " + this.getFirstName() + " " + this.getLastName()); } } dojo.extend(MyClass3, new MyClass1(), new MyClass2()); var mc3 = new MyClass3(); mc3.sayName(); www.assono.de
  • 30. base – Aspektorientierte Programmierung – connect - Ruft eine Methode / Funktion auf, sobald ein Event ausgelöst wurde oder eine Methode eines anderen Objektes aufgerufen wurde. dojo.connect(object: Object|null, event: String, context: Object| null, method: String|Function); - Verknüpfung mit DOM-Knoten dojo.connect(dojo.byId(„foo“), „onmouseover“, function(evt) {console.log(evt)}); www.assono.de
  • 31. base – Aspektorientierte Programmierung – connect - Das Event kann auch einfach ein Methodenaufruf eines anderen Objektes sein. function MyClass(){ this.sayHello = function(inName){ alert("Hello, " + inName)} } function AnotherClass(){ this.echo = function(message){ alert(message + " has been greeted.")} } foo = new MyClass(); bar = new AnotherClass(); var handle = dojo.connect(foo, "sayHello", bar, "echo"); foo.sayHello ("EntwicklerCamp"); www.assono.de
  • 32. base – AJAX - dojo.xhr(method: String, args: dojo.__XhrArgs, hasBody: Boolean?); Startet eine AJAX Anfrage - Unterstützte Methoden: “DELETE“, „GET“, „POST“ & „PUT“ - Alternative - dojo.xhrDelete(args: dojo.__XhrArgs); - dojo.xhrGet(args: dojo.__XhrArgs); - dojo.xhrPost(args: dojo.__XhrArgs); - dojo.xhrPut(args: dojo.__XhrArgs); www.assono.de
  • 33. base – XhrArgs (1) - url:String Die URL für den Aufruf - handleAs:String Format der Serverantwort - text (default) - json - json-comment-optional - json-comment-filtered - javascript - xml www.assono.de
  • 34. base – XhrArgs (2) - form:DOMNode Die Werte des Formulars werden in der Form feld1=wert1&feld2=wert2&.... übertragen - content:Object Die Eigenschaften des Objektes werden in der Form eigenschaft1=wert1&eigenschaft2=wert2&.... übertragen - headers:Object Zusätzlicher HTTP Header Die Eigenschaften des Objektes werden als Name-Wert-Paare übertragen www.assono.de
  • 35. base – XhrArgs (3) - load:Function Funktionsreferenz, die bei erfolgreicher Serverantwort aufgerufen wird - error:Function Funktionsreferenz, die bei fehlerhafter Serverantwort aufgerufen wird - handle:Function Funktionsreferenz, die bei jeder Serverantwort aufgerufen wird www.assono.de
  • 36. base – XhrArgs (4) - sync:Boolean Synchronisierter Aufruf (Browser blockiert bis zur Antwort) - Vorgabe ist false - preventCache:Boolean Bei true wird der Browser daran gehindert die Anfrage zu cachen - timeout:Integer Millisekunden, die auf die Antwort gewartet wird vor Aufrufen der Fehlerfunktion www.assono.de
  • 37. base – Basis Animation - dojo.animateProperty(args: dojo.__AnimArgs); Basis für alle Animationseffekte - dojo.animateProperty({ node: node, duration: 2000, properties: { width: { start: '200', end: '400', unit:"px" }, height: { start:'200', end: '400', unit:"px" }, paddingTop: { start:'5', end:'50', unit:"px" } } }).play(); www.assono.de
  • 38. base – fadeIn & fadeOut - Einblenden und Ausblenden - dojo.fadeOut({node : "myDiv", duration : 2000}).play(); - dojo.fadeIn({node : "myDiv", duration : 2000}).play(); - function doFading() { dojo.fadeOut({node : "myDiv", duration : 2000, onEnd : function() { dojo.fadeIn({node : "myDiv", duration : 2000}).play(); } }).play(); } www.assono.de
  • 39. dojo.fx – Weitere Animationseffekte - dojo.require("dojo.fx"); Nachladen des fx-Packages - dojo.fx.slideTo({ node: node, left:"40", top:"50", unit:"px" }).play(); Verschiebt den DOM-Knoten von seiner aktuellen Position auf die angegebene Position - dojo.fx.wipeIn({ node: node, duration: 200).play(); DOM-Knoten in einem Wischeffekt erscheinen lassen - dojo.fx.wipeOut({ node: node, duration: 200).play(); DOM-Knoten in einem Wischeffekt verschwinden lassen www.assono.de
  • 40. dojo.back – Handling des Back.Buttons - Für die meisten Anwender ist der “Zurück-Knopf“ der wichtigste Knopf - dojo.back erlaubt das Setzen von Referenzpunkten - dojo.require("dojo.back"); - dojo.back.setInitialState(state); - dojo.back.init(); - dojo.back.addToHistory(state); - var state = { back: function() { alert("Back was clicked!"); }, forward: function() { alert("Forward was clicked!"); }}; www.assono.de
  • 41. dojo.behavior – Event Handling - Registrieren von Eventhandlern an beliebigen DOM-Knoten - DOM-Knoten werden anhand von CSS3-Selektoren identifiziert (siehe auch dojo.query()) - dojo.require("dojo.behavior"); dojo.behavior.add({"#myDiv" : { found : function (elem) { alert("Found the div: " + elem); }, onmouseover: function (evt) { alert("onMouseOver fired"); }, onmouseout: function (evt) { alert("onMouseOut fired"); } } }); dojo.behavior.apply(); www.assono.de
  • 42. dojo.dnd – Drag & Drop - Zwei Ansätze - Einfaches Verschieben von HTML-Elementen auf dem Bildschirm - Container-Definitionen zum Bestimmen von Quelle und Ziel - Beide Ansätze sind sehr einfach umgesetzt und bis ins kleinste steuerbar www.assono.de
  • 43. dojo.dnd.movable - dojo.require("dojo.dnd.movable"); Nachladen des Drag&Drop-Packages - <div dojoType="dojo.dnd.Moveable"> Some Content</div> Die Angabe des dojoTypes führt automatisch dazu, dass das HTML-Element beliebig auf dem Bildschirm verschoben werden kann. www.assono.de
  • 44. dojo.dnd.movable – mit „Handle“ - Ein Kindelement innerhalb des zu bewegenden HTML-Elementes kann als “Griffpunkt“ definiert werden. - <div dojoType="dojo.dnd.Moveable" handle="dragHandle"> <div id="dragHandle"></div> <textarea>Dieser Text kann editiert werden </textarea> </div> www.assono.de
  • 45. dojo.dnd.Source – Einfache Containerdefinition - dojo.require("dojo.dnd.Source"); Nachladen des Drag&Drop-Packages - Definition der Liste <div dojoType="dojo.dnd.Source" class="container"> <div class="dojoDndItem">Item X</div> <div class="dojoDndItem">Item Y</div> <div class="dojoDndItem">Item Z</div> </div> - Mit dem richtigen Stylesheet verbunden ergibt sich auch eine visuelle Unterstützung beim Verschieben www.assono.de
  • 46. Weitere dojo core Packages - dojo.cldr – Berücksichtigung von Länderunterschieden - dojo.colors – Farben - dojo.currency – Behandlung von Währungen - dojo.date – Datumsfunktionen - dojo.i18n – Übersetzungshilfen - dojo.io – AJAX-ähnliche Funktionen ohne XmlHttpRequest - dojo.number – Formartieren und Parsen von Zahlen - dojo.regexp – Reguläre Ausdrücke -www.assono.de dojo.string – Stringfunktionen
  • 47. dijit - Einführung - Dijit bezeichnet zwei Dinge - Das Widget Framework basierend auf den base und core Elementen - Ein einzelnes Widget wird auch als dijit bezeichnet - Dijits sind voll „theme-able“ - können im Aussehen angepasst werden - Gewünschtes „Theme“ als CSS einbinden - <body class=“{Theme}“> - Beliebtestes „Theme“ ist „Tundra“ www.assono.de
  • 48. Zwei Arten dijits einzubinden - Dijits können auf zwei Arten eingebunden werden - Deklarativ - Programmatisch - Beim deklarativen Ansatz wird der HTML-Code nach Attributen „dojoType“ abgesucht - Gefundene Elemente werden automatisch um die notwendigen JavaScript-Aufrufe ergänzt - Vorsicht! HTML Validierungs-Services melden den HTML-Code als nicht valide! www.assono.de
  • 49. Dijits deklarativ einbinden - var djConfig = { baseScriptUri : "js/dojo/", parseOnLoad : true }; Konfiguration zum Parsen des HTML-Codes beim Laden - dojo.require("dojo.parser"); Notwendiges Package zum Parsen - dojo.require("dijit.form.Button"); Das zum dijit gehörige Package laden - <button dojoType="dijit.form.Button">ok</ button> Dojo Attribute hinzufügen www.assono.de
  • 50. Dijit programmatisch einbinden - dojo.require("dijit.form.Button"); Das zum dijit gehörige Package laden - var myDijit = new dijit.form.Button( {label : "Ok"} ); dojo.byId("divButton").appendChild (myDijit.domNode); - Der programmatische Ansatz ist der performantere Ansatz. - Nur bei großen HTML-Dokumenten wichtig - Oder bei hoch dynamischen Webseiten www.assono.de
  • 51. Zugriff auf dijits - Jedes dijit wird vom dijit Manager verwaltet - Jedes dijit hat eine eindeutige Id - Entweder manuell definiert - Oder automatisch generiert - Die Methode dijit.byId(<someID>); liefert das dijit Objekt zurück - Nicht zu verwechseln mit dojo.byId(<someID>); - Die Methode liefert den DOM-Knoten zurück www.assono.de
  • 52. dijit Methoden Methode Beschreibung buildRendering Konstruiert die visuelle Repräsentation connect Verbindet ein Object / Event mit entsprechenden Methoden des dijit und registriert für disconnect() create Startet den Lebenszyklus des dijits destroy Zerstört das dijit, lässt aber die Kindelemente intakt destroyDescendants Zerstört alle Kindelemente rekursiv destroyRecursive Zerstört rekursiv das dijit und alle Kindelemente www.assono.de
  • 53. dijit Methoden Methode Beschreibung destroyRendering Entfernt alle DOM-Knoten des dijit disconnect Löst die Verbindungen zu registrierten Objekten / Events getDescandants Liefert alle Kindelemente isFocusable Ermittelt ob das dijit auswählbar ist isLeftToRight Ermittelt die Leserichtung onBlur Wird aufgerufen, wenn das dijit den Fokus verliert onClose Wird aufgerufen, wenn das dijit zerstört wird www.assono.de
  • 54. dijit Methoden Methode Beschreibung onFocus Wird aufgerufen, wenn das dijit den Fokus erhält postCreate Wird aufgerufen, wenn die DOM-Knoten des dijits erzeugt wurden postMixInProperties Wird aufgerufen, nachdem alle Parameter verarbeitet wurde, aber bevor die DOM- Knoten erzeugt werden setAttrbute Setzt HTML Attribute direkt startUp Wird aufgerufen, nachdem alle dijit Kinder erzeugt wurden, aber bevor sie dargestellt werden www.assono.de
  • 55. dijit Attribute Attribut Beschreibung attributeMap Liste aller Attribute, vornehmlich HTML Attribute class HTML Klassen Attribute id Die ID des dijit lang Die Sprache – erlaubt das Übersteuern der automatisch bestimmten Sprache srcNodeRef Referenz auf den DOM-Knoten mit dem dojoType Attribute Der DOM-Knoten wird häufig ersetzt. style Die HTML Style Attribute www.assono.de
  • 56. dijit.form.NumberTextBox - Widget für die Formatierung von Zahlenangaben - Einbindung dojo.require ("dijit.form.NumberTextBox") <input dojoType="dijit.form.NumberTextBox" > - Speichert Zahlenangabe mit „.“ als Dezimaltrennzeichen - In der Standardausführung können die eingegebenen Werte nicht von Domino verarbeitet werden. => dijitDominoPatch.js www.assono.de
  • 57. dijit.form.CurrencyTextBox - Widget für die Formatierung von Währungsangaben - Einbindung dojo.require ("dijit.form.CurrencyTextBox") <input dojoType="dijit.form.CurrencyTextBox" currency="EUR"> - Speichert Zahlenangabe mit „.“ als Dezimaltrennzeichen - In der Standardausführung können die eingegebenen Werte nicht von Domino verarbeitet werden. => dijitDominoPatch.js www.assono.de
  • 58. dijit.form.DateTextBox - Widget für die Datumsauswahl - Einbindung dojo.require ("dijit.form.DateTextBox") <input dojoType="dijit.form.DateTextBox" > - Speichert Datumsangabe im Format [Jahr]-[Monat]-[Tag] - In der Standardausführung können die eingegebenen Werte nicht von Domino verarbeitet werden. => dijitDominoPatch.js www.assono.de
  • 59. dijit.form.TimeTextBox - Widget für die Zeitauswahl - Einbindung dojo.require ("dijit.form.TimeTextBox") <input dojoType="dijit.form.TimeTextBox" > - Speichert Zeitangabe im Format T[Stunden(24h-Basis)]:[Minuten]:[Sekunden] - In der Standardausführung können die eingegebenen Werte nicht von Domino verarbeitet werden. => dijitDominoPatch.js www.assono.de
  • 60. dijitDominoPatch.js - Patch im Entwicklungsstadium - Wandelt Inputfelder vor der Initialisierung von dojo in das richtige Format um. - Formatiert die Eingabe vor der Übertragung auf den Domino Server wieder in das von Domino erwartete Format um. - Benutzung ohne Gewähr! www.assono.de
  • 61. dijitDominoPatch.js - Initailisierung - Anpassung djConfig var djConfig = { afterOnLoad : true, parseOnLoad : false }; - Aufruf von onload="textBoxDominoLoadPatch();" - Die Funktion untersucht alle Input-Elemente auf das Attribut „dojoType“ - Am Ende der Funktion wird mit dojo.parser.parse(); der Parser manuell aufgerufen. www.assono.de
  • 62. dijitDominoPatch.js – Speichern (1) - Mit dojo.connect mit dem onSubmit-Event verbinden dojo.connect(document.forms[0], "onsubmit", textBoxDominoSubmitPatch); - Alle auf der Webseite registrierten Widgets untersuchen dijit.registry.forEach(function(widget, index, hash){...} - Bei entsprechenden Widgets mit dojo.query(„input“, widget.domNode) die Input-Felder suchen. www.assono.de
  • 63. dijitDominoPatch.js – Speichern (2) - Mit dojo.style() nach dem versteckten Input-Element suchen dojo.style(node, "display") == "none" - Den Inhalt neu formatieren node.value = node.value.replace(/^(.*)-(.*)- (.*)$/g, "$3.$2.$1"); www.assono.de
  • 64. dijit.form.ComboBox - Widget für die Zeitauswahl - Einbindung dojo.require ("dijit.form.ComboBox") <input dojoType="dijit.form.ComboBox" > - Einfügen auch neuer Werte! - Notesfeld „Dialogliste“ Option „Neue Werte zulassen“ deaktivieren - In der Auswahlliste „Formel verwenden“ und gespeicherten Wert hinzufügen @Trim(@Unique("Category A" : "Category B" : "Category C" : comboboxfield)) www.assono.de
  • 65. dijit.form.Slider - Widget für die Eingabe einer Zahl über einen Slider - Beispiel, wo es sinnvoller ist das Widget über JavaScript einzubinden - Platzhalter-Div mit ID an gewünschter Stelle positionieren - Das Input-Element zur einfacheren Ansprache auch mit einer ID versehen www.assono.de
  • 66. dijit.form.Slider - Code(1) - Zunächst den Vorgabewert bestimmen var defaultValue = 10; - Dann den aktuellen Wert aus dem Input-Element bestimmen if (dojo.byId("horzsliderfield").value != ""){ defaultValue = dojo.byId("horzsliderfield"). value.replace(/,/g, ".");} - Das value.replace ist notwendig, weil in dem Input- Element das Dezimaltrennzeichen ein Komma ist, aber ein Punkt erwartet wird. www.assono.de
  • 67. dijit.form.Slider - Code(2) - Den Platzhalter-Knoten einer Variablen zuweisen var sliderNode = dojo.byId("slider"); - Neues Sliderobjekt erzeugen und an Platzhalter-Div anbinden var slider = new dijit.form.HorizontalSlider({ name: "slider", value: defaultValue, minimum: 10, maximum: 60, intermediateChanges: true, style: "width:300px;", onChange: function(value){ Funktion zum Aktualisieren var currentValue = value+""; des Input-Elementes dojo.byId("horzsliderfield").value = currentValue.replace(/./g, ","); } }, sliderNode); www.assono.de
  • 68. dijit.form.Slider - Code(3) - Neues Div erzeugen und an das Slider-Div als Kind anhängen var rulesNode = document.createElement('div'); sliderNode.appendChild(rulesNode); - Neues Sliderruler erzeugen und an neuen Dom- Knoten anbinden var sliderRules = new dijit.form.HorizontalRule({ count:11, style:"width:5px;" }, rulesNode); www.assono.de
  • 69. DojoX - Charting - Definition des Chart nur über JavaScript möglich - Erwartet als Daten ein Array von Objekten mit den Werten - Bestimmen der Werte über ein WebQueryOpen- Agent, der entsprechenden JavaScript-Code generiert und ein Feld „ComputedForDisplay“ speichert - Im „HTML Head Content“ den Feldinhalt in JavaScript-Variable schreiben www.assono.de
  • 70. Ressourcen Offizielle Webseite http://www.dojotoolkit.org API Dokumentation http://api.dojotoolkit.org Demos http://demos.dojotoolkit.org DojoCampus http://dojocampus.org/ Dojo Dokumentation http://docs.dojocampus.org/ Alte Webseite http://o.dojotoolkit.org www.assono.de
  • 71. Ressourcen - OpenNTF CodeBin - Dojo - Easy As 123 http://www.openntf.org/Projects/codebin/codebin.nsf/0/ A2A3F3DB69E21F2A8625740E005B8EC9 - Dojomino – Dojo Domino Framework http://dojomino.com/ - Sitepen Labs Dojo http://o.sitepen.com/labs/dojo.php - Dojo Toolbox – Adobe AIR Anwendung mit Offline API http://o.sitepen.com/labs/toolbox/ www.assono.de
  • 72. Bücher - Frank W. Zammetti “Practical Dojo Projects“ Apress Verlag - Matthew A. Russell “Dojo – The Definitive Guide“ O´Reilly Verlag www.assono.de
  • 73. Fragen? jetzt stellen – oder später: bhort@assono.de http://www.assono.de/blog 040/73 44 28-315 Folien & Beispieldatenbank unter http://www.assono.de/blog/d6plinks/ EntwicklerCamp-2010-dojo www.assono.de