SlideShare a Scribd company logo
The Joy of writing JavaScript Applications
How Qooxdoo puts the fun back into programming for the
                        web


                     Tobias Oetiker

                 OETIKER+PARTNER AG


22nd Large Installation System Administration Conference
The Browser: my application platform




      Applications in the Browser: Netscapes original Plan.
      Performance: SquirelFish, V8, Tracemonkey engines.
      JavaScript graduated with Web 2.0
      Widget libraries for breakfast, lunch and dinner.
      A separte hack for every browser.
Qooxdoo: application in the browser




      Web 2.0 is all about the look and feel.
      Web pages with eye candy.
      Applications running in the browser.
      Back to client/server computing.
      Qooxdoo is a complete environment.
Qooxdoo features



      Turns JS into a grown up OO language.
      No HTML or CSS knowledge required.
      Cross Browser: >= FF 1.5, Safari 3, Chrome, IE6, Opera8.
      Multilingual.
      Full API Documentation.
      Users works ’inside the box’.
      LGPL, EPL
      Fun.
Jump right in




      Install Python. http://www.python.org/download/
      Unpack Qooxdoo. http://qooxdoo.org/download/
      Get Js2-mode for emacs
      http://code.google.com/p/js2-mode/
      Do this NOW!
Jump right in




      Install Python. http://www.python.org/download/
      Unpack Qooxdoo. http://qooxdoo.org/download/
      Get Js2-mode for emacs
      http://code.google.com/p/js2-mode/
      Do this NOW!
Generating the first application


      Point your path to qooxdoo-0.8-sdk/tools/bin
      Change directory to your development space.
      Run create-application.py –name hello
      CD into the hello directory.
      Run generate.py source
      Point your browser to hello/source/index.html
Generating the first application


      Point your path to qooxdoo-0.8-sdk/tools/bin
      Change directory to your development space.
      Run create-application.py –name hello
      CD into the hello directory.
      Run generate.py source
      Point your browser to hello/source/index.html
generated files



   hello/generate.py
   hello/config.json
   hello/source/resource/hello/test.png
   hello/source/translation/readme.txt
   hello/source/class/hello/test/DemoTest.js
   hello/source/class/hello/Application.js
   hello/source/index.html
   hello/Manifest.json
   hello/readme.txt
source code: hello/source/class/hello/Application.js I
 1   /* Tell qooxdoo that we need the resources in hello /*
 2   # asset ( hello /*)
 3   */
 4   qx . Class . define ( quot; hello . Application quot; ,
 5   {
 6      extend : qx . application . Standalone ,
 7      members :
 8      {
 9         main : function ()
10         {
11           // Call super class
12           this . base ( arguments );
13           // Enable logging in debug variant
14           if ( qx . core . Variant . isSet ( quot; qx . debug quot; , quot; on quot; ))
15           { // native logging capabilities
16              qx . log . appender . Native ;
17              // additional cross - browser console .
18              // Press F7 to toggle visibility
19              qx . log . appender . Console ;
20           }
source code: hello/source/class/hello/Application.js II

21             // Create a button
22             var button1 = new qx . ui . form . Button (
23                                     quot; First Button quot; , quot; hello / test . png quot; );
24             // Document is the application root
25             var doc = this . getRoot ();
26             // Add button to document at fixed coordinates
27             doc . add ( button1 , { left : 100 , top : 50});
28             // Add an event listener
29             button1 . addListener ( quot; execute quot; , function ( e ) {
30               alert ( quot; Hello World ! quot; );
31             });
32         }
33     }
34   });

     The original Qooxdoo hello world application,
     modified to fit the slide.
Qooxdoo and JavaScript




      It’s just like Perl and OO
      It’s all about anonymous functions
      and closures . . . and scoping.
Qooxdoo and JavaScript




      It’s just like Perl and OO
      It’s all about anonymous functions
      and closures . . . and scoping.
Qooxdoo and JavaScript




      It’s just like Perl and OO
      It’s all about anonymous functions
      and closures . . . and scoping.
A function pointer example




1   var add_alert = function (a , b ){
2       alert ( ’ The Result is : ’ +( a + b ));
3   }
4   add_alert (1 ,2);
Scoping for the naïve

    You know scoping from other languages
1   var j = 100;
2   var z = 22;
3   for ( var z = 1; z <10; z ++){
4      var j = z ;
5   }
6   alert ( ’ And the Winner is j : ’+ j + ’ z : ’+ z );




                             Or so you thought
Scoping for the naïve

    You know scoping from other languages
1   var j = 100;
2   var z = 22;
3   for ( var z = 1; z <10; z ++){
4      var j = z ;
5   }
6   alert ( ’ And the Winner is j : ’+ j + ’ z : ’+ z );




                             Or so you thought
Scoping for the disillusioned

    JavaScript scoping works only within function blocks.
1   var j = 100;
2   var z = 22;
3   for ( var z = 1; z <10; z ++){( function (){
4      var j = z ;
5   })()}
6   alert ( ’ And the Winner is j : ’+ j + ’ z : ’+ z );




                Note that z is outside the function block!
Scoping for the disillusioned

    JavaScript scoping works only within function blocks.
1   var j = 100;
2   var z = 22;
3   for ( var z = 1; z <10; z ++){( function (){
4      var j = z ;
5   })()}
6   alert ( ’ And the Winner is j : ’+ j + ’ z : ’+ z );




                Note that z is outside the function block!
A simple closures example
 1   var set ;
 2   var get ;
 3   var j =2;
 4   ( function (){ // the magic javascript scope trick
 5       var j ;
 6       set = function ( x ){ j = x };
 7       get = function (){ alert ( ’ Hidden j is ’+ j )};
 8   })(); // end of scope
 9   set (33);
10   get ();
11   alert ( ’ Outside j is still ’+ j );




                       Everything as expected.
A simple closures example
 1   var set ;
 2   var get ;
 3   var j =2;
 4   ( function (){ // the magic javascript scope trick
 5       var j ;
 6       set = function ( x ){ j = x };
 7       get = function (){ alert ( ’ Hidden j is ’+ j )};
 8   })(); // end of scope
 9   set (33);
10   get ();
11   alert ( ’ Outside j is still ’+ j );




                       Everything as expected.
A simple closures example
 1   var set ;
 2   var get ;
 3   var j =2;
 4   ( function (){ // the magic javascript scope trick
 5       var j ;
 6       set = function ( x ){ j = x };
 7       get = function (){ alert ( ’ Hidden j is ’+ j )};
 8   })(); // end of scope
 9   set (33);
10   get ();
11   alert ( ’ Outside j is still ’+ j );




                       Everything as expected.
A broken function factory

1   var j = [];
2   for ( var z = 1; z <10; z ++){
3       var g = z ;
4       j [ g ] = function ( a ){
5              alert ( ’ The value for j [ ’ + a + ’] is ’+ g );
6       };
7   }
8   j [2](2);




            JavaScript! Has! No! Scope! For! Loop! Blocks!
A broken function factory

