Skip to content

Instantly share code, notes, and snippets.

@jhthorsen
Created October 27, 2012 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhthorsen/3964764 to your computer and use it in GitHub Desktop.
Save jhthorsen/3964764 to your computer and use it in GitHub Desktop.
digital whiteboard websocket demo
#!/usr/bin/env perl
use Mojolicious::Lite;
my $connections = {};
my $drawings = {};
# demo here: http://whiteboard-jhthorsen.dotcloud.com/
get '/' => sub {
my $self = shift;
unless($self->param('id')) {
$self->redirect_to('/?id=' . time . int rand 10000);
return;
}
$self->render(template => 'index');
};
websocket '/draw' => sub {
my $self = shift;
my $id = $self->param('id') || 'default';
my $tx = $self->tx;
Mojo::IOLoop->stream($tx->connection)->timeout(0);
$connections->{$id}{$self} = $tx;
$drawings->{$id} ||= [];
$self->on(finish => sub { $self->_end($id) });
$self->on(message => sub {
my($self, $pos) = @_;
push @{ $drawings->{$id} }, $pos;
while(my($name, $other) = each %{ $connections->{$id} }) {
next if $name eq "$self";
$other->send($pos);
}
});
for my $pos (@{ $drawings->{$id} }) {
$tx->send($pos);
}
};
app->helper(_end => sub {
my($self, $id) = @_;
$self->app->log->debug("end $id");
delete $connections->{$id}{$self};
unless(%{ $connections->{$id} }) {
$self->app->log->debug("delete $id");
delete $drawings->{$id};
}
});
app->secret('no need for secret');
app->start;
__DATA__
@@ index.html.ep
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes"/>
<style type="text/css">
html, body { height: 100%; width: 100%; margin: 0; padding: 0 }
body { font: 14px normal sans-serif }
a { color: #000 }
.pencil {
background: #f00;
height: 4px;
width: 4px;
position: absolute;
margin-left: -2px;
margin-top: -2px;
}
</style>
<script src="<%= url_for('/js/jquery.js')->to_abs %>"></script>
<script type="text/javascript">
// 19
$(document).ready(function() {
BASEURL = $('script').attr('src').replace(/\/js\/.*/, '');
var id = window.location.href.match(/id=(\w+)/)[1];
var resource = BASEURL.replace(/http/, 'ws') + '/draw?id=' + id;
var websocket = new WebSocket(resource);
window.console && console.log(resource);
var active = false;
var $board = $('body');
var n = 0;
$board.mousedown(function(e) { e.preventDefault(); active = true })
.mouseup(function(e) { active = false })
.mousemove(function(e) {
if(!active) return;
websocket.send(e.pageX + ',' + e.pageY);
draw([e.pageX, e.pageY]);
})
.bind('touchmove', function (e) {
e.preventDefault();
e = e.originalEvent.targetTouches[0];
websocket.send(e.pageX + ',' + e.pageY);
draw([e.pageX, e.pageY]);
});
websocket.onmessage = function(e) {
draw(e.data.split(','));
};
draw = function(xy) {
$board.append(
$('<div class="pencil" style="left:' + xy[0] + 'px;top:' + xy[1] + 'px"/>')
);
};
});
</script
</head>
<body>
%= link_to 'New board', '/';
<div id="board"></div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment