=

desalasworks presents:

a portfolio of work by steven de salas

Object-Oriented JavaScript Inheritance

This is simple but crucial stuff in JavaScript. Its easy to forget how to do object-oriented inheritance from scratch when you are dealing with several JS frameworks and each of them has pre-built methods that support this functionality in a slightly different way.

JavaScript is a functional language that uses prototypal inheritance. That means you can use classical inheritance such as that supported by Java and C#, however you need to be disciplined about the way you write code and need do a couple of things every time you add a class to your type hierarchy.

When creating a new class, we are essentially creating a function and assigning a new instance of another function as the prototype. This is the basis of ‘prototypal’ inheritance, ie. if you are dealing with ‘Dog’ type that inherits from an ‘Animal’ class, the template for your dog is a newly created instance of animal.

For Example:

// Create a new class called 'Animal'
var Animal = function() {};

// Create an instance of the 'Animal'
var anAnimal = new Animal();

// Create a class called 'Dog'
var Dog = function() {};

// Assign the template
Dog.prototype = anAnimal;

// Instantiate the dog
var lassie = new Dog();

Abstracting inheritance

I’ve created a simple static method called ‘extend’ on the Object class. Most frameworks do this in one shape or another (ie ExtJS uses Ext.extend(), John Resig likes to use Class.extend() method, Mootools uses new Class(properties) approach etc).

A ‘static’ method means that only the ‘Object’ class template will have it, so we do not pass it over to our children through inheritance. See the following code:

// Create a static 'extends' method on the Object class
// This allows us to extend existing classes
// for classical object-oriented inheritance
Object.extend = function(superClass, definition) {
    var subClass = function() {};
    subClass.prototype = new superClass();
    for (var prop in definition) {
        subClass.prototype[prop] = definition[prop];
    }
    return subClass;
};

This allows us to simplify the process of using object-oriented inheritance by abstracting the prototype assignment into this separate function call.

// Create an 'Animal' class by extending
// the 'Object' class with our magic method
var Animal = Object.extend(Object, {
    move : function() {alert('moving...');}
});

// Create a 'Dog' class that extends 'Animal'
var Dog = Object.extend(Animal, {
    bark : function() {alert('woof');}
});

// Instantiate Lassie
var lassie = new Dog();

// She can move AND bark!
lassie.move();
lassie.bark();

Adding Constructors

But, we seem to have forgotten one thing. What about constructors?

JavaScript uses the function itself as the constructor for a new object. Thus, when we created the Animal object above we could have simply added some sample code to its constructor as follows:

// Assign the name of the animal when it gets instantiated
var Animal = new function(name) {
  this.name = name;
}

var lassie = new Animal('Lassie');
alert('My pets name is: ' + lassie.name);

Thus we can augment our class creation methodology using the same idea:

// Create a 'Subclass' with a constructor
var SubClass = Object.extend(SuperClass, {
    constructor: function(parameter) {
        this.x = parameter;
    },
    method1: function() {
        // ...
    }
});

// Instantiate it
var subClass = new SubClass('value');
alert(subClass.x);

In order to allow this kind of notation, we can modify our ‘extend’ method to take care of this special ‘constructor’ function. This is done as follows:

// Create a static 'extends' method on the Object class
// This allows us to extend existing classes
// for classical object-oriented inheritance
Object.extend = function(superClass, definition) {
    var subClass = function() {};
    // Our constructor becomes the 'subclass'
    if (definition.constructor !== Object)
        subClass = definition.constructor;
    subClass.prototype = new superClass();
    for (var prop in definition) {
    	if (prop != 'constructor')
            subClass.prototype[prop] = definition[prop];
    }
    return subClass;
};

And put it to use by writing minimal code that is meaningful to read and leaves the object-creation abstraction sitting behind the scenes:

// Create the 'Animal' class by extending
// the 'Object' class with our magic method
// this time using a constructor
var Animal = Object.extend(Object, {
    constructor: function(name) {
        this.name = name;
    },
    move: function() {
        alert('moving...');
    }
});

// Instantiate Lassie (as an animal)
var lassie = new Animal('Lassie');