1   var j = [];
2   for ( var z = 1; z <10; z ++){
3       var g = z ;
4       j [ g ] = function ( a ){
5              alert ( ’ The value for j [ ’ + a + ’] is ’+ g );
6       };
7   }
8   j [2](2);




            JavaScript! Has! No! Scope! For! Loop! Blocks!
A broken function factory

1   var j = [];
2   for ( var z = 1; z <10; z ++){
3       var g = z ;
4       j [ g ] = function ( a ){
5              alert ( ’ The value for j [ ’ + a + ’] is ’+ g );
6       };
7   }
8   j [2](2);




            JavaScript! Has! No! Scope! For! Loop! Blocks!
A working function factory

1   var j = [];
2   for ( var z = 1; z <10; z ++){( function (){ // for a block
3       var g = z ;
4       j [ g ] = function ( a ){
5              alert ( ’ The value for j [ ’ + a + ’] is ’+ g );
6       };
7   })()} // end of block
8   j [2](2);




       Again the anonymous function trick comes to the rescue.
A working function factory

1   var j = [];
2   for ( var z = 1; z <10; z ++){( function (){ // for a block
3       var g = z ;
4       j [ g ] = function ( a ){
5              alert ( ’ The value for j [ ’ + a + ’] is ’+ g );
6       };
7   })()} // end of block
8   j [2](2);




       Again the anonymous function trick comes to the rescue.
fun with this

1   var hello = {
2             world : ’ You ’ ,
3             show : function (){
4       alert ( ’ Hello ’+ this . world + ’ this : ’+ this ); }
5   };
6   hello . show ();              // method call
7   var plain = hello . show ; // function pointer
8   var world = ’ Me ’;           // change this . world
9   plain ();                     // method call




    this refers to                   this refers to the browsers
    the hello object.                base Window object.
fun with this

1   var hello = {
2             world : ’ You ’ ,
3             show : function (){
4       alert ( ’ Hello ’+ this . world + ’ this : ’+ this ); }
5   };
6   hello . show ();              // method call
7   var plain = hello . show ; // function pointer
8   var world = ’ Me ’;           // change this . world
9   plain ();                     // method call




    this refers to                   this refers to the browsers
    the hello object.                base Window object.
Class definition



    In its most basic form, a Qooxdoo class is very simple.
1   qx . Class . define ( ’ my . first . Class ’ );

    In reality you would use something like this
1   qx . Class . define ( quot; my . cool . Class quot; , {
2      // declare constructor , members , ...
3   });

    A regular class can then be instantiated
1   var myClass = new my . cool . Class ;
Class inheritance



    The map contains the meat of the class.
1   qx . Class . define ( quot; my . cool . Class quot; ,
2   {
3      extend : my . great . SuperClass ,
4      construct : function () { ... } ,
5      destruct : function () { ... }
6   });

    Embrace and extend.
Static members


    Static member names are in the statics key.
    They use UPPERCASE names by convention.
1   qx . Class . define ( quot; my . cool . Class quot; , {
2      statics : {
3         FOO : VALUE ,
4         BAR : function () { ... }
5      }
6   });

    Static members are accessed with their full name:
1   my . cool . Class . FOO = 3.141;
2   my . cool . Class . BAR ();
Static members


    Static member names are in the statics key.
    They use UPPERCASE names by convention.
1   qx . Class . define ( quot; my . cool . Class quot; , {
2      statics : {
3         FOO : VALUE ,
4         BAR : function () { ... }
5      }
6   });

    Static members are accessed with their full name:
1   my . cool . Class . FOO = 3.141;
2   my . cool . Class . BAR ();
Instance Members


    Instance members reside in the members map.
1   qx . Class . define ( quot; my . cool . Class quot; , {
2      members : {
3         foo : VALUE ,
4         bar : function () { ... }
5      }
6   });

    Use new to create an instance.
1   var myClass1 = new my . cool . Class ;
2   myClass1 . foo = 3.141;
3   myClass1 . bar ();
Instance Members


    Instance members reside in the members map.
1   qx . Class . define ( quot; my . cool . Class quot; , {
2      members : {
3         foo : VALUE ,
4         bar : function () { ... }
5      }
6   });

    Use new to create an instance.
1   var myClass1 = new my . cool . Class ;
2   myClass1 . foo = 3.141;
3   myClass1 . bar ();
Calling the Superclass


 1   qx . Class . define ( quot; my . cool . Class quot; ,
 2   {
 3      extend : my . great . SuperClass ,
 4      construct : function ( x ) {
 5         this . base ( arguments , x ); // superclass constructor
 6      }
 7      members : {
 8         foo : function ( x ) {
 9           this . base ( arguments , x );
10         }
11      }
12   });

     The this.base construct works for both constructor and
     member functions.
Generic access to static members


 1   qx . Class . define ( quot; my . cool . Class quot; ,
 2   {
 3      extend : qx . core . Object ,
 4      construct : function ( x ){ this . base ( arguments , x )} ,
 5      statics : {
 6         PI : 3.141
 7      }
 8      members : {
 9         circumference : function ( radius ) {
10           return 2 * this . self ( arguments ). PI * radius ;
11         }
12      }
13   });

     this.self only works for subclasses of qx.core.Object
mixins


1   qx . Mixin . define ( ’ my . cool . MMixin ’ ,{
2         // code and variables like in a class
3   });

    Like classes, but without inheritance.
    By convention Mixin names start with ’M’.
1   qx . Class . define ( ’ my . cool . Class ’ , {
2      include : [ my . cool . MMixin , my . other . cool . MMixin ]
3      ...
4   });

    Include mixins when creating new classes.
1   qx . Class . include ( qx . ui . core . Widget , qx . MWidgetFeatures );

    Or even inject them into an existing class.
class access control




    There is the following naming convention for class members.
1   publicMember
2   _protectedMember
3   __privateMember

    In the Qooxdoo build process it is optionally possible to
    randomize the names of private members to protect access.
static, abstract and singleton classes

1   qx . Class . define ( ’ my . static . Class ’ , {
2      type : ’ static ’
3      statics : { ... };
4   });

    Neither members nor constructors are allowed in static classes.
1   qx . Class . define ( ’ my . abstract . Class ’ , {
2      type : ’ abstract ’
3   });

    Abstract classes must be sub-classed for use.
1   qx . Class . define ( ’ my . singleton . Class ’ , {
2      type : ’ singleton ’
3   });
4   var instance = my . singleton . Class . getIntance ()

    There is only one instance which gets created on the first call.
Browser specific code


     Normally Qooxdoo takes care of all browser differences, but if
     you must intervene . . .
 1   members : {
 2     foo : qx . core . Variant . select (
 3       ’ qx . bom . client . Engine . NAME ’ , {
 4          ’ mshtml | opera ’: function () {
 5              // Internet Explorer or Opera
 6          },
 7          ’ default ’: function () {
 8              // All other browsers
 9          }
10       }
11     )
12   }
The demo Browser




1   $ cd $QX / frontend / application / demobrowser /
2   $ ./ generate . py build
3   $ gnome - open build / index . html

    Or surf to http://demo.qooxdoo.org/current/demobrowser
The API Documentation




