Prototype vs Class Inheritance in YUI 3

0

Posted on : 01/07/2010 | By : Jimmy Vu | In : Development News, Solution

As I mentioned in the post YUI 3.0 – Changes From the Root, YUI 3 is a radical evolvement of the framework. One of the most interesting features it provides with is about much better support for OOP.

YUI 3 supports two inheritance patterns via object prototype and “class”. Let’s examine the differences and advantages of each pattern.

Prototypal Inheritance in YUI 3

Suggested by Douglas Crockford, prototypal inheritance pattern is to deal with objects, i.e. objects inherit from objects. YUI 3 supports prototypal inheritance from its core; it means you can utilize the pattern by including the seed file only:

<script type="text/javascript" 
    src="http://yui.yahooapis.com/3.0.0/build/yui/yui-min.js"></script>

Now, for example, we have an object named animal:

var animal = {
    name: "Animal",
    level: "top",
    say: function() {
        return "I am an " + this.name + " at " + this.level + " level.";
    }
};
 
alert(animal.say()); // I am an Animal at top level.

And you want to create an elephant object that is an inheritance of animal. It’s so easy to do:

var elephant = Y.Object(animal);

Of course, you’ll need to modify the newly-born creature to make it a true elephant by overriding its parent properties and adding some new ones:

// override an animal’s property
elephant.level = "second";
 
// add elephant’s own properties
elephant.trunk = 1;
elephant.tusks = 2;

However if you want the elephant to say more about its own belongings, you’ll have to redefine say method completely.

elephant.say = function(){
    return "I am an " + this.name + " at " + this.level + " level."
        + " I have " + this.trunk + " trunk and " + this.tusks + " tusks.";
};
 
alert(elephant.say()); // I am an Animal at second level. I have 1 trunk and 2 tusks.

I think this pattern is quite easy to understand but before going forward to the next one, here are what we learn from it:

  1. We can create a new object that inherits all the properties and methods from an existing object.
  2. We can customize the new object by overwriting some/all of the members or adding new ones.
  3. The dark part is an overwritten property has no way to reference its parent’s property.

    Note: In this pattern, the child’s properties do not really overwrite its parent’s ones but they just take higher precedence. So if we delete a child’s method, the parent’s one will be back magically. For example:

    delete elephant.say;
    alert(elephant.say()); // I am an Animal at second level.

“Class” Inheritance in YUI 3

Yes, I know there are no true classes in JavaScript, however we can make constructor functions act like classes for OOP (you can read more from the book Object-Oriented JavaScript by Stoyan Stefanov).

Note: From now on, for easier to understand the pattern, I’ll call all constructor functions (that are capitalized in examples) classes; don’t be confused.

First, we’ll mimic above example by creating  Animal and Elephant classes as follows:

// parent class
function Animal(){
    this.name = "Animal";	
}
// parent’s properties
Animal.prototype.getName = function(){
    return this.name;
};
Animal.prototype.setName = function(name){
    this.name = name;
};
 
// child class
function Elephant(){}

YUI 3 supports class inheritance via oop module and because this is used widely by almost all other modules, you’ll rarely have to include it explicitly. However, for testing, just call Y.extend() method within oop’s scope (that let Elephant inherit Animal as you can guess):

YUI().use('oop', function(Y){
    Y.extend(Elephant, Animal);
 
    // test code here
    // ...
}

Next we’ll do some tests:

// create an object of Elephant
var jumbo = new Elephant();
 
alert(typeof(jumbo.name)); // undefined
alert(typeof(jumbo.getName)); // function
 
// set name for the Elephant object			
jumbo.setName("Jumbo");
alert(jumbo.getName()); // Jumbo

You can see from the example, jumbo object which is an instance of Elephant class only inherit members of the prototype, not “private” members from parent’s class and it is considered a good practice to leave all instance-specific properties as private properties and to add all the public functionality to the prototype.

Interestingly we can add some new properties with default values to child class via arguments of Y.extend(), for example, to add trunk and tusks to Elephant class:

// create an object of Elephant “class”
var jumbo = new Elephant();
 
alert(typeof(jumbo.name)); // undefined
alert(typeof(jumbo.getName)); // function
 
// set name for the elephant				
jumbo.setName("Jumbo");
alert(jumbo.getName()); // Jumbo

Last but not least, class inheritance has very powerful feature: superclass access. To see how it works, we’ll add a method to Animal class to let it say something.

// parent class
function Animal(){}
 
// parent’s method
Animal.prototype.say = function(){
    return "I am an animal.";
};

Then, we’ll overwrite say method in Elephant class, yet still be able to keep what Animal can say about.

Y.extend(Elephant, Animal, {trunk: 1, tusks: 2});
 
Elephant.prototype.say = function(){
    	  return Elephant.superclass.say() + 
		" I have " + this.trunk + " trunk and " + this.tusks + " tusks.";
};
 
// test
jumbo = new Elephant();
alert(jumbo.say()); // I am an animal. I have 1 trunk and 2 tusks.

In summary, “class” inheritance pattern in YUI 3 is more powerful than prototypal counterpart though harder to get it full, here are some important points:

  1. YUI 3 allows us to implement inheritance at (pseudo) class level in JavaScript.
  2. Inherited classes cannot directly access to parent’s own members, children only inherit prototype members by default.

    Note: Well, it is possible to inherit parent’s own properties by initializing the parent constructor from the child (but it is not always a good OOP practice). See example:

    // parent class
    function Animal(){
        this.name = "Animal";	
    }
    // child class
    function Elephant() {
        // initialize the parent using the child as "this"
        Elephant.superclass.constructor.apply(this, arguments);
    }
     
    Y.extend(Elephant, Animal);
     
    // test
    jumbo = new Elephant();
    alert(jumbo.name); // Animal
  3. You can gain access to the parent’s overridden methods via superclass.

Conclusion

Code reuse is considered as the most confusing part of JavaScript for it lacks robust OOP features that many modern programming languages provide by default. YUI 3 with the two inheritance patterns we’ve gone through is trying to fill the gap.

Prototypal inheritance is easier to understand but limit in object inheritance only. To get full OO support in YUI 3, it is advisable to study “class” inheritance pattern provided by the framework.

Best IE6 “PNG Alpha-Transparency” Fixes

4

Posted on : 12/27/2009 | By : Jimmy Vu | In : Solution

You are likely living in civilized society with Firefox, Safari, Chrome or Internet Explorer 7/8 installed in your computers. Yet, some are still in the dark with the older Microsoft browsers named Internet Explorer 6 (IE6) or, worse, older versions. One of the most painful facts about IE6 is that it does not natively support PNG alpha-channel transparency.

Microsoft probably thought that GIF transparency — where each pixel is either fully transparent or a solid color, not anything between — should be enough for the world. But it’s not! Just compare three “JavaScriptly” logos in transparent GIF, transparent PNG and semi-transparent PNG images on a web page, you’ll recognize the differences.

Transparent PNG vs Transparent GIF

Transparent PNG vs Transparent GIF

(1) The font edge of GIF logo has side-effect which can be only fixed by choosing “color matte” exactly like background color when exporting the image (but we can do nothing optimal if the background has multi-colors like a picture.)

(2) Only PNG can be semi-transparent like the last logo, GIF is out of luck.

Read the rest of this entry »

corMVC: An jQuery-based MVC Framework

5

Posted on : 12/22/2009 | By : Jimmy Vu | In : Solution, jQuery

I know quite a few JavaScript MVC frameworks out there but corMVC is what makes me exited at most for a few reasons.

corMVC stands for “client-only-required” Model-View-Controller and that means it does not depend on specific server-side technology. In case you want to demo something, it would be perfect if everything can be done on client side. Of course, you can save changes or load data from server (via Model) as the general illustration below.

corMVC Overview

corMVC Overview

Not like other JavaScript MVC solutions, corMVC is very simple and has very small footprint. It also does not require you to build the application using scaffolding or any other command-line utilities.

Read the rest of this entry »

Simple Web Chat with Meteor Comet Server

8

Posted on : 09/19/2008 | By : Jimmy Vu | In : Solution

Comet is not really brand-new (Ajax) term today; however, with most of people how it works remains somewhat mysterious.

I have a little hand-on experience with Comet when creating a hobby game project with DWR Reverse Ajax sometime ago. It (DWR) was simple to start and really worked but required a Java web server (Tomcat, Jetty…) that I found rather expensive (in term of resources) for such small application. I want a small, dedicated and reliable server for Comet apps while don’t like to be deeply sunk in technical terms like “Bayeux” or “Continuation”.

After reviewing the Comet Maturity Guide from Comet Daily I decided to give Meteor Comet server a try for several reasons, especially because it’s built on Perl that can be easily deployed in any server with Perl installed (i.e. almost all Linux servers, no?) and it should be lightweight (up to my experience with Perl). Here is other info about Meteor server:

  1. Server daemon will run on any platform for which Perl is available.
  2. In live use typically 1,000 clients per node receiving 2 msgs (~400 bytes) per sec each. Tested up to 5,000 clients per node receiving 1 msg/sec each.
  3. Nodes exist independently, supports broadcasting for message distribution. Cluster of three Meteor nodes runs FT Alphaville.
  4. Transports are completely configurable within simple constraints.
  5. Server supports client ‘catch-up’, allowing clients to regulate quality of service themselves.
  6. Stable, in production use.
  7. GPL v2. Free.

Install & Setup Meteor Server

You can find very good how-to guide for installing Meteor server from Meteorserver.org; actually it’s quite simple to follow. Just download, extract to default location (/usr/local/meteor) and configure daemon service as guided. One notice is on Fedora/Cent OS the start function in init scripts must be changed from:

Read the rest of this entry »

Quick & Useful jQuery Plugins

1

Posted on : 09/16/2008 | By : Jimmy Vu | In : Solution

Here are some quick and useful jQuery plugins from Jason Frame’s “jQuery Grab Bag“.

Auto-Grow TextArea

The technique is borrowed from Facebook that uses an off-screen <div> to calculate the required dimensions of the textarea to reveal all texts inside instead of to display vertical scrollbar. Run the following code line to enable auto-grow behavior to all textareas on page.

$('textarea').autogrow();

Online Demo

Input Hint

It’s not always necessary to attach label to every text field in web form, instead you can use hint to tell user what to type in the fields. This plugin will help keeping away from tedious codes to add hints to input boxes.

First, add hint attribute to input fields.

Read the rest of this entry »

Unobtrusive Draggable Tabbed Navigation

3

Posted on : 09/15/2008 | By : Jimmy Vu | In : Solution

There are many examples on creating tabbed navigation with (or without) help of JavaScript frameworks like Prototype, MooTools or JQuery. However, I find that it’s much easier to create draggable tabbed navigation using Chain.js and its great extension: Interaction.js.

Riziq, creator of Chain.js & Interaction.js, already showed an example on how to utilize the libs to build tab interface in a few JS code lines. However, for its own purpose, the example is not SEO-friendly — disabling JavaScript in your browser will result in empty content and search engines will see nothing on your page consequently. Now say, you want to create a tabbed navigation for your blog to show/hide “Latest Posts”, “Latest Comments” etc. and you want the links can be seen no matter if JavaScript is enabled or not in reader’s browser — something looks like this:

Tabbed navigation for my blog

Blog's tabbed navigation

Step 1: HTML & CSS

Just create a template in HTML and full links to latest posts, comments and most popular articles:

Read the rest of this entry »

LightningDOM to Balance DOM vs innerHTML

4

Posted on : 09/12/2008 | By : Jimmy Vu | In : Solution

Using DOM API versus innerHTML to create/change content on webpage has been in discussion for years. The pain (slow DOM manipulation speed) left by Internet Explorer causes a big concern over DOM API for serious use in practice because the browser is still holding big slice of market share today (about 80%).

We can guess that the browser war (re)started by Firefox and stirred up by Google Chrome lately will result in better IE versions, yet that bright day won’t come any time soon.

Recently, I had reviews on PURE and Chain.js as client-side template engines. Though both libraries take pure, unobtrusive JavaScript approach for implementation, PURE seems more eager about speed when using innerHTML to create elements while Chain.js depends on DOM API for more flexible and direct manipulation.

I cannot say what approach is better. PURE may have some advantage on page with huge number of DOM elements to be created/changed but I think most of projects will be happy with Chain.js for its power. It grows a question: any chance that we can achieve both flexibility and speed in these libs? Probably, LightningDOM donated by Peter Rust will be a right answer.

In the post, Peter places LightningDOM as “a layer between the raw HTML and your templating/data-mapping code, without the slowness of the DOM.” So how it works? Just see the example.

1
2
3
4
var strMarkup = document.getElementById('destination').innerHTML;
var dom = new LightningDOM(strMarkup);
dom.firstChild().innerText("I Love speed!");
document.getElementById('destination').innerHTML = dom.outerHTML();

Not too difficult to understand, right? You give all HTML markups to LightningDOM, do anything you want with familiar getters/setters like you can do with DOM API then assign the result back to real DOM’s innerHTML.

Peter tells more about internal implementation to get both speed and lightness in the library.

Read the rest of this entry »

Chain.js v0.2 – Updated Examples

2

Posted on : 09/09/2008 | By : Jimmy Vu | In : Solution

In previous post, I had a chance to introduce Chain.js with 3 examples and found a few issues due to both bugs in version 0.1 and my unawareness of implemented features. Now version 0.2 of Chain.js has just come out, I’d like to revise the examples to show better implementation we can do with the library in practice.

Basically, we don’t need to call chain() function every time we add or replace items instead just execute it once on DOM ready event, and we can utilize anchor property to define where items to be rendered within table tag.

Example 1: All codes to get it works are here.

1
2
3
4
5
6
7
8
9
10
11
12
13
function render(){
	$.getJSON('json.php', 'lang=' + $('#langList').val(), function(books){
		$('#table_book').items('replace', books);
	});
}
 
$(document).ready(function(){
	$('#table_book').chain({
		anchor: 'tbody' /* defines, where items will be rendered*/
	});
	$('#langList').change(render); 	// handle change event of drop-down list
	setTimeout(render, 100); 		// call render function on load
});

Example 2: Almost the same codes as example 1 plus add, remove and sort functions.

Read the rest of this entry »

JavaScript to Detect Google Chrome

4

Posted on : 09/05/2008 | By : Jimmy Vu | In : Solution, jQuery

The negative side of having a new (and promisingly become popular) browser, no matter how good it can be, is you’ll have to test your web apps with it among many others.

Probably, the first step is to detect the browser from JavaScript code by parsing browser’s user agent, and here is what of Google Chrome.

Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US)
AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13

