Table of Contents
Understanding Properties
Understanding the basics
qooxdoo comes with a sophisticated property management system. You don't access qooxdoo object properties directly, but communicate with them through setters and getters. This allows not only internal flexibility on the exact implementation of these properties, it also makes it possible to attach all kinds of precautions, behaviours, type checking mechanisms etc. during the creation of and read and write access to the properties. Without this your code will look something like this:
qx.Proto.getWidth = function() { return this._width; }; qx.Proto.setWidth = function(vWidth) { if (typeof vWidth != "number") { throw new Error("Invalid value: Need a valid integer value: " vWidth); }; if (this._width != vWidth) { this._width = vWidth; this.setStyleProperty("width", vWidth + "px"); }; return vWidth; };
The most code found in the previous example is for managing the validation and storage of the incoming data. The real implementation code is rather short. This is the place where qooxdoo will assist you. Just have a look at the same thing implemented with qooxdoo:
qx.OO.addProperty({ name : "width", type : "number" }); qx.Proto._modifyWidth = function(propValue, propOldValue, propData) { this.setStyleProperty("width", propValue "px"); return true; };
Cool, ehh ;) Somewhat shorter and nicer. And it only contains the "real code". The modify method can be defined optionally for each property you add to your class. If undefined, you just get generic getter and setter methods for the property.
The comparison between old and new value is included in the property handling. This means that the modifier is only called when there is a difference between the old and the new value (this is sometimes hard to understand ;) ).
Each property also adds an event connection possibility to the object. This means that each property sends out an event named "changeCamelCasePropertyName". You can connect to this and implement some other code there. For example the "element" property sends out an event named "changeElement". To connect to something like this:
myWidget.addEventListener("changeElement", function(e) { e.getNewValue().innerHTML = "Hello World"; });
These property events are used really often in typical qooxdoo applications. The event object (DataEvent) includes both the old and the new value of the property. Each comes with a getter. I will demonstrate this in an ugly example:
myWidget.addEventListener("changeWidth", function(e) { this.setHeight(e.getOldValue() * e.getNewValue()); });
This will in some way sync the width of the widget to the height. A bit crazy, but it should work out of the box.
Available functions
As a user you are more interested in what areas properties helps you to develop your application. To say it simply: Properties make sure that the API of properties of a widget for example is identical. This means that you must only learn one interface. Also we limit the developers of qooxdoo so they don't use interface style A here and interface style B there.
Each property creates a set of functions you can use in your application:
setPropertyName: Setup new value for property.getPropertyName: Returns currently stored valueresetPropertyName: Restore value to default.forcePropertyName: Store the property value without doing any checks, without calling the modifier and without dispatch any events.togglePropertyName: Toggle between true and false. This is only possible for properties of the typeboolean.
Modifying properties at runtime
One of the many advantages of JavaScript is that objects can be modified at runtime. You can attach, change and remove properties, including methods whenever you wish. You can even do that on objects that inherit their properties to descendant objects which are created with the "new" operator and inherit properties and methods from the "superclass".
The easiest way to add or remove is directly after calling qx.OO.defineClass. This is because qx.OO.addProperty and qx.OO.removeProperty make use of qx.Proto. Now what about runtime modification of the properties? No problem. Just be sure to reconfigure qx.Proto before adding your property:
qx.Proto = my.ns.Foo.prototype; qx.OO.addProperty(...)
It doesn't matter whether properties are created during class initialization or later. That means that you can take a standard qooxdoo object, such as qx.core.Target, and fit it with whatever behaviour you'd like all other objects/widgets that inherit from qx.core.Target to have.