1   $ cd $QX / frontend / framework
2   $ ./ generate . py api
3   $ gnome - open api / index . html

    Or surf to http://demo.qooxdoo.org/current/apiviewer
The Qooxdoo generator


  Python is the sole dependency
      generator.py is the tool
      it gets called by generate.py
  The generator has many functions
      source - prep development code
      build - prep code for deployment
      api - build api doc
      lint - check your code for beauty
      pretty - fix the code layout
      ...
Running your Qooxdoo program in source




    Use source code during development
1   $ cd hello
2   $ ./ generate . py source
3   $ gnome - open source / index . html

    As long as you do not use any new classes, press reload in the
    browser to see changes.
Deploying your Qooxdoo program




1   $ cd hello
2   $ ./ generate . py build
3   $ cp - rp build ~/ public_html / hello

        only two js files
        code gets optimized and compressed
        no external dependencies
Button, TextField and some Action
 1   // Create a textfield
 2   var tf1 = new qx . ui . form . TextField ( ’ Demo Text ’ );
 3   // Add button to root
 4   root . add ( tf1 , { column : 0 , row : 0});
 5   // Create a button
 6   var bt1 = new qx . ui . form . Button (
 7           ’ Open Alert ’ , ’ lisa08 / test . png ’ );
 8   // Add button to root
 9   root . add ( bt1 , { column : 1 , row : 0});
10   // Add an event listener
11   bt1 . addListener ( ’ execute ’ , function ( e ) {
12     // closure !!
13     this . info ( ’ TextField : ’+ tf1 . getValue ());
14     alert ( ’ TextField : ’ + tf1 . getValue ());
15   });




     Try F7 to see inline console!
The Layout Manager



     Qooxdoo Widgets can contain other widgets.
     Layout manager positions child widgets.
     qx.ui.container.Composite basic
     qx.ui.container.Scroll draws scroll bars
     qx.ui.window.Window directs children to an inner
     composite pane.
     Layout manager set at construction time
     Modified with setLayout method.
Container and Layout
 1   // a container with horizontal layouyt manager
 2   var hbox = new qx . ui . layout . HBox ();
 3   hbox . setSpacing (4); // set property
 4
 5   // assign layout
 6   var ctr1 = new qx . ui . container . Composite ( hbox );
 7   ctr1 . setWidth (600); ctr1 . setHeight (40);
 8   // layout properties : position
 9   root . add ( ctr1 ,{ column : 0 , row : 1 , colSpan : 2});
10
11   var tf2 = new qx . ui . form . TextField ( ’ Some More Text ’ );
12   var bt2 = new qx . ui . form . ToggleButton ( ’ AllowGrowY ’ );
13   bt2 . addListener ( ’ changeChecked ’ , function ( e ) {
14         // modify widget property
15         tf2 . setAllowGrowY ( e . getData ());
16             this . info ( ’ New Value for AllowGrowY : ’+ e . getData ());
17   });
18   ctr1 . add ( tf2 ); ctr1 . add ( bt2 );
Grid Layout




      qx.ui.layout.Grid
      fully dynamic
      ideal for dialogs
      one widget per cell
      row and column spans
      minimal and maximal column and row sizes
      fixed row and column sizes
About the Qooxdoo Layout Widgets


      A container widget needs a layout manager to place its
      children.
      The layout manager object has properties.
      Every widget has basic properties like: alignment,
      growability, shrinkability, stretchability, margins, padding,
      width and height.
      Each widget can have layout-specific properties.
      Layout properties get checked as the widget is added to a
      layout.
  Lets play with the layout demos!
Localized Applications
 1   var lmgr = qx . locale . Manager . getInstance ();
 2   var bt3 = new qx . ui . form . ToggleButton (
 3         this . tr ( ’ Translate ! ’)
 4   );
 5   root . add ( bt3 , { column : 1 , row : 3});
 6   bt3 . addListener ( ’ changeChecked ’ , function ( e ) {
 7         var lang = e . getData () ? ’ de ’ : ’ en ’;
 8         lmgr . setLocale ( lang );
 9         this . info ( ’ Language set to : ’+ lang );
10   });

         add locale to config.json
         ./generate.py translation
         translate de.po
         ./generate.py source
calling code on the server




      JSON RPC for transport
      various language bindings
      often minimal server code
      async with callbacks
      qx.io.Rpc
An RPC Example: Client
 1   var rpc = new qx . io . remote . Rpc ( ’ jsonrpc . cgi ’ , ’ myclass ’ );
 2   var bt4 = new qx . ui . form . Button ( this . tr ( ’ Call RPC ’ ));
 3   root . add ( bt4 , { column : 1 , row : 4});
 4   var that = this ; // we want this ’ this ’!
 5   var callback = function ( result , ex , id ) {
 6         that . RpcRunning = null ; // free the reference
 7         if ( ex == null ) {
 8              alert ( ’ The RPC call returned : ’+ result );
 9              that . info ( ’ RPC call returned : ’+ result );
10         } else {
11              alert ( ’ Async ( ’ + id + ’) exception : ’ + ex );
12              that . error ( ’ Async ( ’ + id + ’) exception : ’ + ex );
13         }
14   };
15   bt4 . addListener ( ’ execute ’ , function ( e ) {
16         that . RpcRunning = rpc . callAsync (
17              callback , ’ mymethod ’ , ’ Hello ’ );
18   });

     The example only works on a cgi enabled webserver.
An RPC Example: Server CGI
     source/jsonrpc.cgi:
 1   # !/ usr / bin / perl -w
 2   use strict ;
 3   use lib qw ( perl );
 4
 5   use CGI ;
 6   # use CGI :: Fast ;
 7   use CGI :: Session ;
 8   use Qooxdoo :: JSONRPC ;
 9
10   # $Qooxdoo :: JSONRPC :: debug =1;
11   my $cgi = new CGI ;
12   # while ( my $cgi = new CGI :: Fast ){
13       my $session = new CGI :: Session ;
14       Qooxdoo :: JSONRPC :: handle_request ( $cgi , $session );
15   # }

     For best performance use CGI::Fast and configure
     CGI::Session to keep the session data in a database.
An RPC Example: the myclass service

     source/perl/Qooxdoo/Services/myclass.pm:
 1   package Qooxdoo :: Services :: myclass ;
 2   use strict ;
 3
 4   # for now let everyone access the methods
 5   sub GetAccessibility { ’ public ’ };
 6
 7   sub method_mymethod {
 8       my $error = shift ;
 9       my $arg = shift ;
10       return ’ The argument was : ’. $arg ;
11   }
12
13   1;

     The myclass module gets loaded dynamically.
An RPC Example: Getting it to work



      Install language bindings from Qooxdoo website.
      ln -s /var/www/lisa08 build
      ./generate.py build
      cp -rp source/jsonrpc.cgi source/perl build
      Open the application in the browser.
      Make sure the cgis are actually executed
      Watch the Apache error log while testing.
Organizing the code into multiple classes



      Object orientation “by the book”.
      One file per class.
      Java’s file name based approach.
      Supported by the generator.
      Ideal for code re-use.
      Use Inline Docs!
      ./generate.py api
