# Dojo 1.8 und AMD

### Ein Überblick mit Demos

Karsten Lehmann, Mindoo GmbH / @klehmann79

## Über uns

- IBM Business Partner und Notes/Domino Design Partner
- Eclipse/Expeditor-Plugins und Rich-Client-Anwendungen
- XPages-Anwendungen
- Web-Applikationsentwicklung für IBM Websphere und Oracle Glassfish
- Karsten Lehmann und Tammo Riedinger
- Seit 2004 Entwickler von MindPlan für die Haus Weilgut GmbH, Mindmapping und Projekt-Management für IBM Notes
- http://www.mindoo.de

## Ziele

- Konzepte hinter Dojo 1.8 verstehen
- Nachschlagewerk für neue APIs
- Ideen und Stichworte für eigene Experimente
- Tips zur Verwendung von Dojo in XPages in IBM Notes/Domino R9

## Was ist Dojo?

- Umfangreiches, kostenlos nutzbares Web-Toolkit
- APIs für Web und Mobile nutzbar
- ein Toolkit: keine klare Trennung in Web und Mobile
- Dojo 1.8 ist Bestandteil von IBM Notes/Domino R9!

## Was ist Dojo?

Ein SDK mit vier Bereichen:

- dojo - allgemeine Werkzeuge für JS-Entwicklung und Ajax
- dijit - UI-Komponenten, z.B. Layout und Formularelemente
- dojox - weitere UI-Komponenten, u.a. Mobile UI
- util - Werkzeuge zur Build-Generierung und Unittests

## Wo finde ich Hilfe?

- Dojo-API-Dokumentation (Link)
  umfangreiche Sammlung an Tutorials, Referenz- und API-Dokumentation
- Sitepen-Blog (Link)
- letzte Lösung:
  Dojo-Quelltext - es ist alles Open Source!

## Dojo Releases

- Juli 2010 - Dojo 1.5
- März 2011 - Dojo 1.6
- Oktober 2011 - Lotus Notes 8.5.3 mit Dojo 1.6
- Dezember 2011 - Dojo 1.7
- August 2012 - Dojo 1.8
- März 2013 - IBM Notes 9.0 mit Dojo 1.8
- Mai 2013 - Dojo 1.9
- ? - Dojo 2.0 (Roadmap-Diskussion)

## Abgrenzung jQuery, Dojo, extJS

ExtJS / Sencha Touch

- starke Trennung zwischen Daten und Präsentation
- gemischte Lizenz: Open Source und kommerziell
- viele verfügbare kommerzielle Komponenten
- Support durch Hersteller Sencha

## jQuery

- größte Entwicklergemeinde
- optisch sehr ansprechende jQuery-Plugins
- Syntax gewöhnungsbedürftig
- wenig Abstraktion vom Browser-DOM

## Dojo

- umfangreiches Toolkit für Web und Mobile
- wenige Erweiterungen/Zusatzkomponenten im Netz
- lässt sich durch jQuery optisch aufpolieren
- First Class Citizen in XPages, Bestandteil des Frameworks

## Neu in Dojo 1.8 - Web

dojox/calendar (Demo)

(noch Probleme mit der Skalierbarkeit)

## Neu in Dojo 1.8 - Web

dojox/dgauges (Demo)

## Neu in Dojo 1.8 - Web

dojox/treemap (Demo)

## Neu in Dojo 1.8 - Mobile

28 neue Widgets:
Auswahldialoge, Fortschrittsbalken, Audio/Video, Scrollbereiche innerhalb von Seiten, Badge-Icons (Demo)

## Neu in Dojo 1.8

- erste Komponenten ohne Support für Firefox 3.6 und IE6
- XPages im Notes Client R9 basiert weiterhin auf der Firefox 3.6-Engine!

## Neu seit Dojo 1.6 (Notes 8.5.3)

- noch mehr Widgets
- Web: u.a. dgrid - flexible Tabellenkomponente
- Mobile: 21 neue Widgets
  z.B. Popup-Dialoge (Opener, Tooltip), ComboBox, SpinWheel
