For the past eight(8) years Schalk Neethling has been working as a freelance developer under the pseudo of Volume4 and is now the president of Overt Strategy Consulting. During this period he has completed over 300 projects ranging from full web application development to complete branding. As president and lead developer of Overt Strategy Consulting, Schalk Neethling and his team has released a 100% Java standards based content management system called AlliedBridge and business document exchange and review system, called Doc-Central. Schalk Neethling is also actively involved on a daily basis in the open source, web standards and accessibility areas and is a current active member of the Web Standards Group. Schalk is also the co-founder and president of the non-profit The South Web Standards and Accessibility Group, which aims to actively educate and raise awareness of web standards and accessibility to both the developer society as well as business large and small. Schalk also has a long relationship with DZone and is currently zone leader for both the web builder, css.dzone.com, as well as the .NET zone, dotnet.dzone.com, and you can find a lot of his writing there as well as on his blog located at schalkneethling.alliedbridge.com. Schalk is constantly expanding on his knowledge of various aspects of technology and loves to stay in touch with the latest happenings. For Schalk web development and the internet is not just a job, it is a love, a passion and a life style. Schalk has posted 173 posts at DZone. View Full User Profile

JavaScript Chaining Your Methods

05.29.2008
| 12770 views |
  • submit to reddit

In a previous post on JavaScript Ant I reviewed some techniques from JavaScript libraries that could prove to be useful in your own scripts. A final technique that I gave a brief mention of, but did not cover in depth, was (object) method chaining. This technique was made popular in several libraries, but none more so than jQuery. In this straightforward tutorial, I will show you how to implement method chaining with little effort.

In case you were unaware, JavaScript, as well as several other languages, already chain some methods that belong to their parent objects. Consider the String and Array objects in JavaScript, and a few of the popular methods that manage the behavior for those objects.

var rooms = "Master Suite|Living Room|Dining Room|Bathroom";
rooms = rooms.split( "|" ).sort().join( "," ).replace( /\,/g, " - " );

// returns Bathroom - Dining Room - Living Room - Master Suite

Although not terribly efficient, the previous code fragment demonstrates method chaining aptly enough. The variable rooms begins as a string. It is first split using the pipe character as a delimiter, at which point it is transformed into an array. The array is sorted, and each element is then joined using a comma as the new delimiter. Finally, all commas are globally replaced with a hyphen. The alternative would be long-winded without chaining.

var rooms = "Master Suite|Living Room|Dining Room|Bathroom";
rooms = rooms.split( "|" );
rooms = rooms.sort();
rooms = rooms.join( "," );
rooms = rooms.replace( /\,/g, " - " );

// returns Bathroom - Dining Room - Living Room - Master Suite

Rooms is either a String or an Array object, and it is continually returned so that more methods can be executed upon it. Frequently though, the object that needs to be returned, is a DOM element. This can be frustrating as developer when you need to keep specifying the reference to the object before you perform some action. The most common example involves document.getElementById.

# document.getElementById( "myElementId" ).style.visibility = "visible";  
# document.getElementById( "myElementId" ).style.margin = "4px 2px 6px 4px";
# document.getElementById( "myElementId" ).style.width = "100px";
# document.getElementById( "myElementId" ).style.height = "100px";

The size of your script will continue to grow as you manipulate several DOM objects on the page using this wasteful technique. Developers of course, quickly recognized that a variable name could be a substitute for the object reference, and the following technique was born.

var obj = document.getElementById( "myElementId" );
obj.style.visibility = "visible";
obj.style.margin = "4px 2px 6px 4px";
obj.style.width = "100px";
obj.style.height = "100px";

However, there is still something to be said for consolidating this script further, and programmers formulating library design patterns decided to implement chaining. Taking a cue from several of these masters, what if you could do the following instead?

JSANT( "myElementId" ).css( "visibility", "visible" ).css( "margin", "4px 2px 6px 4px" ).css( "width", "100px" ).css( "height", "100px" );

I will be the first to admit that this saves little, if no size in regards to the script at hand. However, it does bring the code more closely in tune with core JavaScript language constructs. It also provides an API mechanism for other developers, so that your JavaScript does not become muddled with object references. The selector leaves much to be desired as well, since it only accounts for grabbing a single element by ID, but for the purpose of this tutorial, I will concentrate on method chaining.

var JSANT = function( el ) {
this.el = document.getElementById( el );
this.css = function( property, value ) {
this.el.style[ property ] = value;
return this;
};
if ( this instanceof JSANT ) {
return this.JSANT;
} else {
return new JSANT( el );
}
};

This really is not that complicated, and the key is the return statement in the css method. Each time we call css, we evaluate a CSS property and value, and then return the JSANT object. Since css belongs to JSANT, we can now perform another evaluation on that method. So long as you continue to return the JSANT object, you can execute the method, or else it will break the chain.

For instance, you might want to create another method called hasClass(), which informs you if your DOM element contains a certain class name. This method would return true or false, and it would break the chain because you lost your reference to the JSANT object. The conditional statement at the end of the JSANT function is in place so that you do not have to use the new keyword with each call to the JSANT object.

Happy chaining!

Article written by Brian Reindel

References
Published at DZone with permission of its author, Schalk Neethling. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)