Code On Fire Passionate About Cool Code

19Jul/090

DOM Events Not Enough

With the move towards Web2.0+ technologies, more and more websites are employing JavaScript to create in-browser applications. User actions are dealt with as DOM events to which you can attach functionality.

In this model it is fairly easy to write small interactive sites. It becomes a pain to code larger Web2.0 type applications in this framework. There are several reasons for this:

  • DOM Events are not semantically meaningful in the context of your application. Essentially, one is forced to write a user action response engine rather than an application. A button containing an onClick event tells me nothing about what it means when I click that button.
  • An interface event might change it’s behaviour depending on the application state. This is still doable in the normal browser event model, but it becomes more and more tangled as your application become more complex.
  • DOM events make it difficult to implement the MVC model. To simplify the code, it is often easier to directly link interface events to the actions they must trigger. This can lead to code where an onClick event contains a function that fetches XML from the server, parses it, and displays it at the correct place on the interface. As your application grows it becomes more and more difficult to follow the code process.

Multiple Languages

Whenever we are dealing with intelligent web-based applications, there are usually quite a few languages involved. The application intelligence is split up between HTML, JavaScript, CSS, Java, Flash, PHP, ASP, SQL and others. This can lead to very tangled code that gets increasingly more difficult to understand as the complexity of your application grows.

It is becoming more and more important to find creative ways of marking your code in order to be able to easily follow the flow.

Web Applications – More Than Just Interactive Websites

Right at the beginning of the Web2.0 revolution, JavaScript and AJAX were used very sparingly and mostly just for interactive enrichment. Those days are over. Users have become accustomed to and are expecting full blown applications running in the browser.

Add to that the general expectation that whatever is in the browser, should be customizable to suit the needs of each and every individual user that pops by for a visit, and you have a recipe for an explosion of source-code.

In this environment, dealing with DOM events become even more of a nightmare.

Semantic Events – A Possible Solution?

In my personal journey toward complex web-based applications, I have found a way to simplify the process and bring scalability back into the picture: Abstracting towards a flexible event delegation model.

How does this work: simple really.

I start off with a JavaScript object I created that manage semantic events. I will discuss this in detail a little later. First let me explain the process of handling a DOM event using my semantic event engine.

Step 1 -  Map a DOM event to a semantic event

Instead of calling the intended function straight from my ‘onClick’ event, I map it to a semantic event:

<a href=”Javascript:;” onClick=”sEvents.trigger(‘request_more_contact_info’);”>Contact Us</a>
Step 2 – Create the function that will deal with that event
function handleMoreContactInfoRequest(){
// Call AJAX handler to get the info requested
// Call the UI handler to create a new modal popup box
// Populate the modal box with the AJAX response received
}
Step 3 – Make my handler function listen to the semantic event
sEvents.listen(‘request_more_contact_info’,handleMoreContactInfoRequest);

Application Triggered Events

At first this might seem like a longer way of doing things. I could just as well have called my handler function directly from my onClick event.

For a simple example like the one above, you may be right. When the scope of your application grows, however, it becomes a lot more manageable to use a semantic event dispatcher.

One example of this is how you can modularize your code using application triggered events.

Let us take the previously mentioned event handler and modify it slightly.

function handleMoreContactInfoRequest(){
sEvents.trigger(‘ajax_request_started’);
// Call AJAX handler to get the info requested
sEvents.trigger(‘ajax_request_ended’);
// Call the UI handler to create a new modal popup box
// Populate the modal box with the AJAX response received
sEvents.trigger(‘handleMoreContactInfoRequest_completed’);
}

Now we have expanded the scope of events beyond basic browser DOM events. We now have application level events that can delegate tasks to any listeners bound to the relevant semantic event. If, for instance, I wanted an indicator showing when an ajax request is under way, i could create a function to show and hide the indicator and bind them to the ajax_request_started and ajax_request_ended events respectively.

Multiple Listeners

The event manager I wrote has support for multiple listeners to any given event. This makes augmenting interaction an easy task. I only need to add a listener in order to extend it’s functionality.

Usually when an extension of this nature is needed, it makes for messy code. I might have to do some ui related stuff, ajax stuff and also DOM updates & datastructure modifications every time a certain button gets clicked. Using the straight-forward DOM event method, I would either have to include all those functions in my onClick event, or I would have to include those functions in my event handler.

With event delegation and semantic events, you can organize your application in a structure that is logical to you without losing any functionality.

Code Modularization

One of the major benefits I find with using this method: I can now replace, maintain, upgrade, extend or completely change the way a particular event is dealt with very easily.

When calling a function directly from a DOM event, one is allowed a lot of freedom with regards to what information you pass along. This seems convenient in the beginning, but later on when you want to make changes to your application, this turns into a nightmare.

Having an event delegation model forces you to always pass information to the event manager in the same format. And the event manager will call the event handlers in a standard way. This forces one to stick to a convention when dealing with user-interactions and even application-initiated events.

Ultimately, it is this convention that saves you time in the future. Event handlers now all have the same inputs. And event triggers always look the same. Which means it becomes a lot easier to replace portions of your code or do site upgrades. It also makes documenting your software a lot easier.

HTML is largely a semantic markup. It is human readable for the most part. Adding semantic events that relate not to what the user did in the browser but rather what the user is trying to accomplish, fits in well with the semantic nature of HTML. This means, your web designer doesn’t need to know anything about the underlying work of the web developer to be able to effect changes on the interface. Events are now semantic, readable and easy to call. And they never need to change, no matter what happens in the underlying engine. There’s a huge business implication there.

Hard to Reach Browser Events

Using this event delegation model, it also becomes a lot easier to deal with hard-to-reach browser events. In my event delegation engine, I have most of these browser events automatically included in case my application needs to access them. If, for instance, I need to know when the mousewheel is being scrolled, I just attach a listener to the ‘browser:mousewheel’ event and my application can make use of it.

Want to disable the right click button in the browser?… easy:

sEvents.listen(‘browser:mouse.click.right’,function(){return false;});

Want to capture CTRL-ALT-LEFTCLICK:

sEvents.listen(‘browser:mouse.click.left|key_ctrl,key_alt’,function(){alert(‘you just CTRL-ALT-LEFTCLICKed’);});

aFrame – The Javascript Client-Side Application Framework

By now, some of you might want to have the code to this event manager. It is part of a larger framework intended to make writing enterprise level in-browser applications a lot easier. This framework is called aFrame and it not yet ready for alpha testing.

If you would like to receive word when this framework is ready, you can subscribe to the announcement list below.