Low Pro For jQuery?

A few days ago a discussion started about porting Low Pro over to jQuery. It’s been on my mind for a while (especially since Bill blogged about agnostic UJS) but I’d hesitated in doing this for a few reasons. Firstly, of course, jQuery is the mortal enemy of Prototype and only one library shall remain come The Quickening. Aside from this completely rational reason, I wondered whether jQuery really needed anything like Low Pro at all. After all, jQuery has always been designed with ‘unobtrusiveness’ in mind and was written with most of what Low Pro originally intended to fix in Prototype implemented from the start. There was no need for something like Event.addBehavior because essentially that’s what jQuery is:

Event.addBehavior({
  'a.external:click': function() { //...code...// },
  'div.product:mouseover': function() { //...code...// }
});

Can be achieved in jQuery like this:

jQuery(function($) {
  $('a.external').click(function() { //...code...// });
  $('div.product').mouseover(function() { //...code...// });
});

And rather than ever going near inline event handlers this unobtrusive style was the de-facto method of working for the jQuery crowd. The angel on your scripting shoulder. However, as you can probably tell from reading this blog, I’ve never really adopted jQuery as my main library and this was due to one big reason (and a bundle of small ones but I’ll leave them out)...

The one big reason was that, while jQuery was super simple and concise when working on smaller projects, it offered no help in structuring larger applications. All you get in jQuery, aside from Ajax methods and a handful of utilities, is the ability to select nodes then doing something with them. On the other hand Prototype is much rounder in scope. It generally plumps out JavaScript as a language adding lots of useful methods to built-ins, a host of functional programming tools and recently a full Class-based OO system with inheritance and the whole shebang which has formed the back bone of Low Pro’s behavior classes.

Low Pro’s behavior classes have become my favourite solution to the problem of structuring complex Ajax applications in a simple and maintainable way. Even hugely complex applications can be separated up into a number of groups of elements with attached behaviors. These behaviors maintain their own state, respond to events and can also expose there own public methods. They are linked to an element but the element doesn’t know about them which eliminates the need for expandos on elements and also most of the reasons for having element references in closures which is good for keeping memory usage at bay. For instance, a click on a TabBar instance can call the loadContent method of a ContentPanel. The result is more than a set of widgets, its a way of splitting up huge complicated interfaces into a collection of small, loosely joined parts each simple in its own right and totally responsible for its part of the interface. This approach becomes incredibly useful when you introduce server-side requests and responses into the mix but that’s a whole other article.

In jQuery land this kind of effect can be achieved via plugins. You’ll find a ton of widgets in the repository that have this kind of UI:

$('#example4').draggable({ helper: 'clone', revert: true });

The plugin architecture is one of jQuery’s many strong points but this kind of approach has a couple of disadvantages. Firstly, the plugin is created within a closure which means usually if you want to change the behavior of the plugin you literally need to pop open the source and change it. The second and related disadvantage is that because of the difficulty in changing plugins they tend to have a whole raft of options to allow you to configure how it works. The problem with this is that individual widgets can end up pretty monolithic. Wouldn’t it be be better if you could just take the basic draggable behavior and just augment it to your liking?

Well, in Low Pro behaviors are classes so we can do this by simply subclassing another behavior and overriding or adding what we need. For example, we can create GhostedDraggable as a subclass of Draggable. No need to hack any existing code at all. As well as having the power and convenience of jQuery’s DOM manipulation we can have a simple and powerful way to structure larger, more complex applications. I can have my jQuery cake and eat it.

So, I’ve started experimenting with Low Pro for jQuery. Here’s a preview:

Hover = $.klass({
  initialize: function(hoverClass) {
    this.hoverClass = hoverClass;
  },
  onmouseover: function() {
    this.element.addClass(this.hoverClass);
  },
  onmouseout: function() {
    this.element.removeClass(this.hoverClass);
  }
});

$('div.products').attach(Hover);

If you want to leave feeedback or abuse jump on the Low Pro list. Do you think it has a place in the jQuery landscape? How do you currently structure complex applications in jQuery?

UPDATE: Thanks to Chris of Err The Blog Low Pro JQ is rocking on GitHub. Fork away.

20 Comments (Closed)

Whatever happens, I’m just happy to see Highlander references in my newsreader.

DonDon at 31.01.08 / 01AM

Heh, glad to be of service :)

DanDan at 31.01.08 / 02AM

let die protothype. Jquery won long time ago

seijuseiju at 31.01.08 / 07AM

Hi Dan,

you wrote ‘Wouldn’t it be be better if you could just take the basic draggable behavior and just augment it to your liking?’

Now actually you can – and almost exactly the same way you are proposing with Low Pro, only that it’s called callbacks instead of classes:

$(...).draggable({ start: function(e,ui) { //...do something at start }, drag: function(e,ui) { //...do something at drag } });

..and there are many more callbacks (in this example, I’m missing stop). And yes, you have full access to all the inner working if you must – using the second argument, which gives you access to the element’s options (ui.options) and the draggable’s instance, too.

Paul BakausPaul Bakaus at 31.01.08 / 08AM

Paul: Yes, you do get callbacks that do allow a certain amount of customisation but this is only going to be as powerful as the plugin author makes it. With behaviors you can just subclass and override anything you need to. The behavior author does not need to provide that facility.

You could in the case of draggable do what I was suggesting with callbacks but my point is that its the onus of the plugin author to provide these callbacks whereas with behavior classes its built in.

However, I’m not suggesting that plugins aren’t the way to go for jQuery widgets, more trying to demonstrate how Low Pro might have a place in aiding developers to organise their jQuery code. It’s just another facility alongside plugins.

DanDan at 31.01.08 / 11AM

IMO one of the biggest annoyances in jQuery is the lack of ability to customize plugins while maintaining upgradeability. It is a nightmare to re-hack the plugins when they are updated. If this plugin could answer to the problem I’d be gratefult.

When do you expect this to be released as final?

MassiveMassive at 31.01.08 / 13PM

Hi Dan,

I like what you’ve done on extending the $ Object on lines #26 tot #80. This in fact was one of the things I am/was missing in jQuery (I’m a Prototype user who recently switched to jQuery). Would be neat if this were to appear on the main jQuery trunk.

wbr, Bram.

Bramus!Bramus! at 31.01.08 / 14PM

Nah, it’s called “LiveQuery”. What’s awesome about it is it automatically rebinds your events after AJAX calls.

Check it out.

jcjc at 01.02.08 / 08AM

jc: I’m aware of LiveQuery. In fact if you include LiveQuery then Low Pro will automatically use it to bind the behaviors so they’ll get reloaded as the DOM changes.

They work brilliantly together rather than covering any of the same ground at all.

DanDan at 01.02.08 / 08AM

This certainly interests me. I’ve recently updated 64squar.es which is entirely written in jQuery. It’s become pretty complex to maintain, because of the lack of OO structure that jQuery provides. I was looking at JS.Class which an interesting angle.

The part about the modifying jQuery plugins is very valid.

weepyweepy at 01.02.08 / 11AM

When can we expect a proper release? Or is this it? :-)

timothytoetimothytoe at 01.02.08 / 18PM

timothytoe: erm, I’m not sure. I’m going to try to get some reasonable test coverage but I’m unsure if it needs anything else added. If you’ve got any suggestions then let me know.

DanDan at 02.02.08 / 04AM

Dan,

I’m just trying to figure out if I should give it a try or wait for kinks to be worked out. I’m on a tight deadline, but I am a sucker for cool stuff like this.

You’re driving me a bit nuts with the lack of documentation.

timothytoetimothytoe at 02.02.08 / 18PM

Okay, no problem. Documentation is coming tomorrow.

DanDan at 03.02.08 / 02AM

I’ve been a big fan of jQuery for a long time but only really used it on smaller projects, for for adding flair to applications.

You make an excellent point, which is that jQuery really isn’t very good for large apps. I have been studying a lot of advanced OO JS application development lately and it seems like jQuery really isn’t a complete javascript framework.

I’ll definitely have to look into Prototype and learn more about it. For a while I felt that Prototype was old news and would eventually die, but I am finding more and more that it’s actually not.

Michael WhalenMichael Whalen at 04.02.08 / 04AM

Michael: Woah there, I’m not suggesting you jump ship to Prototype at all. I’m just suggesting that Low Pro might have a use in structuring large applications using jQuery.

However, I really enjoy using Prototype and it’s by no means old news so maybe you should give it a try.

Point is, this post is not about whether Prototype is better that jQuery. That’s a useless conversation. It’s about whether I should bother making a version of Low Pro for jQuery…

DanDan at 04.02.08 / 12PM

I love what you’re doing here. Could you comment the source code to describe what each section is doing? Not much—just a few hints.

What is $ajaxSetup() do? Or Remote.form() and Remote.link()?

timothytoetimothytoe at 04.02.08 / 14PM

IMO OO programming allows the developer ro expose whatever function he/she needs. functions inside closures work like protected private methods you can overload these function. the ones that are exposed are public methods that you can play with

raymondraymond at 05.02.08 / 03AM

Nice job! I will try it. Thanks.

EvandroEvandro at 15.02.08 / 03AM

yes, trying to customize jquery plugins sucks, in light of the requirement of actually changing the code, rather than overriding/extending the behaviors. i will look at this!!!

chrismarxchrismarx at 19.03.08 / 15PM

About This Article