- mehr Informationen: Link

## Neu seit Dojo 1.6 (Notes 8.5.3)

- AMD: Asynchronous Module Definition
- lädt Dojo-Klassen und eigenen Code, ersetzt dojo.require()
- viele APIs umbenannt und reorganisiert für 2.0,
  alte APIs aber noch nutzbar
- wesentlich kleinerer Dojo-Kern mit zuladbaren Modulen

## Maqetta

- freier WYSIWYG-Editor für Dojo-Anwendungen
- Web und Mobile
- In der Cloud und Server als Download verfügbar (Link)

## Layouting im Web - deklarativ

## Layout im Web - deklarativ

- Layout in Form von HTML-Tags
- per CSS-Stil anpassbar in Breite und Form
- Vielzahl Layout-Container verfügbar,
  die sich verschachtelt lassen
- hauptsächlich für statische Inhalte verwendet

## dojox/layout/BorderContainer

- gut geeignet als Basislayout
- fünf Bereiche: top, left, right, bottom und center
- lediglich center muss befüllt werden
- Mehrere Widgets pro Bereich durch `layoutPriority`-Attribut (definiert Reihenfolge)

## BorderContainer

design="headline", hier zwei Widgets für "right"

## BorderContainer

dasselbe Layout mit design="sidebar":

## BorderContainer

    <!DOCTYPE html>
    <html>
    <head>
    <script type="text/javascript"
      src="/xsp/.ibmxspres/dojoroot-1.8.0-u/dojo/dojo.js"
      data-dojo-config="parseOnLoad:true"></script>
    <link rel="stylesheet" type="text/css"
      href="/xsp/.ibmxspres/dojoroot-1.8.0-u/dijit/themes/claro/claro.css">
    <link rel="stylesheet" type="text/css"
      href="/xsp/.ibmxspres/dojoroot-1.8.0-u/dojo/resources/dojo.css">
    <style>
    html,body {
      width:100%;height:100%;margin:0;overflow:hidden;
    }
    </style>
    <script type="text/javascript">
      <!-- benötigte Widgets laden -->
        require( ['dijit/layout/BorderContainer',
        'dijit/layout/ContentPane'],
          function(BorderContainer, ContentPane) {
          }
        );
    </script>
    </head>
    <body class="claro">
    <!-- BorderContainer -->
    <div id="mainContainer" data-dojo-type="dijit/layout/BorderContainer"
      style="width:100%;height:100%">

      <!-- enthaltene ContentPanes -->
      <div id="topPane" data-dojo-type="dijit/layout/ContentPane"
        data-dojo-props="region:'top'" style="height:30px">
          Top pane
      </div>

      <div id="leftPane" data-dojo-type="dijit/layout/ContentPane"
        data-dojo-props="region:'left',splitter:true" style="width:20%">
          Left pane
      </div>

      <div id="centerPane" data-dojo-type="dijit/layout/ContentPane"
        data-dojo-props="region:'center'">
          center pane
      </div>

      <div id="rightPane1" data-dojo-type="dijit/layout/ContentPane"
        data-dojo-props="region:'right',layoutPriority:1" style="width: 10%">
          1st right pane from right
      </div>

      <div id="rightPane2" data-dojo-type="dijit/layout/ContentPane"
        data-dojo-props="region:'right',layoutPriority:2" style="width: 10%">
          2nd right pane from right
      </div>

      <div id="bottomPane" data-dojo-type="dijit/layout/ContentPane"
        data-dojo-props="region:'bottom'">
          first bottom pane
      </div>

    </div>
    </body>
    </html>

## data-dojo-* Attribute

- HTML5-konforme Attributnamen
- `data-dojo-config`
  zentrale Dojo-Konfiguration

    <script type="text/javascript"
      src="/xsp/.ibmxspres/dojoroot-1.8.0-u/dojo/dojo.js"
      data-dojo-config="parseOnLoad:true"></script>

