Da Fish in Sea

These are the voyages of Captain Observant

Modular Javascript Development With RequireJS

| Comments

RequireJS is a micro-library focused on defining and loading Javascript ‘modules’ so that they can easily be loaded in your own or other peoples projects. Since Javascript has no compiler, the <script> tag has traditionally been the equivalent of the ‘import’ statement in compiled languages. But it has been hard to combine multiple JS libraries which may end up clobbering each others prototypes, leading to mysterious bugs. The module pattern is a well accepted pattern for preventing exposing global variables, although you still have a global variable for the module itself. With RequireJS you can reduce the number of globals even further, since modules are not assigned to global variables but are require() ‘d inside other modules.

Another benefit is performance.. loading scripts should be asynchonous for best usage of the network. Traditional <script> tags are synchronous and blocking, even if the code is not immediately required. Other approaches to loading code use XHR & eval() which makes debugging hard, and restrict to same origin (though there are workarounds). So RequireJS creates script tags dynamically, and appends them to the head of the document.

OK, how do you use it ? If you simply want to include an external script (whatever it may be), you can do this:

1
2
3
require(["some/script.js"], function () {
    //do stuff once it is loaded
});

So what is going one here is that the first argument to ‘require()’ is an array of dependencies, which are paths to Javascript files. The callback function is executed once the file has been loaded. Pretty simple. However the real power of RequireJS comes about when you also define your modules with a special define() function, which in turn declare their dependencies.. and so on, and so on, recursively. Usually, the Module Pattern is implemented with a closure function:

1
2
3
4
5
6
7
8
MyModule = (function () {
    function boo() {
        alert("boo!");
    }
    return {
        frighten: boo
    }
})();

With RequireJS you use the define() function instead of the anonymous closure:

1
2
3
4
5
6
7
8
9
10
define(['dependency/first', 'deependency/second'] , function (d1, d2) {
    //when this gets called, the dependencies are loaded and available as d1, d2
    function boo() {
        alert("boo!");
    }
    //you must return the module explicitly:
    return {
        frighten: boo
    }
});

If this was in a file called /scripts/scary.js, you could obtain an instance of the module as follows (in /index.html):

1
  <script type="text/javascript"><!--mce:0--></script>

Notice that there is no .js on the end of the filename. RequireJS will see that and look for a define() function in the file to get the module with. Note that if you omit the .js on the path, the module must be defined using the define(). Another option, which avoids using any inline script in your HTML, is to use a <script> tag with require.js as the ‘src’, and give a data-main attribute to indicate the entry point of your app.

1
 <script src="scripts/require.js"><!--mce:1--></script>

This would work if we had a script called ‘main.js’ in the scripts folder with something like this in it:

1
2
3
define(['scary'], function (scary)) {
    scary.boo();
};

Notice how the dependency is passed as an argument to the callback function. If there are more than one dependency, they will be passed as additional arguments, in the same order as the dependencies.

If you need to interact with the DOM, you should be aware that your dependencies may be loaded before the document itself is loaded, so you can use the require.ready() function which fires when the document is ready AND all dependencies have loaded…

1
2
3
4
5
6
7
define(['scary'], function (scary)) {
    require.ready(function () {
        //start app
        scary.boo();
        //do DOM stuff...
    });
};

Note that the module name is relative to the directory containing the ‘data-main’ module. Also note, require.ready() uses window.onload for browsers (mostly IE) which do not support the DOMContentLoaded event. This may be slow if you have a lot of stuff on your page.

An example of more advanced usage is that an object literal can be passed in as the first argument to the require() function, to add some additional customization, eg, setting a baseURL, or some paths which will be expanded in the names of the dependencies.

Advanced Usage: CommonJS Compatibility

CommonJS is a JS package standard, used by, eg. NPM (Node Package Manager – see previous post). Therefore it is desirable that RequireJS would grok CommonJS packages. However, you need to specify some additional configuration in you package.json for this to work, eg.

1
2
lib: 'some/dir', //the dir containing the modules, (default = lib)
main: 'script/app' //the name of the module in the lib dir which will be used when someone require() 's the packageName (default = lib/main))

