Friday, October 31, 2008

Viewport, Column Container and nested layouts

I have added a viewport class and a column container class to JX. Please read my earlier posts if you havent.

The viewport takes over the document body element. So you can have only one viewport instance in your application. If you have content in your body element the viewport will hide it. So it is unobtrusive also. Clients with no javascript will see your content. Viewport extends JX.Container so lays out its components vertically.

The column container works similar to the container in my previous post except that it lays out its components horizontally. You can set fitWidth: true to one of its components and the component width will expand to the remaining width of the parent minus its sibling widths.

You can nest the containers within each other and create complex layouts. I will create a a border layout using the viewport and column container. The border layout will resize accordingly when you resize your browser.

Here is the code to create the border layout.
$(document).ready(function() {
    var viewport = new JX.Viewport({
        css: {padding: '0px', margin: '0px'},
        items: [{
            height: 50,
            css: {backgroundColor: '#aaaaaa', padding: '20px'},
            text: $('#north').text(),
            fitWidth: true
        },{
            jxtype: 'columncontainer',
            fitHeight: true,
            items: [{
                text: $('#east').text(),
                width: 150,
                css: {backgroundColor: '#cccccc', padding: '20px'},
                fitHeight: true
            },{
                text: $('#center').text(),
                fitWidth: true,
                css: {backgroundColor: '#eeeeee', padding: '20px', overflow: 'hidden'},
                fitHeight: true
            },{
                text: $('#west').text(),
                width: 150,
                css: {backgroundColor: '#cccccc', padding: '20px'},
                fitHeight: true
            }]
        },{
            height: 50,
            css: {backgroundColor: '#aaaaaa', padding: '20px'},
            text: $('#south').text(),
            fitWidth: true
        }]
    });
});                               


I have added a new jxtype 'columncontainer' for column containers. Other jxtypes i have added are 'container' and 'component'. You need not specify jxtype if you are creating the component with 'new'. Also default is component ('div').


Thursday, October 30, 2008

A jQuery Container Class

Further to my previous post I have created a container class called JX.Container. The container lays out components vertically just like you would if you append. However it has a few extra features.
In the config options it has a 'items' config which is an array of components or component configs.
You can set 'fitWidth' to each component and the component expand to the width of the container. You have to also call doLayout() on the container, this is required because of 'fitWidth'.
We will use the container class to create a login box. Here is the code.
$(document).ready(function() {
    var loginbox = new JX.Container({
        width: 200,
        css:{
            background: 'lightcyan',
            border: '1px solid darkblue',
            padding: '20px',
            fontSize: '12px',
            fontFamily: 'Arial, Helvetica',
            fontWeight: 'bold',
            color: 'darkblue'
        },
        appendTo: document.body,
        items: [{
            text: 'Enter your User Name'
        },{
            jxtype: 'input',
            attr: {type: 'text'},
            fitWidth: true
        },{
            text: 'Enter your Password'
        },{
            jxtype: 'input',
            attr: {type: 'password'},
            fitWidth: true
        },{
            jxtype: 'input',
            attr: {type: 'button', value: 'Login'}
        }]
    });
    loginbox.doLayout();
});                               

Wednesday, October 29, 2008

Configurable jQuery Components

I wanted to create jQuery components easily by passing in config options, that would also take in jQuery method parameters in the config option. You have to read my previous post to understand what is going on here. First I will show you how it works. In the code below I create a button object by passing config options to JX.Component.
$(document).ready(function() {
    var mybutton = new JX.Component({
        jxtype: 'div',
        text: 'Click Me',
        width: 100,
        css:{background: 'darkblue', color: 'lightblue', textAlign: 'center'},
        appendTo: document.body,
        click: function() {
            alert("You clicked a button with text: " + $(this).text());
        },
        hover: [
            function() {
                $(this).css({cursor: 'pointer', opacity: '0.5'})
            },
            function() {
                $(this).css({cursor: 'default', opacity: '1'})
            }
        ]
    });
});                               

You will notice that all config options except jxtype are actually jQuery method names whose values are the parameters to the jQuery method. jxtype tells the component what type of dom element to create. If you dont specify jxtype default is 'div'. Also note the the 'hover' config option takes in an array as its value. So where ever the corresponding jQuery method takes more than one argument you must use an array here.
Here is the code for the new JX.Component.
JX.Component = function() {
    if (JX.isObject(arguments[0])) {
        var config = arguments[0];
        config.jxtype = config.jxtype ? config.jxtype : 'div'; // default type is div
        JX.Component.superclass.init.call(this, document.createElement(config.jxtype));
        this.applyConfig(config);
    } else
        JX.Component.superclass.init.apply(this, arguments);
};

JX.extend(JX.Component, jQuery, {
    applyConfig: function(config) {
        for (var key in config) {
            var a = JX.isArray(config[key]) ? config[key] : [config[key]];
            eval('this.' + key + '.apply(this, a)');
        };
    },
    jxtype: function(jxtype) { 
        this._jxtype = jxtype;
    }
});

To make reusable components you can create a factory function like this.
function buttonFactory(config) {
 var buttonconfig = jQuery.extend({
        jxtype: 'div',
        width: 100,
        appendTo: document.body,
        click: function() {
            alert("You clicked a button with text: " + $(this).text());
        },
        hover: [
            function() {
                $(this).css({cursor: 'pointer', opacity: '0.5'})
            },
            function() {
                $(this).css({cursor: 'default', opacity: '1'})
            }
        ]
 }, config);
 return new JX.Component(buttonconfig);
};

$(document).ready(function() {
    var mybutton = buttonFactory({
        text: 'Click Me',
        css:{background: 'darkblue', color: 'lightblue', textAlign: 'center'},
    });
});


Monday, October 27, 2008

Extending jQuery the Object Oriented Way

Though I have used quite a few Ajax libraries in the last couple of years, nothing has impressed me like jQuery. However jQuery is not object oriented in the traditional sence. You cannot instantiate a jQuery object like this
var myobject = new jQuery();

or extend jQuery like this.
extend(MyClass, jQuery);

So what if you could object orientify jQuery? Imagine all your classes/widgets as extensions of jQuery. You could call all the jQuery functions from within your own 'this' like
this.addClass('classname');
this.click(function() {alert('you clicked me')});

But then you cannot extend jQuery because it does not have a constructor! It is itself an object. But thats where javascript comes to your rescue. Javascript does not differentiate an object from a class. And the jQuery object has some features that will come as a help. It has a prototype object and though it does not have a constructor it does have an init method. Some of you are already figuring where I am headed. But before we go ahead we need a function that will do a proper object oriented extend. And I will also add a namespace and call it "JX" for jQuery Extend. Here is the code.
var JX = {
    extend: function(bc, sc, o) {
        var f = function() {};
        f.prototype = sc.prototype;
        bc.prototype = new f();
        bc.prototype.constructor = bc;
        bc.superclass = sc.prototype;
        for (var m in o)
            bc.prototype[m] = o[m];
    }
};

JX.extend() is a function that will take in three parameters, a baseclass constructor, a superclass constructor and an object of functions to override any superclass methods. Now let us use this method to create a new Class called JX.Component that will be a base class for all our widgets.
JX.Component = function() {
JX.Component.superclass.init.apply(this, arguments);
};
JX.extend(JX.Component, jQuery, {});

The arguments passed can be any argument you pass into the jQuery $() function. Voila! You have a class that extends jQuery!
Now try this.