alternativ als globale Variable:

    <script type="text/javascript">
    dojoConfig={
      parseOnLoad: true
    }
    </script>
    <script type="text/javascript" src="/path/to/dojo.js"></script>

## data-dojo-* Attribute

- `data-dojo-type`
  Klassenname des Widgets (Trenner " / " oder " . ")
- `data-dojo-props` (optional)
  Eigenschaften des Widgets (vgl. API-Dokumentation)

    <div id="topPane" data-dojo-type="dijit/layout/ContentPane"
      data-dojo-props="region:'top'" style="height:30px">
        Top pane
    </div>

## require

- AMD-Befehl zum Laden von Klassen
- je nach Modus blockierend oder asynchron
- Ruft Callback auf, sobald Klassen verfügbar sind
- notwendig, damit aus Tags Widgets werden können

    <script type="text/javascript">
      <!-- benötigte Widgets laden -->
        require( ['dijit/layout/BorderContainer',
          'dijit/layout/ContentPane'],
            function(BorderContainer, ContentPane) {
              //Callback hat Zugriff auf geladene Klassen
            }
        );
    </script>

## Dojo-Parser

- Parser kann auch manuell aufgerufen werden
- parseOnLoad: false
- Vorteil:
  Callback-Aufruf, sobald Widgets generiert sind

    <script type="text/javascript">
      require( ['dijit/layout/BorderContainer', 'dijit/layout/ContentPane',
        'dojo/parser', 'dojo/ready'],
        function(BorderContainer, ContentPane, parser, ready) {
          //dojo/ready wartet bis DOM geladen ist
          ready(function() {
            parser.parse().then(function(arrWidgets) {
              //aufgerufen mit Array aller erzeugten Widgets
                for (var i=0; i<arrWidgets.length; i++) {
                  console.log('Widget erzeugt: '+arrWidgets[i].id);
                }
            });
          });
      });
    </script>

## Andere Layout-Widgets

- `dijit/layout/ContentPane`
  Container für beliebige DOM-Knoten
- `dijit/layout/AccordionPane`mehrere Bereiche untereinander, einer ist sichtbar
- `dijit/layout/TabContainer`Karteireiter
- `dojox/layout/ExpandoPane`
  zuklappbare Sidebar
- `dojox/layout/GridContainer`
  Portallayout

## Portallayout

Portal mit zwei Portlets

    <!DOCTYPE html>
    <html>
    <head>
    <script type="text/javascript"
        src="/xsp/.ibmxspres/dojoroot-1.8.0-u/dojo/dojo.js"></script>
    <link rel="stylesheet" type="text/css"
        href="/xsp/.ibmxspres/dojoroot-1.8.0-u/dijit/themes/soria/soria.css">
    <link rel="stylesheet" type="text/css"
        href="/xsp/.ibmxspres/dojoroot-1.8.0-u/dojo/resources/dojo.css">
    <link rel="stylesheet" type="text/css"
        href="/xsp/.ibmxspres/dojoroot-1.8.0-u/dojox/widget/Portlet/Portlet.css">
    <link rel="stylesheet" type="text/css"
        href="/xsp/.ibmxspres/dojoroot-1.8.0-u/dojox/layout/resources/GridContainer.css">
    <style>
    html,body {width:100%;height:100%;margin:0;overflow:hidden}
    .gridContainerTable {border:0;height:inherit}
    .gridContainer > div {height:inherit}
    </style>
    <script type="text/javascript">
        require( ['dijit/layout/BorderContainer',
        'dijit/layout/ContentPane', 'dojox/layout/GridContainer',
        'dojo/parser', 'dojo/ready',
        'dojox/widget/Portlet'],

        function(BorderContainer, ContentPane, GridContainer, parser,
        ready, Portlet) {
            ready(function() {
                parser.parse();
            });
        });
    </script>
    </head>
    <body class="soria">
    <div id="mainContainer" data-dojo-type="dijit/layout/BorderContainer"
      data-dojo-props="design:'sidebar'" style="width: 100%; height: 100%">

    <!-- Portal im Center-Bereich anzeigen -->
    <div id="portal" data-dojo-type="dojox/layout/GridContainer"
      style="height:100%" data-dojo-props="nbZones:3,region:'center',
      hasResizableColumns:true,isAutoOrganized:false,withHandles:true,
      dragHandleClass:'dijitTitlePaneTitle',colWidths:[20,60,20]">

      <!-- Erstes Portlet -->
      <div id="portlet1" data-dojo-type="dojox/widget/Portlet"
      data-dojo-props="title:'Portlet 1',column:1">
        Hello World.
      </div>

      <!-- Zweites Portlet -->
      <div id="portlet2" data-dojo-type="dojox/widget/Portlet"
      data-dojo-props="title:'Portlet 2',closable:false,column:2">
        Greetings from Entwicklercamp.
      </div>
    </div>
    </body>
    </html>

