Unobtrusive JavaScript Part 2 — Separating Content, Style and Behavior


In my first post, I described some of the major principles that drive UJS style of development.  In this article, I’m going into more detail about separating content from markup.

The Bad Old Days

If you have been around long enough, you’ll remember the days when your only choices for making a web page look half way decent required using Font tags and inline attributes (and don’t forget my personal favorite, the Blink tag) to change the appearance of your content.  If you wanted to have all of your headers to look the same, each one had to be styled manually.  This also meant if you wanted to make a change, every one had to be updated.

The only real tool available for creating a layout was to abuse the <TABLE>.  Nesting tables inside tables inside tables was the really only way to achieve anything more than text and images on the page.  I’m not sure how many times I lost entire sections of content due to missing a closing row or cell tag.

Now that all of the major browser are CSS compliant-ish, these hacks are no longer necessary (I know there now a whole new set of CSS hacks).  You can now remove all styling information from the HTML markup, leaving it to what is good at.  Providing semantic meaning and structure to your documents and putting the style into a separate document that can be applied to all pages on your site.

Semantic Markup

Now it is possible to remove everything from the html markup except for what is needed to fully describe the semantic meaning of the content.  When using html for semantic purposes, you are describing the function of the content, not it’s style or behavior.  Here is an example of appearance driven markup:

<br><br>
<b><font size="2">Widget X</font></b>
<br><br>
<font size="1">Widget X is the greatest things since sliced bread.</font>

This looks something from circa 1998, when these were our only options for putting any kind of design on our web sites.  Hard Line breaks are being created using the
tags, and the tag is being used for styling the text.

Moving to a semantic only would look something like this:

<div id="widgetXContainter">
<h3>Widget X</h3>
<p>Widget X is the greatest things since sliced bread.</p>
</div>

Now the html is used purely to denote the differences in the meaning of the text.  Using a <h3> and <p> tags to describe function, not it’s visual appearance.  You know have free reign or the layout and appearance of the content.

Separating Behavior from Content

When describing the behavior of web pages in the bad old days, we had the same problem.  The only way to really safely attach an event was to do it on the the event attributes on the html itself.  For instance, if you wanted to open a new window, it would look something like this:

<a id="terms" href="javascript:window.open('terms.html','popup‘,'height=500,width=400,toolbar=no’);">
terms and conditions
</a>

We are again mixing functionality within our html markup.  We can clean this up a little bit by using the onclick event to denote what action should take place.

<a id="terms"  href="#" onclick="window.open('terms.html','popup‘,'height=500,width=400,toolbar=no’);">
terms and conditions
</a>

This is better, but we still do not go anywhere without JavaScript and we are still embedding the functionality directly into the markup, mixing semantics with behavior and removing any chance of reuse and maintainability. We can take this one step further  by removing the JavaScript from markup entirely and wire up the click event in the page onload event.  I’ll use jQuery for wiring up the event.  Also, by defining a url for the link, you ensure that functionality will work regardless of the availability of JavaScript.

 

<a id="terms" href="terms.html">terms and conditions</a>
<script>
//onload event
$(document).ready(function(){
    //get a reference to the link using the css id selector syntax 
    //and attach the click event
    $('#terms').click(function(){
        window.open('terms.html','popup‘,'height=500,width=400,toolbar=no’);
        // keep the link from firing
        return false;
    })
});

</script>

 

Now we have achieved our goals.  We separated the behavior from the markup, allowing us to create more modular, reusable scripts (with a little refactoring).  The behavior of the link will work regardless of the functionality of the browser and user configuration. You can also take this one step further by putting the behavior in a separate JavaScript file, allowing the browser to cache the content and further speed up the page load time.

In the next part, I’ll talk more about progressive enhancement and how to incorporate that into your web pages.

Unobtrusive JavaScript Part 1