JavaScript Frameworks
I recently checked out Google’s AJAX Libraries, which, aside from being inaccurately titled, provides a means for web developers to access functionality in a wide variety of popular JavaScript frameworks and toolkits without having to host the libraries themselves. Simply include the base Google library, and then use it to load whatever framework you want to access in you code. It’s not for me, as I’m a total control-freak when it comes to production implementations of my code, and I don’t like having my web pages hang up trying to access URIs on outside domains, which definitely happens to the code I run locally using this tool; however, it does provide a convenient playground for testing out different JavaScript frameworks and toolkits.
You can do anything with JavaScript, but you have to program around its shortcomings. How JavaScript functions depends on the ECMAScript engine running it, with Firefox running TraceMonkey, Chrome running V8, and Internet Explorer running Trident, it makes it difficult to write code that runs the same in all browsers. Then there’s JavaScripts’ object-orientation strategy, which uses prototype chains for inheritance, confusing most OO programmers. Finally, there’s some major oversights in JavaScript functionality, like the fact that it lacks a trim() function.
There are two types of JS Frameworks, those that extend JS functionality for the advanced programmer and those that simplify coding for the novice. If you’re an advanced programmer, it’s nice to have true object-orientation in your JavaScript. If you’re a novice, it’s nice to be able to whip out some fancy special effects with just a few lines of code. What follows is my understanding and impressions of these frameworks as I used Google’s Libraries to play with them.
Beginner Toolkits
The Dojo Toolkit, Yahoo! User Interface Library, jQuery UI, and Script.aculo.us are three toolkits brimming with easy-to-implement effects to enhance a webpage without resorting to plugins like Flash or Silverlight. Underneath these toolkits are frameworks. For instance, Scriptaculous is built on the Protoype framework, and jQuery UI on the jQuery framework. Aaron Newton’s jQuery vs MooTools has a great explanation of the difference between a toolkit and a framework:
Part of this consideration is the notion of a framework vs a toolkit. MooTools is a framework that attempts to implement JavaScript as it should be (according to MooTools’ authors). The aim is to implement an API that feels like JavaScript and enhances everything; not just the DOM. jQuery is a toolkit that gives you an easy to use collection of methods in a self-contained system designed to make the DOM itself more pleasant. It just so happens that the DOM is where most people focus their effort when writing JavaScript, so in many cases, jQuery is all you need.
Each of these toolkits provide their own unique features. For instance, YUI provides sophisticated event timing, categorized into “available,” “contentready,” and “domready,” allowing for executing JavaScript functions when document objects become available, when the object and its children become available, and when the entire document is available to improve the performance of your web page. Nifty, but also a bit esoteric, a reminder that, when we buy into a framework, we are also buying into a development methodology.
One problem I have with all of the larger, bells-and-whistles JavaScript toolkits is that I find myself browsing their libraries of plugins, trying to find some way to work their dazzling features into my web pages; when, in reality, the way I develop, the features I need to implement simply emerge, and I go looking for scripts as I need them. If I adopt a feature-rich framework, then I’m going to be out of luck the moment I need functionality it doesn’t include.
Another thing to consider is how intrusive the toolkit is. If you’re planning on including 50 to 100 kilobytes of framework code in every web page on your site, how much more code is needed to exercise its functions?
Here’s Dojo’s fade-out effect:
dojo.require("dijit.form.Button"); function basicFadeoutSetup() { function fadeIt() { dojo.style("SomeElementId", "opacity", "1"); var fadeArgs = { node: "SomeElementId" }; dojo.fadeOut(fadeArgs).play(); } dojo.connect(dijit.byId("basicFadeButton"), "onClick", fadeIt); } dojo.addOnLoad(basicFadeoutSetup);
Here’s the YUI version of the fade-out effect:
YUI().use('anim-base', function(Y) { var anim = new Y.Anim({ node: 'SomeElementId', to: { opacity: 0 } }); var onClick = function(e) { e.preventDefault(); anim.run(); }; Y.get('SomeElementId .yui-remove').on('click', onClick); });
Here’s the jQuery UI version of the fade-out effect:
$("SomeElementId").hide('highlight');
Finally, we have Scriptaculous’ fade effect:
$('SomeElementId').fade();
On the one hand, the Dojo and YUI examples appear to offer much more customization in the implementation of their features, while the jQuery UI and Scriptaculous examples offer simplicity and ease of implementation. If you need something customized with the latter two toolkits, you’ll need to code around them. While with the former two toolkits you’ll need to customize them their way.
And that can be a real problem. If you are a novice JS developer and you adopt Dojo or YUI, you will never become an advanced JS programmer. You might become an advanced Dojo or YUI programmer, but those are much more narrowly defined skill sets, which are less marketable to companies with established development environments.
Advanced Frameworks
Sam Stephenson’s Prototype framework and the MIT Licensed MooTools are true JavaScript frameworks intended for advanced programmers. Both frameworks overcome the awkwardness of JavaScript’s prototypal inheritance by enabling class-based inheritance to make it function more like a mainstream object oriented language.
You won’t find fade() functions in these frameworks, but you will find enhanced means of accessing the objects in a web page (DOM) (jQuery goes so far as to provide a means to query the DOM for arrays of objects). You will also find useful functions such as trim() and cross-browser, streamlined methods for making AJAX calls. With Prototype and MooTools, you’ll still need to write your functions, but with the adoption of the methodologies within these frameworks, you should find your coding streamlined and more robust.
As thin and streamlined as these frameworks are, they still include much more functionality than most JavaScript developers need in their average web page. If I need a trim() function, I’ll go get one somewhere online. If I need mainstream object-orientation, I’ll use Prototype on the page where I need it. The problem with these frameworks is that, if you’re smart enough to be using them, you’re probably smart enough to not be using them.
Conclusions
Here’s an example of what it takes to roll your own fade-out effect:
var TimeToFade = 1000.0; function fade(eid) { var element = document.getElementById(eid); if(element == null) return; if(element.FadeState == null) { if(element.style.opacity == null || element.style.opacity == '' || element.style.opacity == '1') { element.FadeState = 2; } else { element.FadeState = -2; } } if(element.FadeState == 1 || element.FadeState == -1) { element.FadeState = element.FadeState == 1 ? -1 : 1; element.FadeTimeLeft = TimeToFade - element.FadeTimeLeft; } else { element.FadeState = element.FadeState == 2 ? -1 : 1; element.FadeTimeLeft = TimeToFade; setTimeout("animateFade(" + new Date().getTime() + ",'" + eid + "')", 33); } } function animateFade(lastTick, eid) { var curTick = new Date().getTime(); var elapsedTicks = curTick - lastTick; var element = document.getElementById(eid); if(element.FadeTimeLeft <= elapsedTicks) { element.style.opacity = element.FadeState == 1 ? '1' : '0'; element.style.filter = 'alpha(opacity = ' + (element.FadeState == 1 ? '100' : '0') + ')'; element.FadeState = element.FadeState == 1 ? 2 : -2; return; } element.FadeTimeLeft -= elapsedTicks; var newOpVal = element.FadeTimeLeft/TimeToFade; if(element.FadeState == 1) newOpVal = 1 - newOpVal; element.style.opacity = newOpVal; element.style.filter = 'alpha(opacity = ' + (newOpVal*100) + ')'; setTimeout("animateFade(" + curTick + ",'" + eid + "')", 33); }
Of course, you would hide the above code away in an include file, and invoking the fade effect would simply require:
fade('SomeElementId');
But including the above code, even uncondensed, would require only a small fraction of what including any of these frameworks would necessitate in condensed form. Plus you have the strength of understanding your code and how it works. You don't always have the time to spend a week rewriting someone else's script to fit the specifics of your situation or writing your own from scratch, but if you do, you will be rewarded for it. The script will become your own.
Frameworks and toolkits have their uses, and I don't want to disparage them; however, two rules come out of this analysis for me. First, developers who are novice enough to use a feature-rich toolkit will hurt themselves by adopting one, because they won't be learning mainstream JavaScript. Second, developers who are skilled enough to make use of an advanced framework probably don't need one, but could benefit from analyzing them for techniques to use in their own code.
I'll continue to play with these frameworks from time to time in order to learn new techniques and best practices, but I'll stick to my current strategy of copy-and-pasting code from a wide variety of online sources. The best JavaScript framework, to my mind, remains the World Wide Web.
Further Reading:
Comments
5 responses to “What’s the Right JavaScript Framework, If Any?”