Skip to content

Instantly share code, notes, and snippets.

@ericmoritz
Created July 30, 2010 13:59
Show Gist options
  • Save ericmoritz/500543 to your computer and use it in GitHub Desktop.
Save ericmoritz/500543 to your computer and use it in GitHub Desktop.
<!doctype html>
<html>
<head>
<title>websockets chat</title>
<link type="text/css" href="/upload/js/jquery-ui/css/smoothness/jquery-ui-1.8.2.custom.css" rel="stylesheet" />
<script src="/upload/js/jquery-1.4.2.js"></script>
<script src="/upload/js/jquery.embedly.js"></script>
<script src="/upload/js/jquery-ui/js/jquery-ui-1.8.2.custom.min.js"></script>
<script>
/* UI */
jQuery.fn.text = function(val) {
var $this = $(this);
if(val) {
var safe = val.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
$this.html(safe);
return $this;
} else {
return $this.html();
}
}
jQuery.fn.autolink = function () {
return this.each( function(){
var re = /((http|https|ftp):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%""=-]*>))/g;
$(this).html( $(this).html().replace(re, '<a href="$1" target="_blank">$1</a> ') );
});
}
function makeToast(msg, delay) {
var delay = delay || 1000;
var $toast = $("#toast");
var $chat = $("#chat");
var center = [$chat.innerWidth()/2,
$chat.innerHeight()/2];
$toast.text(msg);
var left = center[0] - $toast.width() / 2;
var top = center[1] - $toast.height() / 2;
$toast.css("left", left);
$toast.css("top", top);
$toast.fadeIn(500)
.delay(delay)
.fadeOut(500);
}
function displayMessage(id, username, text) {
// Clone a copy of the template
var $message = $('.message-template').clone();
var $chat = $("#chat");
// Set the values
$message.find('.username').text(username);
$message.find('.text').text(text);
$message.find('.text').autolink();
$message.find('.text a ').embedly({maxWidth: $chat.width() * 0.5},
function(oembed, elem, options) {
if(oembed) {
elem.before(oembed.code);
$chat.scrollTop($chat.innerHeight());
}
}
);
$message.removeClass("message-template");
$message.attr("id", "message-" + id);
// Append it
$chat.append($message)
$chat.scrollTop($chat.innerHeight());
}
function showConnectFrame() {
$("#input section").hide();
$("#input #connect").show();
}
function showMessageFrame() {
$("#input section").hide();
$("#input #message-frame").show();
}
function showWho(usernames) {
$("#who div").empty();
$.each(usernames, function(i) {
var $p = $("<p>");
$p.text(this);
$("#who div").append($p);
});
}
function log(text) {
var $log_message = $(".log-template").clone();
$log_message.text(text);
$log_message.removeClass("log-template");
$("#chat").append($log_message);
}
/* Main */
var conn;
var username;
function sendMessage(username, text, callback, errback) {
conn.send(JSON.stringify({
'action': 'message',
'username': username,
'text': text}));
if(callback) callback();
}
function connect(username, callback) {
conn = new WebSocket("ws://eric.themoritzfamily.com:8000/");
conn.onmessage = function(evt) {
var data = JSON.parse(evt.data);
switch(data['action']) {
case "message":
displayMessage(data['message-id'], data['username'], data['text'], function() {});
break;
case "disconnect":
log(data['username'] + " disconnected");
conn.send(JSON.stringify({action:'who'}));
break;
case "register":
log(data['username'] + " connected");
conn.send(JSON.stringify({action:'who'}));
break;
case "who":
var usernames = [];
var users = data['users'];
for(key in users) {
usernames.push(users[key]['username']);
}
showWho(usernames);
}
}
conn.onopen = function(evt) {
conn.isopen = true;
conn.send(JSON.stringify({'action': 'register', 'username': username}));
if(callback) callback(conn);
}
conn.onerror = function(evt) {
makeToast("Error");
}
conn.onclose = function(evt) {
if(conn.isopen) {
makeToast("Lost Connection");
} else {
makeToast("Connection Failed");
}
conn.isopen = false;
showWho([]);
showConnectFrame();
}
}
function init() {
$("#chat-container").resizable({ alsoResize: '#chat', handles:"s" });
$("#send").click(function() {
var text = $("#text").val();
if(text) {
sendMessage(username, text,function() {
$("#text").val("");
});
}
});
$("#connect-button").click(function() {
username = $("#username").val();
connect(username,
function() {
showMessageFrame();
})
});
$("#disconnect").click(function() {
conn.close();
});
}
window.onload = init;
</script>
<style>
/** Color Theme **/
body {
color: #2B3E42; // textColor
}
section.block {
border-color: #747E80;
background-color: #F7F3E8;
-webkit-box-shadow: 3px 3px 3px #888;
}
/** **/
body {
font-family: sans-serif;
font-size: 10pt;
}
#chat-container { position: relative; }
#chat {
height: 200px;
overflow: auto;
}
#input {
margin-top: 10px;
}
section.block {
padding: 5px;
border-width: 2px;
border-style: solid;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
section.block h1 {
font-size: 1.1em;
margin: 0px; padding: 0px;
}
#toast {
position: absolute;
display: none;
background-color: black;
-webkit-border-radius: 5px;
padding: 5px;
opacity: 0.75;
}
input, textarea {
border: 1px solid #F2583E;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
padding: 2px;
}
textarea#text { width: 95%; }
#chat .block {
text-shadow: 1px 1px 1px #555;
-webkit-box-shadow: 3px 3px 3px #888;
border-width: 1px;
margin-bottom: 5px;
}
#chat .message {
background-color: #D5E1DD;
}
#chat .log {
background-color: #747E80;
color: #F7F3E8;
}
.message .username:after { content: ":"}
.message .username { color: #F2583E; font-weight: bold;}
.message .text { }
.hidden { display: none; }
.log { font-style: italic; }
.log-template, .message-template { display: none; }
</style>
</head>
<body>
<section id="chat-container">
<div id="toast">Really Long Toast!</div>
<section id="chat" class="block resizable">
<section class="message message-template block">
<span class="username">Buffy</span>
<span class="text">Hello, World!</span>
</section>
<section class="log log-template block">Buffy disconnected</section>
</section>
</section>
<section id="input" class="container">
<section id="connect" class="block">
<div><input placeholder="username" id="username"></div>
<div><input type="button" id="connect-button" value="connect"></div>
</section>
<section id="message-frame" class="block hidden">
<div><textarea id="text" placeholder="message" rows="3"></textarea></div>
<div><input type="button" id="send" value="send"><input type="button" id="disconnect" value="disconnect"></div>
</section>
</section>
<section id="who" class="block">
<h1>Users</h1>
<div></div>
</section>
</body>
</html>
var ws = require(__dirname + '/lib/ws'), //http://github.com/miksago/node-websocket-server
server = ws.createServer({ debug: true}),
sys = require("sys");
var message_count = 0;
var users = {}
server.addListener("connection", function(conn){
conn.addListener("message", function(message){
message = JSON.parse(message);
switch(message['action']) {
case "register":
users[conn.id] = {'username': message['username']}
break
case "who":
conn.write(JSON.stringify({'action': 'who', 'users':users}));
return;
}
server.broadcast(JSON.stringify(message));
});
});
server.addListener("close", function(conn){
var user = users[conn.id];
var message = {
'action': 'disconnect',
'username': user['username']
}
delete users[conn.id];
server.broadcast(JSON.stringify(message));
});
sys.log("Listening on port 8000");
server.listen(8000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment