The week in qooxdoo (2010-03-26)

Here’s another weekly summary of qooxdoo work:

Partloading

Exactly a month ago we talked about our work on an improved qooxdoo part loading. This week we made the final steps to wrap it up: we added the proper error states to the callbacks and added a callback to the preloading mechanism of parts.

Class Data

A new section in the manual explains how class data (image information, translated strings, CLDR data) is generated into the various output packages produced by the generator. This might be helpful to optimize the download profile of your application.

Tutorial series – cont’d

Here comes a recommendation for another part of the qooxdoo app tutorial: in the fourth part of the series qooxdoo’s form handling is leveraged to create a common form-based dialog. Go check it out!

github

qooxdoo has its own official github account, where you can find a git mirror of the original qooxdoo svn repository. We have set up a script that pushes the changes of the svn trunk to the git master. The script runs every night so the repo should be up to date on a daily basis. We are evaluating and gathering more practical experience with possibly using a qooxdoo git master repo in the future. Feel free to play around with git, github and the qooxdoo repository and let us know what you think and what your experiences are.

Bugfixes

For a complete list of bugs fixed during the last working week, use this bugzilla query.

Have a nice weekend!

Tutorial Part 4.1: Form Handling

In the previous steps of this tutorial, we laid the groundwork for a Twitter client application, gave it a neat UI and implemented a communication layer. One thing this application still lacks is a nice way for users to input their Twitter user name and password in order to post a status update. Fortunately, qooxdoo comes with a forms API that takes the pain out of creating form elements and handling user input.

Before we get started, make sure you’re working on the version of the Twitter tutorial application tagged with “Step 3″ in the GitHub repository. This includes the posting part of the communication layer that we’ll be using in this tutorial.

The plan

We want to create a new window with user name and password fields that pops up when the user clicks the “post” button. Provided the fields aren’t empty, their values should be used in the YQL request that posts the Tweet. Seems simple enough, so let’s get right down to business.

Creating the login window

We start by creating a new class called twitter.LoginWindow that inherits from qx.ui.window.Window, similar to the MainWindow class from the first part of this tutorial:

qx.Class.define("twitter.LoginWindow",
{
  extend : qx.ui.window.Window,
  construct : function()
  {
    this.base(arguments, "Login", "twitter/t_small-c.png");
  }
});

The Login window will only contain the form, which takes care of its own layout. So for the window itself, a Basic layout will suffice. We’ll also make the window modal:

    var layout = new qx.ui.layout.Basic();
    this.setLayout(layout);
    this.setModal(true);

Adding the Form

Now it’s time to add a form and populate it with a pair of fields:

    var form = new qx.ui.form.Form();
    var username = new qx.ui.form.TextField();
    username.setRequired(true);
    form.add(username, "Username", null, "username");
    var password = new qx.ui.form.PasswordField();
    password.setRequired(true);
    form.add(password, "Password", null, "password");

Note how the fields are marked as required. This is a simple kind of validation and in this case it’s all we need, which is why the third argument for form.add is null instead of a validation function. Required fields will be displayed with an asterisk (*) next to their label.

The next step is to add a dash of data binding awesomeness:

    var controller = new qx.data.controller.Form(null, form);
    var model = controller.createModel();

Just like in the previous tutorial, we create a controller without a model. Then, we ask the controller to create a model from the form’s elements. This model will be used to serialize the form data.

The form still needs a “submit” button, so we’ll add one, plus a “cancel” button to close the window:

    var loginbutton = new qx.ui.form.Button("Login");
    form.addButton(loginbutton);
    var cancelbutton = new qx.ui.form.Button("Cancel");
    form.addButton(cancelbutton);
    cancelbutton.addListener("execute", function() {
      this.close();
    }, this);

That’s all the elements we need, let’s get them displayed. We’ll let one of qooxdoo’s built-in form renderer classes worry about the form’s layout:

    var renderer = new qx.ui.form.renderer.Single(form);
    this.add(renderer);

The renderer is a widget, so we can just add it to the window. In addition to the standard renderers, it’s fairly simple to create a cusstom renderer by subclassing qx.ui.form.renderer.AbstractRenderer, though that’s outside the scope of this tutorial.

Accessing the form values

Similar to MainWindow, we’ll use an event to notify the other parts of our application of changes to the form. As you’ll remember, the “event” section is on the same level as the constructor in the class declaration:

  events : {
    "changeLoginData" : "qx.event.type.Data"
  },

Then we add a listener to the submit button that retrieves the values from the model object and attaches them to a data event, making sure the form validates, i.e. both fields aren’t empty.

    loginbutton.addListener("execute", function() {
      if (form.validate()) {
        var loginData = {
          username : controller.getModel().getUsername(),
          password : controller.getModel().getPassword()
        };
        this.fireDataEvent("changeLoginData", loginData);
        this.close();
      }
    }, this);

