ModelBinder in Coffeescript 2

Exploring Data Changes when clicking Input field.

by amorris

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.modelbinder/1.0.5/Backbone.ModelBinder.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.modelbinder/1.0.5/Backbone.CollectionBinder.min.js"></script>
This is a simple example that shows how to use the ModelBinding with coffeescript.  Futher, it shows how to update one data attribute in the model in multiple ways. In this example, changes to both sales and sales per square foot are stored in the sales attribute.<br/>
<br/>
Note, for a table with multiple rows, the CollectionBinder can efficently handle the same bindings for multiple rows.
<hr>
<div id="viewContent">

</div>

<script id="my-template" type="text/x-underscore-template">
    <table id="sales_table"  border="1" cellspacing="1" cellpadding="1" summary="table">
      <thead>
      <tr><th COLSPAN=4>Sales Table</th>
      <tr>
        <th>Year</th>
        <th>Sales</th>
        <th>Sales/PSF</th>
        <th>GSF</th>
      </tr></thead>
      <tbody>
        <tr>
            <td name="year"></td>
            <td><input type="text" name="sales" viewFn="one"/></td>
            <td><input type="text" name="sales_psf" viewFn="two"/></td>
            <td><input type="text" name="gsf" viewFn="three"/></td>
        </tr>
      </tbody>
    </table>
</script>

CSS

#sales_table td { text-align: center }
#sales_table th { text-align: center }
#sales_table td input { text-align: center }

CoffeeScript

$.app = $.app || {}
$.app.MyView = $.app.MyView || {}

$ ->
  class MyObject extends Backbone.Model
    defaults:
      year: 1
      sales: 2000
      gsf: 100
      
    # Don't allow GSF < 1 to bypass division by zero errors.
    setGSF: (gsf) ->
      if gsf >= 1
        @set('gsf',gsf)
        return gsf
      else
        @set('gsf',1)
        return 1
      
        
  class MyView extends Backbone.View
    el: '#viewContent'
    template: _.template($('#my-template').html())
    
    initialize: ->
      @modelBinder = new Backbone.ModelBinder()
      @render
        
    close: ->
      @modelBinder.unbind()
        
    gsfConverter: (direction, value, attribute, model) =>
      if direction == 'ViewToModel'
        value = model.setGSF(value)
        @modelBinder._copyModelToView(@modelBinder._attributeBindings['sales'])
        return value
      else
        return value
        
    # Playing with focus in and focus out of inputs to change the value in the input
    # based on whether the user is editing the input or not
    salesConverter: (direction, value, attribute, model, boundEls) ->
      if direction == 'ViewToModel'
        if $(boundEls).is(":focus")
            console.log('v2m-f: '+model.get(attribute)+' vs '+value)
            return model.get(attribute)
        else
            console.log('v2m-o: '+model.get(attribute)+' vs '+value)
            return value
      else
        console.log($(boundEls))
        if $(boundEls).is(":focus")
            console.log('mtov-f: '+model.get(attribute)+' vs '+value)
            return value
        else
            console.log('mtov-o: '+model.get(attribute)+' vs '+value)
            return '$'+(value/1000).toFixed(1).toString()+'k'
        
    salesPSFConverter: (direction, value, attribute, model, boundEls) ->
      if direction == 'ViewToModel'
        return value*model.get('gsf')
      else
        return value/model.get('gsf')
        
    render: ->
      window.appModule = @model
     ...