HTML and CSS Reference
Chapter 10, Feature Detection, provides a solution for the script-side of “Do not
make assumptions” and Chapter 6, Applied Functions and Closures, went over some
techniques that help “Play well with others.” Test-driven development, as described
in Chapter 2, The Test-Driven Development Process, and the examples in Part III,
for the most part takes care of “Work for the next developer.”
“Understanding Events” advises to use event handlers to decouple code. Heil-
mann promotes event delegation as an excellent technique to write lightweight
scripts with loose coupling. Event delegation takes advantage of the fact that most
user events do not only occur on target elements, but also on every containing el-
ement above it in the DOM hierarchy. For instance, given a tabbed panel, there
really is no need to attach click events to all the tabs in the panel. It is sufficient to
attach a single event handler to the parent element, and on each click determine
which tab caused the event, and activate that tab. Implementing events this way
allows for much more flexible APIs, as for instance adding new tabs will not require
any event handler logic at all. Reducing the number of handlers reduces memory
consumption and helps build snappier interfaces.
“Find your hooks and relationships” and “Leave traversing to the experts”
both deal with separation of concerns. By describing documents using rich semantic
HTML, there are lots of natural hooks inherent in the document. Again, imagine a
tabbed panel; certain markup patterns can be discovered and converted to tabbed
panels if necessary script support is available. CSS can keep separate styles for
“enabled” and “disabled” scripted tab features.
9.2.1 An Obtrusive Tabbed Panel
In contrast to such clean separation, consider the horribly obtrusive, yet disappoint-
ingly common tabbed panel solution presented in Listing 9.1.
Listing 9.1 An obtrusive implementation of a tabbed panel
<span class="tabs-nav tabs-selected"
style="float: left; margin-right: 5px;">
<span onclick="tabs = $ ('#cont-1 > .tabs-nav');
var className = $ (this).attr('class');
var fragment_id = /fragment-\d/.exec(className);