In my years of working with JavaScript I’ve seen kind of a natural progression to how I’ve scripted elements within pages. In the beginning, I just kind of wrote some javascript, put it in a function, and attached it with an event on the element itself. So around 2001 or so my scripts looked a lot like this:
1 2 3 4 5 6 | |
As time moved on the idea of unobtrusive JavaScript took hold. The idea
was that we shouldn’t use those fancy onclick attributes since they
dirtied up our markup, but should instead attach the events. I used
Prototype in those days, so my code looked something like this:
1 2 3 4 5 6 7 8 9 10 | |
That was probably 2006 onward for me.
In general, going unobtrusive cleaned up my document a bit, but there
was still a mess of code in the document, it was just hidden elsewhere.
Within the past year or so the way I handled that was to switch to a
series of backing objects that I included in external script files. I’d
instantiate those objects in a script tag in my document, but all the
rest of the code would be stored in scripts outside the document. At
that point, I had moved on to using jQuery. My code
started looking something like this:
1 2 3 4 5 | |
1 2 3 4 5 6 | |
This example is crazy simple, but hopefully you get the idea. Using objects was the right direction, I think, because they gave me a nice bundle for a feature or page’s functionality, but something still felt wrong.
In our latest design refresh of Treehouse,
I started using CoffeeScript rather than JavaScript, and I
started bypassing the script tag in the document and instead just
detecting elements that should have features attached to them. It looked
something like this:
1
| |
1 2 3 4 5 6 7 8 9 10 11 12 | |
I liked this technique when it was for code that I really wanted to apply to every page, but there’s a tradeoff with the technique - it really stinks if you’re detecting a lot of different types of features because a lot of times you’ll call the detection code and nothing matches. That problem lead me to write Featurette.
The idea behind Featurette is that you define new classes representing
features you want to attach to elements and register them.
Any time you want to apply a feature to an
element in your document you give it a class of featurette and add
the data-featurette attribute with the name of the feature you want to
add. Let’s look at how the ClickMeThingy example above would be
implemented with Featurette.
1
| |
1 2 3 4 5 6 7 | |
When the document loads up, Featurette searches for all elements with
the featurette class and instantiates registered objects based on
the data-featurette attribute. Using a class name to find elements that need features attached
ensures that performance stays super fast, thanks
to the DOM’s getElementsByClassName function. It’s a little more markup than
is ideal, but it keeps things fast and it gets rid of the script tags
that plagued my older solutions and the extra document searches that
came with my original attempt at detecting when code should be attached
to elements.
We’ve just started using Featurette with Treehouse, but so far it’s working great. I’d love to hear what you think of it! If you find any issues, please report them in the GitHub issue tracker, and if you have any questions feel free to email me or tweet at me.