Created
December 11, 2012 00:33
-
-
Save mattneary/4254672 to your computer and use it in GitHub Desktop.
Simple JS Chat displaying Prototypes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Socket.io Library Include --> | |
<script src="https://raw.github.com/LearnBoost/socket.io-client/master/dist/socket.io.min.js"></script> | |
<!-- Page Structure --> | |
<ol id="messages"></ol> | |
<input type="text" id="message"> | |
<input type="button" id="send" value="Send"> | |
<!-- Styling --> | |
<style> | |
.msg_to, .msg_from { | |
list-style: none; | |
display: block; | |
padding: 3px; | |
} | |
.msg_to { | |
background: gray; | |
} | |
.msg_from { | |
background: green; | |
} | |
</style> | |
<script> | |
// base UI class | |
var View = (function() { | |
var View = function(el) { | |
this.view = el; | |
}; | |
View.prototype = { | |
content: function(text) { | |
if( arguments.length ) { | |
this.view.innerHTML = text; | |
} else { | |
return this.view.innerHTML; | |
} | |
}, val: function(text) { | |
if( arguments.length ) { | |
this.view.value = text; | |
} else { | |
return this.view.value; | |
} | |
}, insert: function(insertionView) { | |
this.view.appendChild(insertionView.view); | |
}, listen: function(event, cb) { | |
this.view.addEventListener(event, cb); | |
}, append: function(view) { | |
this.view.appendChild(view.view); | |
} | |
}; | |
return View; | |
})(); | |
// Models | |
var MessageStore = (function() { | |
var MessageStore = function() { | |
this.messages = []; | |
}; | |
MessageStore.prototype = { | |
insertSent: function(message) { | |
this.messages.push(new Message(message, "from")); | |
}, insertReceived: function(message) { | |
this.messages.push(new Message(message, "to")); | |
}, each: function(cb) { | |
this.messages.map(cb); | |
} | |
}; | |
return MessageStore; | |
})(); | |
var Message = (function() { | |
var Message = function(content, direction) { | |
this._content = content; | |
this._direction = direction; | |
}; | |
Message.prototype = { | |
content: function() { | |
return this._content; | |
}, direction: function() { | |
return this._direction; | |
} | |
}; | |
return Message; | |
})(); | |
// Views | |
var MessageView = (function() { | |
var MessageView = function(message) { | |
// make an `li` with traits based on message | |
var li = document.createElement("li"); | |
li.innerHTML = message.content(); | |
li.className = "msg_"+message.direction(); | |
this.view = li; | |
}; | |
MessageView.prototype = View.prototype; // inherit | |
return MessageView; | |
})(); | |
var MessageListView = (function() { | |
var MessageListView = function(el) { | |
this.view = el; | |
}; | |
MessageListView.prototype = View.prototype; // inherit | |
MessageListView.prototype.render = function(messageStore) { | |
// set list content to every message in store | |
var view = this; | |
view.content(""); | |
messageStore.each(function(message, index) { | |
view.append((new MessageView(message))); | |
}); | |
}; | |
return MessageListView; | |
})(); | |
var MessageBoxView = (function() { | |
var MessageBoxView = function(boxEl, sendEl) { | |
this.view = boxEl; | |
this.sendEl = sendEl; | |
}; | |
MessageBoxView.prototype = View.prototype; // inherit | |
MessageBoxView.prototype.onSubmit = function(cb) { | |
(new View(this.sendEl)).listen('click', cb); | |
}; | |
return MessageBoxView; | |
})(); | |
// Controllers | |
var SocketHandler = (function() { | |
var listeners = {}; | |
var SocketHandler = function(server, channel) { | |
// on init save channel, make socket and initiate channel | |
this._channel = channel; | |
this.socket = io.connect(server, { | |
'reconnect': true, | |
'reconnection delay': 500, | |
'max reconnection attempts': 10 | |
}); | |
this.socket.on(channel, function(packet) { | |
listeners[packet.event](packet.content); | |
}); | |
}; | |
SocketHandler.prototype = { | |
send: function(event, content) { | |
this.socket.emit(this._channel, { | |
event: event, | |
content: content | |
}); | |
}, listen: function(event, cb) { | |
listeners[event] = cb; | |
}, init: function() { | |
this.socket.emit('initiate', { channel: this._channel }); | |
} | |
}; | |
return SocketHandler; | |
})(); | |
var Messenger = function(boxView, listView) { | |
// `main` controller has no class methods | |
var messageStore = new MessageStore(), | |
socketHandler = new SocketHandler('http://localhost:8081', 'group'); | |
socketHandler.init(); | |
socketHandler.listen('message', function(content) { | |
messageStore.insertReceived(content); | |
listView.render(messageStore); | |
}); | |
boxView.onSubmit(function(event) { | |
var content = boxView.val(); | |
messageStore.insertSent(content); | |
listView.render(messageStore); | |
socketHandler.send('message', content); | |
}); | |
}; | |
// Setup | |
(function() { | |
// get document elements | |
var messageListEl = document.getElementById('messages'); | |
var messageBoxEl = document.getElementById('message'); | |
var messageSendEl = document.getElementById('send'); | |
// abstract over these elements | |
var messageBoxView = new MessageBoxView(messageBoxEl, messageSendEl); | |
var messageListView = new MessageListView(messageListEl); | |
// initiate a controller of these views | |
Messenger(messageBoxView, messageListView); | |
})(); | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var http = require('http'), | |
fs = require('fs'); | |
var io = require('socket.io').listen(8081); | |
io.sockets.on('connection', function (socket) { | |
var channels = [], channelUserGroups = {}; | |
var handler = function(channel) { | |
// rebroadcast data to users on an arbitrary channel | |
return function(data) { | |
channelUserGroups[channel].map(function(socket){ socket.emit(channel, data); }); | |
}; | |
}; | |
var listen = function(channel) { | |
socket.on(channel, handler(channel)); | |
}; | |
socket.on('initiate', function (data) { | |
// listen to a channel if not already | |
if( channels.indexOf(data.channel) == -1 ) { | |
listen(data.channel); | |
channels.push(data.channel); | |
} | |
channelUserGroups[data.channel] = channelUserGroups[data.channel] || []; | |
channelUserGroups[data.channel].push(socket); | |
}); | |
// TODO: handle logoff | |
}); | |
http.createServer(function(req, res) { | |
res.writeHead(200, { | |
'Content-Type': 'text/html' | |
}); | |
fs.createReadStream(__dirname + '/index.html').pipe(res); | |
}).listen(8080); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment