Writing Humble Javascript
Saturday, December 30, 2006Humble Javascript is the ideal I subscribe to when developing Javascript. I define an ideal as a benchmark by which you measure your decisions and actions. It's not a set of hard rules and frankly it's almost always unreachable, but in attempting to get as close as possible you often produce a good outcome. Humble Javascript follows the ideal of Unobtrusive Javascript but is not the same. There are many ways to write Unobtrusive Javascript . Humble Javascript is all about respect - respecting what Javascript does best as well as respecting XHTML and CSS.
Introduction
When building web interfaces one must respect the '3 layers' and the roles they play: XHTML for content, structure and semantics, CSS for presentation and Javascript for behaviour. When constructing the behaviour layer using Javascript one must keep it Humble, it should not impose itself on the semantic layer by requiring you to add non-semantic XHTML tags or attributes. Neither should it attempt to exert control over the presentation layer, that's the job of CSS. Humble Javascript understands its place in the platform and respects the role of the other two layers. Writers of humble Javascript understand its role and do not fail to use it for what it does best.
One of the strengths of the web interface is it's portability. Each layer can be made completely portable between webpages and interfaces. However, failure to seperate the 3 layers decreases their independence. If you start polluting your XHTML with behavioural logic then it becomes less portable, so does your Javascript if you include presentational style information. The ideal of Humble Javascript suggests you should be able to remove the javascript altogether and still have a completely functioning page. Similarly removing the CSS should not leave a dysfunctional page.
The Hooks
When you start to think this way you notice how easily it comes together. It seems almost natural. The semantic layer is the basis for any web interface and the only indispensible layer, the other two layers are applied over the top. XHTML has ready-made hooks for for just style of use, making applying the other two layers a little easier: The tag, the ID and the class.
| Hook | XHTML | CSS | Javascript |
|---|---|---|---|
| Element tag | <tag /> | tag {} | document.getElementsByTagName('tag') |
| Element ID | <tag id="id" /> | #id {} | document.getElementById('id') |
| Element Class | <tag class="class" /> | .class {} | element.className |
The Guidelines
Often all Humble Javascript amounts to is a few simple guidlines:
- Avoid manipulating CSS in javascript
- Avoid adding non-standard attributes or elements to XHTML
- Avoid co-opting standard XHTML attributes contrary to the purposes for which they were indended
- Avoid behavioural effects in CSS
In use it means:
- Make the most of changing element class names instead of style properties.
- Use the tag, ID and class as much as possible.
- Respect standard XHTML elements and attributes, they already have important roles to play and you may be breaking accessibility if you misuse them - XHTML already has implied semantics, use it.
- Use javascript for all behavioural/logical operations.
Examples
The Humble Javascript ideal came about when writing my Real Easy Validation library . My first goal was to make validation as simple and unobtrusive as possible. So I made the most of the elements' class names to describe the validation requirements and then Javascript to describe the logic. Which worked well for simple things like 'validate-number'. But sometimes validation requirements are more complex, for example, if a number is between a minimum and maximum amount. The temptation is to add this logic to the XHTML and keep the Javascript generic. For example do things like write complex class names - 'validate-number-min-10-max-100', or to add custom XHTML attributes - min="10" max="100". I had many emails suggesting these approaches and a few people even extended the library to do this for their own purposes.
However, As a strong believer in semantic XHTML this just didn't feel right because you are removing logic from javascript and adding it to XHTML. Logic is what Javascript does best and XHTML should be left to handle semantics. So according to my ideal I'd simply create a custom class name like 'validate-score' making sure it was a meaningful name relative to my needs and leave the min/max stuff to a custom Javascript validation function. 'validate-score' is a meaningful class name that is easily portable between webpages. In our example here 'validate-score' is a number value between 10 and 100, the logic of which is defined in a single javascript validation library. If the conditions of 'validate-score' change and we have several forms that utilise this concept we have saved that mangement overhead say if we'd instead used XHTML element attributes to define the minimum and maximum: it need only be changed in one spot, the javascript library, instead of the XHTML for each form. It can also be repurposed for other things like CSS (to make 'score' fields look a certain way) or other behavioural Javascript functions (to add a score slider control to each score field).
Benefits
The benefits of Humble Javascript become clearer the more you use it. I find the resulting web interfaces are accessible and compatible to a high degree and often in ways that are surprising. For example, you might find that your web interface offers a highly usable experience through a PC web browser and when you test it on a mobile device you happily discover it works perfectly fine there too.
Humble Javascript does not degrade the browser experience. For example if you use my table sorting script with Javascript turned off and CSS enabled you will find the XHTML table still works just fine. Similarly if you turned off the CSS and enabled Javascript, table sorting will remain functional.
I also find it makes managing a website easier when all the XHTML, CSS and Javascript sources are kept seperate. Fiddling about with CSS in javascript or logic values in HTML is just impractical.
Counter-Examples
There are many Javascript libraries and widgets available on the web. Some libraries are written so that everything is done in script, others remain generic so that all logic is done in XHTML. Also when making a javascript library for common use, one always has to consider how much work to make the implementer do to use it, some libraries are written for people comfortable using javascript and some for people who don't want to write any. I prefer to encourage a balanced approach - to write Javascript where appropriate and to use XHTML and CSS effectively.
The Fuzzy Bits
Obviously, as an ideal, strict adherence is not realistic and possibly silly, There are a few areas where the 3 layers overlap. For example if moving an element or creating a transition effect manipulation of CSS must be done in Javascript. Sometimes the use of ':hover' in CSS is desirable. And XHTML offers a few important behavioural elements like the 'label' element.
That's It
Well, there you have it; the (long-winded!) reason why I write Javascript the way that I do. I get a lot of emails and comments asking 'why dont you...' and I intended this post to be an explanation of why I don't. For me this just works. It feels like the right way, the natural way to create web interfaces that work well.
Some of my inspiration comes from:
6 Comments
Hi Andrew,
I came to you in the first place exactly because of the way you make JS, CSS and XHTML work nicely together - in fact, using each technology for what it is meant to be used, and not against it. It sounds normal, yet not many achieve in doing it as elegantly as you.
Very glad to read a good breakdown of the thinking behind.
Some useful information here. Thanks.
I'm trying to develop an online questionnaire in such a way that the total score of all the variables (questions) is added at the click of a button. Are there any free scripts that might give me a clue that you know of?
You emailed me yesterday, but I get an error message each time I try to respond. My enquiry from yesterday was genuine. Found a partial solution after leaving my post here. Hoping I can work out the last bit!!
I have attempted to implement Javascript in a stress survey, but get "Expected J" and "Expected Object" errors. Wondered if you could offer some guidance?
Survey is located at www- -dot- longerstrongerliving - dot - com/stresscalc.htm
"Total Score" box will not display sum of responses.
Hi Lewis, you should avoid naming a field with a number. called them a1, a2, etc. Also the eval()s are not needed.
Many thanks Andrew. I would have had no hope of picking this!
Appreciate your time and help.