March 30, 2007

When it comes to rich graphical interfaces, we’re currently being swarmed by all these big and small players readily available on the net – there’s Script.aculo.us, YahooUI, Yui-Ext, Moofx, to name a few of the most prominent. All’s fine and dandy until you try coding some of the stuff inside views of actions.

Now there a number of ways in which you can code with these libraries. The quick’n'dirty approach would be to have the whole code inside the *Success.php template files, which is messy, but gets the job done. Wreaks havoc on screen readers, but hey, if you’re building an application that _REALLY_ need some rich widget components, you’re working on a user interface that would be too complicated for people with impaired vision to use anyway.

But, since that’s a nightmare to debug and, well, let’s face it, look at, we decide to clean up most of the inline Javascript and try to move the code into separate JS files. Here we hit a snag – so how do we include those separate JS files?

One way would be to include the files at the top of the template file, which would make it load when the site displays the template. If you’re using a quirky connection or just a slow proxy, you might get the page loaded up to a header, then have to wait until the Javascript loads, and then have the page display down to the end of it. Sure, after the first load there’s no wait, since the cache takes over, but what if the Javascript is so bloated it takes forever to load it (remember, when it comes to application responsiveness, seconds matter)?

So we move up and explore our options. Since Symfony enables us to manipulate the response on the action level, we could in fact add the appropriate Javascript file inclusion:

Okay, so we’re not bloating the view template. Excellent. One problem though – the model shouldn’t contain display logic. Ouch. Back to square one.

Let’s go a level still further up. One of the first things you learn is that Symfony has configuration files that handle things like page titles, content types, included files, etc. It’s called the view.yml file and it could well solve the problem for us. By creating a view.yml file inside the config directory of the current module, you can specify the Javascript file inclusion using simply a javascripts: directive for the action in question:

someRichGuiAction:
javascripts: [some_rich_gui]

This will append the some_rich_gui.js file to the action and take care of the inclusion for you.

The only problem left is how do you organize all these stray Javascript files in your application. One way would be to create subdirectories in the /web/js directory with the same names as the modules, with action names as the names for the Javascripts, and voilá! we have convention over configuration, which is the driving force behind Symfony itself.

But, here’s where it ends, for now. This is where we come to the point where we have to ask ourselves just how streamlined do we want to have our efforts made. If the application development time justifies building a Javascript autoloader via convention, then you could write up a filter inside Symfony that would add appropriate Javascript files if those existed (kinda analogous to the .yml files located in the optional config directories on the module level). If not, just use the solution provided above – should work pretty well, even if you have to write up 10 different action views containing rich GUIs.

If you are seriously considering writing up such a filter, might I pose a different question: do you really need such a complicated GUI?

@Fet:
You are correct. Here, I’m assuming you’re using Javascripts for most of the actions you’re writing GUIs for, so the Javascrips would be different anyways. You could, for example, use the view.yml to compound different Javascripts to form the GUI, if the GUI itself is modular and can be assembled like that. That way, you could have files assembled by the view.yml file and not have to worry about it neither in the action nor the template itself.