Tuesday, May 18, 2010

Unobtrusive JavaScript and jQuery

What is Unobtrusive JavaScript?
jQuery was originally designed to follow the concept of Unobtrusive JavaScript. This philosophy of web page design considers any JavaScript expressions or statements embedded in the <body> of HTML pages, either as attributes of HTML elements or in script blocks placed within the body of the page, to be incorrect.

After reading this, I’m sure you’re nodding your head and thinking, “YES! that’s excellent...but wait, how do we link any JavaScript behavior to the elements that initiate that behavior?” The simple answer to this is somewhat a purest response - put all of your javascript in the head section of your page and then register all of your element behavior when the page loads. A simple before and after example is shown below:

Why would you want to do this in the first place? There are several reasons why this is a good approach to take. Firstly, it is much cleaner - you don’t have script elements scattered throughout your page. Secondly, it allows you to gracefully handle browsers that have disabled JavaScript. Lastly, it is much more stable - all behavior is registered after a given element is determined to exist within the page.

The cost of such an approach? It requires more code be written for one. But most importantly, it requires that each developer be disciplined enough to follow this approach as well as employ good coding practices to client-side script.

Introducing jQuery

The basis of jQuery selection is founded on a concept originally defined with the introduction of CSS known as selectors. A selector provides a way of concisely locating an element within a page’s DOM.
For example, the CSS selector

td a

refers to the group of all links (anchor tags - <a> elements) that are nested inside a table cell <td> element.

jQuery makes use of this same concept and then some. It supports the selector logic that is commonly supported by all major current browsers as well as more powerful ones not yet fully supported by most browsers - from the CSS 3 specification. The jQuery site provides a nice list of selectors that can be used at the following address - http://api.jquery.com/category/selectors/. An example selection by jQuery is done like so

jQuery(selector)

or

$(selector)

So in order to select the same anchor tag group as explained earlier (using the $ abbreviated alias reference used in our second example) our code would like like

$(“td a”)

The $() function returns an object that contains an array of the DOM elements that match our criteria. This jQuery wrapper object provides many useful predefined methods that can act upon this array of elements.

One very useful feature of many of the methods provided by the wrapper object is that they support method chaining. If you’re not familiar with method chaining, it is when one method’s return value can then be manipulated by the next method in the chain - much like how an assembly line works. To make this concept a little more concrete look at the following

$(“div”).methodA().methodB().methodC();

How this is interpreted is that the $(“div”) selects all <div> elements within the DOM and wraps them in our jQuery object. This object is then sent to the methodA() method which modifies the list of DOM elements. These modified elements are then sent to the methodB() method where they are modified further and so forth. This is a slight simplification, of course, but it captures the underlying concept. Because these methods work on the entire array of selected elements, there is never a need to iterate over each of the elements, this is done implicitly for us!

Adding Behavior to the Page Once the Document Structure has been Loaded and Parsed

To avoid having to wait for all resources to load into the browser as what happens with the document.onLoad() function, we utilize a jQuery utility that executes a function as soon as the document structure has been loaded and parsed by the browser, but prior to any other resources (images in particular) have been fully loaded. This helps to prevent pages that load very slowly from having a jarring effect on the user by changing behavior once all resources have completed downloading. This is accomplished via the jQuery document ready handler -
$(document).ready(function() {
  // function logic to add behavior, etc.
});
The short hand notation for this - $(function() { /* function logic */ }); performs the exact same but is more concise in its syntax. An added benefit of using the document ready handler is that you can call it multiple times within the page and each handler will be executed in the order it appears in the rendered page as soon as the DOM is ready to be manipulated (this is in vast contrast to the document.onLoad() function which allows only one call per page).

Extending jQuery to Provide Custom Behavior

jQuery was designed specifically to include only the most utilized functions as its core library but allow any developer to easily extend its behavior.
$.fn.myfunc = function() {
    return this.each(function() {
        // perform custom behavior logic
    });
}
This example shows how simple it is to extend jQuery to include new behavior while still working perfectly in concert with other jQuery functions. To briefly explain what is going on, the $.fn.myfunc defines a new extension wrapper called myfunc. Inside the new function we call the jQuery function each which iterates over the current DOM element and returns the results as a wrapped collection and so will fit seamlessly into any other chain of jQuery function calls. The reference to this within the function is a pointer to the specific DOM element for the current iteration.

