Skip to content

Commit

Permalink
Added demos used in presso at RootsConf 2011
Browse files Browse the repository at this point in the history
  • Loading branch information
trygve-lie committed May 26, 2011
1 parent 1fc7043 commit 5d347b5
Show file tree
Hide file tree
Showing 7 changed files with 340 additions and 0 deletions.
53 changes: 53 additions & 0 deletions src/server.js
@@ -0,0 +1,53 @@
var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');
var sys = require('sys');
var io = require('socket.io');


// Simplest HTTP server eva!
server = http.createServer( function ( request, response ){

var uri = url.parse(request.url).pathname;
var filepath = "www" + uri;
if (filepath.substring(filepath.length - 1) === '/') {
filepath += 'index.html';
}

path.exists(filepath, function ( ex ) {

if (!ex) {
response.writeHead(404, {'Content-Type': 'text/html'});
response.write("404 - File not found: " + uri);
response.end();
return;
}

fs.readFile(filepath, "binary", function ( error, filecontent ) {

if (error) {
response.writeHead(500, {'Content-Type': 'text/html'});
response.write("500 - Could not read " + filepath + " from file system!");
response.end();
return;
}

response.writeHead(200, {'Content-Type': 'text/html'});
response.write(filecontent, "binary");
response.end();
});

});

});
server.listen(8080);


// Even simpler websocket server
var socket = io.listen(server);
socket.on('connection', function ( client ) {
client.on('message', function ( message ) {
client.broadcast( message );
});
});
39 changes: 39 additions & 0 deletions src/www/chat/index.html
@@ -0,0 +1,39 @@
<!document html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, maximum-scale=1.0">
<title>Simple Chat</title>
<style>
div {margin-top: 100px; margin-left: auto; margin-right: auto; width: 50%;}
textarea {padding: 5px 5px 5px 5px;}
</style>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = new io.Socket(null, {port: 8080, rememberTransport: true});
socket.connect();

socket.on('message', function( obj ){

if ( typeof obj !== 'object' ) {
var dataObj = JSON.parse(obj);
if ( dataObj.demo.type === "chat" ) {
var recEl = document.getElementById("rec");
recEl.value = dataObj.demo.message;
}
}
});

var send = function (ev) {
var chat = {"demo" : {
"type" : "chat",
"message" : ev.value
}};
socket.send(JSON.stringify(chat));
};
</script>
</head>
<body>
<textarea id="rec" rows="20" cols="80" onkeyup="send(this);"></textarea>
</body>
</html>
48 changes: 48 additions & 0 deletions src/www/index.html
@@ -0,0 +1,48 @@
<!document html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, maximum-scale=1.0">
<title>"HTML5" Clients Interacting Demos</title>
</head>
<body>
<h1>"HTML5" Clients Interacting Demos</h1>
<p>
These are small demos on two or more clients interacting with each other. Many of the demos has a recorder
and a screen. The recorder are intended to be used as a "remote" to control whats going on on the "screen".
When using a demo with both a recorder and a screen, open the recorder in the client (device) which shall be
the controlling part and the screen in the client which shall be the controlled part.
</p>

<hr>

<h2>Simple Chat</h2>
<p>
<a href="chat/">A simple chat</a> example. The example use WebSockets to transfer plain text between two or
more clients.
</p>

<hr>

<h2>Instant Camera</h2>
<p>
A demo using the Device API for accessing the camera on a device and instantly projecting snapshot images from
the recording client to a screen client. The snapshot images are transferred between the clients by a
WebSocket connection.
</p>
<p>
<a href="instant_camera/recorder.html">Open recorder</a> - <a href="instant_camera/screen.html">Open screen</a>
</p>

<hr>

<h2>Remote Rotation</h2>
<p>
A demo using the DeviceOrientation API to capture the rotation of the recording client and remotely rotate a
a image in a screen client. Communication between the clients are done with WebSockets.
</p>
<p>
<a href="remote_rotation/recorder.html">Open recorder</a> - <a href="remote_rotation/screen.html">Open screen</a>
</p>
</body>
</html>
64 changes: 64 additions & 0 deletions src/www/instant_camera/recorder.html
@@ -0,0 +1,64 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, maximum-scale=1.0">
<style>
body {width: 100%;}
canvas {display: none;}
</style>
<title>Instant Camera - Recorder</title>
<script src="/socket.io/socket.io.js"> </script>
<script>

var video, canvas, msg;

