Clientcide 3.0, Behavior 1.0, MooTools Development, and so much more

Monday, June 13th, 2011 @ 4:04 pm | filed under: Code Releases

Greetings programmers. It’s been too long.

First, a quick personal update: For the last 2.5 years I’ve been busy at Cloudera helping them build a bunch of tools for Apache Hadoop which I’ve written about here and elsewhere. Over that period I wrote a lot of JavaScript, nearly all of which could be found on github but it wasn’t ever packaged up for your easy consumption. In that same period, I posted here infrequently as I was so busy contributing to MooTools and doing my job. All good things must come to an end though, and as of mid-May I decided it was time to move on and try and focus my career back where I’m happiest which has, historically, been building web sites and applications for consumers and culture. In a week or two I’ll likely be taking on a role that sees me programming a lot less, at least for my day job.

Anyway, over that 2.5 years of cranking out tons of JavaScript, I was always itching to put the polish on the things that were most interesting to release them for your consumption. I spent the last few days doing that and finally updating my download builder to work with the new MooTools dependency system so that I could release my latest work. So let’s get to it!

Clientcide 3.0

After a shameful delay, mostly due to the fact that my download packager was built around the old “scripts.json” dependency system, I’m finally ready to release the latest Clientcide code. I push to this codebase regularly as I fix bugs and add features, but rolling a release was always at the bottom of a long list of priorities. The big thing to note is that this release is finally on MooTools 1.3 – no compat layer needed as only native 1.3 methods are used. Woot.

The second thing you’ll likely notice is that there’s a lot fewer things on the list. I’ve deprecated stuff that I wasn’t willing to continue supporting; stuff that I just doubt many people were using. The list of deprecated plugins is rather long – about 25 files. Fear not! All those files are still on github on the 1.2x branch of Clientcide if you need them. If you find that you want something on that list, I encourage you to take the files and release them yourself.

For more details, check out the release notes in the readme in the Clientcide repo on github. This release is actually tagged 3.0.1.

Behavior

As mentioned here a while ago, while at Cloudera we implemented an abstraction for code invocation (typically the stuff you put in a domready statement) that reads configuration from declarative HTML. It’s changed the way I build things so much that I doubt I’ll ever build anything without it. The nutshell is that instead of having a domready function that finds the stuff in your DOM and sets up instances of classes and whatnot, you put the configuration in the HTML itself and write the code that calls “new Foo(…)” only once. Example:

Instead of this:

$$('form').each(function(form){
  new FormValidator(form, someOptions);
  new Form.Request(form, someOptions);
});
new Tips($$('.tip'));
$$('.accordion').each(function(container){
  new Accordion(container.getElements('.toggler'), container.getElements('.section'), someOptions);
});
etc

You do this:

<form data-behavior="FormValidator FormRequest" data-formvalidator-options="{someOptions}">...</form>
<a data-behavior="Tip" title="I'm a tip!">blah</a>
<div data-behavior="Accordion" data-accordion-options="{someOptions}">...</div>

Why?

Think of it as delegation (as in event delegation) for class invocation. If you use domready to do your setup and you want to swap out some HTML with XHR, you need to reapply that startup selectively to only your components that you’re updating, which is often painful. Not with Behavior, you just apply the filters to the response and call it a day.

You do a lot less DOM selection; you only ever run $$(‘[data-behavior]’) once (though some filters may run more selectors on themselves – like Accordion finding its togglers and sections).

Domready setup is always closely bound to the DOM anyway, but it’s also separated from it. If you change the DOM, you might break the JS that sets it up and you always have to keep it in sync. You almost can’t do that here because the DOM and its configuration is closely bound and in the same place.

Developers who maybe aren’t interested in writing components don’t need to wade into the JS to use it. This is a big deal if you’re working with a team you must support.

Behavior is designed for apps that are constantly updating the UI with new data from the server. It’s NOT an MVC replacement though. It’s designed for web development that uses HTML fragments not JSON APIs (though it can play nicely with them). If you destroy a node that has a widget initialized it’s easy to make sure that widget cleans itself up. The library also allows you to create enforcement to prevent misconfiguration and an API that makes it easy to read the values of the configuration.

There are some other nifty things you get out of it; you get essentially free specs tests and benchmarks because the code to create both of them is in the Behavior filter. Here’s an example of what it takes to write a spec for a widget and ALSO the benchmark for its instantiation.

Behavior.addFilterTest({
  filterName: 'OverText',
  desc: 'Creates an instance of OverText',
  content:  '<input data-behavior="OverText" title="test"/>',
  returns: OverText
});

