The problem

Javascript usually applies behavior to elements on page load. Usually, there’s a list or some sort of registry of behaviors, and it’s iterated through on document ready time, and applied then. For elements that get created by javascript though, behaviors don’t get automatically applied to them. The application of those behaviors happens only at document ready time, and new elements don’t get processed magically.

Opencore’s solution

We’ve handled this in the past by explicitly calling a generic function that would apply the behaviors to elements. So when a new element was added, we would follow up the addition with an explicit “breatheLife” call. This worked, but we had to remember to call the breatheLife function every time we added elements that we wanted particular behaviors attached to.

Jquery solution

Jquery has a particular solution for this problem for a particular subset of behaviors: live events. The solution however, is a little bit different from ours. Instead of applying behaviors to new elements as they are attached to the dom, jquery gets the event as it bubbles up, and then figures out if its coming from an element that has special behavior. This technique is called event delegation. Currently, not all event types are supported, but a common set are.

Other applications

Using event delegation is also useful for situations when there are a lot of elements that need behavior applied to them. For example, if we had a huge table of links, or a large number of list items, we could add a handler to the table or unordered list, and figure out the target of the event from there. Instead of adding an event handler for each element, we can get away with only adding one that can handle all of the elements.

Filed June 26th, 2009 under best-practices

­Almanac ui

We’re nearing the end of another community almanac development cycle, where we changed the ui quite a bit. Here are some of my thoughts on it.

The operation that we wanted to optimize for was contributing a page to an almanac. We used to call them “stories” but we tried to stress the book/page metaphor a little bit more now. We also tried to make sure that adding a simple page was very easy, while also providing flexibility for the user.

Previously, we had taken a wizard-like approach for this case. A user was presented with a series of questions, taking them through the process of adding their story. This forced the user to go through the process of adding a story in a very strict way, and presented more questions to the user than was usually necessary, at least for the simple cases.

A different approach

This go around, we took an approach that feels a bit like basecamp. Instead of providing a wizard, or series of questions that the user should enter, the user is presented with a set of tools that control the type of content that the user is contributing. This allows the user to add the type of data that they are interested in, without forcing the concept of “metadata” to the user.

An advantage with this model is that it offers more flexibility for creating pages. Users can add the types of data that they want, in a way that makes the page flow more naturally. They can now have several locations, descriptions, or none at all. It also feels a lot more like what the site should be all about: adding pages to a community’s almanac.

Under the hood

Implementation wise, this means that we have to be able to generate lots of forms on demand through javascript. There are a couple of ways to manage this, but we decided to have the server generate these forms, and the client side would issue ajax requests to send/receive all data. This keeps the javascript simple, with the server handling most of the logic.

This is similar to how we handled opencore’s javascript. The client sends a request to the server (usually getting the url from an anchor or the form that the object is in), and knows how to handle a couple of different responses in a generic fashion. Usually the variations are simply to take some html returned from the server and put it somewhere, either by replacing an element, or adding it somewhere else on the page.

There was an additional complication on the almanac side, which was that we needed to apply some side effects for the content to be displayed properly. This is sort of like the “breathe life” problem, except we needed it to simply display the content properly, as opposed to interacting with additional events. For example, when a map is returned, some javascript needs to run to display the map correctly, with the right features displayed on it. For audio playback, some flowplayer behavior needs to get applied to it before it can play in the browser through flash. We did also have to tackle adding behavior as well (so the forms that got returned where submitted through ajax), but we were able to use jquery’s live events for a lot of it.

Always something

Since we’re loading a lot of javascript on page loads as well, we ran into an issue where you could click on a link before it got its document.ready behavior applied to it. The user gets presented with a download dialog box, asking to download the json return value. We worked around this by having empty onclick handlers in the markup itself, which prevented the dialog boxes. Ideally we would have non-javascript fallbacks everywhere, but we didn’t focus on dealing with that issue because a large portion of the site deals with map interactions, which isn’t really feasible without javascript. You can say that you can have page loads for each click, like panning or zooming, but drawing features on a map without javascript is tough.

Thoughts for the future

The similarities of the ajax approaches of both almanac and opencore got me thinking if these are both more specific instances of a general pattern. Kss as a solution comes to mind. What worries me about kss however is that it seems focused on completely removing all javascript from the application. But on the other hand, it seems like the concept of applying js behavior to elements in the same kind of way as style is applied to elements is a reasonable approach. And kss is a way of standardizing the behaviors, in the same sort of way that styles standardize on the display. In fact, most of the javascript that I write involves selecting some elements, and applying a simple behavior to them. Behavior will probably vary a bit more than style, but I definitely prefer having a solution for most cases than no solution at all. In any case though, I definitely think kss is a cool concept.

­

Filed June 26th, 2009 under best-practices, programming, ui