NB: for the package’s modules to be loaded they must be wrapped in a define () function as below .. this can be done manually or with a script (RequireJS provides some scripts for mass conversion).

1
2
3
4
5
define(function(require, exports, module) {
    exports.boo = function () {
        alert("boo!");
    }
});

This must be exactly specified as above! (ie the parameters of the function must be ‘require’, ‘exports’, ‘module’ in that order). This seems a bit weird … how do you declare dependencies, if you must stick to this exact function signature? Well, the answer is that there is some magic at work… RequireJS looks for any ‘require()’ function calls in your module, and makes sure they are all loaded before the function is called! This is done because CommonJS has its own require() function, which is synchronous, so RequireJS essentially overrides it with its own asynchronous version. It is the ‘require’ parameter which triggers this behaviour. But what about the ‘exports’ and ‘module’ parameters ? Well, the exports argument is what will be returned when require() is called for this module. It is not necessary to return anything from the define() function, the value of ‘exports’ will be automatically returned. I’m not quite sure what the ‘module’ argument is for, as I haven’t seen it used anywhere, so its probably best to leave it alone.. perhaps it just provides backwards compatibility with CommonJS syntax? In fact, it is possible to leave out the ‘exports’ and ‘module’ arguments if you return the module explicitly from the function given to define() .. exactly as in normal non-CommonJS usage. See here.

Optimization

RequireJS provides an optimization tool, which uses UglifyJS as its compressor.

TO use it, clone or download the RequireJS source code as a sibling of your project and run the following command from the scripts (or lib, if in a CommonJS package) dir:

1
   ../../requirejs/build/build.sh name=main out=main-built.js baseUrl=.

And you will have a compressed main-built.js file with all your dependencies in it, so they can be required with a single HTTP request. Eg., you could change the script tag above to:

1
  <script src="scripts/require.js"><!--mce:2--></script>;

The RequireJS docs are excellent, and even nice to look at, so I recommend checking them out for more info, or if this becomes out of date…

API Docs

http://requirejs.org/docs/api.html

NodeJS and Friends

| Comments

Javascript Dev Tools: NodeJS, NPM, CommonJS, Teleport

I’ve recently discovered some neat tools which help make Javascript development easier. Everyone is excited about HTML5, which Brendan Eich (the inventor of Javascript) describes as ‘The unicorn which craps skittles from its rear end’. The Javascript language awaits a much needed update with ES5 Harmony, but in the meantime it has access to some cool new APIs in the form of HTML5 features such as Canvas, Local Storage, etc.

But what about outside of the browser? There have been some attempts to use Javascript on the server, but they don’t seem to have gained much widespread adoption. Then came NodeJS. If you haven’t heard about NodeJS I recommend you checkout this video by Ryan Dahl, the creator of NodeJS:

NodeJS is revolutionary in that it give Javascript access to the filesystem and network, with a performance oriented event-based approach that solves concurrency elegantly without the pain of multithreading. In itself this might only be interesting to hardcore server geeks, but NodeJS is being used as the infrastructure for a lot of other projects. Some of them are deployed by NPM, the Node Package Manager, which (surprise!) is a package management system for NodeJS applications. So once you have installed NodeJS and NPM, you can easily install other libraries on the command line. And you can create your own projects, using the CommonJS package format. This is made easy by the ‘npm init’ command, which creates a package.json configuration file for you automatically (I will give an example later).

But what if you’re more interested in client-side applications which run in a web-browser? No problem! Teleport comes to the rescue. This is itself a NodeJS package which you can install using NPM. Now once you have created a basic NPM / Common JS app, you just include the teleport library as a dependency. Then you can write your Javascript just as you usually would for a web-app. To test the app in a browser you run ‘teleport activate’ and Teleported will spawn a nodeJS webserver with your app running in it.

Once you have an awesome app ready, you can publish it to the NPM repository library with a single command (npm publish), so that other people can install it. No fussing about with web servers or downloading code. I’m really excited about the possibilities this creates for sharing client-server applications where the server is your own machine. Suddenly Javascript becomes a viable language for serious desktop applications with access to the filesystem and the network, as well as all the new HTML5 GUI goodness. Because the app runs on your own system, you can run it offline, and performance is going to be way better than over the internet.