This code above can be used to validate that the HTML fragment passed in does, in fact, create an OverText instance and it can also be used with Benchmark.js to see which of your filters are the most expensive. More on this stuff in a minute.

Included in the library is also a file called Delegator which is essentially the same thing except for events. For example, let’s say you have a predictable UI pattern of having a link that, when clicked, it hides a parent element. Rather than writing that code each time:

document.body.addEvent("click:a.hideParent", function(e, link){
  e.preventDefault();
  link.getParent().hide();
});

You register this pattern with Delegator and now you just do:

<a data-trigger="hideParent" data-hideparent-options ="{'target': '.someSelector'}">Hide Me!</a>

It provides essentially the same value as Behavior, but at event time. The above example is pretty straight forward so, you know, why bother, right? But consider how many of these little things you write to make a web app function. If you can create them once and configure them inline, you save yourself a lot of code. For example, one of the things I’m releasing today is a delegator that makes it easy to have a link that updates any specified DOM element; basically AJAX without the J.

MooTools Development

I also wrote a while back about a portable MooTools development environment. Since then this little project has progressed to add a lot of useful features for a development sandbox. With a little bit of configuration work, you get docs, demos, specs testing, and benchmarks. It’s seriously pretty awesome and I use it now exclusively for working on front-end coding. By working in the sandbox, writing docs and specs, I’m much more likely to end up with generic, reusable code that isn’t too tied to any specific application. Enough talk, here, check it out running here on Clientcide:

dev.clientcide.com

As you can see you get docs with a simple quick-search, demos of all the components with the ability to view the source of any demo (and not just the HTML for the demo but also any other “interesting” files you choose to highlight), specs tests that anyone can run in their browser, and benchmarks which will show you how your code performs. Using this environment makes it easier for me to just focus on the code and use these tools over and over again.

The other thing that’s really nice about it is the ability to create a code configuration and share it with others. For example, you can run this development environment locally yourself with just the few following commands (assuming you have python 2.6 installed):

$ git clone git://github.com/anutron/mootools-development.git
$ cd mootools-development
$ git checkout -b behavior origin/behavior
$ ./go install             # or just "./go i"
$ ./go depender_check      # or just "./go d" - this checks the JS dependency tree
$ ./go run                 # runs the server on port localhost:9876

This will give you the development environment set up for Clientcide and Behavior (basically what’s running at dev.clientcide.com). If you don’t check out the behavior branch before you build, you’ll just get MooTools Core and More.

More Behaviors

Finally, the last shiny new present I have for you is a starter collection of Behaviors that you can use in your own apps. While working at Cloudera I authored maybe 50 of these things, but I haven’t had time to polish all of them up. Included in today’s release you’ll find Behaviors in the Clientcide release and another, stand-alone repo called “More Behaviors” which is principally used for instantiating widgets from MooTools More. Not everything has a Behavior filter, but you’ll get the idea of what they’re for and how to use them. Maybe chip in and help me write more of them! There’s a handful of Delegator triggers in there, too, and while they aren’t really related to MooTools More they dovetail nicely with the other plugins and show you how to use them.

Where?

Ok, so I’m releasing all this stuff, but how do you get it? Well, you can download a single JS package with everything you need, as always, on the download page. You can dig into the docs and demos at the new dev.clientcide.com. Finally, you can get it all on github:

But if you want to be really cool, you’ll just check out the development environment and run it locally. It’s what all the kids are doing these days.

Etcetera

I’m excited to release all this stuff finally and hope that you find it useful. Some of it may migrate over to official MooTools status, but maybe not; we’ll see. If you find yourself using these things please give me feedback and maybe send me a pull request to make it better. Getting involved in helping the code grow is the fastest way to ensure it meets your needs and that I keep working on it.