The textclick class I
 1   /* *
 2     * textclick combines a textfield and a button .
 3     */
 4   qx . Class . define ( quot; lisa08 . ui . textclick quot; ,
 5   {
 6      extend : qx . ui . container . Composite ,
 7      /* *
 8        * @param button_text { String } button text .
 9        */
10      construct : function ( button_text ) {
11         this . base ( arguments ,
12              new qx . ui . layout . HBox (). set ({ spacing : 4})
13         );
14         this . __tf = new qx . ui . form . TextField ();
15         this . __bt = new qx . ui . form . Button ( button_text );
16         this . add ( this . __tf );
17         this . add ( this . __bt );
18      },
19
20
The textclick class II


21     members :
22     {
23     /* *
24       * Get a handle to the Button widget .
25       */
26        getButton : function () { return this . __bt } ,
27     /* *
28       * Get a handle to the TextField widget .
29       */
30        getTextField : function () { return this . __tf } ,
31        __bt : null ,
32        __tf : null
33     }
34   });
Using the textclick class



1   var mywi = new lisa08 . ui . textclick (
2               this . tr ( ’ Copy Text from Example 1 ’ ));
3
4   mywi . getButton (). addListener ( ’ execute ’ , function ( e ) {
5        mywi . getTextField (). setValue ( tf1 . getValue ());
6        this . info ( ’ Set textfield to ’+ tf1 . getValue ());
7   });
8
9   root . add ( mywi ,{ column : 0 , row : 5 , colSpan : 2});
The Message Bus

         Communication in “large” applications.
         Singleton message bus class.
         Careful with references: memory leaks!

 1   var mywi2 = new lisa08 . ui . textclick (
 2                            this . tr ( ’ Send Hello to Textfield ’ ));
 3   var bus = qx . event . message . Bus . getInstance ();
 4   mywi2 . getButton (). addListener ( ’ execute ’ , function ( e ) {
 5         bus . dispatch ( ’ mybus .1 ’ , ’ Hello World ’ );
 6         this . info ( ’ Sent Hello World on this bus ’ );
 7   } , this ); // context provided for console
 8   bus . subscribe ( ’ mybus .1 ’ , function ( m ){
 9         mywi2 . getTextField (). setValue ( m . getData ());
10         this . info ( ’ Got ’+ m . getData ()+ ’ from the bus ’ );
11   } , this );
12
13   root . add ( mywi2 ,{ column : 0 , row : 6 , colSpan : 2});
Code walk through of the SmokeTrace application.
?
Tobi Oetiker <tobi@oetiker.ch>

More Related Content

What's hot

TDD per Webapps
TDD per WebappsTDD per Webapps
TDD per Webapps
CarloBottiglieri
 
Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 6/8Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 6/8
Wilson Su
 
Server1
Server1Server1
Server1
FahriIrawan3
 
Oxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resourcesOxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resources
corehard_by
 
Practical JavaScript Programming - Session 5/8
Practical JavaScript Programming - Session 5/8Practical JavaScript Programming - Session 5/8
Practical JavaScript Programming - Session 5/8
Wilson Su
 
Building fast interpreters in Rust
Building fast interpreters in RustBuilding fast interpreters in Rust
Building fast interpreters in Rust
Ingvar Stepanyan
 
Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 1/8Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 1/8
Wilson Su
 
Rust ⇋ JavaScript
Rust ⇋ JavaScriptRust ⇋ JavaScript
Rust ⇋ JavaScript
Ingvar Stepanyan
 
Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516
SOAT
 
The Ring programming language version 1.5.4 book - Part 69 of 185
The Ring programming language version 1.5.4 book - Part 69 of 185The Ring programming language version 1.5.4 book - Part 69 of 185
The Ring programming language version 1.5.4 book - Part 69 of 185
Mahmoud Samir Fayed
 
Nantes Jug - Java 7
Nantes Jug - Java 7Nantes Jug - Java 7
Nantes Jug - Java 7
Sébastien Prunier
 
Javascript basics
Javascript basicsJavascript basics
Javascript basics
Fin Chen
 
Project fast food automaton
Project fast food automatonProject fast food automaton
Project fast food automaton
varun arora
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
matuura_core
 
The Ring programming language version 1.5.1 book - Part 9 of 180
The Ring programming language version 1.5.1 book - Part 9 of 180The Ring programming language version 1.5.1 book - Part 9 of 180
The Ring programming language version 1.5.1 book - Part 9 of 180
Mahmoud Samir Fayed
 
Wwe Management System
Wwe Management SystemWwe Management System
Wwe Management System
NeerajMudgal1
 
20110424 action scriptを使わないflash勉強会
20110424 action scriptを使わないflash勉強会20110424 action scriptを使わないflash勉強会
20110424 action scriptを使わないflash勉強会Hiroki Mizuno
 

What's hot (18)

TDD per Webapps
TDD per WebappsTDD per Webapps
TDD per Webapps
 
Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 6/8Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 6/8
 
Server1
Server1Server1
Server1
 
Oxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resourcesOxygine 2 d objects,events,debug and resources
Oxygine 2 d objects,events,debug and resources
 
Practical JavaScript Programming - Session 5/8
Practical JavaScript Programming - Session 5/8Practical JavaScript Programming - Session 5/8
Practical JavaScript Programming - Session 5/8
 
Sbaw091006
Sbaw091006Sbaw091006
Sbaw091006
 
Building fast interpreters in Rust
Building fast interpreters in RustBuilding fast interpreters in Rust
Building fast interpreters in Rust
 
Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 1/8Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 1/8
 
Rust ⇋ JavaScript
Rust ⇋ JavaScriptRust ⇋ JavaScript
Rust ⇋ JavaScript
 
Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516
 
The Ring programming language version 1.5.4 book - Part 69 of 185
The Ring programming language version 1.5.4 book - Part 69 of 185The Ring programming language version 1.5.4 book - Part 69 of 185
The Ring programming language version 1.5.4 book - Part 69 of 185
 
Nantes Jug - Java 7
Nantes Jug - Java 7Nantes Jug - Java 7
Nantes Jug - Java 7
 
Javascript basics
Javascript basicsJavascript basics
Javascript basics
 
Project fast food automaton
Project fast food automatonProject fast food automaton
Project fast food automaton
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
 
The Ring programming language version 1.5.1 book - Part 9 of 180
The Ring programming language version 1.5.1 book - Part 9 of 180The Ring programming language version 1.5.1 book - Part 9 of 180
The Ring programming language version 1.5.1 book - Part 9 of 180
 
Wwe Management System
Wwe Management SystemWwe Management System
Wwe Management System
 
20110424 action scriptを使わないflash勉強会
20110424 action scriptを使わないflash勉強会20110424 action scriptを使わないflash勉強会
20110424 action scriptを使わないflash勉強会
 

Viewers also liked

Heden, verleden en toekomst van video conferencing
Heden, verleden en toekomst van video conferencingHeden, verleden en toekomst van video conferencing
Heden, verleden en toekomst van video conferencing
robert blaas
 
