Tweetbox with Mithril and Mobservable

by ramnathv

HTML

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="//rawgit.com/mweststrate/mobservable/master/dist/mobservable.min.js"></script>
<div class="container-fluid" id="main">
  <div class="row">
    <div class="col-xs-12 col-md-4">
      <div id="app"></div>
    </div>
  </div>
</div>

CSS

#main{margin-top: 20px;}

CoffeeScript

## https://gist.github.com/impinball/5e4d6e64aba2ffb7cd23
## Patches Mithril to accept components as well as strings
@m = ((o) ->
  Object.assign (->
    (if typeof arguments[0] == 'string' then o else o.component).apply undefined, arguments
  ), o
)(m)

{observable, autorun} = mobservable

Model = observable
  text: ""
  disableBtn: -> @text is ""
  remainingChars: -> 140 - @text.length - 23*@photoAdded
  photoAdded: false
  photoBtnText: ->
    if @photoAdded then 'Photo Added' else 'Add Photo'

TextArea =
  view: (ctrl, props) ->
    m 'textarea.form-control', {
      oninput: (e) -> 
        Model.text = e.target.value
      style: {"margin-bottom": "20px"}
    }
    
TweetButton = 
  view: ->
    m 'button', {
      disabled: Model.disableBtn
      class: 'btn btn-primary btn-sm'
    }, 'Tweet'
    
PhotoButton =
  view: ->
    m 'button.btn.btn-default.btn-sm', {
      onclick: -> Model.photoAdded = !Model.photoAdded
    }, Model.photoBtnText
    
RemainingText =
  view: ->
    m 'span', Model.remainingChars
    
App =
  view: (ctrl, props) ->
    m 'div.well.clearfix',
      m TextArea
      m 'div.pull-right', 
        m PhotoButton
        m TweetButton
      m RemainingText
      
autorun -> m.render(
  document.getElementById("app"),
  m App
)