http://qooxdoo.org


        1
EXAMPLES




   2
EXAMPLES




   3
EXAMPLES




   4
5
IT'S NOT A TOY




      6
IT'S NOT A TOY

                     let's count files:

Penny:downloads singles$ wget http://downloads..../qooxdoo-1.5-sdk.zip
[...]
HTTP request sent, awaiting response... 200 OK
Length: 67875249 (65M) [application/zip] !!!
Saving to: `qooxdoo-1.5-sdk.zip'

100%[=======================================>] 67,875,249      616K/s   in 96s

2011-10-01 19:10:51 (693 KB/s) - `qooxdoo-1.5-sdk.zip' saved
[67875249/67875249]

Penny:downloads singles$ tar -xf qooxdoo-1.5-sdk.zip
Penny:downloads singles$ ls -R qooxdoo-1.5-sdk | wc -l
   15517 !!! (includes test files, icons for 3 themes etc.)




                                     7
IT'S NOT A TOY

let's see example api page:




             8
IT'S NOT A TOY

              let's see some code:
qx.Class.define("foo.lib.io.HttpRequest",
{
    type: 'abstract',
    extend : qx.io.request.Xhr,
    implement: [IFooInterface, IBarInterface],
    include : [app.MMessage],
    properties : {
        showLoadingDialog : {
            check : "Boolean",
            init : true
        }
    },
    construct : function(vUrl, vMethod) {
        this.base(arguments, vUrl);
        this.addListener("fail", this._onError, this);
    },
    members : {
        _onError : function() {
            this.showError(Tools.tr("io.request:error"));
        },
    }
});



                                        9
IT'S NOT A TOY

              let's see some code:
qx.Class.define("foo.lib.io.HttpRequest",
{
    type: 'abstract',                                     class type
    extend : qx.io.request.Xhr,
    implement: [IFooInterface, IBarInterface],
    include : [app.MMessage],
    properties : {
        showLoadingDialog : {
            check : "Boolean",
            init : true
        }
    },
    construct : function(vUrl, vMethod) {
        this.base(arguments, vUrl);
        this.addListener("fail", this._onError, this);
    },
    members : {
        _onError : function() {
            this.showError(Tools.tr("io.request:error"));
        },
    }
});



                                        10
IT'S NOT A TOY

              let's see some code:
qx.Class.define("foo.lib.io.HttpRequest",
{
    type: 'abstract',
    extend : qx.io.request.Xhr,                        inheritance
    implement: [IFooInterface, IBarInterface],
    include : [app.MMessage],
    properties : {
        showLoadingDialog : {
            check : "Boolean",
            init : true
        }
    },
    construct : function(vUrl, vMethod) {
        this.base(arguments, vUrl);
        this.addListener("fail", this._onError, this);
    },
    members : {
        _onError : function() {
            this.showError(Tools.tr("io.request:error"));
        },
    }
});



                                       11
IT'S NOT A TOY

              let's see some code:
qx.Class.define("foo.lib.io.HttpRequest",
{
    type: 'abstract',
    extend : qx.io.request.Xhr,
    implement: [IFooInterface, IBarInterface],         interfaces
    include : [app.MMessage],
    properties : {
        showLoadingDialog : {
            check : "Boolean",
            init : true
        }
    },
    construct : function(vUrl, vMethod) {
        this.base(arguments, vUrl);
        this.addListener("fail", this._onError, this);
    },
    members : {
        _onError : function() {
            this.showError(Tools.tr("io.request:error"));
        },
    }
});



                                       12
IT'S NOT A TOY

              let's see some code:
qx.Class.define("foo.lib.io.HttpRequest",
{
    type: 'abstract',
    extend : qx.io.request.Xhr,
    implement: [IFooInterface, IBarInterface],
    include : [app.MMessage],                             mixins !
    properties : {
        showLoadingDialog : {
            check : "Boolean",
            init : true
        }
    },
    construct : function(vUrl, vMethod) {
        this.base(arguments, vUrl);
        this.addListener("fail", this._onError, this);
    },
    members : {
        _onError : function() {
            this.showError(Tools.tr("io.request:error"));
        },
    }
});



                                        13
IT'S NOT A TOY

              let's see some code:
qx.Class.define("foo.lib.io.HttpRequest",
{
    type: 'abstract',
    extend : qx.io.request.Xhr,
    implement: [IFooInterface, IBarInterface],
    include : [app.MMessage],
    properties : {
        showLoadingDialog : {
            check : "Boolean",                          like C#, but better :)
            init : true
        }
    },
    construct : function(vUrl, vMethod) {
        this.base(arguments, vUrl);
        this.addListener("fail", this._onError, this);
    },
    members : {
        _onError : function() {
            this.showError(Tools.tr("io.request:error"));
        },
    }
});



                                       14
