Attaching Behavior to Content Using CSS Selectors

Author: Ron Lancaster 
Date: August 5th, 2005

Summary

Similar to using CSS for HTML to separate style from content, we can use Behaviour.js to separate javascript behaviors from content. This means content is more readable and that javascript can be contained in separate files providing modularity and reuse.

Referrers

Article

In web coding today, there is a heavy emphasis on separating style from content. In other words, you don't use font tags to style the text. Instead, you use CSS to make your words come alive in ruby red with a fire graphic underneath.

With the advent of cross-browser support for XMLHttpRequest (the engine behind Ajax if you're cool, DHTML if you're old school), we now have started seeing a resurgence in using javascript to control the behavior of the content. Examples include:

  • showing/hiding content,
  • the Yellow Fade Technique (YFT) where the background of new content added to the page fades from yellow to transparent,
  • and the holy grail of today - dynamically requesting HTML or XML and inserting the result at points on the page.

The most common and reliable way of attaching behavior to an element is through the Traditional Event Handlers (term of art coined byQuirksmode). So, the easiest way to attach an event is with the inline event registration. Example: <a href="somewhere.html" onClick="alert('I\'ve been clicked!')">. However, this example is bad style since it mixes code with our content. For styling, we use CSS to separate style from content. For javascript, we use Behavior.

Behaviour.js is a small script introduced to the community under a BSD license by Ben Nolan. [1] The driving idea is that you can identify the elements you wish to attach behavior to through CSS selectors. This coupled with passing a function pointer allows you to attach behavior to arbitrary elements in the page DOM.

Instead of:

<li>
  <a onclick="this.parentNode.removeChild(this)" href="#">Click me to delete me</a>
</li>

Your markup remains:

<ul id="example">
  <li>
    <a href="/someurl">Click me to delete me</a>
  </li>
</ul>

Then, in a separate script, you can provide the behavior using CSS selectors.

var myrules = {
  '#example li' : function(el) {
    el.onclick = function() {
      this.parentNode.removeChild(this);
    }
  }
};

Behaviour.register(myrules);

The above example is saying to execute the provided function once for each element that is an "li" tag and that is a descendent of the element with id = "example". In this case, only one element matches. The function would be invoked a single time at page load and is passed the matching element(s). In this case, the provided function sets the onclick event handler to a an event handler that removes the current element.

Finally, if you modify your DOM, then calling Behaviour.apply() will reapply the rules.

Update: I've modified this implementation to use cssQuery. See Modified Behavior for details.

[1] "Using CSS selectors to apply Javascript behaviors." Ben Nolan, June 2004. http://ripcord.co.nz/behaviour/.