Archive for the 'javascript' CategoryPage 2 of 4

Back to Basics

Most of us JavaScript developers can’t work without using a JavaScript Library/Framework today. JavaScript is a very nice language, but it requires for you to write a lot of code before you can implement some interesting animation, drag and drop feature, or Ajax request/polling.
This is in part due to the fact that every line of code we write must be browser compatible, and that adds lots of “ifs” to our code.
So I guess it’s understandable to think that choosing a framework that can abstract these kind of things for us is good. By using a framework we can concentrate on other kind of problems, more like high-level-usability-pattern problems.

Some frameworks stick with JavaScript as their main language (like MooTools or JQuery). Other frameworks simply let you type another kind of language that then gets compiled into JavaScript. I guess that having a language with built-in classical inheritance syntax and a nice IDE to support it are good reasons to develop these kind of libraries that translate some code into another.

Frameworks are undeniably good, but most of the things I learn about the JavaScript programming language were learn while hacking some pure JavaScript code.
When hacking pure JavaScript code you find yourself hacking common language idioms that are usually abstracted by frameworks. And it’s nice to understand how these things work. When you get how a specific JavaScript pattern/idiom works you get to understand lots of things about the language itself.

Most of the people don’t do this today. You can see posts about call and apply, closures and private members patterns very often in Reddit and Ajaxian, and each time that post appears lots of other people upmod it. So that means that most of the people today probably use the bind Function method without really knowing what it does.

The worst part is that JavaScript is a very beginner-friendly language, a good start for people not having a computer sicence related background, but at the same time there are lots of things about the language itself that are advanced features (object mutability, booleans as defaults, functions as first class citizen, prototypal inheritance) and most of the users are never aware of these features, most of the time due to the abstraction of the frameworks they’re using.

An Example

This is a very simple example (and interesting interview question also).
If you’re dealing with the dom when hacking JavaScript then you might often use the hasClass and removeClass methods from JQuery, MooTools, or whatever.

So, how would you write them?

function hasClass(domElement, className) {
 //code here...
}

function removeClass(domElement, className) {
//code here...
}

Please, if you’re reading this, take five minutes of your time and write these functions out before reading the answers. Believe me, it’s worth the effort. I mean, how much time can it take?

The Answers

click here to show the answers

Conclusion

These methods could have probably been written differently if disk space and performance weren’t such an important issue in JavaScript, but with those constraints even the most trivial methods like hasClass and removeClass can be interesting to read.
So this is my recommendation: try to understand how things you normally use are implemented. There are lots of interesting JavaScript libraries that make excellent code that’s performant and save disk space (:P) so check them out, you might learn about lots of things, even the most simple functions can have interesting concepts.

Drawing Trees

While trying to fix a SpaceTree layout issue for version 1.1.2 of the JavaScript InfoVis Toolkit I found a Microsoft Research paper that describes a functional programming approach for rendering trees in an aesthetically pleasing way.

But what is aesthetically pleasing?

Andrew J. Kennedy takes Radack and Walker rules:

  1. Two nodes at the same level should be placed at least a given distance apart.
  2. A parent should be centred over its offspring.
  3. Tree drawings should be symmetrical with respect to reflection—a tree and
    its mirror image should produce drawings that are reflections of each other. In
    particular, this means that symmetric trees will be rendered symmetrically.
  4. Identical subtrees should be rendered identically—their position in the larger
    tree should not affect their appearance.
  5. Trees should be as narrow as possible without violating these rules

In order to calculate nodes’ positions Kennedy takes a “bottom-up” approach:

Starting from the root node, draw for each node all its subtrees without breaking any rules. Fit these subtrees together without changing their shape, and also without breaking rules 1 and 3 (i.e do not break symmetry and avoid cluttering/overlapping of nodes). Finally, center their parent above them like specified in rule 2.

The “fitting” of the subtrees is calculated by operating on subtrees extents. A subtree extent is a data structure containing the relative coordinates of the boundary of a subtree. One frequent operation between extents is merging:

Other operations involve setting the distance between two extents, translating extents, etc.

Implementation

Kennedy implements this algorithm in Standard ML. I made a JavaScript adaptation. I like the Standard ML version a lot more; in this case rich typing makes very elegant code.

Here’s my code implementation, in case you want to compare it to Kennedy’s.
My version takes into account different tree layouts (left, right, bottom, top), siblings and subtrees offsets and different node sizes as opposed to Kennedy’s version.

 function movetree(node, prop, val, orn) {
   var p = (orn == "left" || orn == "right")? "y" : "x";
   node[prop][p] += val;
 };

 function moveextent(extent, val) {
     var ans = [];
     $each(extent, function(elem) {
         elem = slice.call(elem);
         elem[0] += val;
         elem[1] += val;
         ans.push(elem);
     });
     return ans;
 };

 function merge(ps, qs) {
   if(ps.length == 0) return qs;
   if(qs.length == 0) return ps;
   var p = ps.shift(), q = qs.shift();
   return [[p[0], q[1]]].concat(merge(ps, qs));
 };

 function mergelist(ls, def) {
     def = def || [];
     if(ls.length == 0) return def;
     var ps = ls.pop();
     return mergelist(ls, merge(ps, def));
 };

 function fit(ext1, ext2, subtreeOffset, siblingOffset, i) {
     i = i || 0;
     if(ext1.length <= i ||
        ext2.length <= i) return 0;

     var p = ext1[i][1], q = ext2[i][0];
     return Math.max(fit(ext1, ext2, subtreeOffset, siblingOffset, ++i) + subtreeOffset,
                 p - q + siblingOffset);
 };

 function fitlistl(es, subtreeOffset, siblingOffset) {
   function $fitlistl(acc, es, i) {
       i = i || 0;
       if(es.length <= i) return [];
       var e = es[i], ans = fit(acc, e, subtreeOffset, siblingOffset);
       return [ans].concat($fitlistl(merge(acc, moveextent(e, ans)), es, ++i));
   };
   return $fitlistl([], es);
 };

 function fitlistr(es, subtreeOffset, siblingOffset) {
   function $fitlistr(acc, es, i) {
       i = i || 0;
       if(es.length <= i) return [];
       var e = es[i], ans = -fit(e, acc, subtreeOffset, siblingOffset);
       return [ans].concat($fitlistr(merge(moveextent(e, ans), acc), es, ++i));
   };
   es = slice.call(es);
   var ans = $fitlistr([], es.reverse());
   return ans.reverse();
 };

 function fitlist(es, subtreeOffset, siblingOffset) {
    var esl = fitlistl(es, subtreeOffset, siblingOffset),
        esr = fitlistr(es, subtreeOffset, siblingOffset);
    for(var i = 0, ans = []; i < esl.length; i++) {
        ans[i] = (esl[i] + esr[i]) / 2;
    }
    return ans;
 };

 function design(graph, node, prop, config) {
     var orn = config.orientation;
     var auxp = ['x', 'y'], auxs = ['width', 'height'];
     var ind = +(orn == "left" || orn == "right");
     var p = auxp[ind], notp = auxp[1 - ind];

     var cnode = config.Node;
     var s = auxs[ind], nots = auxs[1 - ind];

     var siblingOffset = config.siblingOffset;
     var subtreeOffset = config.subtreeOffset;

     var GUtil = Graph.Util;
     function $design(node, maxsize, acum) {
         var sval = (cnode.overridable && node.data["$" + s]) || cnode[s];
         var notsval = maxsize || ((cnode.overridable && node.data["$" + nots]) || cnode[nots]);

         var trees = [], extents = [], chmaxsize = false;
         var chacum = notsval + config.levelDistance;
         GUtil.eachSubnode(node, function(n) {
             if(n.exist) {
                 if(!chmaxsize)
                    chmaxsize = getBoundaries(graph, config, n._depth);

                 var s = $design(n, chmaxsize[nots], acum + chacum);
                 trees.push(s.tree);
                 extents.push(s.extent);
             }
         });
         var positions = fitlist(extents, subtreeOffset, siblingOffset);
         for(var i=0, ptrees = [], pextents = []; i < trees.length; i++) {
             movetree(trees[i], prop, positions[i], orn);
             pextents.push(moveextent(extents[i], positions[i]));
         }
         var resultextent = [[-sval/2, sval/2]].concat(mergelist(pextents));
         node[prop][p] = 0;

         if (orn == "top" || orn == "left") {
            node[prop][notp] = acum;
         } else {
            node[prop][notp] = -acum;
         }
         return {
           tree: node,
           extent: resultextent
         };
     };
     $design(node, false, 0);
 };

The JavaScript InfoVis Toolkit 1.1 is Out!

After several months of hard work I can finally announce version 1.1 of the JavaScript InfoVis Toolkit.

What’s the JavaScript InfoVis Toolkit?

The JavaScript InfoVis Toolkit provides tools for creating Interactive Data Visualizations for the Web.

What’s new in this version?

Code-Related

  • The library has been split into modules for code reuse.
  • All visualizations are packaged in the same file. You can create multiple instances of any visualization. Moreover, you can combine and compose visualizations. If you want to know more take a look at the Advanced Demos.
  • This Toolkit is library agnostic. This means that you can combine this toolkit with your favorite DOM/Events/Ajax framework such as Prototype, MooTools, ExtJS, YUI, JQuery, etc.
  • You can extend this library in many ways by adding or overriding class methods. The JavaScript InfoVis Toolkit has a robust (and private) class system, heavily inspired by MooTools’, that allows you to implement new methods in the same class without having to define any new Class extension. By creating mutable classes you can add new custom Node and Edge rendering functions pretty easily.
  • Custom visualizations are created by adding or changing Node/Edge colors, shapes, rendering functions, etc. You can also implement many controller methods that are triggered at different stages of the animation, like onBefore/AfterPlotLine, onBefore/AfterCompute, onBefore/AfterPlotNode, request, etc.
    You can also add new Animation transitions like Elastic or Back with easeIn/Out transitions.
    If you want to know more about these features please take a look at the Demos code.

As you can see, this new version has been built with four concepts/goals in mind: Modularity, Customization, Composition and Extensibility. I already explained some of these things in the previous post.