In order to demonstrate just how easy this all is I will break it down for you, assuming you have nothing installed. Here we go:

Prerequisites:

sudo npm install teleport

Create a NPM app (I called mine frappuccino) using the command line:

mkdir frappucino
cd frappucino
npm init

At this point, you will go through a wizard to generate the package.conf file. It is just to provide metadata for your app, don’t worry too much about the answers, most of them are fine as they are. You can always edit it afterwards. For the ‘module entry point’ question I left it as default, and for the ‘where do your modules live’ I said ‘lib’ (this is standard, but not default). It actually guessed I was using a Git repo which I have in my home directory, which is not the repo I want to use, so I had to remove that reference afterwards. If you run it in a git repo, it will figure it out and use the info from that for the repository info. So if you want to do that, you should create the git repo first. After removing the incorrect repo info, my package.conf file looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
    "name": "frappucino",
    "description": "Frothy App",
    "version": "0.0.0",
    "author": "David Wilhelm ",
    "directories": {
        "lib": "lib"
    },
    "engines": {
        "node": "*"
    },
    "dependencies": {
        "teleport": "&lt;=0.2.2"
    }
}

The other change I made was to add the “dependencies” config, which will ensure that Teleport is installed as a dependency. OK, there are now a couple of other files you need to create:

The index.html page. Mine looks like this:

1
2
<script src="support/teleport/teleport.js" type="text/javascript"></script>
<script type="text/javascript"></script>

Note the included teleport file (which npm will supply), and the application js file (which we will create next). Now create the /lib folder in the frappucino folder, and in it create a file called app.js. In it I have the following, as a test.

alert("Frappucino is the best!");

Ok, now you should have the following file structure:

frappucino/
    index.html
    package.json
    lib/
        app.js

Finally, to get npm to supply the dependencies, and register the app locally, type this within the ‘frappucino’ directory:

sudo npm link

I get some nice pink and green output with ‘npm ok’ at the end to let me know it worked.

Now, to run the app, do:

teleport activate

If all goes, well, it should say something like:

Teleport is activated: http://localhost:4747/frappucino

Now you can open another terminal window and type:

open http://localhost:4747/frappucino

And you will see your app in all its glory (or lack thereof, such as in this case.. just an alert window. But its a start :).

My 10KApart Entry Is Live !

| Comments

My entry to the 10KApart Javascript competition is a lightweight version of the Turtle Graphics explorer I’ve been working on. Aside from leaving out the the procedures browser, and doing some compression (I used YUICompressor) I did not have to change the code, and I didn’t remove any of the turtle’s abilities. In fact there are a couple of new features, notably the showing of the turtle itself on screen.

So check it out, and rate it ! It turns out that community voting is no longer considered for the Community Prize, but it will make me feel better :)

I posted the source code on github also.

Turtle Graphics With Javascript and Canvas

| Comments

One of my earliest experiences of computer programming was when my school acquired a computer lab, and we did some Turtle Graphics programming, probably in Logo. The school even had a robotic turtle which was used to draw lines on paper on the floor. I think one project we did was to draw the letters of the alphabet which made up the name of the school, or some other message. In any case I remember making the turtle go round drawing lines.

Your browser does not support canvas, please upgrade.

Earlier this year I read Mindstorms by Seymour Papert, which describes how computers can be used by children to learn about Mathematics and programming, and how the Turtle Graphics system is a better system for exploratory learning than the Math is conventionally taught. One of the reasons for this is that the child is able to identify with the turtle, and solve problems by walking out the path of the turtle, and performing the instructions of the program. There is a fascinating description of how younger children were actually better at figuring out how to get the turtle to draw a circle by going forward a bit and turning a bit repeatedly, than were older children who had already learned more objective facts about circles, such as that they have a radius and a center. Even older children who had learned the algebraic formula for a circle were actually incapable of solving the problem.

Recently I discovered the Holy Grail of the field, the definitive Turtle Graphics by Andrea di Sessa and Harold Abelson, who also co-wrote the Structure and Interpretation of Computer Programming. I’ve only just read the first chapter, but I was inspired to try out implementing a Turtle Graphics environment in Javascript, using Canvas as a rendering surface.


