Using Raphael.js and Backbone.js together

I'm a big fan of Backbone.js. It's lightweight enough to throw into any webapp I'm building, large or small. At the very least it gives me some guidelines on how to organize my code. In larger apps the synchronization with the backend makes my life a lot easier.

An app I'm currently working on makes heavy use of Raphael.js, a great SVG library. In order to unify my handling of user events, I extended the Backbone.js library a little. It's a simple change, but I really like what it did to the organization of code.

class Backbone.RaphaelView extends Backbone.View  
  delegateRaphaelEvents: (elements)->
    for name,element of elements
      @delegateRaphaelElementEvents name, element
  delegateRaphaelElementEvents: (name, element) ->
    events = [
      "mouseup"
      "mousedown"
      "mousemove"
      "mouseover"
      "mouseout"
      "click"
      "dblclick"
      "touchcancel"
      "touchend"
      "touchmove"
      "touchstart"
    ]
    for event in events
      element[event] (e) =>
        @.$el.trigger "raphael:#{name}:#{e.type}", e

class Box extends Backbone.RaphaelView  
  initialize: ->
    @paper = Raphael 10, 50, 320, 200
    @box1 = @paper.rect 10, 10, 25, 25
    @box2 = @paper.rect 50, 10, 25, 25
    @circle = @paper.rect 50, 50, 40
    @delegateRaphaelEvents
      box1: @box1
      box2: @box2
      circle: @circle
  events: ->
    "raphael:box1:click"  : "hello"
    "raphael:box2:click"  : "goodbye"
    "raphael:circle:mouseover" : "foo"
  hello: (j_event, r_event) ->
    alert "Hello"
  goodbye: (j_event, r_event) ->
    alert "Goodbye"
  foo: (j_event, r_event) ->
    console.log "mouseover event"

As you can see, my goal was to be able to address user interaction with Raphael object in the way I can address interaction with the DOM. DOM events can be specified under events via a <selector> <event> syntax, so one can do .button click or #myElement customEvent. Since Raphael abstracts out the DOM from the SVG objects, I wanted to preserve the Raphael events but be able to throw them in with DOM events. So the delegateRaphaelEvents method converts Raphael events to DOM events in the form raphael:<object name>:<event>. The assigned callback function gets passed two objects, a jquery event object and a raphael event object.

It works great and keeps my code well organized.  Enjoy!

comments powered by Disqus