This function would be used by first selecting your DOM context using the jQuery selector syntax just discussed and then chaining our function to this selection (and chaining further method calls after our function if need be) such as the following:

$(“form#ccform input”).myfunc();

As you can imagine, this is a very powerful extension architecture and requires only a small amount of scaffolding code in order to create new behavior.

Creating DOM Elements

Although, I’m not entirely fond of this idea, the $() function allows you to dynamically create and add arbitrary HTML elements by passing a valid HTML string as its parameter.

Coming up to Speed with jQuery

I’m an avid reader of anything that relates to technology - web, programming, algorithmic, AI, investing... The only limiter for what interests me is the amount of time I have that I can focus on any one thing at a time. Recently I picked up a book on the “new” ASP.Net MVC framework - ASP.NET MVC in Action by Palermo, Scheirman and Bogard. Although this book was written by very knowledgeable authors who truly understood their domain, I ended the book feeling that it was very disorganized and really didn’t pertain to ASP.Net MVC much at all. Most of the book was advertising the MvcContrib (which the authors created) and the CodeCampServer project. Much of the discussion was spent on describing how they weren’t going to explain the “nitty-gritty” but ended up not really explaining anything. Don’t think I’m being ungrateful for the contents of the book, it’s just that its benefit ended up being vastly different than what I had originally picked it up in the hopes of discovering. I’m sure at this point you’re wondering how this has anything to do with jQuery and that’d be a fair concern. What’s interesting about the MVC framework created by Microsoft is that they bundle in jQuery. This truly came as a surprise to me when I first downloaded it simply for the fact that Microsoft is not well known for using anything that was not built in-house - most likely due to the penchant for everyone to sue them. When I first discovered this I was intrigued and so I started my journey to see what jQuery had to offer. 

Over the past several weeks I’ve been working on a project that utilizes the ASP.NET MVC 2 framework for its underlying web architecture. Since I knew that jQuery was already “compatible” with MVC I decided to see what it could do. I started to search ad hoc on the web for different packages to determine how healthy the project was and how vibrant its community participation was. Overall, it’s has a very solid  following. At this point I’ve already integrated several of the core plugin packages such as jQuery UI (which itself has several UI components included within it as well as an absolutely great theming utility on its website) and jqGrid (open source version). These plugins work great out of the box, but as with anything that you start to use, you’ll eventually get to the point where you need a little more control over everything. This brings me to the purpose of this (now long-winded) blog. Over the next several posts I hope to cover in a decent amount of depth how jQuery works and provide a running example (with working site code) to show the items in action. I’m still new to blogging, so if my style does not work well in this media, please give feedback so that I can improve and provide the most value to you. 

Monday, May 3, 2010

Adding CSS styles to ASP.NET MVC 2 Drop Down List Binding

Just read a pretty nice article describing how to perform the equivalent of data binding in MVC 2 with a drop down list at - http://www.nickriggs.com/posts/rendering-and-binding-drop-down-lists-using-asp-net-mvc-2-editorfor/

The only thing that I found myself needing to add was a per instance css class/classes. The Html.EditorFor() method has an additionalViewData parameter that can be used for this to pass the required css class to the underlying partial view control. In this example I'm assuming you've read the article mentioned above and so I won't explain the meaning of the files and their relationship.

As a side note, I also followed the directions found on codingfreak to enable the much nicer syntax highlighting library...and in case you're wanting to add this to your blog as well, I'll pass on my stupidity so hopefully I'll save you the same...the "Preview" provided by blogger.com does not format it correctly, you actually have to post the blog for it to take the proper form.

The first item is to add the @css entry as the second parameter to the EditorFor method.

// Index.aspx<br />...<br />  <div><label id="lblGender">Gender</label><br />     <br />  </div>
...<br />

Now to consume this properly, all you have to do is utilize a mixture of the htmlAttributes anonymous object in the Html.DropDownListFor method along with the value you set in the Html.EditorFor additionViewData anonymous object as shown below.

<br /><%= Html.EditorFor(m => m.GenderList, new { @css = "search_gender_text" }) %>

It's not rocket science, but hopefully it might save you a couple of minutes of research and tinkering.