Penelitian Pasar Pameran
Penelitian Pasar PameranPenelitian Pasar Pameran
Penelitian Pasar PameranNoersal Samad
 
Persiapan Sebelum Mengunjungi Objek Wisata Alam
Persiapan Sebelum Mengunjungi Objek Wisata AlamPersiapan Sebelum Mengunjungi Objek Wisata Alam
Persiapan Sebelum Mengunjungi Objek Wisata AlamNoersal Samad
 
The role of TANDBERG videoconferencing in the new way of working
The role of TANDBERG videoconferencing in the new way of workingThe role of TANDBERG videoconferencing in the new way of working
The role of TANDBERG videoconferencing in the new way of working
robert blaas
 
LISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsLISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial Handouts
Tobias Oetiker
 

Viewers also liked (6)

Heden, verleden en toekomst van video conferencing
Heden, verleden en toekomst van video conferencingHeden, verleden en toekomst van video conferencing
Heden, verleden en toekomst van video conferencing
 
Penelitian Pasar Pameran
Penelitian Pasar PameranPenelitian Pasar Pameran
Penelitian Pasar Pameran
 
Persiapan Sebelum Mengunjungi Objek Wisata Alam
Persiapan Sebelum Mengunjungi Objek Wisata AlamPersiapan Sebelum Mengunjungi Objek Wisata Alam
Persiapan Sebelum Mengunjungi Objek Wisata Alam
 
The role of TANDBERG videoconferencing in the new way of working
The role of TANDBERG videoconferencing in the new way of workingThe role of TANDBERG videoconferencing in the new way of working
The role of TANDBERG videoconferencing in the new way of working
 
Web 2.0
Web 2.0Web 2.0
Web 2.0
 
LISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial HandoutsLISA Qooxdoo Tutorial Handouts
LISA Qooxdoo Tutorial Handouts
 

Similar to LISA QooxdooTutorial Slides

dojo.Patterns
dojo.Patternsdojo.Patterns
dojo.Patterns
Peter Higgins
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
Visual Engineering
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
Ganesh Samarthyam
 
Es6 hackathon
Es6 hackathonEs6 hackathon
Es6 hackathon
Justin Alexander
 
The mighty js_function
The mighty js_functionThe mighty js_function
The mighty js_functiontimotheeg
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
Michiel Borkent
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
Manoj Kumar
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
Michael Girouard
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
Guillaume Laforge
 
Groovy
GroovyGroovy
Groovy
Zen Urban
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
David Padbury
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 
Java script for web developer
Java script for web developerJava script for web developer
Java script for web developer
Chalermpon Areepong
 
Php 7 evolution
Php 7 evolutionPhp 7 evolution
Php 7 evolution
Félix Gómez López
 
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume LaforgeGR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
10 Catalyst Tips
10 Catalyst Tips10 Catalyst Tips
10 Catalyst Tips
Jay Shirley
 
Trimming The Cruft
Trimming The CruftTrimming The Cruft
Trimming The Cruft
Peter Higgins
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?
Christophe Porteneuve
 
Introduction to ES6 with Tommy Cresine
Introduction to ES6 with Tommy CresineIntroduction to ES6 with Tommy Cresine
Introduction to ES6 with Tommy Cresine
Movel
 

Similar to LISA QooxdooTutorial Slides (20)

dojo.Patterns
dojo.Patternsdojo.Patterns
dojo.Patterns
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Advanced Debugging Using Java Bytecodes
Advanced Debugging Using Java BytecodesAdvanced Debugging Using Java Bytecodes
Advanced Debugging Using Java Bytecodes
 
Es6 hackathon
Es6 hackathonEs6 hackathon
Es6 hackathon
 
The mighty js_function
The mighty js_functionThe mighty js_function
The mighty js_function
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
Groovy
GroovyGroovy
Groovy
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
Java script for web developer
Java script for web developerJava script for web developer
Java script for web developer
 
Php 7 evolution
Php 7 evolutionPhp 7 evolution
Php 7 evolution
 
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume LaforgeGR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
10 Catalyst Tips
10 Catalyst Tips10 Catalyst Tips
10 Catalyst Tips
 
Trimming The Cruft
Trimming The CruftTrimming The Cruft
Trimming The Cruft
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?
 
Introduction to ES6 with Tommy Cresine
Introduction to ES6 with Tommy CresineIntroduction to ES6 with Tommy Cresine
Introduction to ES6 with Tommy Cresine
 

Recently uploaded

GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Product School
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
Elena Simperl
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Ramesh Iyer
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 

Recently uploaded (20)

GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...Mission to Decommission: Importance of Decommissioning Products to Increase E...
Mission to Decommission: Importance of Decommissioning Products to Increase E...
 
Knowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and backKnowledge engineering: from people to machines and back
Knowledge engineering: from people to machines and back
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
Builder.ai Founder Sachin Dev Duggal's Strategic Approach to Create an Innova...
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 

