The State (And Future) Of The UJS Plugin

Over the past few weeks loads of people have been asking me about what’s going on the UJS plugin. It’s obviously fallen in to disrepair so people, understandably, have been concerned. There has been a reason for this aside from the fact that I am a lazy barsteward (which of course I am, but that’s beside the point). Here is a letter I’ve just written to the UJS mailing list that I’d thought I’d post here to try to get a little more feedback. It’s a little bit long but bear with me…

I’ve been chatting to Luke and users of UJS about what to do with it and still haven’t quiet decided hence the lack of news but below is a rundown of where we are at on the whole thing. However, this is definitely personal opinion and doesn’t necessarily represent Luke’s opinion on the matter.

Essentially, the status is that, of late, I personally have not used UJS at all and have found a much better process by using Low Pro on its own without all the Ruby scaffolding of the UJS plugin. Secondarily, after talking to lots of developers at RailsConf it seems that the UJS plugin has failed to truly achieve it’s main goal which is to get Rails developers to write JavaScript using progressive enhancement. Many people seem to mainly use the plugin to get their JavaScript in to a separate file which is actually not even essential to progressive enhancement and I think this is a failing in the design of UJS itself. To achieve progressive enhancement you really need to think of JavaScript as a separate layer on top of a working HTML application but UJS lets you get away with keeping behavior in your views and hence leads many developers to think in the same way as they did before but think they are unobtrusive because they don’t see any JavaScript in their HTML – which is obviously not what we wanted to achieve. While many people can and do successfully use UJS for progressive enhancement even more seem not to – UJS has not been the ‘angel on your shoulder’ that I originally wanted it to be.

On top of this, the method by which the generated JavaScript is kept in the session has many limitations which myself and Luke have been aware of from the start. It’s not generally a good idea to keep this much information in the session (in fact, normally I never store more than a user ID if I can help it) and while acceptable for light to medium use it does have an upper limit depending on the type of session storage you are using. Rails edge now uses cookies to store session info by default which have a very very low limit which will cripple UJS completely. We have considered other alternatives such as some kind of file based storage but every time it just strikes me as too much scaffolding just to allow developers to put behavior in their view files which, as a said above, I’ve come to believe is a really bad idea anyway.

One of the things that I do personally like and something that has received the most positive feedback are the behavior helpers (the make_*) stuff which essentially encapsulate common tasks with sensible defaults in a very Rails like way. It’s a real time saver and the conventions provided mean that the best path (such as using this.href for the Ajax url) is the easiest. Recently, I’ve come to do this in my own projects via Low Pro and it’s behavior ‘classes’ (although they need a better name!). Now via Low Pro I can write stuff like:

Event.addBehavior({
  '.product a.description' : Remote.Link({ update : 'product_description' }),
  '.product' : Draggable({ revert : true }),
  '#basket' : Droppable
});

I really like this and am slowly building up a library (which you can see if you look at the Low Pro trunk) of common behaviors. There’s a date picker, a drag/drop implementation and the remote stuff I’ve illustrated above. I’m planning on writing autocompleters and in-place editors as behaviors as well. But behaviors have proven really easy to write and I love them as a tool for building site specific components. In fact, as I’ve worked with Low Pro it’s become apparent to me that behaviors are by far the killer feature which is interesting as they were just an experiment I hacked together one day without much thought.

So what to do? Well, there’s two ways to go as far as I can see. The first is to shut down development on UJS completely (or hand it over to another party if anyone is interested) and go on to promote the techniques of implementing progressive enhancement using Low Pro that I’ve found to be so successful recently. This could possibly be via the UJS4Rails site or through my own site – I’m not sure which would be a better platform right now.

The other would be to re-think the UJS plugin totally and go for some kind of 2.0 release that would take a completely different tack. However, all of the ideas for this I’ve thought of or heard so far don’t really compel me to write them. I think to work on this myself I’d need to be sure that I’d want to use it and so far this is not the case but any ideas and feedback are very welcome so please do drop me a mail or feedback on this list.

Either way, we need to make fixes to the current plugin to make it work with Rails 1.2.3 which I’ve been working on recently but I’d love patches if you’ve already solved these issues yourself (which it appears many of you have).

So yes, that’s it. Let me know what you think, I’d appreciate any feedback you have.

21 Comments (Closed)

Using the UJS plugin helped me to learn how easy it is to attach behaviors with LowPro. Since then I’ve done most of my Javascript coding in Javascript + LowPro without the help of the UJS plugin.

So it’s great as an entry point to writing unobtrusively and designing with Javascript as a layer instead of driving core functionality, but one grows past it quickly.

Rails did a good job of marketing Javascript/AJAX and showing how easy it could be.

