Rigel Group

They shoot Yaks, don't they?

A Batmanjs Mixin for Cycling CSS Class Names

Recently we needed to cycle through some CSS class names when rendering a Batmanjs template. Something like alternating ‘odd’ and ‘even’ classes on table rows, for example. This turned out to be harder than I had first thought it would be. I tried several approaches, but this was the one that I finally got to work.

First, create a Cycler class. (Using a Batman object for this is probably overkill, but it does give me one more opportunity to type ‘Batman’.)

1
2
3
4
5
6
7
8
9
10
11
12
13
MyApp.Cycler extends Batman.Object
  isObservable: false

  constructor: (@values) ->
    @values = @values.split(',') if typeof @values is 'string'
    @idx = -1

  reset: ->
    @idx = -1

  next: ->
    @idx = (@idx + 1) % @values.length
    @values[@idx]

Now we create the mixin…

1
2
3
4
5
6
7
# Use a global property to hold the cycler, which holds the state
Batman.mixins.cycler =
  initialize: ->
    $node = $(@)
    cyclerName = "cycler-#{$node.data('cycler-name')}"
    MyApp.getOrSet(cyclerName, => new MyApp.Cycler($node.data('cycler-values')))
    $node.addClass(MyApp.get(cyclerName).next())

Now, to use it in your template, you can do something like this:

1
2
3
4
5
<ul>
  <li data-foreach-post="posts" data-mixin="cycler" data-cycler-values="left,right" data-cycler-name="all-posts">
    <a data-route="post" data-bind="post.title"></a>
  </li>
</ul>

Which would render to something like this (leaving out the batman tags for clarity)

1
2
3
4
5
6
7
8
9
10
11
<ul>
  <li class="left">
    <a href="/posts/1">Post 1</a>
  </li>
  <li class="right">
    <a href="/posts/2">Post 2</a>
  </li>
  <li class="left">
    <a href="/posts/3">Post 3</a>
  </li>
</ul>

So, that’s it. As you can see we have to create some global properties, and name them, so that we can have multiple cyclers in the app without conflict. This does bother me a bit, but there are plenty of other dragons to slay, so it will have to do for the time being.