Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Use separate model & composite view for status creation.

  • Loading branch information...
commit 34c681129ea4cd340ff84904494e66a503ee51ac 1 parent 2f8b0fd
@paulmillr paulmillr authored
View
1  app/controllers/sidebar_controller.coffee
@@ -1,5 +1,6 @@
Controller = require 'controllers/controller'
SidebarView = require 'views/sidebar_view'
+StatusView = require 'views/status_view'
module.exports = class NavigationController extends Controller
initialize: ->
View
22 app/models/status.coffee
@@ -0,0 +1,22 @@
+mediator = require 'mediator'
+Model = require 'models/model'
+
+module.exports = class Status extends Model
+ minLength: 1
+ maxLength: 140
+
+ validate: (attributes) ->
+ text = attributes.text
+ if (not text) or (text.length < @minLength) or (text.length > @maxLength)
+ return 'Invalid text'
+
+ calcCharCount: (value) ->
+ @maxLength - value
+
+ sync: (method, model, options) ->
+ provider = mediator.user.get('provider')
+ timeout = setTimeout options.error.bind(options, 'Timeout error'), 4000
+ provider.T.Status.update model.get('text'), (tweet) =>
+ window.clearTimeout(timeout)
+ options.success(tweet.attributes)
+ return
View
2  app/styles/main.styl
@@ -133,7 +133,7 @@ h1
font-size: 14px
color: lightblack
-.composable-tweet
+.status
padding: 12px
border-radius: 6px
background: #f8f8f8
View
22 app/views/composite_view.coffee
@@ -0,0 +1,22 @@
+View = require 'views/view'
+
+module.exports = class CompositeView extends View
+ initialize: ->
+ super
+ @subViews = []
+
+ attachView: (view) ->
+ @subViews.push view
+
+ renderSubViews: ->
+ _(@subViews).forEach (view) =>
+ @$(view.containerSelector).append view.render().el
+
+ render: =>
+ super
+ @renderSubViews()
+
+ dispose: =>
+ super
+ _(@subViews).forEach (view) =>
+ view.dispose()
View
33 app/views/sidebar_view.coffee
@@ -1,8 +1,9 @@
mediator = require 'mediator'
-View = require 'views/view'
+CompositeView = require 'views/composite_view'
+StatusView = require 'views/status_view'
template = require './templates/sidebar'
-module.exports = class SidebarView extends View
+module.exports = class SidebarView extends CompositeView
# This is a workaround.
# In the end you might want to used precompiled templates.
@@ -14,11 +15,9 @@ module.exports = class SidebarView extends View
initialize: ->
super
+ @attachView new StatusView()
@subscribeEvent 'loginStatus', @loginStatusHandler
@subscribeEvent 'userData', @render
- _(['keyup', 'keydown']).each (eventName) =>
- @delegate eventName, '.composable-tweet-text', @updateCharacterCount
- @delegate 'click', '.composable-tweet-send-button', @createTweet
loginStatusHandler: (loggedIn) =>
if loggedIn
@@ -26,27 +25,3 @@ module.exports = class SidebarView extends View
else
@model = null
@render()
-
- # TODO: move this to separate view.
- updateCharacterCount: (event) =>
- max = 140
- $charCount = @$('.composable-tweet-character-count')
- $send = @$('.composable-tweet-send-button')
- count = $(event.currentTarget).val().length
- charsLeft = max - count
- $charCount.text charsLeft
- if charsLeft < 0 or charsLeft is max
- unless charsLeft is max
- $charCount.addClass 'composable-tweet-character-count-invalid'
- $send.attr 'disabled', 'disabled'
- else
- $charCount.removeClass 'composable-tweet-character-count-invalid'
- $send.removeAttr 'disabled'
-
- createTweet: (event) =>
- $textEl = @$('.composable-tweet-text')
- api = mediator.user.get('provider').api
- text = $textEl.val()
- api.updateStatus text, (tweet) =>
- console.debug 'New tweet:', tweet
- $textEl.val('')
View
54 app/views/status_view.coffee
@@ -0,0 +1,54 @@
+mediator = require 'mediator'
+Status = require 'models/status'
+View = require 'views/view'
+template = require './templates/status'
+
+module.exports = class StatusView extends View
+ @template: template
+ id: 'status'
+ className: 'status'
+ containerSelector: '#status-container'
+ autoRender: no
+
+ initialize: ->
+ super
+ @subscribeEvent 'loginStatus', @loginStatusHandler
+ @subscribeEvent 'userData', @render
+
+ loginStatusHandler: (loggedIn) =>
+ if loggedIn
+ @model = new Status()
+ else
+ @model = null
+ @render()
+
+ updateCharacterCount: (valid, count) =>
+ $charCount = @$('.status-character-count')
+ $createButton = @$('.status-create-button')
+ $charCount.text count
+ if valid
+ $charCount.removeClass 'status-character-count-invalid'
+ $createButton.removeAttr 'disabled'
+ else
+ $charCount.addClass 'status-character-count-invalid'
+ $createButton.attr 'disabled', 'disabled'
+
+ updateStatusText: (event) =>
+ text = $(event.currentTarget).val()
+ @updateCharacterCount (@model.set {text}), @model.calcCharCount text.length
+
+ createStatus: (event) =>
+ @model.save {},
+ error: (model, error) =>
+ console.log 'Tweet error', error
+ success: (model, attributes) =>
+ console.log 'Tweet success', attributes
+
+ render: =>
+ super
+ console.log 'Render', this
+ # @delegate 'keyup', '.status-text', @updateStatusText
+ _(['keyup', 'keydown']).each (eventName) =>
+ @delegate eventName, '.status-text', @updateStatusText
+ # @modelBind 'change:text', @updateCharacterCount
+ @delegate 'click', '.status-create-button', @createStatus
View
8 app/views/templates/sidebar.hbs
@@ -13,13 +13,7 @@
<li class="stat-following"><strong>{{friends_count}}</strong> following</li>
<li class="stat-followers"><strong>{{followers_count}}</strong> followers</li>
</ul>
- <div class="composable-tweet">
- <textarea class="composable-tweet-text" placeholder="What's happening?"></textarea>
- <div class="composable-tweet-info">
- <span class="composable-tweet-character-count">140</span>
- <button class="composable-tweet-send-button btn btn-primary" disabled>Tweet</button>
- </div>
- </div>
+ <div class="status-container" id="status-container"></div>
{{else}}
<div class="app-description">
Tweet your brunch is a simple twitter client built with <a href="http://brunch.io/">Brunch</a> &amp; <a href="https://github.com/paulmillr/brunch-with-chaplin">Brunch with Chaplin</a>.
View
7 app/views/templates/status.hbs
@@ -0,0 +1,7 @@
+{{#if_logged_in}}
+ <textarea class="status-text" placeholder="What's happening?"></textarea>
+ <div class="status-info">
+ <span class="status-character-count">140</span>
+ <button class="status-create-button btn btn-primary" disabled>Tweet</button>
+ </div>
+{{/if_logged_in}}
View
6 app/views/view.coffee
@@ -206,7 +206,7 @@ function'
# Main render function
# Always bind it to the view instance
render: =>
- #console.debug "View#render\n\t", this, "\n\tel:", @el, "\n\tmodel/collection:", (@model or @collection), "\n\tdisposed:", @disposed
+ # console.debug "View#render\n\t", this, "\n\tel:", @el, "\n\tmodel/collection:", (@model or @collection), "\n\tdisposed:", @disposed
return if @disposed
@@ -244,11 +244,11 @@ function'
# This method is called after a specific `render` of a derived class
afterRender: ->
- #console.debug 'View#afterRender', this
+ # console.debug 'View#afterRender', this
# Automatically append to DOM if the container element is set
if @$container
- #console.debug '\tappend to DOM'
+ # console.debug '\tappend to DOM'
@$container.append @el
# Trigger an event
@trigger 'addedToDOM'
Please sign in to comment.
Something went wrong with that request. Please try again.