Maybe LowPro needs more marketing to beginners to show how easy it is to use? Then UJS wouldn’t be needed anymore.

This could be as simple as a Rails plugin that copies LowPro and Prototype 1.5.1 to your public directory along with a basic application.js that shows how to do simple requests and updates. Some people seem to take external libraries less seriously if they are not available as a Rails plugin.

topfunkytopfunky at 16.06.07 / 18PM

http://svn.danwebb.net/externam/lowpro/trunk/behaviors/ needs a password

LuigiLuigi at 16.06.07 / 19PM

I agree with topfunky—UJS4Rails was a great stepping stone, but LowPro feels like a much lighter destination.

I think that using UJS4Rails.com to promote LowPro could work; ‘UJS4Rails’ as a term describing how LowPro is used—rather than the name of an actual plugin.

Whatever you decide, I think that LowPro has a bright future and could certainly benefit from having its own public facing web site.

MeekishMeekish at 16.06.07 / 19PM

Luigi – try http://svn.danwebb.net/external/lowpro/

MeekishMeekish at 16.06.07 / 19PM

Perhaps UJS4Rails could be converted into an assistive tool. I was thinking that the :unobtrusive declaration for javascript_include_tag could locate files in a controllers view path:

—/views /blog —/blog.ujs.erb —/index.html.erb

Inside of blog.ujs.erb you would be able to use the add_behavior ruby code to enhance the views for that controller. Get’s people thinking in the right way and allows for the ujs to be tied to the views in question rather than a monolithic application.js which they may get lost in. The ujs controller would render that file—perhaps one could even allow per view ujs files too.

This would obviously do away with the functionality which extracts js from the views and moves that into a generated file. This would be a stepping stone to using LowPro directly, without mingling in the actual views.

nkrypticnkryptic at 16.06.07 / 19PM

Dan, We met at the LRUG bash on Monday, and I guess I’m one of those who found it great for weaning me off the rails js helpers - which I never like - and towards a cleaner separation of concerns, a la CSS.

These days, virtually all my behaviours are in the app helper file under two all-encompassing helpers default_behaviours, and default_user_behaviours (for logged in users), and are mostly pretty clean.

However, I’m not sure I get how I’d use LowPro to do one thing which UJS currently allows me to do, which is to add behaviours based on server-side conditions. This could be trivial (was the form rendered via an xhr request), or more complicated.

I guess I could add the js to the view, but that seems very inelegant. Could you point me to the One True Way on this.

Chris TChris T at 16.06.07 / 20PM

Chris: In one app I’ve been working on (which doesn’t actually use UJS, but no matter), I’ve communicated server dependent information by setting variables in <head> which are used as parameters by my javascript controllers.

Yes, it’s adding JavaScript to the view (well, to the layout), but I’m comfortable if all that that javascript does is describe state.

Piers CawleyPiers Cawley at 17.06.07 / 09AM

I agree with you Dan, the UJS plugin is a help in getting people into the right frame of mind but it becomes inpractical when you are dealing with larger volumes of JS and I have stopped using it now in favour of hand writing stuff.

The world doesnt need any more abandoned Rails plugins so if the decision is taken to wind down development of the UJS plugin (assuming noone wants to take it over), I would suggest changing the purpose of that site to become a resource for unobtrusive programming with Rails, using LowPro or other libraries too.

This is something I would be interested in helping with if you take it in that direction.

DaveDave at 18.06.07 / 10AM

topfunky, Dave: Yep, I’m thinking this is the way to go as well. I’ll get a new version of ujs4rails designed as a resource site. I really like the idea the more I think about it actually. And yes, it would be incredibly good to have a few contributors to the site if you are interested.

DanDan at 18.06.07 / 10AM

I stopped using the Rails helpers quite early on, now I come to think of it, but I use LowPro for everything. It’s the only thing that makes Prototype usable, for me. Well, 1.5.1 is quite a lot better but I still…

I’ve also converted most of my classes to behaviours – they’re such a nice way to separate the logic.

Mike StenhouseMike Stenhouse at 18.06.07 / 14PM

I’m one of those who were asking you about UJS at RailsConf and also one of those who told you I stopped using it after a week in favor of now beloved LowPro. I think I was pretty drunk when I came up to chat with you, my apologies. ;-)

All that to say : I give my 100% go for UJS4Rails as a website about unobstrusive JS in rails with LowPro and othet ujs libs. UJS4Rails was a beautiful project and the initiator of great quality plugins but it hasn’t done what you wanted. Let’s move on !

Thanks for you great help with ujs, it wouldn’t be as easy for a designer to do good, maintainable ujs without you’re precious help.