IT'S NOT A TOY

                let's see some code:
qx.Class.define("foo.lib.io.HttpRequest",
{
    type: 'abstract',
    extend : qx.io.request.Xhr,
    implement: [IFooInterface, IBarInterface],
    include : [app.MMessage],
    properties : {
        showLoadingDialog : {
            check : "Boolean",
            init : true
        }
    },
    construct : function(vUrl, vMethod) {
        this.base(arguments, vUrl);
        this.addListener("fail", this._onError, this);
    },
    members : {                                               protected member
                                                              (also private & public)
          _onError : function() {
              this.showError(Tools.tr("io.request:error"));
          },
      }
});



                                         15
OVERENGINERED?




      16
OVERENGINERED?

     NO.




      17
OVERENGINERED?

     NO.

WELL DESIGNED!


      18
BUT!




 19
BUT!

YOU HAVE TO KNOW WHAT
    YOU ARE DOING



          20
BUT!

YOU HAVE TO KNOW WHAT
    YOU ARE DOING

   IN ANOTHER CASE...

           21
22
QOOXDOO
    =
FRAMEWORK
    +
GUI TOOLKIT

     23
LOT OF FEATURES




       24
LOT OF FEATURES

BUT WE DON'T HAVE TIME
 TO TALK ABOUT ALL OF
       THEM, SO...



          25
LOT OF FEATURES

BUT WE DON'T HAVE TIME
 TO TALK ABOUT ALL OF
       THEM, SO...

 HTTP://QOOXDOO.ORG/ABOUT


            26
THINGS WORTH
MENTIONING *


               * IMHO
     27
DOCUMENTATION




      28
DOCUMENTATION




      463pages
    justmanual
  withoutapidocs


                 29
DOCUMENTATION



   + DEMOS

+ PLAYGROUND
 (RIA  MOBILE)

       30
MIXINS




  31
MIXINS




Something like interfaces, but
   with implementation.



              32
MIXINS

qx.Mixin.define(foo.lib.tools.MAwesomeLogger,
{
  members : {
    logWithTrace : function(what) {
      console.log(what);
      console.trace();
    }
  }
});

qx.Class.define(foo.app.Bar,
{
  include: [foo.lib.tools.MAwesomeLogger],
  construct: function() {
    this.logWithTrace(this);
  }
}




                                     33
PROPERTIES




    34
35
qx.Class.define('foo.bar', {
  extend: qx.core.Object,
  properties: {
    phrase: {                              // autogenerate setter and getter and ...
      apply: '_applyPhrase'                // fire on property modification (not init!) - return
                                           // value is ignored

      nullable: true,                      //   can be null
      event: 'someEvent'                   //   default changeFoo - fires on property change
      check: ['suit up', 'bazinga'],       //   check possible inserts, also could be defined as a
                                           //   function - works only in development!

      transform: '_transformPhrase'        // transform value - BEFORE check and apply
      validate: qx.util.Validate.string    // works in development and production
    },
    awesome:   { init: false, check: 'Boolean' }
    nerd:      { init: false, check: 'Boolean' }
  },
  members: {
     _transformPhrase: function(value) {
       return value + '!';
     }
     _applyPhrase: function(value, old, name) {
       if (value === 'suit up!') {
         this.toggleAwesome('awesome');
       } else if (value === 'bazinga!') {
         this.toggleAwesome('nerd');
       }
     }
  }
});



                                                   36
LOT OF CONSISTENT(!) GUI
     COMPONENTS



           37
GUI COMPONENTS




      38
GUI COMPONENTS




      39
GUI COMPONENTS




      40
GUI COMPONENTS




      41
GUI COMPONENTS




Themeable of course ;)




          42
EASY KEY/COMMANDS
      BINDING



        43
EASY KEY/COMMANDS BINDING

var findWindow = new qx.ui.window.Window('search');
//findWindow configuration...

var find = new qx.event.Command(Ctrl+F),
    close = new qx.event.Command('Esc');

find.addListener(execute, function() {
  findWindow.open();
}, this);
close.addListener(execute, function() {
  findWindow.close();
}, this);




                           44
EASY ELEMENTS
  POSITIONING
(WITH LAYOUTS)



      45
EASY ELEMENTS POSITIONING




           46
EASY REST CALLS




       47
EASY REST CALLS
var description = {
  index:    { method: GET, url: /photos }
  create:   { method: POST, url: /photos }
  show:     { method: GET, url: /photos/:id }
  update:   { method: PUT, url: /photos/:id }
}
var photos = new qx.io.rest.Resource(description); //declaratively
photos.map('destroy', 'DELETE', '/photos/:id');    //programatically
photos.index(); // -- GET /photos
photos.show({id: 1}); // -- GET /photos/1

// success is fired when any request associated to resource receives a
response
photos.addListener(success, function(e) {
  e.getAction(); // -- index or show
});

// indexSuccess is fired when the request associated to the index action
receives a response
photos.addListener(indexSuccess, function(e) {
  e.getAction(); // -- index
});



                                       48
HTML EDITOR
OUT OF THE BOX



      49
HTML EDITOR




The html editor does have some issues. Just not to give the impression
that it would try to compete with more advanced editors like ckEditor,
     etc., because it doesn't. Still fine for many products, though.
                             [Andreas Ecker]

                                50
ADVANCED BUILD TOOL




         51
ADVANCED BUILD TOOL

Penny:frontend singles$ ./generate.py list
 Available jobs:
  - api     -- create api doc for the current library
  - api-data     -- create api doc json data files
  - build
  - clean -- remove local cache and generated .js files (source/build)
  - distclean    -- remove the cache and all generated artefacts of this library (source,
build, ...)
  - fix     -- normalize whitespace in .js files of the current library (tabs, eol, ...)
  - info    -- collects environment information like the qooxdoo version etc., and prints it out
  - inspector    -- create an inspector instance in the current library
  - lint    -- check the source code of the .js files of the current library
  - migration    -- migrate the .js files of the current library to the current qooxdoo version
  - pretty
  - profiling    -- includer job, to activate profiling
  - simulation-build       -- (experimental) create a runner app for simulated interaction tests
  - simulation-run    -- (experimental) launches simulated interaction tests generated with
simulation-build
  - source
  - source-all -- create source version of current application, with all classes
  - source-hybrid     -- create a hybrid version (app classes as source files, others compiled)
  - test    -- create a test runner app for unit tests of the current library
  - test-source       -- create a test runner app for unit tests (source version) of the current
library
  - translation       -- create .po files for current library




                                               52
WORKS:
 STANDALONE (IN BROWSER),
INSIDE EXISTING WEBPAGES OR
   NATIVE (WITHOUT GUI)




            53
MOBILE SUPPORT




      54
MOBILE SUPPORT




      55
DEVELOPER FRIENDLY
  (TESTS  TOOLS)




        56
DEVELOPER FRIENDLY




        57
DEVELOPER FRIENDLY




        58
LOCALIZATION AND
  TRANSLATION



       59
AND MUCH MORE...




       60
WAIT W AIT. I T L OOKS L IKE I
CAN U SE I T J UST F OR U GLY A N
  BORING W EB A PPLICATIONS


                                         61
NOT REALLY...




      62
HTTP://WWW.LORDOFULTIMA.COM/EN/

              63
QUESTIONS?




    64
THANKS!




   65
name: Radosław Benkel
                                   nick: singles
                                   www: http://www.rbenkel.me
                                   twitter: @singlespl




* and I have nothing in common with http://www.singles.pl ;]


                                              66