$(document).ready(function() {
    var mydiv = new JX.Component(document.createElement('div'));
    mydiv.text("Hello World").click(function(){alert("You Clicked Me!")});
    mydiv.appendTo(document.body);
);

Now let us get down to something more usefull. Let us extend JX.Component to make a button class.

JX.Button = function() {
JX.Button.superclass.constructor.apply(this, arguments);
this.initialize();
};
JX.extend(JX.Button, JX.Component, {
    initialize: function() {
        var component = this;
        this.hover(
            function() {
                component.css({cursor: 'pointer', opacity: '0.5'})
            },
            function() {
                component.css({cursor: 'default', opacity: '1'})
           }
        );
        this.click(function() {
            alert("You clicked a button with text: " +component.text());
        });
    }
});

Now try your button class with this code.

$(document).ready(function() {
    var mybutton = new JX.Button(document.createElement('div'))
        .text("Click Me")
        .css({background: 'darkblue', color: 'lightblue', textAlign: 'center', width: '100px'})
        .appendTo(document.body);
});    

If you noticed the Button constructor called its "superclass.constructor". However JX.Component when it extends jQuery calls its "superclass.init". And thats the trick in extending jQuery.

Friday, September 05, 2008

First ever Printed book had Chinese hardware and Indian software and Open Source Licence!

I was reading a book by Amartya Sen (Noble prize winner in Economics 1998) and found an interesting little fact I wasn't aware of, so I thought I must post it here. Let me quote from the book here.

"The first printed book in the world with a date (corresponding to 868 CE), which was a Chinese translation of a Sanskrit treatise, the so called 'Diamond Sutra', (Kumarajiva had translated it in 402 CE), carried the remarkable motivational explanation: 'for universal free distribution'".

And from the footnote.

"Kumarajiva was a half-Indian half-Kucian scholar who studied in India but had a leading position in the Institute of Foriegn Languages and literature in Xian, from 402 CE".

So here we have the first printed book in the world and the machinery it was printed on (the hardware) being Chinese, and the contents (software) attributable to original author and the translator of the book both being Indian.

Wednesday, September 03, 2008

Google's Chrome Strategy

If you haven't yet downloaded the new Google Chrome browser, launched yesterday, you can download it here. It's worth it. This is what a browser really should be. However this post is not about workings of the browser. There are a lot of articles about this in the last couple of days. This post is about Google's strategy for knocking Microsoft out of the race.

Really why would Google want to create a new browser when we have atleast half a dozen competent browsers already. As a matter of fact Google pays to support Firefox and that agreement is valid through 2011. And the Google Chrome browser itself is based on the WebKit rendering engine which is already being used by Apple's Safari browser. So really no advantage there except for the fact that chrome runs each tab you open as a separate process.

So what does Chrome have that the other browsers don't? A javascript compiler. Thats right, other browsers have javascript interpreters, but Chrome's V8 is really a Javascript compiler, that compiles and runs the javascript code as machine code, which is much faster than interpreting.

Thats the key. Faster javascript, means that you can run larger applications on your browser. If you have seen Google docs, you already have a spreadsheet, editor, and presentation software running on the browser. If you have faster javascript you could have software on your browser that can compete with standalone applications like Microsoft Office etc.

Think about this, over the years I have been using less of standalone applications, and more of applications on the browser. I use my browser for email, editing, spreadsheet and presentation. The only other applications I use is when I want to watch a movie or listen to music on my computer. Even that can be moved to the browser.

So there are many days that the only application I need to run on my computer is a browser. And Google has understood this for years now. That all your applications will eventually move to the browser. So Google docs and all other google apps are a step towards that goal.

Imagine the scenario. All the applications you need, now run on your browser. Does it matter what operating system you have in that case? No. Does it matter if you have an operating system at all? No. Your browser itself could be the OS too! So boot up your browser and shut down your browser! Far fetched or not, I bet this is already sending shivers down Microsoft's Spine.

Monday, September 01, 2008

Three Rules for Successful Software Development

In my years of software development I have been looking for that "holy grail" of software development methodology. There are many methodologies, Six Sigma, Agile, Extreme programming to mention a few. However these methodologies have concrete rules to be followed, and they seem to restrict the element of creativity in the process of development.

If you look at the successful software developed in recent years, especially the open source ones, none of them have been developed using the above methodologies. On the other hand they have evolved to what they are today over the years. It is in this context that I would like to set three rules for successful software development. Look at your software as an evolving organism.

1) Only software that can be partially usefull, when implemented partially, can succeed. You need your software to evolve into what your ultimate goal is. Start with a small release that you think will make it usefull for a small group of people or solves a small set of problems. Based on feedback let it evolve into the next stage, and so on until you have what you need.

2) Your software is never in sync with its current requirements. Because of the very nature of the evolutionary process, your software has adapted to the previous requirements, and is currently being adapted to the present requirements.

3) Finally Orgel's Rule, named after the evolutionary biologist Leslie Orgel. "Evolution is smarter than you are". Let your current users point out what is missing. Let them set your agenda. No one person or group of developers or analysts can point out what is missing better than your current users.

This blog was inspired by an excellant article called "In praise of evolvable systems" by Clay Shirkey.