Da Fish in Sea

These are the voyages of Captain Observant

Building on a Solid Foundation With Ext JS 4

| Comments

I’ve been working with Ext JS a lot at work over the last year, and have grown to like it. Last year I went to the Sencha Conference in San Francisco, and was very impressed by the features of the upcoming release of Ext JS 4. One of the big changes is the new Class system, which makes defining classes easy and also loads required classes dynamically when required. The build tools which Sencha (The company which makes Ext JS) provides make it easy to produce a single compressed .js file of your app for deployment. All in all it is a great framework.

Ext JS 4 is well modularized, and you can use as little or as much of it as you like. For the Canvasteroids game framework that I’m working on, I decided to use the ‘ext-foundation.js’ file which is the essential core of the library, which defines the Class management system, as well as a useful collection of utility methods for the core Javascript types. However no changes are made to the native object prototypes, so there will not be complications when combining Ext 4 with other frameworks.

The Ext JS 4 class system lets you define a class as follows:

1
2
3
4
5
6
7
8
9
Ext.define('some.Thing', {
    extend: 'some.ThingElse',
    constructor: function () {
        this.name = "Thing1";
    },
    greet: function () {
        alert("o hai");
    }
});

Obviously, the ‘constructor’ function is what becomes the class constructor. The ‘extend’ property will cause this class to inherit the given class. Note also the use of namespaces, eg ‘foo.Bar’ in the names of classes. In Ext JS 3 you had to explicitly declare all your namespaces, but in v4 this is handled automagically.

Mix it up with Mixins

Additionally, you can have ‘mixins’ which add in methods (or properties) of the given class. This is very helpful as it enables another way of re-using code besides inheritance. This is how you declare mixins (an example from Canvasteroids):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Ext.define('drawable.DrawableLine', {
    extend: 'geometry.Line',
    mixins: ['drawable.Drawable'],
    constructor: function (props) {
        this.callParent([props]);
        //this is a base drawable class -- set context (required property)
        this.initDrawable(this.context);
    },
    draw: function (ctx) {
        this.beforeDraw(ctx);
        this.ctx.beginPath();
        this.ctx.moveTo(this.start.x, this.start.y);
        this.ctx.lineTo(this.end.x, this.end.y);
        this.ctx.stroke();
        this.afterDraw(ctx);
    }
});

The initDrawable(), beforeDraw(), draw(), and afterDraw() methods all come from the Drawable mixin class (which is defined in the same was a regular class except it does not have a constructor). Drawing is a behaviour, and this is a good use case for using a Mixin. As with inheritance, you can override methods or properties from a Mixin class. In this case I overrode the ‘draw’ method with a custom implementation. In this way Mixins can act like Abstract Classes, but you are free to use more than one at a time.

callParent() is super!

Also note the call to callParent() : this is equivalent to super() in ActionScript.. it calls the same method from which it is called on the parent class. So in a constructor it will call the super-class’s constructor. Note that the arguments must be passed as an array.

Getting Loaded with Ext.Loader

If you’ve worked on a large scale Javascript application, you know it can become a pain to maintain a large number of script tags, and resolve dependencies. Every time you add a new class to the system, you have to add it to the list of scripts includes in your HTML page, and you have to figure out where in the list of includes it has to go in order to have all of its dependencies satisfied and to satisfy its dependents. This is usually done by trial and error and can be quite annoying. Ext.Loader to the rescue! Once properly configured, you will never need to add another script tag again! Here’s how to set up dynamic loading in your main HTML file:

1
2
<script src="../../lib/extjs/ext-foundation-debug.js" type="text/javascript"><!--mce:0--></script>
<script type="text/javascript"><!--mce:1--></script>

The ‘enabled:true’ attribute of the object passed to Ext.Loader.setConfig() is what turns on the dynamic loading of classes. When this is turned on, Ext JS will dynamically add a ‘script’ tag when it notices that it needs to load a class. By default, it will look for a file with the same name as the class (replacing ‘.’ with ‘/’) relative to the HTML file. If you wish to use a different path you will need to add a mapping to the ‘paths’ hash object. By default, the ‘Ext’ namespace is mapped to the ‘src’ directory of the library so it will load other classes from the framework if you are using them.

Then you load your main app using a call to Ext.require(). In this case I required the main Asteroids game class, which was in the same directory as the HTML file this code is in. The ‘Asteroids’ class itself has multiple dependent classes, and the Loader will recursively parse them until they are all satisfied.For example the ‘canvasutils.Context2D’ class will be resolved to ‘../../lib/canvasutils/Context2D.js’. NB: make sure you name your class correctly, or errors will occur in the loading process. In addition to any classes referenced in an ‘extends’ or ‘mixins’ definition, there is a ‘requires’ property which can be used to explicitly declare a class’s dependencies. For example in the Asteroids class, I have defined the requires as follows:

1
2
3
4
5
6
7
Ext.define('Asteroids', {
    extend: 'oop.InitProps',
    requires: ['eventbus.EventBus', 'controller.TouchPad', 'drawable.DrawableLine',
     'soundeffects.SoundEffects', 'sprites.Rock', 'sprites.Ship', 'sprites.ShipFragment',
     'sprites.Bullet', 'drawable.Layer', 'controller.Keyboard', 'ui.Button', 'ui.Text',
     'interactive.DraggableLayer'],
    //...

When the Loader is enabled, Ext JS will wait until all the dependent classes have been loaded before executing Ext.onReady(). At this point you can simply instantiate the class normally with ‘new’ as I have done. Alternatively, you can use Ext.create() with the class name as a string. This has the advantage that if for some reason the class was not loaded, the Loader will load the class synchronously. However, this is non-optimal for performance, and you will be warned in the console about this. Since I want to avoid this, and for ease of debugging, I tend to use the old fashioned form of instantiation with ‘new Xxx()’, and remember to add the class to the list of ‘requires’.

Note that the order of the classes in the ‘requires’ array does not matter.

Building a Deployment version

While loading .js files dynamically is nice for debugging, it is not optimal for deployment, due to all the additional HTTP requests. It is recommended to combine all the required Javascript files into one, and compress it by removing comments, whitespace, etc. If you have used the Ext.Loader as I describe above, this will be very easy. First you will need to install the free Sencha tools from here (see the links for the different platforms tools near the bottom of the page). Then use a terminal to go to the same directory as you HTML file and type the following command:

1
sencha create jsb -a index.html -p app.jsb3

This will create a .jsb3 (JSBuilder, Sencha’s JavaScript compression tool) configuration file for the application. If that worked then do this:

1
sencha build -p app.jsb3 -d .

And you should have a app-all.js file which will be the combined and compressed version of your app. You should create another HTML file for deployment which references this file, rather than the Ext.Loader config we used for develpoment. That’s it! Your Ext JS 4 app is ready to go.

This is a brief overview of the Class system, for more info see the excellent docs:

Class System docs

Ext JS 4 Getting Started