meet.js - QooXDoo

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
    IT'S NOT ATOY let's count files: Penny:downloads singles$ wget http://downloads..../qooxdoo-1.5-sdk.zip [...] HTTP request sent, awaiting response... 200 OK Length: 67875249 (65M) [application/zip] !!! Saving to: `qooxdoo-1.5-sdk.zip' 100%[=======================================>] 67,875,249 616K/s in 96s 2011-10-01 19:10:51 (693 KB/s) - `qooxdoo-1.5-sdk.zip' saved [67875249/67875249] Penny:downloads singles$ tar -xf qooxdoo-1.5-sdk.zip Penny:downloads singles$ ls -R qooxdoo-1.5-sdk | wc -l 15517 !!! (includes test files, icons for 3 themes etc.) 7
  • 8.
    IT'S NOT ATOY let's see example api page: 8
  • 9.
    IT'S NOT ATOY let's see some code: qx.Class.define("foo.lib.io.HttpRequest", { type: 'abstract', extend : qx.io.request.Xhr, implement: [IFooInterface, IBarInterface], include : [app.MMessage], properties : { showLoadingDialog : { check : "Boolean", init : true } }, construct : function(vUrl, vMethod) { this.base(arguments, vUrl); this.addListener("fail", this._onError, this); }, members : { _onError : function() { this.showError(Tools.tr("io.request:error")); }, } }); 9
  • 10.
    IT'S NOT ATOY let's see some code: qx.Class.define("foo.lib.io.HttpRequest", { type: 'abstract', class type extend : qx.io.request.Xhr, implement: [IFooInterface, IBarInterface], include : [app.MMessage], properties : { showLoadingDialog : { check : "Boolean", init : true } }, construct : function(vUrl, vMethod) { this.base(arguments, vUrl); this.addListener("fail", this._onError, this); }, members : { _onError : function() { this.showError(Tools.tr("io.request:error")); }, } }); 10
  • 11.
    IT'S NOT ATOY let's see some code: qx.Class.define("foo.lib.io.HttpRequest", { type: 'abstract', extend : qx.io.request.Xhr, inheritance implement: [IFooInterface, IBarInterface], include : [app.MMessage], properties : { showLoadingDialog : { check : "Boolean", init : true } }, construct : function(vUrl, vMethod) { this.base(arguments, vUrl); this.addListener("fail", this._onError, this); }, members : { _onError : function() { this.showError(Tools.tr("io.request:error")); }, } }); 11
  • 12.
    IT'S NOT ATOY let's see some code: qx.Class.define("foo.lib.io.HttpRequest", { type: 'abstract', extend : qx.io.request.Xhr, implement: [IFooInterface, IBarInterface], interfaces include : [app.MMessage], properties : { showLoadingDialog : { check : "Boolean", init : true } }, construct : function(vUrl, vMethod) { this.base(arguments, vUrl); this.addListener("fail", this._onError, this); }, members : { _onError : function() { this.showError(Tools.tr("io.request:error")); }, } }); 12
  • 13.
    IT'S NOT ATOY let's see some code: qx.Class.define("foo.lib.io.HttpRequest", { type: 'abstract', extend : qx.io.request.Xhr, implement: [IFooInterface, IBarInterface], include : [app.MMessage], mixins ! properties : { showLoadingDialog : { check : "Boolean", init : true } }, construct : function(vUrl, vMethod) { this.base(arguments, vUrl); this.addListener("fail", this._onError, this); }, members : { _onError : function() { this.showError(Tools.tr("io.request:error")); }, } }); 13
  • 14.
    IT'S NOT ATOY let's see some code: qx.Class.define("foo.lib.io.HttpRequest", { type: 'abstract', extend : qx.io.request.Xhr, implement: [IFooInterface, IBarInterface], include : [app.MMessage], properties : { showLoadingDialog : { check : "Boolean", like C#, but better :) init : true } }, construct : function(vUrl, vMethod) { this.base(arguments, vUrl); this.addListener("fail", this._onError, this); }, members : { _onError : function() { this.showError(Tools.tr("io.request:error")); }, } }); 14
  • 15.
    IT'S NOT ATOY let's see some code: qx.Class.define("foo.lib.io.HttpRequest", { type: 'abstract', extend : qx.io.request.Xhr, implement: [IFooInterface, IBarInterface], include : [app.MMessage], properties : { showLoadingDialog : { check : "Boolean", init : true } }, construct : function(vUrl, vMethod) { this.base(arguments, vUrl); this.addListener("fail", this._onError, this); }, members : { protected member (also private & public) _onError : function() { this.showError(Tools.tr("io.request:error")); }, } }); 15
  • 16.
  • 17.
  • 18.
    OVERENGINERED? NO. WELL DESIGNED! 18
  • 19.
  • 20.
    BUT! YOU HAVE TOKNOW WHAT YOU ARE DOING 20
  • 21.
    BUT! YOU HAVE TOKNOW WHAT YOU ARE DOING IN ANOTHER CASE... 21
  • 22.
  • 23.
    QOOXDOO = FRAMEWORK + GUI TOOLKIT 23
  • 24.
  • 25.
    LOT OF FEATURES BUTWE DON'T HAVE TIME TO TALK ABOUT ALL OF THEM, SO... 25
  • 26.
    LOT OF FEATURES BUTWE DON'T HAVE TIME TO TALK ABOUT ALL OF THEM, SO... HTTP://QOOXDOO.ORG/ABOUT 26
  • 27.
  • 28.
  • 29.
    DOCUMENTATION 463pages justmanual withoutapidocs 29
  • 30.
    DOCUMENTATION + DEMOS + PLAYGROUND (RIA MOBILE) 30
  • 31.
  • 32.
    MIXINS Something like interfaces,but with implementation. 32
  • 33.
    MIXINS qx.Mixin.define(foo.lib.tools.MAwesomeLogger, { members: { logWithTrace : function(what) { console.log(what); console.trace(); } } }); qx.Class.define(foo.app.Bar, { include: [foo.lib.tools.MAwesomeLogger], construct: function() { this.logWithTrace(this); } } 33
  • 34.
  • 35.
  • 36.
    qx.Class.define('foo.bar', { extend: qx.core.Object, properties: { phrase: { // autogenerate setter and getter and ... apply: '_applyPhrase' // fire on property modification (not init!) - return // value is ignored nullable: true, // can be null event: 'someEvent' // default changeFoo - fires on property change check: ['suit up', 'bazinga'], // check possible inserts, also could be defined as a // function - works only in development! transform: '_transformPhrase' // transform value - BEFORE check and apply validate: qx.util.Validate.string // works in development and production }, awesome: { init: false, check: 'Boolean' } nerd: { init: false, check: 'Boolean' } }, members: { _transformPhrase: function(value) { return value + '!'; } _applyPhrase: function(value, old, name) { if (value === 'suit up!') { this.toggleAwesome('awesome'); } else if (value === 'bazinga!') { this.toggleAwesome('nerd'); } } } }); 36
  • 37.
    LOT OF CONSISTENT(!)GUI COMPONENTS 37
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
    EASY KEY/COMMANDS BINDING varfindWindow = new qx.ui.window.Window('search'); //findWindow configuration... var find = new qx.event.Command(Ctrl+F), close = new qx.event.Command('Esc'); find.addListener(execute, function() { findWindow.open(); }, this); close.addListener(execute, function() { findWindow.close(); }, this); 44
  • 45.
    EASY ELEMENTS POSITIONING (WITH LAYOUTS) 45
  • 46.
  • 47.
  • 48.
    EASY REST CALLS vardescription = { index: { method: GET, url: /photos } create: { method: POST, url: /photos } show: { method: GET, url: /photos/:id } update: { method: PUT, url: /photos/:id } } var photos = new qx.io.rest.Resource(description); //declaratively photos.map('destroy', 'DELETE', '/photos/:id'); //programatically photos.index(); // -- GET /photos photos.show({id: 1}); // -- GET /photos/1 // success is fired when any request associated to resource receives a response photos.addListener(success, function(e) { e.getAction(); // -- index or show }); // indexSuccess is fired when the request associated to the index action receives a response photos.addListener(indexSuccess, function(e) { e.getAction(); // -- index }); 48
  • 49.
  • 50.
    HTML EDITOR The htmleditor does have some issues. Just not to give the impression that it would try to compete with more advanced editors like ckEditor, etc., because it doesn't. Still fine for many products, though. [Andreas Ecker] 50
  • 51.
  • 52.
    ADVANCED BUILD TOOL Penny:frontendsingles$ ./generate.py list Available jobs: - api -- create api doc for the current library - api-data -- create api doc json data files - build - clean -- remove local cache and generated .js files (source/build) - distclean -- remove the cache and all generated artefacts of this library (source, build, ...) - fix -- normalize whitespace in .js files of the current library (tabs, eol, ...) - info -- collects environment information like the qooxdoo version etc., and prints it out - inspector -- create an inspector instance in the current library - lint -- check the source code of the .js files of the current library - migration -- migrate the .js files of the current library to the current qooxdoo version - pretty - profiling -- includer job, to activate profiling - simulation-build -- (experimental) create a runner app for simulated interaction tests - simulation-run -- (experimental) launches simulated interaction tests generated with simulation-build - source - source-all -- create source version of current application, with all classes - source-hybrid -- create a hybrid version (app classes as source files, others compiled) - test -- create a test runner app for unit tests of the current library - test-source -- create a test runner app for unit tests (source version) of the current library - translation -- create .po files for current library 52
  • 53.
    WORKS: STANDALONE (INBROWSER), INSIDE EXISTING WEBPAGES OR NATIVE (WITHOUT GUI) 53
  • 54.
  • 55.
  • 56.
    DEVELOPER FRIENDLY (TESTS TOOLS) 56
  • 57.
  • 58.
  • 59.
    LOCALIZATION AND TRANSLATION 59
  • 60.
  • 61.
    WAIT W AIT.I T L OOKS L IKE I CAN U SE I T J UST F OR U GLY A N BORING W EB A PPLICATIONS 61
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
    name: Radosław Benkel nick: singles www: http://www.rbenkel.me twitter: @singlespl * and I have nothing in common with http://www.singles.pl ;] 66