## Portallayout

3 Spalten, Portlets verschiebbar per Drag&Drop

## Demo: Portallayout

## Widgets erzeugen in JavaScript

- Widget-Generierung in JavaScript
- im Zusammenspiel mit Ajax sehr flexibel
- Dojo-Widgets bilden eine Baumstruktur:

    require(['dijit/registry', 'dijit/layout/ContentPane'],
      function(registry, ContentPane) {

      //Ergänzen von Widgets mit addChild()
      //main: vorhandener dijit/layout/BorderContainer
      var mainContainer=registry.byId('main');
      var newPanel=new ContentPane({
        id: 'contentpane1',
        content: 'Pretty dynamic content '+(new Date()).toString(),
        region:'bottom',
        splitter: true
      });
      mainContainer.addChild(newPanel);
      //resize berechnet Positionen neu
      mainContainer.resize();

      //Auslesen von enthaltenen Widgets mit getChildren()
      var arrChildren=mainContainer.getChildren();

      //Entfernen von Widgets mit removeChild()
      var childWidget=arrChildren[0];
      mainContainer.removeChild(childWidget);
      //falls nicht mehr benötigt, Freigabe aller Ressourcen
      childWidget.destroyRecursive();
    }

## Demo: Dynamische UI

## Formular-Widgets

Widgets können frei platziert werden, entweder deklarativ:

    <body>
    Lorem ipsum dolor sit amet.<br />
    <input type="text" data-dojo-type="dijit/form/TextBox" /><br />
    consetetur sadipscing elitr.
    </body>

## Formular-Widgets

...oder programmatisch:

    require(['dojo/_base/window', 'dojo/dom', 'dijit/registry'],
      function(win, dom, registry) {
        //Ziel-DOM-Knoten mit ID 'targetDomNodeId' finden:
        var targetDomNode=dom.byId('targetDomNodeId');
        //Bestehendes Widget mit ID 'myWidgetId' finden:
        var myWidget=registry.byId('myWidgetId');
        //Widget-Position ändern
        //(first/last=erstes/letztes Kind,
        //before/after=vor/nach Referenz-Knoten)
        myWidget.placeAt(targetDomNode, 'first');
      }
    });

## Demo: Überblick Formular-Widgets

Link

## Eine Sammlung wichtiger APIs:

( Bitte alles auswendig lernen! ;-) )

## Wichtige Widget-APIs

Widget über dessen ID auffinden

    // dijit/registry
    var widget=registry.byId('widgetId1');

Lesen/Schreiben von Eigenschaften

    var propValue=myWidget.get('value')
    myWidget.set('value', 'xyz');

## Wichtige DOM-APIs

DOM-Knoten über dessen id auffinden

    // dojo/dom
    var nodeWithId=dom.byId('nodeId1')

Lesen und Ändern von Stilen

    // dojo/dom-style
    var styleValue=domStyle.get(node, 'display');
    domStyle.set(node, 'backgroundColor', '#ff0000');

## Wichtige DOM-APIs

