Editable Item List (Mithril + CoffeeScript)

by ramnathv

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/mithril/0.2.3/mithril.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<div class="container" id="main">
  <div class="row">
    <div class="col-xs-12 col-md-6">
      <div id="app"></div>
    </div>
  </div>
</div>

CoffeeScript

myStore =
  todos: m.prop [{task: "Item 1"}]
  editorText: m.prop("")
  itemBeingEdited: m.prop(2)
  textBeingEdited: -> @todos()[@itemBeingEdited()]?.task || ""
  buttonText: -> 
    if @itemBeingEdited() < @todos().length then 'Save' else 'Add'
  editorIsEmpty: -> @editorText() is ""
  onAddItem: ->
    if (@itemBeingEdited() > @todos().length)
      console.log("Adding")
      @todos().push({task: @editorText()})
      @itemBeingEdited(@itemBeingEdited() + 1)
      @editorText("") 
    else
      console.log("Saving")
      @todos()[@itemBeingEdited()].task = @editorText()
      @editorText("")
      @itemBeingEdited(@todos().length + 1)  
  onDeleteItem: (i) ->
    if (@itemBeingEdited() is i)
      @editorText("")
      @itemBeingEdited(@todos().length + 1)
    @todos().splice(i, 1)
  onEditItem: (i) ->
    @itemBeingEdited(i)
    @editorText(@textBeingEdited())

ListItem = view: (ctrl, props) ->
  console.log("Rendering ListItem")
  m "li.list-group-item.clearfix.constraint",
    m "span.pull-left", props.todo.task
    m "span.pull-right", m ".btn-group",
      m "button.btn.btn-danger.btn-xs delete", 
        {onclick: props.deleteItem}, "x"
      m "button.btn.btn-success.btn-xs delete", 
        {onclick: props.editItem}, "-"

ListGroup = view: (ctrl, {store}) ->
  console.log "Rendering ListGroup"
  m "ul.list-group", store.todos().map (d, i) ->
    m ListItem, 
      key: i 
      todo: d
      deleteItem: (e) => store.onDeleteItem(i)
      editItem: (e) => store.onEditItem(i)

TextEditor = view: (ctrl, {store}) ->
  console.log "Rendering TextEditor"
  m '.editor', 
    m 'h4', 'Constraint Editor'
    m 'textarea.form-control', 
      value: store.editorText()
      oninput: (e) => store.editorText(e.target.value)
    m 'button.btn.btn-default.btn-sm', {
      onclick: store.onAddItem.bind(store)
      disabled: store.editorIsEmpty()
    }, store.buttonText()

App = view: (ctrl, {store}) ->
  m '.constraint-editor',
    m TextEditor, store: store
   ...