Using Low Pro for jQuery

read 15 comments

Recently I have been getting a real buzz out of developing with jQuery. I've been using the library since 2006, releasing sporadic bits of code. In April of this year, I released the third revision of my most complex plugin, jMaps, and updated several other plugins, which are available in my mercurial repository.

This was also the same month I discovered a new plugin which has dramatically changed how I develop applications with jQuery. The plugin in question is Dan Webb's Low Pro for jQuery, a port of the plugin of the same name for Prototype.

What is Low Pro?

So what is Low Pro? It's a plugin that provides a way of making more object-oriented JavaScript through event delegation. jQuery's plugin architecture provides a really simple way of extending the core functionality, but there is no easy way of making macros of code that do several types of events on one element. Until now!

Probably the simplest way to explain how Low Pro works is to build a quick demonstration. Sometimes I find that too many tutorials out there expect prior knowledge, so with that in mind, I will try to make the tutorial as simple as possible. However, this example does use another couple of plugins that are outside the scope of this tutorial:

  • Live Query - Low Pro uses this plugin to make binding to dynamic elements in the DOM easier.
  • jQuery Validation - We'll use this plugin to show how we can bind other plugin functions to events.

Both these plugins already have excellent documentation, so if you wish to extend this example, please check them out.

Example 1: Creating a re-usable registration form

For this example we'll build a simple user registration form. This is something that is common enough on the web, but a nice advantage of this example is that it can be used over and over again with little or no modification. Hopefully once you have learned this pattern, you will be able to see lots of other applications that can be reused over and over again in the same fashion.

Our first step is to create our basic form:

HTML:
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  2.  "http://www.w3.org/TR/html4/strict.dtd">
  3. <html>
  4.   <head>
  5.     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  6.     <title>Lowpro Example</title>
  7.     <script type="text/javascript" src="js/jquery.js" />
  8.     <script type="text/javascript" src="js/jquery.livequery.js" />
  9.     <script type="text/javascript" src="js/lowpro.jquery.js" />
  10.     <script type="text/javascript" src="js/jquery.validate.js" />
  11.     <script type="text/javascript" src="js/reg-form.js" />
  12.   </head>
  13.   <body>
  14.     <div id="form-container">
  15.       <form method="post" action="." id="lowpro-form">
  16.         <fieldset>
  17.           <legend>User Details</legend>
  18.           <ul>
  19.             <li>
  20.               <label for="username">Username</label>
  21.               <input type="text" id="username" name="username" />
  22.             </li>
  23.             <li>
  24.               <label for="email">Email</label>
  25.               <input type="text" id="email" name="email" />
  26.             </li>
  27.             <li>
  28.               <label for="password1">Password</label>
  29.               <input type="password" id="password1" name="password1" />
  30.             </li>
  31.             <li>
  32.               <label for="username">Password (Again)</label>
  33.               <input type="password" id="password2" name="password2" />
  34.             </li>
  35.           </ul>
  36.           <input type="submit" class="register" value="Register" />
  37.         </fieldset>
  38.       </form>
  39.     </div>
  40.   </body>
  41. </html>

Now, we create our JavaScript file called reg-form.js. In here, we will create our class that we'll attach to the form. Inside this class, we'll create some functions that trigger on specific events. Every class created with Low Pro takes the form of $.klass({...});. Inside the curly braces, we use JavaScript prototype nature to create a pseudo-class. We will call our example RegisterForm.

JavaScript:
  1. RegisterForm = $.klass({
  2.   initialize : function(options) {
  3.  
  4.   }
  5. });

If you have developed in languages like PHP, Python, or Java, you've probably seen something like this before. This first function, initialize, is a reserved function in Low Pro that accepts one parameter—an options parameter (we'll discuss that later). This function is always called whenever you bind a class to an element. Because it does not require any event to trigger, it is very useful for setting up initial data or events on dynamic DOM elements.

Validation

The first thing we'll do is create our JavaScript validation rules. This tutorial does not cover the creation of these rules; however, they should be reasonably understandable. If you would like more information, please check out the excellent documentation.