And that’s it for the LoginWindow class. Now to integrate it with the other parts of the application. TwitterService.post currently uses prompt() to ask for the user name and password, so we’ll remove these two lines. Instead, we add two new arguments to the method:

    post : function(message, username, password)

The post() method is called from the main application class, so let’s take another look at Application.js. We want to display the login window before posting, so we’ll modify the “post” event listener’s callback function (line 79). We need to create an instance of twitter.LoginWindow and attach a listener to its “changeLoginData” event which calls service.post() with the username and password values from the event data. We also want to make sure that only one LoginWindow instance is used during the application’s runtime. This is a good idea because creating and disposing widgets is quite expensive in terms of CPU time. In our application, it also means users won’t have to retype their login data for every post.

      // post handling
      main.addListener("post", function(e) {
      var msg = e.getData();
      if (!this.__loginWindow) {
        this.__loginWindow = new twitter.LoginWindow();
        this.__loginWindow.addListener("changeLoginData", function(ev) {
          var loginData = ev.getData();
          service.post(msg, loginData.username, loginData.password);
        });
        this.__loginWindow.moveTo(320,30);
        this.__loginWindow.open();
      }
      else {
        this.__loginWindow.open();
      }
    }, this);

OK, time to run generate.py source and load the application in a browser to make sure everything works like it’s supposed to.

Twitter client application with login window

Twitter client application with login window

And that’s it for the form handling chapter. As usual, you’ll find the tutorial code on GitHub. Watch out for the next chapter, which will focus on developing your own custom widgets.

The week in qooxdoo (2010-03-19)

Welcome back to another status update.

New news hosting

We moved news.qooxdoo.org to a new server hardware. As you are reading this, the new DNS record is propagating around the world, and chances are level that you are reading the post from either the old or the new server, depending on whether the DNS server you are using is still caching the old value or not. If you are on the new server, you shouldn’t perceive much difference, other than improved speed and a slightly newer version of the blog software. This is just another step to move our project services off of the old hardware that simply shows its age and limitations. So if you hardly perceive the transition, that’s a good thing :-) .

I18N as Parts

As already announced, I18N information can now be generated as dedicated parts. The feature is triggered by specifying the packages/i18n-with-boot : false configuration option. (This currently forces you to provide at least a minimal part configuration, specifying a boot part). After that, I18N information like locale settings and translated strings will no longer be generated as part of the loader script of your application. Rather, for each language you specified for your application like en, en_GB, fr, … a separate JS file is generated holding the corresponding data for that particular language. These files have the standard structure of other qooxdoo packages. Corresponding parts are automatically generated (you don’t have to worry about those) and their specifics are added to the loader.

But now the I18N information is not automatically available to your application as before. Like with any other part, you have to deliberately load one of the I18N parts, using the standard qx.io.Partloader#require call. You usually want to do that early during the life time of your application, e.g. after a user-specific profile has been loaded which includes the user’s language preferences. Of course, this all only makes sense if your application supports multiple languages and has a decent amount of translated strings for each, but then you can save a lot of bandwidth and memory by only loading a single, dedicated language part.

Documentation

We replaced the outdated architecture diagram in the manual. Take a look at the new one, feedback as always welcome.

UI architecture

Bugfixes

For a complete list of tasks accomplished during the last working week, use this bugzilla query.

That’s it for now. C U around next time.

We’re hiring!

To further improve and grow qooxdoo we are looking for talented and experienced JavaScript developers. There are three open positions within 1&1, the world’s #1 web host, for both qooxdoo framework development and in-house qooxdoo application support.

The first position is to be restaffed by a senior-level JavaScript expert. You will work directly with the fine colleagues of the qooxdoo core team at 1&1 in Karlsruhe/Germany, one of Europe’s premier technology regions. Solid work experience with JavaScript, excellent OO programming skills and a good knowledge of and passion for web-related technologies will enable you to actively advance and co-architecture qooxdoo as one of the most innovative web application frameworks. For an easy integration into the local corporate environment we are primarily but not exclusively looking for German-speaking candidates.

The other two positions for JavaScript developers are to support the expansion of the development teams at 1&1 in Bucharest/Romania. Besides co-developing the qooxdoo framework in close cooperation with the core team, you will also enable and support other in-house developers in creating impressive qooxdoo applications. Of course, good JavaScript knowledge and web-related programming skills are key for becoming part of a great new qooxdoo competence team in an international setting. Also see the online job description.

If you are interested in any of the job offers, feel free to ask questions and/or send in your resume to me. If you know somebody that could be interested, please let him/her know. We’re looking forward to hearing from you and hopefully to having you become part of the qooxdoo team. :-)

Andreas Ecker
Project Lead
andreas DOT ecker AT 1und1 DOT de