Skip to content

Commit

Permalink
Working chat app with jQuery tabs and Backbone. Adds a small chat pos…
Browse files Browse the repository at this point in the history
…ting box

Signed-off-by: Akash Manohar J <akash@akash.im>
  • Loading branch information
HashNuke committed Mar 10, 2012
1 parent 6d0f370 commit 2ed6093
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 16 deletions.
1 change: 1 addition & 0 deletions app/assets/javascripts/application.js
Expand Up @@ -17,3 +17,4 @@
//= require lib/backbone
//= require backbone/kandan
//= require_tree .

18 changes: 18 additions & 0 deletions app/assets/javascripts/backbone/broadcasters/faye.js.coffee
@@ -0,0 +1,18 @@
class Kandan.Broadcasters.FayeBroadcaster

constructor: ()->
@faye_client = new Faye.Client("/remote/faye")
@faye_client.disable('websocket')
auth_extension = {
outgoing: (message, callback)->
if message.channel == "/meta/subscribe"
# TODO move fetching auth token to a helper
message['ext'] = {auth_token: $.data(document, 'current_user').auth_token}
callback(message)
}
@faye_client.addExtension(auth_extension)

subscribe: (channel)->
console.log "Subscribing to #{channel}"
@faye_client.subscribe channel, (data)=>
console.log data.user.first_name, "says", data.content
36 changes: 32 additions & 4 deletions app/assets/javascripts/backbone/kandan.js.coffee
Expand Up @@ -10,12 +10,40 @@ window.Kandan =
Collections: {}
Views: {}
Routers: {}
Broadcasters: {}
init: ->
# new Kandan.Routers.Main()
# Backbone.history.start({pushState: true})
chat_area = new Kandan.Views.ChatArea()
$('.container').html(chat_area.render().el)
# $('.container').append(chat_box)
channels = new Kandan.Collections.Channels()
channels.fetch({success: ()=>

chat_area = new Kandan.Views.ChatArea({channels: channels})
$('.container').html(chat_area.render().el)

chatbox = new Kandan.Views.Chatbox()
$('.container').append(chatbox.render().el)

# TODO move this to a helper
# can also be done by checking the active tab in the post event in the Chatbox view
$('#channels').tabs({
select: (event, ui)->
channel_id = $("#channels .ui-tabs-panel").eq("#{ui.index}").data('channel_id')
console.log "set channelID to", channel_id
# TODO move setting current channel ID to a seperate helper
$('.chatbox').data('active_channel_id', channel_id)
})

# TODO move broadcast subscription to a helper
# TODO change this to use the broadcaster from the settings
# TODO set as global to debug. remove later.
window.broadcaster = new Kandan.Broadcasters.FayeBroadcaster()
for channel in channels.models
window.broadcaster.subscribe "/channels/#{channel.get('id')}"

# TODO move this to a helper
$('.chatbox').data('active_channel_id',
$("#channels .ui-tabs-panel").eq($('#channels').tabs('option', 'selected')).data('channel_id'))
})


$(document).ready ->
Kandan.init()
13 changes: 4 additions & 9 deletions app/assets/javascripts/backbone/views/chatarea.js.coffee
Expand Up @@ -3,16 +3,11 @@ class Kandan.Views.ChatArea extends Backbone.View
template: JST['chatarea']
# className: 'channels'

initialize: ()->
@channels = new Kandan.Collections.Channels()

render: ->
@channels.fetch({success: ()=>
$(@el).html(@template({channels: @channels}))
for channel in @channels.models
view = new Kandan.Views.ListActivities({channel: channel})
$(@el).append(view.render().el)
$('#channels').tabs()
})
$(@el).html(@template({channels: @options.channels}))
for channel in @options.channels.models
view = new Kandan.Views.ListActivities({channel: channel})
$(@el).append(view.render().el)
$(@el).attr('id', 'channels')
@
27 changes: 27 additions & 0 deletions app/assets/javascripts/backbone/views/chatbox.js.coffee
@@ -0,0 +1,27 @@
class Kandan.Views.Chatbox extends Backbone.View