Hope you enjoy it.

More about the JavaScript InfoVis Toolkit 1.1

I’ve been putting a lot of effort in the upcoming version of the JavaScript InfoVis Toolkit lately, and I though it would be a good idea to show some of the new features I came up with.

The new version isn’t finished yet, but I’ve come pretty far and wanted to make a sort of checkpoint for the things I’ve done, the things I’ll be doing and the things I’m thinking about doing.

So what have I been working on?

  • A new project page design.
  • A complete documentation. I made an API documentation that is also mixed with some narrative documentation for each Class, so you can learn how the visualizations are implemented and how to use them.
  • Packaging All visualizations will be packaged in the same file, and you’ll be able to make your own build based on what you’re going to use (Treemaps, Hypertrees, RGraphs, Spacetrees or any combination of those). This is a cool aspect of making modular code.
    The other good thing about modular code is that the size of the full package will drop in ~30% compared to version 1.0.8a
  • Examples I’ve been coding some new visualization examples that will be packaged with the library. Some of them are very similar to the ones found in 1.0.8a, but adapted for version 1.1. Other examples show some of the new features of the library, and others try to expose some features of version 1.0.8a that were not properly documented.

Library features

I’ve been building this library with four things in mind:

  • Extensibility The library has multiple access points where it can be extended in different ways. For example, all main Classes are mutable objects, so you can extend or implement any method of any class in-place, like for example re-implement the nodes coloring method in the Squarified treemap:

       //TM.Strip, TM.SliceAndDice also work
       TM.Squarified.implement({
         'setColor': function(json) {
           return json.data.$color;
         }
       });
    

    …or adding new node/edge plotting methods in the Hypertree, ST or RGraph:

    Hypertree.Plot.NodeTypes.implement({
      'my-node-rendering-method': function(node, canvas) {
        //implement node rendering here
      }
    });
    

    etc.

  • Customization The library provides many ways for customizing the visualizations. There are controller methods that determine the behavior of the visualization, and configuration parameters like node and edge types, color and dimensions. Node shapes can be square, rectangle, circle, ellipse, etc. and edge shapes: line, hyperline and arrow. I also added transition effects like Quart, Bounce, Elastic, Back, etc. for the animations.
  • Modularity As explained above, the code has been divided into modules, providing a way for making custom builds of the library. Modularity also takes care of namespacing: I only add Classes that are meant to be accessed by the user and I don’t pollute the window object with unnecessary global objects.
  • Composition A major improvement in this version is that all visualizations can co-exist in the same namespace. That means that multiple instances of different visualizations can be used and composed to make new visualizations. I haven’t explored this feature of the library yet, but this would mean that for example I can make a Treemap that has Hypertrees rendered as leaves, or a Spacetree that has Treemaps as nodes, or… well, any other combination of things.

Examples

As you might know, I don’t have the most suited computer for making screencasts, so sorry if you see some performance problems.

This is a short video I made of a RGraph example.

The main idea behind this example is Customization.
That can be seen for example in the different node types, edge types and colors used, as well as in the Elastic transition effect for the animation.

This is just an example to expose as much features as I can in one visualization, so don’t take this as a “useful” visualization example please.

Here is another short video: it illustrates how Graph Operations can be made with the Hypertree visualization.

You’ll see 4 consecutive operations:

  1. Removing a subtree The bottom right subtree will be removed with an animation.
  2. Removing edges Edges from the top left subtree will be removed with an animation.
  3. Adding a graph A graph will be added with an animation
  4. Morphing The graph will transform into another graph -with an animation

Enjoy.

Sharp Variables

I was looking for some way to easily create, read, manipulate and print cyclic or recursive data structures in some programming languages, and got to the cool concept of sharp variables.

Manipulating Recursive Structures in Python

A straightforward way of defining a recursive structure is to first assign a base (non-recursive) structure to a variable, and then alter or extend that variable with a recursive expression. For example, in Python you can write:

my_rec_var = [1, 2, 3]
my_rec_var.append(my_rec_var)

That code will create a recursive data structure: [1, 2, 3, [1, 2, 3, [...]]],
or a = [1, 2, 3, a].

Actually, Python’s print function lets you print a representation of a recursive structure without recursing indefinitely:

>>> print my_rec_var
[1, 2, 3, [...]]

Python’s pickle module lets you dump a recursive data structure into a file. You can also read that serialized structure from the file:

import pickle

#dump it to file
output = open("out.pkl", "wb")
pickle.dump(my_rec_var, output)

However, there’s no literal way of creating, reading or modifying that structure:

>>> my_rec_var = [1, 2, 3, [...]]
 ERROR

Manipulating Recursive Structures in Lisp

For manipulating/printing recursive data structures in Common Lisp we first assign T to the global variable *print-circle*

(setq *print-circle* T)

We can define a recursive structure just as we did with Python, by defining some base structure and then modifying the structure to be recursive:

(defvar *my-rec-var* (list 1 2 3 _))
;Replace the underscore placeholder with a self-reference
(setf (fourth *my-rec-var*) *my-rec-var*)

The final structure is represented with sharp variables:

>>> (print *my-rec-var*)
#1=(1 2 3 #1#)

This is just as the “Mathematical” definition we gave above:
a = [1, 2, 3, a].

What’s interesting about this “serialization format” is that expressions involving sharp variables are truly expressions: these “objects” can be read and manipulated just like any other structure:

>>> (defvar *another-rec-var* ‘#1=(1 2 3 #1#))
#1=(1 2 3 #1#)

>>> (fourth ‘#1=(1 2 3 #1#))
#1=(1 2 3 #1#)

>>> (cons 5 ‘#1=(1 2 3 #1#))
(5 . #1=(1 2 3 #1#))

Sharp variables seem like an excellent solution for creating, reading and manipulating cyclic data structures.

Sharp Variables in JavaScript

Mozilla’s JavaScript implementation has Sharp Variables. They’ve been introduced by Brendan Eich and they are inspired by Common Lisp’s syntax.
Sharp Variables can be pretty useful in JavaScript, since most of the time we’re manipulating object references and Firefox’s toSource() method is pretty useful for debugging (among other things).

var myArray = [1, 2, 3];
myArray.push(myArray);
myArray.toSource();

Try running that in your Firefox console, it should return “#1=[1, 2, 3, #1#]“.

Oh, and did I mention that you can also explicitly manipulate cyclic structures in JavaScript?

//Assign a literal recursive data structure
var anotherArray = #1=[1, 2, 3, #1#];

console.log(anotherArray.toSource());
//"#1=[1, 2, 3, #1#]"

console.log(anotherArray[0]);
//1

console.log(anotherArray[3].toSource());
//"#1=[1, 2, 3, #1#]"

I was happy to find such an interesting Lisp feature in JavaScript.

Generic Functions and JavaScript

In my last post I mentioned Operator Overloading, and why I think it would be interesting to see this as a proposal for the ECMAScript 4 specification (the new JavaScript specification).
I’ve been following the ECMA discussion list and the ES 4 wiki, and I was surprised to see that I feel the same way as some people in the ECMA group do about operator overloading.
The Operator Overloading proposal has been made a couple of times before, but it was disregarded as beeing too weak to be considered.

However, this proposal has been superseeded by some other (very interesting) proposal: generic functions (a.k.a multimethods).

What are generic functions?

The first time I discovered generic functions was while playing with Common Lisp’s Object System (CLOS).
In fact, early Lisp systems worked as Smalltalk did, by implementing a send function:


(send object :foo)

instead of just doing:


(foo object)

They finally came with the solution of creating generic functions that could be implemented by methods. This design is far more expressive that the classic OO design, implemented in languages such as Java.
Since this design is far from classical OO ones, explaining by example turns out to be quite difficult: the wikipedia examples aren’t very enlightening (see the article’s discussions).

So here I go.

Java has function overloading: that means that several methods with the same name can be defined in the same class, provided that the type (or number of arguments) defined in each method is not the same.

So, for example, lets define a Java class Person with two eat methods:

  class Person {
    public void eat (Food f) { println ("eating food"); }
    public void eat(Pasta p) { println ("eating pasta"); }
  }

(Pasta extends Food)

We have succesfully overloaded the eat method. However, the overloading happens at compile time, and there’s no dynamic dispatch. So, for example this code:

  Food food = new Pasta();
  somePerson.eat(food);

Will answer “eating food”, which isn’t exactly what we want.

Now lets consider this code:

class John extends Person {
    public void eat(Food f) { println ("mmm...."); }
    public void eat(Pasta p) { println ("Yummy!"); }
  }

  Person me = new John();
  Food pasta   = new Pasta();
  me.eat(pasta);

This code will answer “mmm…”. But there’s one important thing: we’ve called a method from John’s class, instead of some eat method from Person.

This had to be decided at run time, since me is of type Person, but we assigned a John to it…

Now lets define, in pseudo-code, an abstraction of these eat methods, that could be thought as decoupled from the John and Person classes. For example, we could re-write John and Person eat methods as four independent functions:

public void function eat(John john, Food f) { ... }
public void function eat(John john, Pasta p) { ... }

public void function eat(Person person, Food f) { ... }
public void function eat(Person person, Pasta p) { ... }

What we know about these methods is that Java checks its first argument type at runtime, but all other arguments are checked at compile-time.
So, as far as dynamic dispatch concerns, Java has single dispatch, and function overloading only refers to compile-time checked types, which in general doesn’t yield the expected result. (This problem beeing solved by the visitor pattern in most cases).

A generic function can be seen as a family of functions that provide multiple dispatch, that means that all arguments of the function are checked at runtime (on invocation). Not only the first argument, but all.
Compared to Java, this approach would, in most cases, yield the expected answers without having to implement some patterns like the visitor pattern.

The four methods defined above could be redefined in CLOS as:

(defmethod eat ((john John) (f Food)) ... )
(defmethod eat ((john John) (p Pasta)) ... )

(defmethod eat ((person Person) (f Food)) ... )
(defmethod eat ((person Person) (p Pasta)) ... )

Generic Functions in JavaScript

The Generic Functions JavaScript proposal aims to solve all weaknesses existing in the Operator Overloading proposal, but it also provides a more generic way of defining and manipulating functions.
Operator Overloading should be seen as a particular case of what can be done with generic functions in JavaScript.

In JavaScript, a generic function could be defined as:


generic function f(x, y);

Since a generic function defines a family of functions, there’s no function body in it.
A generic function can also be defined with type annotations:


generic function f(x: Numeric, y: Object): MyClass;

A method is then defined over an existing generic function, using specializers:


 generic function f(x:int, y:boolean): string {
      if (y)
          return string(x);
      else
          return "37";
  }

Eventually, built-in generic functions could be defined for common operators, providing a way of overloading operators:


generic function +(a:Complex, b:Complex) {
   return new Complex(a.x + b.x, a.y + b.y);
}

For a JavaScript canvas developer, this would be wonderful, since we mess with Complex, Polar, Matrix classes all the time, and a simple interpolation expression of two complex numbers could be transformed from this:

(to.$add(from.scale(-1))).$scale(delta).$add(from)

into this:


from + (to - from) * delta

Cushion Treemaps

Remember Treemaps?

There was a thread at the Google Group for the JIT asking for Gradients in Treemaps.

Actually they’re called cushion treemaps, and they have been created by Ph.Ds Jarke J. van Wijk and Huub van de Wetering. Cushion Treemaps have been used in successful applications like SequoiaView and companies like MagnaView are building very interesting visualizations with cushion treemaps.

The paper is quite interesting: cushion treemaps were created by using shading to show a tree’s structure:

“How can we use shading to show the tree structure? The human visual system is trained to interpret variations in shade as illuminated surfaces [6]. Hence, we can answer the question by constructing a surface which shape encodes the tree structure.”

Shadowing is created by adding bumps to rectangles.

In the JavaScript InfoVis Toolkit, this can be done by overriding the leafBox method of the Treemap class. This method renders a leaf node (nodes which are generally colored in the Treemap).
By adding an image of a radial gradient inside that div we can emulate cushion treemaps.

Instead of creating a new class that extends TM and overrides that method, we can take advantage of JavaScript’s object mutability feature and re-implement the method in the same class.


    TM.Squarified.implement({
       leafBox: function(json, coord) {
        var config = this.config;
        var backgroundColor = config.Color.allow && this.setColor(json),
        offst = config.offset,
        width = coord.width - offst,
        height = coord.height - offst;
        var c = {
         'top': (offst / 2) + "px",
         'height':height + "px",
         'width': width + "px",
         'left': (offst / 2) + "px"
        };
        if(backgroundColor) c['background-color'] = backgroundColor;
       //Add an image to our leaf node to create a cushion treemap.
        var img = "<img src='gradient.png' style='position:absolute; z-index:2; top:0; left:0; width:" + c.width + "; height:"+ c.height +"'; />"; 

        return "<div class='leaf' style=" + this.toStyle(c) + ">" + img + json.name + "</div>";
       }
    });

And that’s it, now we have Squarified Cushion Treemaps. I must say that I love cushion treemaps, they look a lot more cool than simple treemaps.

I made a small POC where you can enable/disable the cushion feature, among other interesting things:

cushion treemap

Why not Operator Overloading in JavaScript?

Disclaimer: Some of this post arguments are inspired by the great talk by Guy Steele: Growing a Language.

So I was checking out the new JavaScript spec. (ECMAScript 4) lately, and I was very surprised (and disappointed) to see that Operator Overloading wasn’t even accepted as a proposal for ECMAScript 4.
I’ve noticed last year that the proposal was denied by all browser vendors, as you can see in the ECMAScript 4 progress spreadsheet created by John Resig, under the name of “Operator Overloading”.

This is heartbreaking for me… let me explain you why.

Why Operator Overloading (in general)?

Operator Overloading is a special case of polymorphism, in which operators like +, /, *, … can be overloaded by the user.
This is very useful in languages where the user can define special types (or classes), since it allows the developer to use notation that is closer to the target domain, and allows user types to look like types built into the language.

What Guy Steele said about Operator Overloading is that:

“If we grow the language in these few ways, then we will not need to grow it in a hundred other ways; the users can take on the rest of the task.”

To see why, think about these structures:

  • 2D, 3D Vectors
  • Matrices
  • Intervals
  • Complex Numbers
  • Polar Coordinates
  • Rational Numbers

One thing all these structures have in common is that their sum and product operations have a different definition than the one we give to integers.

There’s also an interesting fact about these structures: a lot of people use them, but a lot of people don’t.
For example, Matrices might be used by OpenGL/Direct3D developers, but it’s not very common to use this structure for manipulating the DOM or building AJAX applications.

However, each of these structures must be considered in any programming language.
Adding them all into some standard library might be too much. However, sooner or later, some developer will want to use them.

Here’s the dilemma as exposed by Guy Steele:
I might say “yes” to each one of these, but it is clear that I must say “no” to all of them!“.

Operator Overloading solves this problem by giving the user the power to overload built-in operations and turn a non-domain specific language into a perfect tool for a developer’s specific needs.

By using Operator Overloading a developer can define operations on any custom type and its use will blend perfectly well into the language.

Wouldn’t be just beatifull if a and b beeing Complex Numbers, we could do this:

a + b * c

instead of this? :

add (a, multiply (b,c))

Ok, so now that I made my point about the power of operator overloading, let me explain you why I think this should be more carefully considered by the new JavaScript spec.

Why Operator Overloading in JavaScript?

To see why we should take seriously Operator Overloading in JavaScript, we first have to take a look at what happened to JavaScript in the last few years.

Only one thing happened to JavaScript in the last few years, AJAX.

The XMLHTTPRequest concept was first created by Microsoft, and wasn’t part of the web standards. They first used it in the year 2000, but a couple of years later Mozilla, Safari and Opera were also implementing it.
The standards covered that topic a lot of time after it was already implemented in all major browsers, and AJAX was already in the wild.

One strong aspect of JavaScript that was pretty important and that, IMHO, made the adoption of the “AJAX paradigm” a lot easier, is that JavaScript was already compliant with the “event-driven” programming paradigm, and the use of the XMLHTTPRequest object didn’t add anything new to this paradigm.
Just as callbacks were added to respond to DOM Element’s events, callbacks were used to handle server side answers. Although AJAX changed the way web applications were created, it did that by mantaining the event-driven programming paradigm.

Oh, another thing happened to JavaScript in the last couple of years, Canvas.

Canvas is following the same trend the XMLHTTPRequest object followed. It has been adopted by most browsers (Opera, Gecko, Webkit) and despite Internet Explorer’s efforts to not adopt this new feature, libraries already exist to make Canvas compatible with IE (to a certain point).
A couple of nice libraries that used Canvas were released last year: John Resig published Processing JS. Some other libraries that make use of canvas were also released, one of them is the JavaScript InfoVis Toolkit (my library! :) ).
The number of Canvas related stories really grew at Ajaxian, and there were also new breakthroughs by Opera and Firefox on the implementation of Canvas 3D.

There is one caveat to this Canvas thing though, it doesn’t use extensively the event-driven paradigm. Since all these Canvas implementations are related to Cairo and also take things from OpenGL and Direct3D (this is notably the case for the Canvas’ 3D API), IMO these concepts are more related to a functional programming paradigm than anything else.
I mean, 2D/3D graphics are all about geometrical operations. And geometrical operations are mathematical functions. These concepts might be harder to grasp than the “”AJAX paradigm”", and that’s why the adoption curve won’t be as high as the AJAX one, but there’s no doubt that Canvas developers are a niche.

And do you know which objects/types/classes are related to geometrical computation, Canvas, Canvas 3D, Cairo, OpenGL and Direct3D?

  • 2D, 3D Vectors
  • Matrices
  • Intervals
  • Complex Numbers
  • Polar Coordinates

That’s exactly what I mean. The next logical step to bring a easier use for Canvas related programming should be operator overloading. This is the one feature that will be extensively used by JavaScript Canvas developers, since they have to deal with points, 2D and 3D coordinates all day.

For a last example, consider an interpolation function between two complex numbers

(to.$add(from.scale(-1))).$scale(delta).$add(from)

The same thing with operator overloading would be:

from + (to - from) * delta

You would make a developer’s life happier.

Anonymous Recursive Functions

I learned this “trick” some time ago, while reading the source code for the MooTools JavaScript framework (version 1.1, I think).

I used this “trick” not so long ago, when developing the Spacetree visualization for the JavaScript InfoVis Toolkit library.

When clicking a node, the Spacetree visualization unselects all tree nodes and then selects the nodes in between the root node and the selected node. This can be implemented as a recursive function, since we have to iterate through the clicked node and its ancestors to set those nodes as selected.

I defined an anonymous recursive function that receives a node and a special value as formal parameters, and sets the selected property from this node and its ancestors to the specified value:

  (function(node, val) {
      if(node == null) return;
      node.selected = val;
      return arguments.callee(node.parent, val);
  })

arguments.callee holds a reference to the defined function.
You can check that by copying this code:

  (function(text) {
    alert(arguments.callee);
    alert(text);
  })("some text");

and running it in your Firefox console.

Unfortunately, our anonymous recursive function needs to be called more than once, since we first need to unselect previous selected nodes, and then to select the nodes in between the clicked node and the root node.
Similar to the “return this” trick to chain method calls, we can add “return arguments.callee” to chain function calls.

  (function(node, val) {
      if(node == null) return arguments.callee;
      node.selected = val;
      return arguments.callee(node.parent, val);
  })

This way, we can call our function multiple times. I’ll first pass the previous clicked node in order to unselect the previous selected path, and then I’ll pass the new clicked node in order to select our new path:

  (function(node, val) {
      if(node == null) return arguments.callee;
      node.selected = val;
      return arguments.callee(node.parent, val);
  })(nodePrev, false)(nodeNew, true);

What’s more interesting though, it’s trying to do the same thing in another language, like Lisp or OCaml.
Who knows, you might sumble upon the Y combinator.

Visualizing Linux package dependencies

I’ve been building a Linux package dependency visualizer with Python and the JavaScript Infovis Toolkit that gathers all dependencies for a linux package and displays them in an interactive tree visualization.

So, let’s say your query is wine and you want to see dependencies for that package. The visualization will display wine as the centered node, laying its dependencies on outer concentric circles like this:

rg1

By clicking on xbase-clients you’ll set this node as root:

rg2

Then, the visualization will query for xbase-clients dependencies, morphing its state into the new node’s perspective:

rg3

You can play with the example here.

I’ll explain how to build this in case you want your own at home.
I guess this is going to be also a nice tutorial on how to configure the RGraph visualization to run advanced examples, including the new morphing animations in version 1.0.7a.

Server Side

Server side we need to build a service that can transform the apt-rdepends output for package dependencies into a JSON tree structure.

The apt-rdepends is a linux tool (which you can install with apt-get install apt-rdepends) that displays a hierarchy of package dependencies for a given package. Here’s an example when querying for erlang:

cmd1

You can either use popen2 or commands.getoutput to fetch the output for a system call in Python, I’ll do the latter.
The main function that makes the system call and returns the answer could be something like this:

def get_dependency_tree(package=''):
    out = commands.getoutput("apt-rdepends " + package).split("\n")
    ans = []
    #if dependencies were found for this package.
    if len(out) > 3 and out[3].strip() == package:
        ans = out[3:]
    else:
        ans = [package]
    return make_tree(package=ans[0].strip(), source=ans, level=2)

The make_tree function will create the tree structure that will then be serialized into JSON to be processed client side.

We will first need a make_tree_node function that creates a tree node structure from a package’s name:

#returns a tree node
def make_tree_node(id, node_name):
    node_name = node_name.strip()
    return {
            'id': id,
            'name': node_name,
            'children': [],
            'data': []
    }

As you can see, this is the same tree node as the JSON tree structure defined for the JIT:

var json = {
	"id": "aUniqueIdentifier",
	"name": "usually a nodes name",
	"data": [
	    {key:"some key",       value: "some value"},
		{key:"some other key", value: "some other value"}
	],
	children: [/* other nodes or empty */]
};

Our make_tree function will receive as formal parameters the root package, the response from the apt-rdepends call, an integer that will specify the max depth for the tree (in case we want to prune it to some level) and an id prefix that will be set for each node:

def make_tree(package='', source=[], level=1, prefix=''):
    node = make_tree_node(package + '_' + prefix, package)
    if level > 0:
        deps = get_package_deps(package, source)
        [node['children'].append(make_tree(elem, source, level -1, package)) for elem in deps]
    return node

As you can see, make_tree recursively creates nodes and appends them to their parent children property.

Finally, I also made a get_package_deps function that retrieves all children for a given package, parsing source:

def get_package_deps(package_name='', source=[]):
    ans, found_package_name = [], False
    #test if is a dependency line
    dependency = lambda package: package.strip().startswith('Depends:')
    for line in source:
        #package name line
        if not found_package_name and package_name == line.strip():
            found_package_name = True
        #it's a package dependency, add its name to the answer
        elif found_package_name and dependency(line):
            ans.append(line.split("Depends: ")[1].split("(")[0].strip())
        #end of dependency lines
        elif found_package_name and not dependency(line):
            return ans
    return ans

If you used Django, then you could expose your service in the views.py file like this:

def apt_dependencies(request, mode, package):
    json = aptdependencies.get_dependency_tree(package)
    json_string = simplejson.dumps(json)
    return render_to_response('raw.html', { 'json' : json_string })

Client Side

All the JavaScript Infovis Toolkit visualizations are customizable via controller methods.
If this is the first time you use this library, perhaps it would be better to start with the RGraph quick tutorial first.

First we define a simple Log object, that will write the current state of the graph to a label (like loading… or stuff like that).

I’ll use Mootools, but you can use whatever you want.

var Log = {
	elem: false,
	getElem: function() {
		return this.elem? this.elem : this.elem = $('log');
	},

	write: function(text) {
		var elem = this.getElem();
		elem.set('html', text);
	}
};

Then we can define an init function, that instanciates the RGraph object and returns it.
We will pass a controller to this object, that implements the onBeforeCompute, onAfterCompute, onPlaceLabel and onCreateLabel methods.
I’ll also define some utility methods, like requestGraph and preprocessTree:

function init() {
  //Set node radius to 3 pixels.
  Config.nodeRadius = 3;

  //Create a canvas object.
  var canvas= new Canvas('infovis', '#ccddee', '#772277');

  //Instanciate the RGraph
  var rgraph= new RGraph(canvas,  {
	//Here will be stored the
	//clicked node name and id
  	nodeId: "",
  	nodeName: "",

  	//Refresh the clicked node name
	//and id values before computing
	//an animation.
	onBeforeCompute: function(node) {
  		Log.write("centering " + node.name + "...");
		this.nodeId = node.id;
  		this.nodeName = node.name;
  	},

  //Add a controller to assign the node's name
  //and some extra events to the created label.
  	onCreateLabel: function(domElement, node) {
  		var d = $(domElement);
  		d.setOpacity(0.6).set('html', node.name).addEvents({
  			'mouseenter': function() {
  				d.setOpacity(1);
  			},
  			'mouseleave': function() {
  				d.setOpacity(0.6);
  			},
  			'click': function() {
				if(Log.elem.innerHTML == "done") rgraph.onClick(d.id);
  			}
  		});
  	},

	//Once the label is placed we slightly
	//change the positioning values in order
	//to center or hide the label
  	onPlaceLabel: function(domElement, node) {
		var d = $(domElement);
		d.setStyle('display', 'none');
		 if(node._depth <= 1) {
			d.set('html', node.name).setStyles({
				'width': '',
				'height': '',
				'display':''
			}).setStyle('left', (d.getStyle('left').toInt()
				- domElement.offsetWidth / 2) + 'px');
		}
	},

	//Once the node is centered we
	//can request for the new dependency
	//graph.
	onAfterCompute: function() {
		Log.write("done");
		this.requestGraph();
	},

	//We make our call to the service in order
	//to fetch the new dependency tree for
	//this package.
   	requestGraph: function() {
  		var that = this, id = this.nodeId, name = this.nodeName;
  		Log.write("requesting info...");
  		var jsonRequest = new Request.JSON({
  			'url': '/service/apt-dependencies/tree/'
					+ encodeURIComponent(name) + '/',

  			onSuccess: function(json) {
  				Log.write("morphing...");
				//Once me received the data
				//we preprocess the ids of the nodes
				//received to match existing nodes
				//in the graph and perform a morphing
				//operation.
  				that.preprocessTree(json);
				GraphOp.morph(rgraph, json, {
  					'id': id,
  					'type': 'fade',
  					'duration':2000,
  					hideLabels:true,
  					onComplete: function() {
						Log.write('done');
					},
  					onAfterCompute: $empty,
  					onBeforeCompute: $empty
  				});
  			},

  			onFailure: function() {
  				Log.write("sorry, the request failed");
  			}
  		}).get();
  	},

	//This method searches for nodes that already
	//existed in the visualization and sets the new node's
	//id to the previous one. That way, all existing nodes
	//that exist also in the new data won't be deleted.
 	preprocessTree: function(json) {
  		var ch = json.children;
  		var getNode = function(nodeName) {
  			for(var i=0; i<ch.length; i++) {
  				if(ch[i].name == nodeName) return ch[i];
  			}
  			return false;
  		};
  		json.id = rgraph.root;
		var root = rgraph.graph.getNode(rgraph.root);
  		GraphUtil.eachAdjacency(root, function(elem) {
  			var nodeTo = elem.nodeTo, jsonNode = getNode(nodeTo.name);
  			if(jsonNode) jsonNode.id = nodeTo.id;
  		});
  	}

  });

  return rgraph;
}

I did say advanced example.
You can always go to a simpler example to begin here.

Finally we have to initialize the visualization when the page loads, so we’ll attach an initialization function like this:

window.addEvent('domready', function() {
	var rgraph = init();
	new Request.JSON({
	  	'url':'/service/apt-dependencies/tree/wine/',
	  	onSuccess: function(json) {
			  //load wine dependency tree.
			 rgraph.loadTreeFromJSON(json);
			  //compute positions
			  rgraph.compute();
			  //make first plot
			  rgraph.plot();
			  Log.write("done");
			  rgraph.controller.nodeName = name;
	  	},

	  	onFailure: function() {
	  		Log.write("failed!");
	  	}
	}).get();

HTML and CSS

These are the HTML and CSS files I used to make this example/tutorial.
The HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>

Linux package dependency visualizer

</title>
<link type="text/css" href="/static/css/style.css" rel="stylesheet" />
<script type="text/javascript" src="/static/js/mootools-1.2.js"></script>

<!--[if IE]>
<script language="javascript" type="text/javascript" src="/static/js/excanvas.js"></script>
<![endif]-->
<script language="javascript" type="text/javascript" src="/static/js/core/RGraph.js"></script>
<script language="javascript" type="text/javascript" src="/static/js/example/example-rgraph.js"></script>

</head>

<body onload="">

<canvas id="infovis" width="900" height="500"></canvas>
<div id="label_container"></div>

</body>
</html>
<div id="log"></div>

Note: You’ll probably have to change the path to the CSS and JavaScript files.

and the CSS file:

html,body {
	width:100%;
	height:100%;
	margin:0;padding:0;
	background-color:#333;
	text-align:center;
	font-size:0.94em;
	font-family:"Trebuchet MS",Verdana,sans-serif;
}

#infovis {
	width:900px;
	height:500px;
	background-color:#222;

}

.node {
	color: #fff;
	background-color:#222;
	font-weight:bold;
	padding:1px;
	cursor:pointer;
	font-size:0.8em;
}

.hidden {
	display:none;
}

Remarks

Although still in alpha, the JavaScript Infovis Toolkit can be used to perform advanced animations, customizing your visualization via a controller and not messing with the code.
This example also shows that it can be used to do more advanced things that only plotting static animations, interacting with services and handling pretty well visualizations where the dataset changes over time.
You can download the library here, latest version is 1.0.7a.
You can also go to the main project page to know more.

Hope it was useful.
Feel free to post any comment or questions.
Bye!