17 Responses to “Clientcide 3.0, Behavior 1.0, MooTools Development, and so much more”

  1. arieh Says:

    Very cool!
    I’ve just finished working on an article detailing my own experience with Behavior… though it seems like there were some (just looked at the repo) *HUGE* changes since the last time I pulled the repo, so I guess I’ll have to look into it before publishing it.

  2. arieh Says:

    A thought about the Delegator api – I don’t quite understand why you should use it. What I found so appealing about behavior was that it adds a level of separation between the sever and the client. The server doesn’t acknowledge the client’s logic. it only supplies extra data which might or might not be used.
    the trigger API however actually involves writing logic in the HTML, which is not very far from writing actual JS. it seems like a limited version of writing inline-events (I know it’s not quite the same since you can turn it on and off).

  3. Aaron N. Says:

    Using Delegator has a few benefits. First, delegation itself is valuable because you can update the document with new links or forms and not have to attach new events to each one. Second, if you’re building your app well, it should gracefully degrade w/o delegation. For example, let’s say you have a to-do list that lets you add and remove items from the list. The links to remove an item, when clicked, can go to the server and delete the item and load a new version of the page with the item gone without JavaScript in the equation. You can then gracefully degrade this behavior by having the link do so via AJAX and then remove itself from the view with a sweet animation. But you have to write this “glue” code. You could use Behavior for it, but you’d attach an event to each and every link. Delegator is basically Behavior that gets invoked at event time.

    The whole point of Behavior is not to separate client and server but to enable presentation data (HTML) to invoke function (Classes) in a way that puts the connective tissue is in the presentation layer instead of a domready function somewhere else. It makes that “glue” code reusable and portable. If you don’t include events in that system, then you still need that domready code. Its not inline-events either. It’s inline behavior.

  4. Sunny Says:

    No DatePicker anymore? :/ Hm, not that good. But i love Behavior! Nice idea. Thx for all your (hard) work!

  5. Aaron N. Says:

    My datepicker, frankly, sucked. There are far better ones in the forge and frankly I didn’t want to take the time to rewrite mine. It was a pain in the ass to author the first time.

  6. Thomas Allmer Says:

    Behavior sure looks awesome and as far as I can tell I will definitely try to use it :)
    yet another awesome way to reduce complexity for the people using it :)

    However one drawback I see is that using it won’t allow for a valid W3C document as it will at least use one not standard html attribute named data-behavior=”…”

    However I guess that’s a small price to pay compared to the benefits you get :)
    Still something worth mentioning :p (and I guess there is no way to overcome this “problem”)

    thx for this fine piece of “coding style” – will hopefully change the way I write JavaScript (again :p)

  7. Stefan Galinski Says:

    Hi Thomas,

    The document will validate if you are using HTML5. The new standard introduces custom data attributes to store private data directly in the HTML/DOM.

    http://www.w3.org/TR/html5/elements.html#custom-data-attribute

  8. Tim John Says:

    Looking good! I’m very much looking forward to getting into these Behaviours.

    Unless I’m missing something, your packager application doesn’t offer any compression. Is this something you can implement?

    Cheers!

  9. Aaron N. Says:

    I’m using the packager-web app from the mootools team found on github (https://github.com/kamicane/packager-web). I’ve built 3 of these packagers myself and now that there’s a semi-official one, I’m using it. It does support compression, but it uses YUI’s java implementation and my host (bluehost) doesn’t support executing java, so I’m SOL. You can always download the packager and use it yourself, you can also download the compressor yourself and use it or use the online version of YUI’s compressor: http://www.refresh-sf.com/yui/

  10. Daniel K. Says:

    Looks very promising! There may be a problem with the packager, however. When I select the entire Clientcide package and download it, the code assigns Autocomplete.Local before Autocomplete is defined. Perhaps connected is the fact that it will allow me to deselect Autocompleter, but won’t allow me to deselect Autcompleter.Local.

  11. Aaron N. Says:

    Thanks Daniel. It’s fixed now.

  12. MooTools Dev App now ships with a builder » Clientcide (Formerly CNET's Clientside) Says:

    […] added a JS builder (similar to what you see at http://clientcide.com/js) to the MooTools Dev App which I wrote about earlier this week. You can see this in action […]

  13. Alex Says:

    Is it possibile to download the full clientcide library as one file without dependences?

  14. Aaron N. Says:

    Yeah, I had a bug in my download builder. I fixed it this morning. Sorry about that.

  15. Daniel K. Says:

    Thanks for fixing the bugs in the builder!

    Hmm… is there some reason you removed the Waiter? Was it not compatible with Mootools 1.3? We’ve been making use of it, so if we upgrade to the new Clientcide, we’ll either have to copy over the old Waiter or find a replacement.

  16. Aaron N. Says:

    Waiter is now Spinner in MooTools More. It’s pretty close to the Waiter class. It’s code signature isn’t a 100% match, but it has all the same features and is if anything easier to use: http://mootools.net/docs/more/Interface/Spinner

  17. Developing MooTools with my Dev App » Clientcide (Formerly CNET's Clientside) Says:

    […] My last few posts have covered the development sandbox I’ve been working on for the last few months. I thought I’d take the time to crank out a screencast of what it does and how you use it. […]