Friday, February 6, 2009

jQuery: Use Convention Over Configuration to Make Your Pages Smart

If you're not familiar with jQuery, it is a JavaScript library that lets you quickly access page elements using CSS-like selectors, and then do common effects, animations, and transformations against those elements.  It nicely brushes away browser-compatibility issues and gives you a clean, simple way to do client-side "stuff". 

It ships in ASP.NET MVC, so I've been using it in one of our first MVC apps, and love it.  What I particularly like, though, is using it to develop 'convention over configuration' for the app's client-side behavior.  Instead of wiring up each individual form element, button, etc., I can declaratively say 'all elements with this class should behave this way.'  This is done once in my site.master, so that in the actual pages, applying a behavior is as easy as including a css class name on an element.

Let's look at some examples.  The first step in most jQuery code is to wire up the document ready function.  This tells the browser to execute some function whenever the document finishes loading, which believe it or not is quite difficult to do in a cross-browser way that plays well with other scripts.  To do this, I have a script in my site.master's <head> section that looks like this:

<script type="text/javascript">
        $(document).ready(function() {
            //TODO: set up conventions
        });
</script>

The dollar is how you select page elements in jQuery.  $(document) says "get the current document" (also non-trivial in un-aided javascript).  You can also use css-like selectors.  For example $("#myButton") will return all elements with the id "myButton".  $(".initialFocus") will return all elements with the class "initialFocus".  Which leads to my first "convention":

$(".initialfocus").focus();

Now, in any page that uses the master page, if a particular field should get focus when the page loads, simply specify the class "initialFocus":

<input type="text" class="initialfocus" name="somefield"/>

Or, in MVC parlance:

Html.TextBox("QuantityDelivered", currentTransaction.QuantityDelivered, new { @class = "initialfocus" })

Which is a nice UI touch, but let's look at something more advanced.  I also want a convention to let me specify that a field can be populated using a pop-up date chooser.  For this, I download the jQuery UI framework, and set up the convention:

$(".shortdate").datepicker();

Similarly, I add 'shortdate' as a class to any textbox, and the date chooser appears on the element.  If I decide I want to change some behavior site-wide, I have one simple place to change it.  For example, I could use one of the dozen other jQuery date pickers, or roll my own.

It's also possible to 'stack' effects.  For example, this application displays informative message as a div with the class name "messageBox".  If one of these appears when the page first loads, it hides after a few seconds.  To accomplish this, you simply 'stack' an "animate" (which in this case is just used as a 5 second delay), followed by a fadeOut:

$(".messagebox")
    .animate({ opacity: 1.0 }, 5000)
    .fadeOut("slow"); 

All told, this particular app currently has 6 'conventions', with more planned:

$(document).ready(function() {
         $(".initialfocus").focus();
         $(".shortdate").datepicker();
         $(".longdatetime").datepicker();
         $(".print").click(function() { window.print(); });
         $(".delete").click(function() { return confirm("This record will be deleted.  Are you sure you want to continue? Click 'Ok' to delete this record or 'Cancel' to stay on this page."); });
         $(".messagebox")
             .animate({ opacity: 1.0 }, 5000)
             .fadeOut("slow"); 
     });
So, go get jQuery, whether or not you're using MVC.  With just a few lines, you can really spice up an application's client-side experience.

No comments: