Saturday, March 12, 2011

Unobtrusive jQuery UI (jquery.ui.unobtrusive)

I am very enthusiastic about unobtrusive JavaScript. It's a design pattern and usual warnings apply:
  • It doesn't apply to every scenario.
  • It will hurt if you use it wrong.
  • Long etc.
Very short version of this post

I hope someone creates a complete jquery.ui.unobtrusive plugin. Since I'm a developer I have already started one at:
https://bitbucket.org/rodolfograve/jquery.ui.unobtrusive

The bad news is that I'm not an expert JavaScript nor jQuery developer, so I'm sure the quality of what I'm doing can be greatly improved. It will be great if someone with more expertise could continue this work or start his own and make it public.

Long version

I think unobtrusive JavaScript solves several old and current problems:

  • How do we make advanced HTML + JavaScript stuff from server-side code?
  • How do we reuse JavaScript code that interacts with the elements of a page?

Until now I've seen incomplete and ugly approaches (the latter is obviously a personal opinion):
  • Don't do advanced HTML + JavaScript from server-side code at all and create custom JavaScript code for each page you have.
  • Generate small pieces of script from server-side code, intermingled with the final HTML code (outside the head tag), and handle elements' IDs and classes.
With unobtrusive JavaScript we have a new great approach: generate HTML attributes in your tags and let your unobtrusive scripts do their science (I appreciate science more than magic).

This new approach is:
  • Flexible: you can use whatever you like to generate the attributes (ASP.NET MVC HtmlHelpers, your own framework, write attributes by hand in your HTML, etc).
  • Testable: unobtrusive scripts can (or even must) be developed as reusable components, with their own tests (JavaScript as a Framework).
  • Readable: your HTML code will declaratively express what it does (no need to look IDs nor classes in JavaScript files).
No more obscure separation between the appearance and the behavior. This separation is good and encouraged, but it's much better without the "obscure" feature added by current implementations (you must look your IDs or CSS classes in your JavaScript code to know what's going on with an HTML element).

<html>
  <head>
<script type="text/javascript">
  $(document).ready(function() {
    $("myDatePicker").datepicker({
      showOn: "button",
      buttonImage: "../themes/mytheme/calendar.gif"
    });
  });Notice this piece of script usually is in another file (even worst).
</script>
  </head>
  
  Lots of stuff, and then hidden some where in the page:

  <input id="myDatePicker" name="myDatePicker" type="text" >

With unobtrusive JavaScript you keep the separation at the implementation level, and avoid the separation at the code level.

<input type="text" ui-datepicker="true" ui-datepicker-showOn="button"
                                             ui-datepicker-buttonImage="../themes/mytheme/calendar.gif" >

This last code looks much better to me and I wish we soon have the unobtrusive "mapper" of the most popular JavaScript frameworks out there.

What do you think?

3 comments:

Scott said...

Hi Rodolfo. I checked out your repository and I love what I see. I especially love that you made this available on nuget. IMO, the repo needs an AMD solution, so that your code can be used with script loaders like Require.js. I also recommend keeping your code as object-oriented as possible, with unit tests. I didn't see any tests there on the repo.

For a project I'm working on right now, I'm building a simple unobtrusive-management-registry, so that you can register your unobtrusive attributes anywhere in your code at runtime, and assign function handlers for them, which would be executed on $(document).ready

I could add that to your repo if it's successful, and I think it may be worthwhile for you to integrate it into your existing repo.

This way, you could have a generic way of setting up the jquery-ui unobtrusive attributes, and it might make it easier for others to add their contributions. fyi, in case you didn't know, twitter bootstrap already uses the unobtrusive approach for a lot of their components. I recommend checking out their source code if you haven't already to see how they do it.

Scott said...

forgot to mention this in my last post.

Rodolfo Grave said...

Hi Scott.

It's been a while since I don't youch this jquery.ui.unobtrusive and I'm glad to see you find it useful.

I took a look to the link you shared and it seems like that solution is in a better shape.

In any case, I'll be more than happy to integrate the improvements you propose. Just drop me a note or make a pull request.