Lesen/Ändern von DOM-Knoten-Klassen

    // dojo/dom-class
    var nodeHasClass=domClass.has(node, 'myclass');
    domClass.add(node, 'myclass');
    domClass.remove(node, 'myclass');

Erzeugen und Platzieren von DOM-Knoten

    // dojo/dom-construct
    domConstruct.empty(refNode);
    var createdNode=domConstruct.create('div',
      {innerHTML:'<b>Test</b>'}, refNode, 'first');
    domConstruct.place(refNode, otherNode, 'before');

Abmessungen von DOM-Knoten

    // dojo/dom-geometry
    var box=domGeom.getMarginBox(node);
    //box.width, box.height, box.top, box.left

## Wichtige DOM-APIs

Finden von DOM-Knoten über CSS-Selector

    // dojo/query
    var arrNodes = query('.headline', bodyNode);

## Wichtige Dojo-APIs

Sprachabhängige Formatierung eines Datums

    // dojo/date/locale
    var formattedDateStr=locale.format(myDate, {selector:'date'});

Konvertierung zwischen Date und ISO8601-Format

    // dojo/date/stamp
    var parsedDate=stamp.fromISOString(isoDateStr);
    var dateAsString=stamp.toISOString(mydate);

Suche nach einem Wert in Arrays

    // dojo/_base/array
    var index=array.indexOf(myArray, valueToFind);

## Wichtige Dojo-APIs

Parsen von JSON-Strings und Formatieren von Objekten als JSON

    // dojo/json
    var parsedJsonObj=JSON.parse("{'foo':'bar'}");
    var jsonStr=JSON.stringify( {foo:'bar'} );

…und schließlich:

    // dojo/_base/lang
    // Objekt rekursiv klonen
    var clonedObj=lang.clone(obj);

    // Code in anderem Scope ausführen
    var myfunction=lang.hitch(mygrid,
      function(key, value) {this.set(key, value);} );
    myfunction('store', newStore);

    // Datentypprüfung:
    lang.isArray(x) / lang.isFunction(x) / lang.isObject(x) /
    lang.isString(x)

    // Textersetzung
    lang.replace("Hello {name.first} {name.last}!",
      { name: {first:  "Rudi", last: "Knegt"} });

## Events registrieren

Reagieren auf Ereignisse

## Das neue dojo/connect

dojo.connect wurde aufgeteilt:

- dojo/on - DOM-Events
- dojo/aspect - Hooks für Klassenmethoden

## dojo/on

"on" im Event-Namen wird gestrichen:

    //Registrieren von Event-Code für onClick-Event:
    //verwendet dojo/dom und dojo/on
    var myDomNode=dom.byId('nodeId');
    var signal=on(myDomNode, 'click',
      function(evt) {alert('Node clicked'); });

    //Entfernen von Event-Code:
    signal.remove();

## Event-Delegation

Abfangen von 'hochbubblenden' Events in Eltern-Containern

    <div id="parentDiv">
      <button id="button1" class="clickMe">Click me</button>
      <button id="button2" class="clickMe">Click me also</button>
      <button id="button3" class="clickMe">Click me too</button>
      <button id="button4" class="clickMe">Please click me</button>
    </div>
    <script>
    require(["dojo/on", "dojo/dom", "dojo/domReady!"],
      function(on, dom, domReady) {

        var myObject = {
          id: "myObject",
          onClick: function(evt){
            alert("The scope of this handler is " + this.id);
          }
        };
        var div = dom.byId("parentDiv");
        on(div, ".clickMe:click", myObject.onClick);
      });
    </script>

## dojo/aspect

- Aspektorientierte Programmierung
- aspect.before, aspect.after und aspect.around

    require(['dojo/aspect', 'dojo/json', 'dojo'],
      function(aspect, JSON, dojo) {

      //veraltete Funktion 'dojo.xhrGet()' überschreiben
      aspect.around(dojo, "xhrGet", function(originalXhr) {
        return function(args) {
          var t0=new Date().getTime();

          //Originalfunktion aufrufen
          var deferred = originalXhr(args);

          //wir führen ein Callback zum Deferred-Objekt hinzu
          deferred.then(function(data) {
            var t1=new Date().getTime();
            console.log("Data read in "+(t1-t0)+
              "ms with request: "+JSON.stringify(args));
          });

          //und geben es an den Aufrufer weiter
          return deferred;
        }
      });
    });

## dojo/topic

- Publish/Subscribe-Architektur
- entkoppelt Sender und Empfänger von Nachrichten
- verwendet für Drag and Drop-System:
  /dnd/start, /dnd/cancel, /dnd/drop

    require(['dojo/topic'], function(topic) {
      topic.subscribe("some/topic", function(event){
        // Objekt 'event' verarbeiten
      });
      //neues Event-Objekt publizieren an alle Subscriber
      topic.publish("some/topic", {name:"My Birthday Party",
        location:"Karlsruhe"});
    });

## Arbeiten mit Daten

Webformulare und Ajax

## Dojo-Formulare

- `dijit/form/Form` vereinfacht Arbeit mit Webformularen
- Lesen und Schreiben der Formulardaten als JS-Objekt
- Validieren des Formulars mit `myform.validate()`

## Dojo-Formulare

`dijit/form/Form` wird zu FORM-Tag im DOM:

    <div id="myformid" data-dojo-type="dijit/form/Form">
      <table>
        <tr>
          <td>Firstname</td>
          <td><input type="text" name="firstname"
            data-dojo-type="dijit/form/TextBox" /></td>
        </tr>
        <tr>
          <td>Lastname</td>
          <td><input type="text" name="lastname"
            data-dojo-type="dijit/form/TextBox" /></td>
        </tr>
      </table>
    </div>

## Dojo-Formulare

Formulardaten lassen sich komplett abziehen und setzen:

    require(['dojo/json', 'dijit/registry'],
      function(JSON, registry) {
        var myform=registry.byId('myformid');
        var formData=myform.get('value');

        //Formulardaten als JSON-String anzeigen:
        alert(JSON.stringify(formData));

        //Formularfelder aktualisieren, basiert auf
        //"name"-Attribute der Felder
        myform.set('value', {firstname:'Rudi', lastname:'Knegt'});

        //Formular validieren
        if (!myform.validate())
          alert('Formulardaten ungültig!');
      }
    });

## Demo: Formulardaten lesen/schreiben

## Ajax-Requests

## dojo/request/xhr

- ersetzt dojo.xhrGet() / .xhrPost()
- xhr-Paket umfasst auch Cross-Domain-Protokolle wie IFrame/JSONP

    require(["dojo/request/xhr"], function(xhr) {
      xhr("myxagent.xsp", {
        handleAs: "json"
        method: "GET"
      }).then(function(data) {
            //Daten verarbeiten (hier JS-Objekt von JSON-Daten)
          }, function(err) {
            //Fehler melden bzw. loggen
          }, function(evt){
            //Fortschrittsinfo verarbeiten
            //(erfordert XHR2-Support im Browser)
          });
    });

## Demo: Notes-Ansichten mit dem LazyTreeGrid

## AMD

Asynchronous Module Definition

## AMD

- Classloader für Dojo-Klassen und eigenen Code
- experimentell in Dojo 1.6, Standard seit 1.7
- neuer asynchroner Modus generiert Script-Tags statt xhr
- besserer Durchsatz im Browser als bei xhr
- neue API-Aufteilung führt zu kleineren Code-Einheiten
- kompaktere Custom Builds, aber mehr HTTP-Requests ohne Optimierung

## Mehr HTTP-Requests?

Soviele können das doch nicht sein!

## Das war unser Grid-Beispiel :-)

## Lösungen

- Custom Builds (Tutorial)
- XPages-Runtime-Optimizer:
  "Use runtime optimized JavaScript and CSS resources"
- fassen Dojo-Klassen und Abhängigkeiten zusammen

## Asynchrones Classloading

Aktivierung über data-dojo-config:

    <script type="text/javascript" src="path/to/dojo.js"
      data-dojo-config="async:true"></script>

