Node.jsとSocket.ioで別ウィンドウのイベントを共有する

以下の記事を見て触発されたので、ウィンドウ間でイベントを共有するサンプルを作ってみました。作成時間30分くらい。
PCのプレゼン資料を、スマホで操作。「シンクスライド」がスゴイぞ|タブロイド|オトコをアゲるグッズニュース

簡単に説明すると、ウィンドウAで起きたイベントをsocket.emit()でサーバ側に通知、受け取ったイベントをsockets[i].emit()で全ウィンドウに通知します。このサンプルで共有しているイベントは以下の通りです。

  • mouseover
  • mouseout
  • scroll

スワイプに関しては実装してませんが、適当なライブラリをインポートすれば良いかなと思います。
イベントを共有するウィンドウを指定するなら、一意のURLを発行して、それでsokets[i]を限定すれば良いかな。
ではプロジェクトを作るところから。

$ mkdir syncevent
$ cd syncevent
$ npm init
$ npm install socket.io --save

使っているファイルは以下の通りです。

  • index.html
  • index.js

index.js

var app = require('http').createServer(handler)
	, io = require('socket.io').listen(app)
	, fs = require('fs')

app.listen(8080);

function handler (req, res) {
	fs.readFile(__dirname + '/index.html',
	function (err, data) {
		if (err) {
			res.writeHead(500);
			return res.end('Error loading index.html');
		}

		res.writeHead(200);
		res.end(data);
	});
}

var sockets = [];

io.sockets.on('connection', function (socket) {
	// connect
	sockets[socket.id] = socket;

	socket.on('disconnect', function () {
		sockets.splice(socket.id, 1);
		data = {
			name: socket.id,
			text: 'disconnected'
		};
	});

	socket.on('mouseover', function () {
		for (i in sockets) {
			sockets[i].emit('sync_mouseover');
		}
	});
	socket.on('mouseout', function () {
		for (i in sockets) {
			sockets[i].emit('sync_mouseout');
		}
	});
	socket.on('scroll', function (data) {
		for (i in sockets) {
			sockets[i].emit('sync_scroll', data);
		}
	});
});

index.html

<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<style type="text/css">
#log {
	width: 200px;
	height: 100px;
	border: 1px solid silver;
	padding: 10px;
	background-color: ghostwhite;
	overflow:auto;
}
#log:hover {
	background-color: pink;
}
</style>
<script>
var socket = io.connect('http://localhost');


var format_time = function() {
	var mydate = (new Date());
	var strdate = mydate.getHours() + ':' + mydate.getMinutes() + ':' + mydate.getSeconds() + ':' + mydate.getMilliseconds();
	return strdate;
}


var event_mouseover = function() {
	socket.emit('mouseover');
}
var event_mouseout = function() {
	socket.emit('mouseout');
}

var event_scroll = function() {
	var data = $('#log').scrollTop();
	socket.emit('scroll', data);
}

var my_init =  function () {
	for (var i = 0; i < 100; i++) {
		var html = format_time() + '<br/>';
		$('#log').append(html);
	}
}

socket.on('sync_mouseover', function () {
	$('#log').css('background-color', 'pink');
});
socket.on('sync_mouseout', function () {
	$('#log').css('background-color', 'ghostwhite');
});
socket.on('sync_scroll', function (data) {
	$('#log').scrollTop(data);
});


$(document).ready(function(){
	my_init();
	$('#log').mouseover(function(){
		event_mouseover();
	});
	$('#log').mouseout(function(){
		event_mouseout();
	});
	$('#log').scroll(function(){
		event_scroll();
	});
});

</script>
</head>
<body>
	<div id="log">
	</div>
</body>