I guess old JavaScript codes can mistakenly tell it Safari like when running the code snippet below using JQuery’s browser utility.

1
2
3
4
$.each($.browser, function(i, val) {
	 $("<div>" + i + " : <span>" + val + "</span></div>")
		.appendTo(document.body);
});

It may be no problem until you find something wrong when your apps running on Chrome only. So, here is the code line to detect Chrome generally:

1
var is_chrome = /chrome/.test( navigator.userAgent.toLowerCase() );

We’ll have to change the JQuery browser utility to support Chrome detection as follows:

1
2
3
4
5
6
7
8
9
10
11
var userAgent = navigator.userAgent.toLowerCase();
 
// Figure out what browser is being used
jQuery.browser = {
	version: (userAgent.match( /.+(?:rv|it|ra|ie|me)[\/: ]([\d.]+)/ ) || [])[1],
	chrome: /chrome/.test( userAgent ),
	safari: /webkit/.test( userAgent ) && !/chrome/.test( userAgent ),
	opera: /opera/.test( userAgent ),
	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
};

Now, correct result shows on test screen:

Just one notice: Current version of JQuery (1.2.6) is treating Chrome as if it was Safari and basically no serious problem has been found yet. Modifying browser detection can cause the lib render pages/elements incorrectly for it has no knowledge of Chrome’s rendering engine. To keep compatibility, you can change line 7 back to:

7
	safari: /webkit/.test( userAgent ),

Read the rest of this entry »

10 Alternative JavaScript Frameworks

1

Posted on : 09/04/2008 | By : Jimmy Vu | In : Solution

In modern web development, some JavaScript frameworks have made their names like Prototype, Mootools, YUI, JQuery. But if you find them not wholly suitable to your next project there are some other good frameworks out there.

Jacob Gube has given out a nice introduction of “10 alternative and capable JavaScript frameworks/libraries to explore” going over the good of them. Here they are:

  1. SproutCore
  2. Spry
  3. JavaScriptMVC
  4. qooxdoo
  5. midori
  6. Archetype JavaScript Framework
  7. June Framework
  8. UIZE
  9. SimpleJS
  10. Fleegix.js

Some of them provide comprehensive solutions that allow you to build a (complicated) desktop-like application with ready-made components (SproutCore, Spry, qooxdoo, UIZE), other focus on DOM selector and effects with minimal weight and, specifically, framework JavaScriptMVC presents the Model-View-Controller (MVC) architectural pattern to JavaScript.

Read the rest of this entry »