// Now lassie has a name which is
// defined inside the object constructor
alert('My pets name is: ' + lassie.name);

Calling constructors through the inheritance chain.

Now we have come up against a small problem, our ‘Animal’ class can have a constructor, but its child class ‘Dog’ has no way to call this constructor so it can take advantage of the logic for instantiating all animals.

In order to do this we are going to add a special ‘superClass’ property to all of our classes automatically, then use the magic ‘call’ function to call this using the context of the dog instance (to put it in plain english, this will make each ‘Dog’ run the logic for an ‘Animal’).

Lets see, all together now:

// Create a static 'extends' method on the Object class
// This allows us to extend existing classes
// for classical object-oriented inheritance
Object.extend = function(superClass, definition) {
    var subClass = function() {};
    // Our constructor becomes the 'subclass'
    if (definition.constructor !== Object)
        subClass = definition.constructor;
    subClass.prototype = new superClass();
    for (var prop in definition) {
    	if (prop != 'constructor')
            subClass.prototype[prop] = definition[prop];
    }
    // Keep track of the parent class
    // so we can call its constructor too
    subClass.superClass = superClass;
    return subClass;
};

// Create the 'Animal' class by extending
// the 'Object' class with our magic method
// this time using a constructor
var Animal = Object.extend(Object, {
    constructor: function(name) {
        this.name = name;
    },
    move: function() {
        alert('moving...');
    }
});

// Create a 'Dog' class that inherits from it
var Dog = Object.extend(Animal, {
    constructor: function(name) {
        // Remember to call the super class constructor
        Dog.superClass.call(this, name);
    },
    bark: function() {
        alert('woof');
    }
});

// Instantiate Lassie
var lassie = new Dog('Lassie');

// She can move AND bark AND has a name!
lassie.move();
lassie.bark();
alert('My pets name is: ' + lassie.name);

Multiple inheritance using Interfaces

Now its possible to add support for multiple inheritance to our object creation syntax in Javascript. In single-inheritance object-oriented languages such as Java and C#, multiple inheritance (inheriting properties and methods from more than one class chain) is done using Interfaces.

The implementation is a bit more crude than in Java or C#, the reason why is because Javascript, unlike these languages, is not compiled so we cant throw compilation-time errors. This means that when we implement an interface we are limited to checking that the appropriate members are there at runtime and if not we through an error.

So, lets start first with our intended usage for Interfaces:

var SubClass = Object.extend(SuperClass, {
     method1: function() {
         alert('something');
     }
}).implement(Inteface1, Interface2 ...);

Going by this approach, we need to create a method ‘implement’ for every class, since in Javascript our classes are instances of the ‘Function’ object, this means adding this method to Function.prototype.

The code does start to be a bit hairy from this point, its important to point out that the context of this function call (ie this) is the class that we are testing for implementation of a particular interface.

Function.prototype.implement = function() {
    // Loop through each interface passed in and then check
    // that its members are implemented in the context object (this)
    for(var i = 0; i < arguments.length; i++) {
         var interf = arguments[i];
         // Is the interface a class type?
         if (interf.constructor === Object) {
             for (prop in interf) {
                 // Check methods and fields vs context object (this)
                 if (interf[prop].constructor === Function) {
                     if (!this.prototype[prop] ||
                          this.prototype[prop].constructor !== Function) {
                          throw new Error('Method [' + prop
                               + '] missing from class definition.');
                     }
                 } else {
                     if (this.prototype[prop] === undefined) {
                          throw new Error('Field [' + prop
                               + '] missing from class definition.');
                     }
                 }
             }
         }
    }
    // Remember to return the class being tested
    return this;
}

And there you have it! Its important to point out that this is one of many ways to abstract object-orientation in Javascript. There are different approaches, and as a programmer it helps to pick one you are more comfortable with. Personally, I like this approach because of its simplicity, readability, and ease of use:

// Create a 'Mammal' interface
var Mammal = {
    nurse: function() {}
};

// Create the 'Pet' interface
var Pet = {
    do: function(trick) {}
};