P.S. : If I can help in any way my email is attached ! By the way I’ll be working on Google Maps for the next few weeks for a client. I’m might try and get to your new “Behavior” kind of UJS programming with LowPro and build bricks for LowPro and Gmaps (this is a theoretical supposition I have been into Gmaps code yet). Or write an article on unobstrusive JS with Gmaps, Low Pro (and rails) for the new UJS4Rails site if you’d like. Tell me.

npnp at 18.06.07 / 22PM

Dan, I’ve been reading up about UJS because I’m starting a new project soon and was deciding if I should use it or not.

Using just lowpro looks like the best option. However, there are no simple, basic examples about how to use lowpro in a Rails project. This is a massive barrier to someone who’s not familiar with the concept.

How about writing up just a simple example that shows one page rendering from a Rails controller with one view and a couple of behaviors added to that page.

I think this is absolutely crucial to the success of it here.

Thanks, David.

David jonesDavid jones at 21.06.07 / 05AM

In my side projects, I have found that just using LowPro is a lot easier, or at least had less conceptual overhead.

At the very least I would like to see LowPro get some more development, it’s very handy.

Adam SandersonAdam Sanderson at 22.06.07 / 15PM

Indeed, I kind of like nkryptic’s idea. I really like the behavior helpers themselves, but it did always feel weird to put them in the view. Combining the concept of MinusR/MinusMOR and the usefulness of the behavior helpers would be a great way to maintain the separation while still providing some neat tools.

ShadowfiendShadowfiend at 22.06.07 / 17PM

Hi, I have been using UJS for a while now and found it useful as I’ve always preferred the separation of concerns method even though my code has not always been the best when it comes to progressive enhancement.

After reading this article I have decided to switch over to Lowpro exlusively. But I ran into a few problems when doing so.

The main one happened when I started using the behaviours: I moved all my events into application.js and that worked fine but when I tried to use Remote.Form or Remote.Link I get the error “observer has no properties” lowpro.js line 312, strangely Draggable works fine. My code is Event.addBehavior({ ‘a.header-link’ : Remote.Link({ update : ‘right-col-header’ }) });

Any ideas here would be greatly appreciated, I’m sure I could shave off ~100 lines of code if I could figure this one out.

The other thing is figuring out out to add behaviours based on server-side conditions at the moment im still using ujs for this but it would be nice to find a more elegant method for this.

Overall though thanks for the effort with UJS and Lowpro, its all pretty solid.

Cheers

Paul OdeonPaul Odeon at 28.06.07 / 16PM

@Dan: I think it is definitely a better route to go using lowpro instead of ujs.

I’m really curious as to why lowpro is not in prototype – any reason? The Event Observe stuff specifically; perhaps I missed you talking about this somewhere.

RobertRobert at 03.07.07 / 16PM

Same problem as Paul: Remote.link doesn’t seem to be implemented in lowpro.js available in the trunk…

any news about this?

ZenoZeno at 05.07.07 / 10AM

paul, Zeno: Remote.Link and Remote.Form are still under development but you can find them in trunk under the behaviors folder. They are in a reasonable state but possibly aren’t quite production ready yet. When they are (Im just battle testing them in some projects at the moment) I’ll probably roll them into the core build of Low Pro.

Dan WebbDan Webb at 05.07.07 / 10AM

Dan, I was quick to adopt UJS 4rails when it first came out for a variety of reasons. A, it felt right not to be shoving loads of code into my html. B, I didn’t have to learn anything new just plug in UJS and it automatically converts all the existing helpers to be magic UJS helpers. It now seems that UJS is no longer the way forward and I’m keen to learn the “correct” way of doing things like form_remote_tag etc. Just saying “use Lowpro” is a bit of a barrier. I don’t know a massive amount about javascript, behaviours and classes and why you use one rather than the other. Please could you provide a few more examples of how to replace a UJS4Rails piece of javascript with a Lowpro piece. I wanna do the right thing I just need to be pointed in the right direction. BTW thanks very much for all the effort that went into the original UJS4Rails plugin. Using it has been great. Tom

Tom StylesTom Styles at 19.07.07 / 16PM

Tom: I’ve just posted a 2 part series about how to write Low Pro behaviours which should start you off….otherwise there’s an article about Low Pro in the archives thats a good place to start. I do however plan to write more on this blog about various parts of Low Pro and how I use it to approach various problems.

Dan WebbDan Webb at 19.07.07 / 16PM

Tom: I’m writing a series of introductory articles about the migration from the standard Rails Ajax/Javascript helpers to Low Pro.

The two first parts are already published, the third one coming out later this week.

Part 1 Part 2

Jarkko LaineJarkko Laine at 07.08.07 / 06AM

About This Article