var load = function () {

video = document.getElementById('video');
canvas = document.getElementById('canvas');
msg = document.getElementById('error');

var socket = new io.Socket(null, {port: 8080, rememberTransport: true});
socket.connect();

if( navigator.getUserMedia ) {

video.onclick = function () {
var context = canvas.getContext("2d");
context.drawImage(video, 0, 0, 240, 320);

var image = {"demo" : {
"type" : "device",
"image" : canvas.toDataURL("image/png")
}};
var imageObj = JSON.stringify(image);

socket.send(imageObj);
};

var success = function ( stream ) {
video.src = stream;
};

var error = function ( err ) {
msg.innerHTML = "Error: " + err.code;
};

navigator.getUserMedia('video', success, error);

} else {
msg.innerHTML = "Native web camera not supported :(";
}

};

window.addEventListener('DOMContentLoaded', load, false);
</script>
</head>
<body>
<video id="video" width="240" height="320" autoplay> </video>
<p id="error">Click on the video to send a snapshot to the remote screen</p>
<canvas id="canvas" width="240" height="320"> </canvas>
</body>
</html>
43 changes: 43 additions & 0 deletions src/www/instant_camera/screen.html
@@ -0,0 +1,43 @@
<!document html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, maximum-scale=1.0">
<title>Instant Camera - Screen</title>
<style>
img { float: left; margin-right: 5px; margin-bottom: 5px; }
</style>
<script src="/socket.io/socket.io.js"> </script>
<script>
var socket = new io.Socket(null, {port: 8080, rememberTransport: true});
socket.connect();

var el;

var load = function (){
el = document.getElementById('container');
};

socket.on('message', function( obj ){

if ( typeof obj !== 'object' ) {

var dataObj = JSON.parse(obj);

if ( dataObj.demo.type === "device" ) {
var img = document.createElement('img');
img.src = dataObj.demo.image;
el.appendChild(img);
}

}

});

window.addEventListener('DOMContentLoaded', load, false);
</script>
</head>
<body>
<div id="container"> </div>
</body>
</html>
38 changes: 38 additions & 0 deletions src/www/remote_rotation/recorder.html
@@ -0,0 +1,38 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, maximum-scale=1.0">
<title>Remote Rotation - Recorder</title>
<script src="/socket.io/socket.io.js"> </script>
<script>
var socket = new io.Socket(null, {port: 8080, rememberTransport: true});
socket.connect();

var el;

var load = function (ev) {
el = document.getElementById('status');
};

var update = function (ev) {
var orientation = {"demo" : {
"type" : "orientation",
"alpha" : ev.alpha,
"beta" : ev.beta,
"gamma" : ev.gamma
}};
el.innerHTML = "Alpha: " + ev.alpha + " Beta: " + ev.beta + " Gamma: " + ev.gamma;
socket.send(JSON.stringify(orientation));
};

window.addEventListener('DOMContentLoaded', load, false);
window.addEventListener('deviceorientation', update, true);
</script>
</head>
<body>
<h1>Remote Rotation</h1>
<p>Rotate the device to control the image on the remote screen</p>
<div id="status"> </div>
</body>
</html>
55 changes: 55 additions & 0 deletions src/www/remote_rotation/screen.html
@@ -0,0 +1,55 @@
<!document html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, maximum-scale=1.0">
<title>Orentation - Screen</title>
<style>
#container {
width: 400px;
height: 400px;
margin-top: 50px;
margin-left: auto;
margin-right: auto;
}

#img {
position: relative;
left: 72px;
top: 72px;
width: 256px;
height: 256px;
}
</style>
<script src="/socket.io/socket.io.js"> </script>
<script>
var socket = new io.Socket(null, {port: 8080, rememberTransport: true});
socket.connect();

var el;

var load = function (){
el = document.getElementById('img');
};

socket.on('message', function( obj ){

if ( typeof obj !== 'object' ) {
var dataObj = JSON.parse(obj);
if (dataObj.demo.type === "orientation") {
el.style = "-moz-transform: rotate(" + dataObj.demo.alpha + "deg); -ms-transform: rotate(" + dataObj.demo.alpha + "deg); -o-transform: rotate(" + dataObj.demo.alpha + "deg); transform: rotate(" + dataObj.demo.alpha + "deg);"
}
}

});

window.addEventListener('DOMContentLoaded', load, false);
</script>
</head>
<body>
<div id="container">
<img src="data:image/png;base64,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"
id="img">
</div>
</body>
</html>

0 comments on commit 5d347b5

Please sign in to comment.