JavaScript:
  1. RegisterForm = $.klass({
  2.   initialize : function(options) {
  3.     this.element.validate({
  4.       rules: {
  5.         username: {
  6.           required: true,
  7.           minlength: 4
  8.         },
  9.         email : {
  10.           required: true,
  11.           email: true
  12.         },
  13.         password2 : {
  14.           equalTo: "#password1"
  15.         }
  16.       },
  17.       messages : {
  18.         username : {
  19.           required: 'Your username is required',
  20.           minlength: 'The minimum number of characters is 4'
  21.         },
  22.         email : {
  23.           required: 'You must enter your email',
  24.           email: 'You must enter a valid email'
  25.         },
  26.         password2 : {
  27.           equalTo: 'Your passwords must match'
  28.         }
  29.       }
  30.     });
  31.   }
  32. });

Notice that I am using this.element instead of $('#lowpro-form') inside the function. Low Pro provides this handy alias so you always work with the correct object. If you are going to be writing a complex function, it's always a good idea within the function to assign it to another variable.

But this code isn't actually doing anything yet. This is because we now need to bind the class to the form. Here is where we go back to the good old jQuery we know and love. Below the class, put this in the file:

JavaScript:
  1. $(document).ready(function(){
  2.   $('#lowpro-form').attach(RegisterForm);
  3. });

Now, open up the page in your browser and start to type into the fields. You should start to see the validation rules apply to the fields. Congratulations, you've written your first re-usable class with Low Pro!

Enhancements

Now that we have our validation rules, let's start to make the form a bit more sexy. First, something simple. Let's make sure that the first field (the username field) is always selected first, so the user can easily tab down the form. After the validation method inside the initalize function, add this:

JavaScript:
  1. $('#username').focus();

Refresh the page, and your username field should now get the focus.

Now let's introduce another event into the mix. When the user submits the form, we want to let the user know that it's being sent to the server. To do this, we could notify the user by changing the text on the button from "Register" to "Submitting".

JavaScript:
  1. RegisterForm = $.klass({
  2.   initialize : function(options) {
  3.     ...
  4.   },
  5.   onsubmit : function() {
  6.     $form = this.element;
  7.     $('.register').val('Submitting');
  8.         /* If your using Ajax it goes in here */
  9.         return false;
  10.   }
  11. });

So there we have it: A reusable, fully functional Ajax registration form with validation. You can check out a demo here and also grab the source code of this example from my repository.

One final thing I should touch on in this first tutorial is the initialize function's options parameter. When attaching any Low Pro class, the initialize function accepts an object containing any options you want to pass into the function:

JavaScript:
  1. $('#myform').attach(MyFunction, {foo:'moo', bar:2}

In our above example, we'll add a tag to display a message of the day. In the HTML, create a div with a class of motd. Next, add the following code into the initalize function:

JavaScript:
  1. if (options.motd) {
  2.   $('.motd').text(options.motd);
  3. }

Now, when we attach our class to the form, we use the following:

JavaScript:
  1. $(document).ready(function(){
  2.   $('#lowpro-form').attach(RegisterForm, {motd: 'jQuery Rocks!'});
  3. });

When you now refresh the form, you should see a message on the screen.

Well, that wraps it up for this tutorial. I hope I've given you a small idea of the power that Low Pro contains. In conjunction with LiveQuery, you can really create some dynamic and interesting applications.

If anyone would be interested in more tutorials like this, then please leave a comment and let me know what you think.

Tane Piper is a full time web developer, geek and Humanist from Edinburgh, Scotland.(55.957898, -3.159792) He has released or is working on several open source projects including jMaps and Mercurial manager. He is also available for hire as a freelance developer, working with PHP, Python and JavaScript.
comment feed

15 comments

  1. My opinion is that low pro is never necessary and it would be better to write a reusable jQuery plugin that others can use. Writing on top of low pro does not benefit the jQuery economy, because you are writing on top of a dependency of low pro. IMO, low pro only serves as an intermediary step between switching from mootools/prototype to jQuery and shouldn't be used if you already know how to write reusable code within the jQuery landscape.

    jQuery itself has everything you need to write reusable code.

  2. Marc I happen to disagree. Low Pro provides something that is very much missing from jQuery - structure and a general class system that allow building complex web applications. Writing reusable code doesn't mean writing maintainable and scalable code. jQuery with its unobtrusiveness and plugin architecture works like a charm for small to middle-sized websites. Unfortunately it does not provide any comprehensive tools for quickening the process of building larger class-based apps.

    Tane thanks for writing this intro to low pro. It'd be great if you could write more on event delegation and other useful techniques that low pro brings to the table.

  3. John wrote an article on, "Classy Query" addressing this line of thinking:

    "If one thing has become apparent to me it's that users enjoy working with the typical Class-style of object creation and inheritance. Because of this I've constructed the entirety of Classy Query in an classical manner (you can inherit and override any piece of functionality that you desire)."

    http://ejohn.org/blog/classy-query/

    Did I mention its an april fool's joke?

  4. Barry

    How is this any different from just writing a function that applies the behaviour to an element?

    
    function registerForm(form) {
        form.validate({
          rules: { ... }
        });
        $('#username').focus();
        form.submit(function() {
            $('.register').val('Submitting');
            // Ajax goes here
            return false;
        });
    }
    registerForm($('#lowpro-form'));
  5. i´ve been off js for half a year(beeing on rails), but this was something i really needed back than. Way to go, LowPro and LiveQuery will be rocking my current app!

    Thanks

  6. @marc - Maybe this first example missed some points of how powerful Low Pro can be, but I wanted to use this example to kick things off and show how to create some really re-usable code.
    The power of Low Pro really comes when you start working with the dynamic nature of the DOM creating/removing elements and binding events to them in association with Livequery.

    I'm building some complex forms with it, and with permission of my work I might use some of that code in another tutorial.

    Another thing is coming from me coming from an OO background, I find LowPro's way of handling the prototype nature of the language much easier to handle.

  7. The bottom line is that this style of code doesn't provide any tangible benefit, other than the fact that some people like writing code this way.

  8. Thomas

    "other than the fact that some people like writing code this way."

    Well screw that, then. Happiness and productivity are benefits for weaklings.

  9. @Marc: Really not true. One of the main benefits it gives you is the ability to extend object easily. This article doesn't really demonstrate this, but it's the main advantage of using LowPro.

    You might argue that you can do the same with a plugin architecture, and while this is somewhat true it's often inconvenient and usually the responsibility is with the plugin author to make a developers life easier. And no, providing a massive options object for configuration doesn't classify as easy in my definition.

    The common use case I come across is having to use a component/plugin on the same page or site, however each use requires slightly different configuration or functionality. With your average jQuery plugin I need to open the source, fiddle around until I can abstract the bits of functionality I want to replace.

    Great article btw, if you can do another demonstrating these advantages you might pursued a few more people that this is a good idea :)

  10. "it gives you is the ability to extend object easily. This article doesn't really demonstrate this, but it's the main advantage of using LowPro."
    I'd like to see the code, I haven't seen anything I can't already do in a straight forward way without low pro.

    "The common use case I come across is having to use a component/plugin on the same page or site, however each use requires slightly different configuration or functionality."
    I don't see how hacking a plugin externally with low pro, helps over modifying the plugin itself and sending the author the code updates. Ultimately the plugin author needs to integrate the code you need - it is better for everyone that way.

    "And no, providing a massive options object for configuration doesn't classify as easy in my definition."
    Plugin authors have been modularizing the code instead of providing a massive options object. I need to follow the modularization practice going forward. We are all learning here what the best way to code plugins is.

    side note:
    "low pro serves as an intermediary step between switching from mootools/prototype to jQuery" -me.
    Your company's website, http://www.jbinteractive.com.au/ is using MooTools. It seems anyone using lowpro is a convert to jQuery.

  11. Ok, so you didn't address the fact that modularizing plugins is still the responsibility of the plugin author. Sure they can modularize, they can abstract, but your average jQuery plugin only does this to a certain extent.

    You did mention contributing back to a plugin, but in reality this is not what most developers want. Try considering this from a production environment point of view: In a production environment I want the tools available to me that I can customize on the fly!

    Side note noted! That site was written by another developer here over a year ago. You'll also note then that we no longer use mootools in any other more recent project to my knowledge, and that the JS on our main site, while separated into Objects, is not really OO and is only really split up into namespaces. So while your argument may be true for some people, it's not for us and is anecdotal at best.

    I think in the end this is just a difference in opinion. You're obviously a hardcore jQuery advocate, and while I certainly consider myself one too, I'm open to the possibility of using jQuery as a tool for developing larger apps in different ways.

  12. "So while your argument may be true for some people, it's not for us and is anecdotal at best."
    Yes, my opinion is based on observing the community's responses and doesn't apply to everyone.

    "I think in the end this is just a difference in opinion. You're obviously a hardcore jQuery advocate, and while I certainly consider myself one too, I'm open to the possibility of using jQuery as a tool for developing larger apps in different ways."
    Best of luck. I am open to anything once I see an example of something I can't already do in a straight forward way.

  13. I'm a bit late to the game here but I thought I'd put my two cents in. Basically, Low Pro (for Prototype) started out as a mixed back of patches and additions to Prototype that I used to support unobtrusive scripting but one part of the library that really took on its own life was the idea of Behaviour classes and that is essentially what Low Pro for jQuery contains as all the other stuff is not needed.

    So, it seems that the purpose if Behaviour classes is a bit unclear. You can't do anything else with Low Pro that you couldn't do another way. It *is* just a way of working and organising larger applications. It does have a number of really large advantages though:

    1. It allows you to create front end components that are completely decoupled from the mark up and each other. The configuration of these comes at the binding layer (when you use $().attach()) which is a much better than the alternatives which are either custom attributes or unsemantic use of class names).

    2. It gives you a easy to use inheritance mechanism so its easy to take existing behaviors and add or adapt their behaviour in any way you like. For instance, I often bulid on Remote.Link or Remote.Form to create any behaviour that deals with Ajax. This is a big advantage over standard plugins where you nearly always need to depend on hooks the plugin developer uses for you or hack the source yourself. However, Im not saying that behaviours should replace plugins. They work alongside each other. For example, something like livequery is a good example of something that should be a plugin but on the otherhand, I think that a UI component such as a calendar widget would be better suited to being a behavior as a large degree of customisation is often needed.

    3. Probably the biggest advantage for me is that it guides my way of designing front end code. With behaviours I can treat each part of the UI as a distinct entity rather than having to comprehend the whole UI at once. Even really complex interfaces are easy to split up into very small discreet behaviours. Once you've got these behaviours you can mix and match across your project, extend them, reuse them on other projects. Your front end code becomes I collection of useful tools rather than a bunch of functions that only work on that particular page. It's something that I only realised after using it for a while.

    If you have the time to try it I think you'll see the benefits pretty quickly. If you don't then fair enough, it's not buying you any new JS super powers or anything. But then again, what is jQuery apart from a new and better way of achieving the same result?

  14. This comment is kinda late, oh well...

    @Dan Webb: "It gives you a easy to use inheritance mechanism so its easy to take existing behaviors and add or adapt their behaviour in any way you like."
    Implementation inheritance is bad for code reuse and stability. Not to say about strong coupling... Simply say 'no'.

    Have you heard of (Liskov) substitution principle? There's a nice essay written by Oleg Kiselyov regarding this topic.

  15. VERY INTERESTING ARTICLE SO MANY USEFUL INFORMATIONS REALLY GOOD WORK
    THX SO MUTCH FOR GREAT ITEM :)

One Ping

  1. Learning jQuery » Using Low Pro for jQuery...

    Learning jQuery » Using Low Pro for jQuery...

Sorry, but comments for this entry are now closed.