- `async:false (Default)`
  Laden von Legacy-APIs, z.B. dojo.connect, dojo.xhrGet etc.
- `async:true`
  nur dojo-Nano-Kernel laden (klein)
- Bei XPages in R9 leider immer `async:false`

## Legacy-APIs

bei async:true können Legacy APIs als Modul "dojo" geladen werden:

    require(['dojo'], function(dojo) {
      dojo.connect(...);
    });

## define

Eigene AMD-Module definieren

## define

Syntax analog zu require:

- Abhängigkeiten einbinden
- Callback-Funktion wird nach Ladevorgang aufgerufen
- Unterschied: Wir geben etwas zurück!

    //Inhalt von "/subdir/db.nsf/dojo/mindoo/tools/XspUtil.js":

    define(['dojo/query'], function(query) {
      //einfaches JS-Objekt mit einer Methode zurückgeben
      return {
        //getClientId findet DOM-Knoten, deren ID mit sComponentId endet
        getClientId: function(sComponentId) {
          var arrNodes=query("[id$='"+sComponentId+"']");
          if (arrNodes && arrNodes.length>0) {
            var sId=arrNodes[0].id;
            return sId;
          }
       }
      }
    });

## require

Verwenden des definierten Moduls:

- Package-Ort bekanntmachen
- Module/Klasse laden

    <script type="text/javascript">
    dojoConfig={
      packages:[
        { name:'mindoo', location:'/subdir/db.nsf/dojo/mindoo' }
      ]
    }
    </script>
    <script type="text/javascript" src="path/to/dojo.js"></script>
    <script type="text/javascript">
      //Klassenname des neuen Modus an require übergeben:
      require(['mindoo/tools/XspUtil', 'dojo/domReady!'],
        function(XspUtil, domReady) {
          //neu definierte Methode aufrufen:
          var clientId=XspUtil.getClientId('mytextfield');
          alert(clientId); // view:_id1:mytextfield
      });
    </script>

## define für Fortgeschrittene

Vererbung von Klassen mit define:

    define(['dojo/_base/declare', 'dojox/data/QueryReadStore'],
      function(declare, QueryReadStore) {
        //Klasse "mindoo/data/QueryReadStoreExt" von
        //"dojox/data/QueryReadStore" ableiten
        //1. Parameter mit Klassenname in declare() ist optional,
        //wird globale Variable:
        return declare("mindoo/data/QueryReadStoreExt", [QueryReadStore], {

           fetch:function(request) {
             request.serverQuery = {q:request.query.name};

             //Methode der Elternklasse aufrufen:
             return this.inherited("fetch", arguments);
           }
        });
    });

Ergebnis kann per require geladen werden und mit new instanziiert.

## Laden von Dateien

- AMD-Spezialmodul "module" liefert Pfad zur aktuellen Klasse
- AMD-Plugin "dojo/text" lädt Dateien per Ajax

    require(['module', 'dojo/dom'],
      function(module, dom) {
        var moduleUri=module.uri;

         //Pfad zu template berechnen
         var templatePath=moduleUri+"/../templates/mytemplate.html";

         //HTML-Datei laden
         require(['dojo/text!' + templatePath], function(template) {
            dom.byId('content').innerHTML = template;
         });
    });

Parsen von Template und Wertersetzung z.B. über
Django Template Language dojox/dtl

## Das hat Potenzial!

Demo: Activity Stream in NSF

## Integration in XPages

## Widgets verwenden

Dojo-Option "parseOnLoad" über Dojo-Panel der XPage aktivieren:

## Widgets verwenden

Benötigte Dojo-Klassen im Ressourcen-Tab eintragen:

Notation mit " . " in R9 Beta hier erforderlich, um JS-Optimizer verwenden zu können

## Widgets verwenden

- Tags mit Dojo-Typ und -Attributen ausstatten
- für Layout-Widgets wahlweise xp:div oder xp:panel

## Widgets verwenden

