Adding an “include” tag to Underscore.js templates

I use Backbone.js a lot lately, and since Backbone requires Underscore.js, I usually end up using Underscore’s templates rather than introducing another Javascript library dependency like Mustache templates. But Underscore’s micro-templating language has an omission that bothered me today: templates can’t include each other.

So here’s a quick and dirty <% include %> tag for Underscore templates:

As you can see, the code simply replaces tags like

with the contents of the element with id “foo”. Use it by throwing code like this into the body of your HTML page:

And in your Javascript code, do this:

Enjoy! I leave as an exercise for the reader:

  1. Cache included templates so the template() function needn’t keep doing document.getElementById().innerHTML for an often-included template
  2. Create replaceable blocks in templates
  3. Pass variables from one template to another

Using jQTouch.js with iButton.js

jQTouch is a jQuery-based Javascript library that simulates an iPhone-like interface using only Javascript and HTML5. It’s designed for WebKit browsers (Safari Desktop, Safari Mobile, Android, Chrome) but is adaptable to Firefox with little work. (Don’t ask about IE.) By default, it renders HTML like this:

<span class=”toggle”><input type=”checkbox”></span>

… as toggle switches, like this:

 Another library, iButton.js, provides similar functionality but has some advantages: it works on all browsers, you can easily togglify your checkboxes at runtime, dragging laterally across the control with your mouse or fingertip works as expected, and frankly it makes prettier toggles:

So you might be motivated to combine jQTouch with iButton.js. It should be simple — just remove all the <span class=”toggle”> tags and run iButton’s initialization method — but you’ll run into some troubles. (If you don’t believe me when I say “troubles”, skim this discussion.)

So, here’s the precise problem with combining these two libraries.

When jQTouch initializes, it styles every top-level div with display=none, except for the currently showing div. Here’s the CSS rules it uses:

This way jQTouch can treat top-level divs like screens (for you iOS devs, that’s a UIViewController) in an iOS app, hiding and showing them according to where the user is in the navigation stack.

When iButton.js initializes, it wraps every checkbox with its fancy toggle-control HTML, and then it measures the width of the HTML it created so it knows how far to slide the toggle control when a user clicks on it.

Alas, it’s impossible to measure the width of a hidden element. First jQTouch hides all but the current div, then iButton tries to initialize all the toggles, and it thinks they’re all zero pixels wide.

My solution is to wait for jQTouch to display a page before I run iButton on the checkboxes in that page, like so:

_.uniq() and _.each() are from underscore.js. I use _uniq() to ensure I don’t bind the event handler multiple times to pages with multiple checkboxes.

A final note: if you create checkboxes dynamically after the page has loaded, you must call $(my_new_checkbox_element).iButton() on them, once they’re visible, to ensure they get the proper toggle-switch behavior.