template: JST['chatbox']
tagName: 'div'
className: 'chatbox-area'

events:
"keypress .chatbox": 'postMessage'

postMessage: (event)->

if event.keyCode== 13
$chatbox = $(".chatbox")
activity = new Kandan.Models.Activity({
'content': $chatbox.val(),
'action': 'message',
'channel_id': $chatbox.data('active_channel_id')
})

activity.save({success: ()->
console.log "posted! enjoy your day"
})


render: ()->
$(@el).html(@template())
@
Expand Up @@ -7,4 +7,5 @@ class Kandan.Views.ListActivities extends Backbone.View
activity_view = new Kandan.Views.Activity({activity: activity})
$(@el).append(activity_view.render().el)
$(@el).attr('id', "channels-#{@options.channel.get('id')}")
$(@el).data('channel_id', @options.channel.get('id'))
@
1 change: 1 addition & 0 deletions app/assets/templates/chatbox.jst.eco
@@ -0,0 +1 @@
<input type="text" class="chatbox"/>
1 change: 1 addition & 0 deletions app/controllers/activities_controller.rb
Expand Up @@ -10,6 +10,7 @@ def index

def create
@activity = Channel.find(params[:channel_id]).activities.build(params[:activity])
@activity.user_id = current_user.id if @activity.action == "message"
if @activity.save
respond_to do |format|
format.json { render :json => @activity, :status => :created }
Expand Down
6 changes: 4 additions & 2 deletions app/models/activity_observer.rb
@@ -1,7 +1,9 @@
class ActivityObserver < ActiveRecord::Observer

def after_save(activity)
faye_channel = "/channels/#{activity.channel.to_param}/messages"
Kandan::Config.broadcaster.broadcast(faye_channel, activity.attributes)
faye_channel = "/channels/#{activity.channel.to_param}"
# TODO move this to a rabl template
broadcast_data = activity.attributes.merge({:user => activity.user.attributes})
Kandan::Config.broadcaster.broadcast(faye_channel, broadcast_data)
end
end
23 changes: 23 additions & 0 deletions config.ru
Expand Up @@ -3,13 +3,35 @@
require ::File.expand_path('../config/environment', __FILE__)
require 'faye'

# TODO move this to the lib dir
class DeviseAuth
def incoming(message, callback)
if message['channel'] == "/meta/subscribe"
auth_token = message['ext']['auth_token']
user = User.find_by_authentication_token(auth_token)
if user
return callback.call(message)
else
message['error'] = "Invalid auth token"
end
end
puts "Message: #{message.inspect}"
callback.call(message)
end

#TODO disable publishing by users
end


faye_server = Faye::RackAdapter.new(:mount => "/faye", :timeout => 5)
faye_server.add_extension(DeviseAuth.new)

# TODO send pull request to faye to get this fixed
# by adding a rack_prefix option
# which should then make the faye server object available
# via the get_client() method on the server


FAYE_CLIENT = faye_server.get_client

faye_server.bind(:subscribe) do |client_id|
Expand All @@ -18,6 +40,7 @@ end

faye_server.bind(:disconnect) do |client_id|
puts "DISCONNECT #{client_id}"
User
end

run Rack::URLMap.new({
Expand Down
4 changes: 3 additions & 1 deletion lib/broadcasters/faye.rb
Expand Up @@ -3,7 +3,9 @@ class Faye
class << self
def broadcast(channel, message)
# NOTE FAYE_CLIENT is set in the config.ru file due to the faye bug
if defined?(FAYE_CLIENT) && (not FAYE_CLIENT.nil?)
puts "CHECKING TO BEGIN BROADCAST"
if defined?(FAYE_CLIENT)
puts "BROADCASTING... to #{channel}"
FAYE_CLIENT.publish channel, message
else
puts "OOPS! FAYE_CLIENT is not defined"
Expand Down

0 comments on commit 2ed6093

Please sign in to comment.