Analoges vorgehen für Felder:

## Eigene Klassen verwenden

Package-Location definieren über
"Resources / Add / Dojo Module Path Resource",
dann Klasse als "Dojo Module" aufnehmen

## Eigene Klassen verwenden

Ort der Dojo-Datei im DB-Design (Package-Explorer)

## Partial-Refresh-feste Oberflächen

- Partial Refresh sendet Feldinhalte an Server, dieser berechnet Seitenbereich neu
- Rückgabe-HTML wird in Seite eingefügt und auf Dojo-Widgets-Markup geprüft
- führt ggf. zu Zurücksetzen von Widget-Eigenschaften:
  aktiver Reiter, Scrollposition in BorderContainer etc.
- Lösung: Partial Refresh selektiv einsetzen oder gar nicht

## Endlich lesbare Dojo-Quelltexte!

- neue Eigenschaft in Notes/Domino R9:
  "Use uncompressed resource files (CSS & Dojo)"
- Gold wert beim Debuggen von Problemen

# Vielen Dank!

### Zeit für Fragen!

## Ressourcen

Argumente für Dojo

- 10 Reasons Why Your Projects Should Use the Dojo Toolkit

Dojo Features

- Differences between 1.6 and 1.7
- What's coming in Dojo 1.8 | The Dojo Toolkit Blog
- Dojo 1.8 Release Notes — The Dojo Toolkit - Reference Guide
- Calendar Sample: Desktop
- Learning Dojo 1.8 | Blog | SitePen

## Ressourcen

Dojo Features

- API Documentation - The Dojo Toolkit
- assonos blog : dojo-Artikelserie und Vortrag

Dojo Mobile 1.7 und 1.8

- Dojo Mobile Showcase
- Get started with Dojo Mobile 1.7
- Dojo Mobile 1.7 New Widgets
- Dojo Mobile 1.8 Work-In-Progress
- What's new in Dojo Mobile 1.8, Part 1
- What's new in Dojo Mobile 1.8, Part 2
- What's new in Dojo Mobile 1.8, Part 3

## Ressourcen

Dojo 2.0

- Dojo 2.0: Modular, Mobile, and Reinventing Web App Development

Layouts

- Dijit layout — The Dojo Toolkit - Reference Guide
- DojoX Portlet In a GridContainer example
- Layout with Dijit - The Dojo Toolkit

Dojo-Forms

- Forms and Validation - The Dojo Toolkit
- dojo dijit.form.DateTextBox constraints

## Ressourcen

Event-Handling

- Events with Dojo - The Dojo Toolkit
- Using dojo/aspect
- Keyboard Events with Dojo - The Dojo Toolkit

Drag and Drop

- Dojo Drag'n'Drop Redux | Blog | SitePen

AMD

- Learn more about AMD! | The Dojo Toolkit Blog
- The Dojo Loader — The Dojo Toolkit - Reference Guide
- Defining Modules - The Dojo Toolkit
- Differences between CommonJS wrapper and AMD define

## Ressourcen

AMD

- dojo/domReady! — The Dojo Toolkit - Reference Guide
- dojo/text — The Dojo Toolkit - Reference Guide

Special effects

- Gruppler's Effect Demos
- Textillate.js
- Parallax Scrolling
- Scrollorama

Mobile Scrollpane

- iScroll 4

## Ressourcen

Alternative UI-Komponenten

- Create a Clearable TextBox with the Dojo Toolkit
- Demos - JavaScript InfoVis Toolkit
- Icicle - Icicle Tree with static JSON data
- Icicle - Icicle tree with limited levels shown
- Fixed Icicle request loading - philogb/jit - GitHub
- Highcharts

Custom Builds

- Creating Builds - The Dojo Toolkit

## Ressourcen

Sonstiges

- ensure - Ensures relevant script and html are loaded
- Wink toolkit - A mobile JavaScript framework
- 10 Great Google Font Combinations You Can Copy
- Findings
- CoolCarousels - Showcasing 64 cool jQuery carousel examples