// Create a 'Dog' class that inherits from 'Animal'
// and implements the 'Mammal' and 'Pet' interfaces
var Dog = Object.extend(Animal, {
     constructor: function(name) {
          Dog.superClass.call(this, name);
     },
     bark: function() {
          alert('woof');
     },
     nurse: function(baby) {
          baby.food = 100;
     },
     do: function(trick) {
          alert(trick + 'ing...');
     }
}).implement(Mammal, Pet);

// Instantiate it
var lassie = new Dog('Lassie');
lassie.move();
lassie.bark();
lassie.nurse(new Dog('Baby'));
lassie.do('fetch');
alert('My pets name is: ' + lassie.name);

Markit Environmental Registry

The Markit Environmental Registry is a central repository for tracing the ownership of carbon credits anywhere in the world and is the 1st ranked registry in 2012 Environmental Finance’s survey.

Rich Application for Carbon Market Transactions

Development of a fully Object-Oriented Javascript interface using the latest version of the EXT JS framework, a fully featured AJAX and GUI widget library based on Yahoo UI.

This was a 6 month project going live in September 2010 as part of the Markit suite of environmental products. The Markit Environmental Registry is a central repository for tracing the ownership of carbon credits anywhere in the world and has helped Markit gain 1st place for ‘Best Registry Provider’ in 2012 Environmental Finance’s survey.

While the work was primarily focused on individual paid-for access, there is also a complimentary public view interface that allows non-users to query database directly (written in plain HTML for SEO optimization).

Registry Landing Page

Delivering Features with Optimal Usability

Deliverables include a fully-operating Graphic User Interface compatible with IE (6,7 and 8), Firefox (3.0 upwards), Chrome and Safari in the form of an 8,000 line JavaScript library with 43 compiled javascript classes using object-oriented inheritance for minimal code-repetition and Java nomenclature and namespace breakdown wherever possible (with a view to find a replacement Java programmer) .

AJAX Architecture

The end result is a rich interface for a data-driven web application, with look-and-feel similar to that of a desktop application like Excel or Outlook. The users of the registry can access the following features:

Advanced Dockable Components

Standardised components such as grids (for record lists) allow for easily building functionality with components that can be docked in tab panels or within a popup window. Base components provide key functionality, such as layout, ordering, paging and searching and can be extended depending on the requirements for each section of the application.

Advanced Dockable Components

Simplified Search Criteria

Search criteria is simplified and prioritised to hide items that are less relevant to the user. Searching requires minimal input from the user (usually mouse-scroll and click).

Simplified Search Criteria

Predictive Search

An AJAX favourite. The implementation within the Registry is done using DOM buffering (only the items displayed are being rendered in the browser) which allows for thousands of records to be quickly filtered down to those that fit relevant criteria in milliseconds.

Predictive Search

Context Menus (right mouse button)

Context menus are used for right-clicking on a piece of information to find out relevant actions that can be performed. This is ported from functionality found in desktop application such as Outlook or Excel.

Context Menus

Windowed Interface

Window “lightboxes” are used to display information about individual records. These are pop-ups rendered within the page as modal windows, which provide a high degree of responsiveness in the application and the look-and-feel of traditional desktop applications.

Windowed Interface

Server-Side Validation Messages

Intuitive and appealing server side validation messages (without needing to refresh the page). The fields a user has entered incorrectly are clearly highlighted and provide additional information when hovering above them.

Server Validation

Hierarchical Data Representation (expanding trees)

Data is presented hierarchically wherever relevant, for example a syndication “Basket” used for risk management, can be constructed to contain other items within in. The User Interface displays this as an expandable item, with other items within it.

Hierarchical Data Representation

Object-Oriented Inheritance

The interface is designed as a self-contained JavaScript class library with components (Classes) that inherit from each other. This is done to reduce code-duplication and make the software more manageable.

Object Inheritance

Environmental Registry in the News

Markit Environmental Registry named ‘Best Registry Provider
April 2012

 

Feedback on the Registry

Some of the feedback received on this project:

UserEli Goncalves (End User)
www.personalco2zero.com

13 Sep 2010 – Your new platform really became more practical. Congrats!

UserHelen Robinson (Founder)
www.markitenvironmental.com

20 Sep 2010 – You guys have done a wonderful job, thank you very much!