I started out typing my functions into the Javascript Console of Chrome, but I had a vision of a web-based interactive Turtle Graphics environment, where users could run their own code and see the results instantly. So this weekend I hacked together the Turtle Graphics Explorer. Its not going to work in any released version of IE (I’ll add Chrome Frame soon), but that will change when IE9 ships. A new version of Chrome, Safari, Firefox, or Opera should be fine, though I admit I’ve not tested thoroughly. Hopefully it is easy to understand.. load an example, or look at the procedures to see how they work. There is only very rudimentary error detection, so if it does not seem to be working, you may need to re-load a working example, hit ‘clear screen’, or just refresh the browser.

Here is a screenshoot of the application.. click on it to open it up, and start exploring ;)

Turtle Graphics Explorer

All the code is available at the GitHub project.

Drawing in 3D

| Comments

Last year Seb Lee-Delisle posted about how it would be nice to be able to draw in 3D with the same ease as you can draw in 2D, using the flash drawing API. It inspired me to try something similar, but with a different approach. I was looking into WebGL and OpenGL late last year, and though I got a bit bogged down with my lack of C knowledge, I found I liked the procedural API. The entire scene is actually redrawn every frame. This year I’ve also been thinking about the Turtle graphics system I once used in school, and how it works in a similar way (albeit in 2D). So I took a stab at creating a simple procedural 3D drawing API, along the lines of OpenGL and Logo. First the demo..

flash 10 required

It is currently implemented as a base class which exposes the following methods:

    rotate(angleX, angleY, angleZ)
    draw(x,y,z)
    move(x,y,z)

    pushMatrix()
    popMatrix()

The x, y, z values here are relative to the current position. The current position (and rotation) is maintained by the modelViewMatrix. By calling pushMatrix() you can save the current state and return to it later with popMatrix(). If you have subroutines, it is generally a good idea if they return the modelViewMatrix to the same state. For example in this example the drawSquare() method does this:

private function drawSquare()
{
    draw(100,0,0);
    rotate(0,0,90);
    draw(100,0,0);
    rotate(0,0,90);
    draw(100,0,0);
    rotate(0,0,90);
    draw(100,0,0);
    rotate(0,0,90);//return to starting orientation
}

So this simply draws 4 lines of length 100, rotating 90 degrees around the Z axis. The final rotation isn’t necessary for the drawing, but it ensures that the state is not changed after the routine is called. To draw a cube, we call the drawSquare routine while rotating and moving in 3D.

private function drawCube()
{
    //draw cube
    //back
    drawSquare();

    //left
    pushMatrix();
    rotate(0,90,0);
    drawSquare();
    popMatrix();

    //top
    pushMatrix();
    rotate(-90,0,0);
    drawSquare();
    popMatrix();

    //right
    pushMatrix();
    move(100,0,0);
    rotate(0,90,0);
    drawSquare();
    popMatrix();

    //bottom
    pushMatrix();
    move(0,100,0);
    rotate(-90,0,0);
    drawSquare();
    popMatrix();

    //front 
    pushMatrix();
    move(0,0,-100);
    drawSquare();
    popMatrix();

}

finally, to draw the cubes, we call the drawCube() routine inbetween calls to push/popMatrix() and any changes in position we wish to make.

    pushMatrix();
    drawCube();
    popMatrix();

    pushMatrix();
    move(150,0,0);
    drawCube();
    popMatrix();

    pushMatrix();
    move(-150,0,0);
    drawCube();
    popMatrix();

Once you get the hang of this approach, it is quite intuitive, and reduces the need for calculating a lot of 3D coordinates. This is done behind the scenes in the draw() method, which adds the real 3D coordinates to a list of vertices, which ultimately get projected to 2D coordinates. It’s easy to rotate the objects in the scene by calling rotate() before drawing the objects in the scene.

I’ve used Haxe here because of the faster compile time. There is also an earlier ActionScript version which I’ll link to below.

Da Code

DrawCubes.hx

Draw3D.hx

MatrixStack.as (the AS3 prototype)

GitHub