LISA QooxdooTutorial Slides

  • 1. The Joy of writing JavaScript Applications How Qooxdoo puts the fun back into programming for the web Tobias Oetiker OETIKER+PARTNER AG 22nd Large Installation System Administration Conference
  • 2. The Browser: my application platform Applications in the Browser: Netscapes original Plan. Performance: SquirelFish, V8, Tracemonkey engines. JavaScript graduated with Web 2.0 Widget libraries for breakfast, lunch and dinner. A separte hack for every browser.
  • 3. Qooxdoo: application in the browser Web 2.0 is all about the look and feel. Web pages with eye candy. Applications running in the browser. Back to client/server computing. Qooxdoo is a complete environment.
  • 4. Qooxdoo features Turns JS into a grown up OO language. No HTML or CSS knowledge required. Cross Browser: >= FF 1.5, Safari 3, Chrome, IE6, Opera8. Multilingual. Full API Documentation. Users works ’inside the box’. LGPL, EPL Fun.
  • 5. Jump right in Install Python. http://www.python.org/download/ Unpack Qooxdoo. http://qooxdoo.org/download/ Get Js2-mode for emacs http://code.google.com/p/js2-mode/ Do this NOW!
  • 6. Jump right in Install Python. http://www.python.org/download/ Unpack Qooxdoo. http://qooxdoo.org/download/ Get Js2-mode for emacs http://code.google.com/p/js2-mode/ Do this NOW!
  • 7. Generating the first application Point your path to qooxdoo-0.8-sdk/tools/bin Change directory to your development space. Run create-application.py –name hello CD into the hello directory. Run generate.py source Point your browser to hello/source/index.html
  • 8. Generating the first application Point your path to qooxdoo-0.8-sdk/tools/bin Change directory to your development space. Run create-application.py –name hello CD into the hello directory. Run generate.py source Point your browser to hello/source/index.html
  • 9. generated files hello/generate.py hello/config.json hello/source/resource/hello/test.png hello/source/translation/readme.txt hello/source/class/hello/test/DemoTest.js hello/source/class/hello/Application.js hello/source/index.html hello/Manifest.json hello/readme.txt
  • 10. source code: hello/source/class/hello/Application.js I 1 /* Tell qooxdoo that we need the resources in hello /* 2 # asset ( hello /*) 3 */ 4 qx . Class . define ( quot; hello . Application quot; , 5 { 6 extend : qx . application . Standalone , 7 members : 8 { 9 main : function () 10 { 11 // Call super class 12 this . base ( arguments ); 13 // Enable logging in debug variant 14 if ( qx . core . Variant . isSet ( quot; qx . debug quot; , quot; on quot; )) 15 { // native logging capabilities 16 qx . log . appender . Native ; 17 // additional cross - browser console . 18 // Press F7 to toggle visibility 19 qx . log . appender . Console ; 20 }
  • 11. source code: hello/source/class/hello/Application.js II 21 // Create a button 22 var button1 = new qx . ui . form . Button ( 23 quot; First Button quot; , quot; hello / test . png quot; ); 24 // Document is the application root 25 var doc = this . getRoot (); 26 // Add button to document at fixed coordinates 27 doc . add ( button1 , { left : 100 , top : 50}); 28 // Add an event listener 29 button1 . addListener ( quot; execute quot; , function ( e ) { 30 alert ( quot; Hello World ! quot; ); 31 }); 32 } 33 } 34 }); The original Qooxdoo hello world application, modified to fit the slide.
  • 12. Qooxdoo and JavaScript It’s just like Perl and OO It’s all about anonymous functions and closures . . . and scoping.
  • 13. Qooxdoo and JavaScript It’s just like Perl and OO It’s all about anonymous functions and closures . . . and scoping.
  • 14. Qooxdoo and JavaScript It’s just like Perl and OO It’s all about anonymous functions and closures . . . and scoping.
  • 15. A function pointer example 1 var add_alert = function (a , b ){ 2 alert ( ’ The Result is : ’ +( a + b )); 3 } 4 add_alert (1 ,2);
  • 16. Scoping for the naïve You know scoping from other languages 1 var j = 100; 2 var z = 22; 3 for ( var z = 1; z <10; z ++){ 4 var j = z ; 5 } 6 alert ( ’ And the Winner is j : ’+ j + ’ z : ’+ z ); Or so you thought
  • 17. Scoping for the naïve You know scoping from other languages 1 var j = 100; 2 var z = 22; 3 for ( var z = 1; z <10; z ++){ 4 var j = z ; 5 } 6 alert ( ’ And the Winner is j : ’+ j + ’ z : ’+ z ); Or so you thought
  • 18. Scoping for the disillusioned JavaScript scoping works only within function blocks. 1 var j = 100; 2 var z = 22; 3 for ( var z = 1; z <10; z ++){( function (){ 4 var j = z ; 5 })()} 6 alert ( ’ And the Winner is j : ’+ j + ’ z : ’+ z ); Note that z is outside the function block!
  • 19. Scoping for the disillusioned JavaScript scoping works only within function blocks. 1 var j = 100; 2 var z = 22; 3 for ( var z = 1; z <10; z ++){( function (){ 4 var j = z ; 5 })()} 6 alert ( ’ And the Winner is j : ’+ j + ’ z : ’+ z ); Note that z is outside the function block!
  • 20. A simple closures example 1 var set ; 2 var get ; 3 var j =2; 4 ( function (){ // the magic javascript scope trick 5 var j ; 6 set = function ( x ){ j = x }; 7 get = function (){ alert ( ’ Hidden j is ’+ j )}; 8 })(); // end of scope 9 set (33); 10 get (); 11 alert ( ’ Outside j is still ’+ j ); Everything as expected.
  • 21. A simple closures example 1 var set ; 2 var get ; 3 var j =2; 4 ( function (){ // the magic javascript scope trick 5 var j ; 6 set = function ( x ){ j = x }; 7 get = function (){ alert ( ’ Hidden j is ’+ j )}; 8 })(); // end of scope 9 set (33); 10 get (); 11 alert ( ’ Outside j is still ’+ j ); Everything as expected.
  • 22. A simple closures example 1 var set ; 2 var get ; 3 var j =2; 4 ( function (){ // the magic javascript scope trick 5 var j ; 6 set = function ( x ){ j = x }; 7 get = function (){ alert ( ’ Hidden j is ’+ j )}; 8 })(); // end of scope 9 set (33); 10 get (); 11 alert ( ’ Outside j is still ’+ j ); Everything as expected.
  • 23. A broken function factory 1 var j = []; 2 for ( var z = 1; z <10; z ++){ 3 var g = z ; 4 j [ g ] = function ( a ){ 5 alert ( ’ The value for j [ ’ + a + ’] is ’+ g ); 6 }; 7 } 8 j [2](2); JavaScript! Has! No! Scope! For! Loop! Blocks!
  • 24. A broken function factory 1 var j = []; 2 for ( var z = 1; z <10; z ++){ 3 var g = z ; 4 j [ g ] = function ( a ){ 5 alert ( ’ The value for j [ ’ + a + ’] is ’+ g ); 6 }; 7 } 8 j [2](2); JavaScript! Has! No! Scope! For! Loop! Blocks!
  • 25. A broken function factory 1 var j = []; 2 for ( var z = 1; z <10; z ++){ 3 var g = z ; 4 j [ g ] = function ( a ){ 5 alert ( ’ The value for j [ ’ + a + ’] is ’+ g ); 6 }; 7 } 8 j [2](2); JavaScript! Has! No! Scope! For! Loop! Blocks!
  • 26. A working function factory 1 var j = []; 2 for ( var z = 1; z <10; z ++){( function (){ // for a block 3 var g = z ; 4 j [ g ] = function ( a ){ 5 alert ( ’ The value for j [ ’ + a + ’] is ’+ g ); 6 }; 7 })()} // end of block 8 j [2](2); Again the anonymous function trick comes to the rescue.
  • 27. A working function factory 1 var j = []; 2 for ( var z = 1; z <10; z ++){( function (){ // for a block 3 var g = z ; 4 j [ g ] = function ( a ){ 5 alert ( ’ The value for j [ ’ + a + ’] is ’+ g ); 6 }; 7 })()} // end of block 8 j [2](2); Again the anonymous function trick comes to the rescue.
  • 28. fun with this 1 var hello = { 2 world : ’ You ’ , 3 show : function (){ 4 alert ( ’ Hello ’+ this . world + ’ this : ’+ this ); } 5 }; 6 hello . show (); // method call 7 var plain = hello . show ; // function pointer 8 var world = ’ Me ’; // change this . world 9 plain (); // method call this refers to this refers to the browsers the hello object. base Window object.
  • 29. fun with this 1 var hello = { 2 world : ’ You ’ , 3 show : function (){ 4 alert ( ’ Hello ’+ this . world + ’ this : ’+ this ); } 5 }; 6 hello . show (); // method call 7 var plain = hello . show ; // function pointer 8 var world = ’ Me ’; // change this . world 9 plain (); // method call this refers to this refers to the browsers the hello object. base Window object.
  • 30. Class definition In its most basic form, a Qooxdoo class is very simple. 1 qx . Class . define ( ’ my . first . Class ’ ); In reality you would use something like this 1 qx . Class . define ( quot; my . cool . Class quot; , { 2 // declare constructor , members , ... 3 }); A regular class can then be instantiated 1 var myClass = new my . cool . Class ;
  • 31. Class inheritance The map contains the meat of the class. 1 qx . Class . define ( quot; my . cool . Class quot; , 2 { 3 extend : my . great . SuperClass , 4 construct : function () { ... } , 5 destruct : function () { ... } 6 }); Embrace and extend.
  • 32. Static members Static member names are in the statics key. They use UPPERCASE names by convention. 1 qx . Class . define ( quot; my . cool . Class quot; , { 2 statics : { 3 FOO : VALUE , 4 BAR : function () { ... } 5 } 6 }); Static members are accessed with their full name: 1 my . cool . Class . FOO = 3.141; 2 my . cool . Class . BAR ();
  • 33. Static members Static member names are in the statics key. They use UPPERCASE names by convention. 1 qx . Class . define ( quot; my . cool . Class quot; , { 2 statics : { 3 FOO : VALUE , 4 BAR : function () { ... } 5 } 6 }); Static members are accessed with their full name: 1 my . cool . Class . FOO = 3.141; 2 my . cool . Class . BAR ();
  • 34. Instance Members Instance members reside in the members map. 1 qx . Class . define ( quot; my . cool . Class quot; , { 2 members : { 3 foo : VALUE , 4 bar : function () { ... } 5 } 6 }); Use new to create an instance. 1 var myClass1 = new my . cool . Class ; 2 myClass1 . foo = 3.141; 3 myClass1 . bar ();
  • 35. Instance Members Instance members reside in the members map. 1 qx . Class . define ( quot; my . cool . Class quot; , { 2 members : { 3 foo : VALUE , 4 bar : function () { ... } 5 } 6 }); Use new to create an instance. 1 var myClass1 = new my . cool . Class ; 2 myClass1 . foo = 3.141; 3 myClass1 . bar ();
  • 36. Calling the Superclass 1 qx . Class . define ( quot; my . cool . Class quot; , 2 { 3 extend : my . great . SuperClass , 4 construct : function ( x ) { 5 this . base ( arguments , x ); // superclass constructor 6 } 7 members : { 8 foo : function ( x ) { 9 this . base ( arguments , x ); 10 } 11 } 12 }); The this.base construct works for both constructor and member functions.
  • 37. Generic access to static members 1 qx . Class . define ( quot; my . cool . Class quot; , 2 { 3 extend : qx . core . Object , 4 construct : function ( x ){ this . base ( arguments , x )} , 5 statics : { 6 PI : 3.141 7 } 8 members : { 9 circumference : function ( radius ) { 10 return 2 * this . self ( arguments ). PI * radius ; 11 } 12 } 13 }); this.self only works for subclasses of qx.core.Object
  • 38. mixins 1 qx . Mixin . define ( ’ my . cool . MMixin ’ ,{ 2 // code and variables like in a class 3 }); Like classes, but without inheritance. By convention Mixin names start with ’M’. 1 qx . Class . define ( ’ my . cool . Class ’ , { 2 include : [ my . cool . MMixin , my . other . cool . MMixin ] 3 ... 4 }); Include mixins when creating new classes. 1 qx . Class . include ( qx . ui . core . Widget , qx . MWidgetFeatures ); Or even inject them into an existing class.
  • 39. class access control There is the following naming convention for class members. 1 publicMember 2 _protectedMember 3 __privateMember In the Qooxdoo build process it is optionally possible to randomize the names of private members to protect access.
  • 40. static, abstract and singleton classes 1 qx . Class . define ( ’ my . static . Class ’ , { 2 type : ’ static ’ 3 statics : { ... }; 4 }); Neither members nor constructors are allowed in static classes. 1 qx . Class . define ( ’ my . abstract . Class ’ , { 2 type : ’ abstract ’ 3 }); Abstract classes must be sub-classed for use. 1 qx . Class . define ( ’ my . singleton . Class ’ , { 2 type : ’ singleton ’ 3 }); 4 var instance = my . singleton . Class . getIntance () There is only one instance which gets created on the first call.
  • 41. Browser specific code Normally Qooxdoo takes care of all browser differences, but if you must intervene . . . 1 members : { 2 foo : qx . core . Variant . select ( 3 ’ qx . bom . client . Engine . NAME ’ , { 4 ’ mshtml | opera ’: function () { 5 // Internet Explorer or Opera 6 }, 7 ’ default ’: function () { 8 // All other browsers 9 } 10 } 11 ) 12 }
  • 42. The demo Browser 1 $ cd $QX / frontend / application / demobrowser / 2 $ ./ generate . py build 3 $ gnome - open build / index . html Or surf to http://demo.qooxdoo.org/current/demobrowser
  • 43. The API Documentation 1 $ cd $QX / frontend / framework 2 $ ./ generate . py api 3 $ gnome - open api / index . html Or surf to http://demo.qooxdoo.org/current/apiviewer
  • 44. The Qooxdoo generator Python is the sole dependency generator.py is the tool it gets called by generate.py The generator has many functions source - prep development code build - prep code for deployment api - build api doc lint - check your code for beauty pretty - fix the code layout ...
  • 45. Running your Qooxdoo program in source Use source code during development 1 $ cd hello 2 $ ./ generate . py source 3 $ gnome - open source / index . html As long as you do not use any new classes, press reload in the browser to see changes.
  • 46. Deploying your Qooxdoo program 1 $ cd hello 2 $ ./ generate . py build 3 $ cp - rp build ~/ public_html / hello only two js files code gets optimized and compressed no external dependencies
  • 47. Button, TextField and some Action 1 // Create a textfield 2 var tf1 = new qx . ui . form . TextField ( ’ Demo Text ’ ); 3 // Add button to root 4 root . add ( tf1 , { column : 0 , row : 0}); 5 // Create a button 6 var bt1 = new qx . ui . form . Button ( 7 ’ Open Alert ’ , ’ lisa08 / test . png ’ ); 8 // Add button to root 9 root . add ( bt1 , { column : 1 , row : 0}); 10 // Add an event listener 11 bt1 . addListener ( ’ execute ’ , function ( e ) { 12 // closure !! 13 this . info ( ’ TextField : ’+ tf1 . getValue ()); 14 alert ( ’ TextField : ’ + tf1 . getValue ()); 15 }); Try F7 to see inline console!
  • 48. The Layout Manager Qooxdoo Widgets can contain other widgets. Layout manager positions child widgets. qx.ui.container.Composite basic qx.ui.container.Scroll draws scroll bars qx.ui.window.Window directs children to an inner composite pane. Layout manager set at construction time Modified with setLayout method.
  • 49. Container and Layout 1 // a container with horizontal layouyt manager 2 var hbox = new qx . ui . layout . HBox (); 3 hbox . setSpacing (4); // set property 4 5 // assign layout 6 var ctr1 = new qx . ui . container . Composite ( hbox ); 7 ctr1 . setWidth (600); ctr1 . setHeight (40); 8 // layout properties : position 9 root . add ( ctr1 ,{ column : 0 , row : 1 , colSpan : 2}); 10 11 var tf2 = new qx . ui . form . TextField ( ’ Some More Text ’ ); 12 var bt2 = new qx . ui . form . ToggleButton ( ’ AllowGrowY ’ ); 13 bt2 . addListener ( ’ changeChecked ’ , function ( e ) { 14 // modify widget property 15 tf2 . setAllowGrowY ( e . getData ()); 16 this . info ( ’ New Value for AllowGrowY : ’+ e . getData ()); 17 }); 18 ctr1 . add ( tf2 ); ctr1 . add ( bt2 );
  • 50. Grid Layout qx.ui.layout.Grid fully dynamic ideal for dialogs one widget per cell row and column spans minimal and maximal column and row sizes fixed row and column sizes
  • 51. About the Qooxdoo Layout Widgets A container widget needs a layout manager to place its children. The layout manager object has properties. Every widget has basic properties like: alignment, growability, shrinkability, stretchability, margins, padding, width and height. Each widget can have layout-specific properties. Layout properties get checked as the widget is added to a layout. Lets play with the layout demos!
  • 52. Localized Applications 1 var lmgr = qx . locale . Manager . getInstance (); 2 var bt3 = new qx . ui . form . ToggleButton ( 3 this . tr ( ’ Translate ! ’) 4 ); 5 root . add ( bt3 , { column : 1 , row : 3}); 6 bt3 . addListener ( ’ changeChecked ’ , function ( e ) { 7 var lang = e . getData () ? ’ de ’ : ’ en ’; 8 lmgr . setLocale ( lang ); 9 this . info ( ’ Language set to : ’+ lang ); 10 }); add locale to config.json ./generate.py translation translate de.po ./generate.py source
  • 53. calling code on the server JSON RPC for transport various language bindings often minimal server code async with callbacks qx.io.Rpc
  • 54. An RPC Example: Client 1 var rpc = new qx . io . remote . Rpc ( ’ jsonrpc . cgi ’ , ’ myclass ’ ); 2 var bt4 = new qx . ui . form . Button ( this . tr ( ’ Call RPC ’ )); 3 root . add ( bt4 , { column : 1 , row : 4}); 4 var that = this ; // we want this ’ this ’! 5 var callback = function ( result , ex , id ) { 6 that . RpcRunning = null ; // free the reference 7 if ( ex == null ) { 8 alert ( ’ The RPC call returned : ’+ result ); 9 that . info ( ’ RPC call returned : ’+ result ); 10 } else { 11 alert ( ’ Async ( ’ + id + ’) exception : ’ + ex ); 12 that . error ( ’ Async ( ’ + id + ’) exception : ’ + ex ); 13 } 14 }; 15 bt4 . addListener ( ’ execute ’ , function ( e ) { 16 that . RpcRunning = rpc . callAsync ( 17 callback , ’ mymethod ’ , ’ Hello ’ ); 18 }); The example only works on a cgi enabled webserver.
  • 55. An RPC Example: Server CGI source/jsonrpc.cgi: 1 # !/ usr / bin / perl -w 2 use strict ; 3 use lib qw ( perl ); 4 5 use CGI ; 6 # use CGI :: Fast ; 7 use CGI :: Session ; 8 use Qooxdoo :: JSONRPC ; 9 10 # $Qooxdoo :: JSONRPC :: debug =1; 11 my $cgi = new CGI ; 12 # while ( my $cgi = new CGI :: Fast ){ 13 my $session = new CGI :: Session ; 14 Qooxdoo :: JSONRPC :: handle_request ( $cgi , $session ); 15 # } For best performance use CGI::Fast and configure CGI::Session to keep the session data in a database.
  • 56. An RPC Example: the myclass service source/perl/Qooxdoo/Services/myclass.pm: 1 package Qooxdoo :: Services :: myclass ; 2 use strict ; 3 4 # for now let everyone access the methods 5 sub GetAccessibility { ’ public ’ }; 6 7 sub method_mymethod { 8 my $error = shift ; 9 my $arg = shift ; 10 return ’ The argument was : ’. $arg ; 11 } 12 13 1; The myclass module gets loaded dynamically.
  • 57. An RPC Example: Getting it to work Install language bindings from Qooxdoo website. ln -s /var/www/lisa08 build ./generate.py build cp -rp source/jsonrpc.cgi source/perl build Open the application in the browser. Make sure the cgis are actually executed Watch the Apache error log while testing.
  • 58. Organizing the code into multiple classes Object orientation “by the book”. One file per class. Java’s file name based approach. Supported by the generator. Ideal for code re-use. Use Inline Docs! ./generate.py api
  • 59. The textclick class I 1 /* * 2 * textclick combines a textfield and a button . 3 */ 4 qx . Class . define ( quot; lisa08 . ui . textclick quot; , 5 { 6 extend : qx . ui . container . Composite , 7 /* * 8 * @param button_text { String } button text . 9 */ 10 construct : function ( button_text ) { 11 this . base ( arguments , 12 new qx . ui . layout . HBox (). set ({ spacing : 4}) 13 ); 14 this . __tf = new qx . ui . form . TextField (); 15 this . __bt = new qx . ui . form . Button ( button_text ); 16 this . add ( this . __tf ); 17 this . add ( this . __bt ); 18 }, 19 20
  • 60. The textclick class II 21 members : 22 { 23 /* * 24 * Get a handle to the Button widget . 25 */ 26 getButton : function () { return this . __bt } , 27 /* * 28 * Get a handle to the TextField widget . 29 */ 30 getTextField : function () { return this . __tf } , 31 __bt : null , 32 __tf : null 33 } 34 });
  • 61. Using the textclick class 1 var mywi = new lisa08 . ui . textclick ( 2 this . tr ( ’ Copy Text from Example 1 ’ )); 3 4 mywi . getButton (). addListener ( ’ execute ’ , function ( e ) { 5 mywi . getTextField (). setValue ( tf1 . getValue ()); 6 this . info ( ’ Set textfield to ’+ tf1 . getValue ()); 7 }); 8 9 root . add ( mywi ,{ column : 0 , row : 5 , colSpan : 2});
  • 62. The Message Bus Communication in “large” applications. Singleton message bus class. Careful with references: memory leaks! 1 var mywi2 = new lisa08 . ui . textclick ( 2 this . tr ( ’ Send Hello to Textfield ’ )); 3 var bus = qx . event . message . Bus . getInstance (); 4 mywi2 . getButton (). addListener ( ’ execute ’ , function ( e ) { 5 bus . dispatch ( ’ mybus .1 ’ , ’ Hello World ’ ); 6 this . info ( ’ Sent Hello World on this bus ’ ); 7 } , this ); // context provided for console 8 bus . subscribe ( ’ mybus .1 ’ , function ( m ){ 9 mywi2 . getTextField (). setValue ( m . getData ()); 10 this . info ( ’ Got ’+ m . getData ()+ ’ from the bus ’ ); 11 } , this ); 12 13 root . add ( mywi2 ,{ column : 0 , row : 6 , colSpan : 2});
  • 63. Code walk through of the SmokeTrace application.
  • 64. ?