mouseover on clicks will show client data
mouseover on clicks will show client data

file:a/.gitignore -> file:b/.gitignore
node_modules node_modules
bower_components bower_components
  dist
   
file:b/Gruntfile.js (new)
  module.exports = function(grunt) {
 
  grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  concat: {
  options: {
  separator: ';'
  },
  dist: {
  src: ['bower_components/socket.io-client/socket.io.js', 'src/js/c.js'],
  dest: 'dist/<%= pkg.name %>.js'
  }
  },
  uglify: {
  options: {
  banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
  },
  dist: {
  files: {
  'dist/js/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
  }
  }
  },
  cssmin: {
  dist: {
  options: {
  banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
  },
  files: {
  'dist/css/<%= pkg.name %>.min.css': ['src/css/c.css']
  }
  }
  },
  copy: {
  main: {
  files: [
  {expand: true, cwd: 'src/', src: ['admin.html'], dest: 'dist/'},
  {expand: true, cwd: 'src/js', src: ['a.js'], dest: 'dist/js'},
  ],
  },
  },
  jshint: {
  files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
  options: {
  globals: {
  jQuery: true,
  console: true,
  module: true,
  document: true
  }
  }
  },
  watch: {
  files: ['<%= jshint.files %>'],
  tasks: ['jshint']
  }
  });
 
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-copy');
 
  //grunt.registerTask('test', ['jshint']);
 
  grunt.registerTask('default', [/*'jshint', */'concat', 'uglify', 'cssmin', 'copy']);
  };
file:a/index.js -> file:b/index.js
var express = require('express'); var express = require('express');
var app = express(); var app = express();
var http = require('http').Server(app); var http = require('http').Server(app);
var io = require('socket.io')(http); var io = require('socket.io')(http);
   
app.get('/', function(req, res){ app.get('/admin', function(req, res){
res.sendFile(__dirname + '/public/index.html'); res.sendFile(__dirname + '/dist/admin.html');
}); });
   
app.get('/admin', function(req, res){ app.use(express.static(__dirname + '/dist'));
res.sendFile(__dirname + '/public/admin.html');  
});  
   
app.use(express.static(__dirname + '/public'));  
app.use(express.static(__dirname + '/bower_components')); app.use(express.static(__dirname + '/bower_components'));
   
var admin = []; var admin = [];
  var resolutions = [];
   
io.on('connection', function(socket){ io.on('connection', function(socket){
var mouse = []; var mouse = [];
var color = "#"+((1<<24)*Math.random()|0).toString(16); var color = "#"+((1<<24)*Math.random()|0).toString(16);
var id = socket.id; var id = socket.id;
   
socket.on('t:connect', function (msg) { socket.on('t:connect', function (msg) {
if (msg.admin == 1234) { if (msg.admin == 1234) {
console.log ("admin connected " + id); console.log ("admin connected " + id);
admin.push(id); admin.push(id);
  } else {
  console.log ("user connected " + id);
} }
if (msg.color != null) { if (msg.color != null) {
color = msg.color; color = msg.color;
socket.emit('t:connected', {}); socket.emit('t:connected', {});
} else { } else {
socket.emit('t:connected', {color:color}); socket.emit('t:connected', {color:color});
  }
  var resolution = msg.w + 'x' + msg.h;
  index = resolutions.indexOf(resolution);
  if (index == -1) {
  resolutions.push(resolution);
  for (key in admin) {
  io.to(admin[key]).emit('t:resolutions', resolutions);
  }
} }
}); });
   
socket.on('disconnect', function () { socket.on('disconnect', function () {
index = admin.indexOf(id); index = admin.indexOf(id);
if (index != -1) { if (index != -1) {
console.log ("admin disconnected " + id); console.log ("admin disconnected " + id);
admin.splice(index, 1); admin.splice(index, 1);
} }
}); });
   
socket.on('t:mousemove', function(msg){ socket.on('t:mousemove', function(msg){
mouse.push(msg); mouse.push(msg);
if (mouse.length > 2) { if (mouse.length > 2) {
mouse.shift(); mouse.shift();
} }
if (mouse.length == 2) { if (mouse.length == 2) {
for (key in admin) { for (key in admin) {
io.to(admin[key]).emit('t:mousemove', mouse); io.to(admin[key]).emit('t:mousemove', mouse);
} }
} }
}); });
   
socket.on('t:click', function(click){ socket.on('t:click', function(click){
click.color = color; click.color = color;
for (key in admin) { for (key in admin) {
//console.log ("\tsend click to admin " + admin[key]);  
io.to(admin[key]).emit('t:click', click); io.to(admin[key]).emit('t:click', click);
} }
}); });
   
socket.on('t:changemm', function(msg){ socket.on('t:changemm', function(msg){
index = admin.indexOf(id); index = admin.indexOf(id);
if (index != -1) { if (index != -1) {
io.emit('t:changemm', {msg}); io.emit('t:changemm', {msg});
} }
}); });
}); });
   
http.listen(3000, function(){ http.listen(80, '192.168.0.3', function(){
console.log('listening on *:3000'); console.log('listening on 192.168.0.3:80');
}); });
   
{ {
"name": "realtime-mouse-tracking", "name": "realtime-mouse-tracking",
"version": "0.0.1", "version": "0.0.1",
"description": "tracking users mouse movments and clicks", "description": "tracking users mouse movments and clicks",
"dependencies": { "dependencies": {
"express": "4.10.2", "express": "4.10.2",
"socket.io": "1.2.0" "socket.io": "1.2.0"
  },
  "devDependencies": {
  "grunt": "^0.4.5",
  "grunt-contrib-concat": "^0.5.1",
  "grunt-contrib-copy": "^0.8.2",
  "grunt-contrib-cssmin": "^0.14.0",
  "grunt-contrib-jshint": "^0.12.0",
  "grunt-contrib-uglify": "^0.11.0",
  "grunt-contrib-watch": "^0.6.1"
} }
} }
   
file:a/public/admin.html (deleted)
<!DOCTYPE html>  
<html>  
<head>  
<meta charset='utf-8'>  
<meta content='IE=edge' http-equiv='X-UA-Compatible'>  
<meta content='width=device-width,initial-scale=1' name='viewport'>  
<title>Tracking</title>  
</head>  
<body>  
<div id="div"></div>  
<script type="text/javascript">  
(function(i,s,o,g){a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','/js/a.js');  
</script>  
 
</body>  
</html>  
file:a/public/index.html (deleted)
<!DOCTYPE html>  
<html>  
<head>  
<meta charset='utf-8'>  
<meta content='IE=edge' http-equiv='X-UA-Compatible'>  
<meta content='width=device-width,initial-scale=1' name='viewport'>  
<title>Tracking</title>  
</head>  
<body>  
<div id="div"></div>  
<script type="text/javascript">  
(function(i,s,o,g){a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','/js/a.js');  
(function(i,s,o,g){a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','/js/c.js');  
</script>  
 
</body>  
</html>  
file:a/public/js/a.js (deleted)
var host = "/";  
 
function loadJs(i,s,o,g,c){  
a=s.createElement(o);m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m);  
a.onload=function(){  
c();  
}  
}  
loadJs(window,document,'script','/socket.io-client/socket.io.js', function(){NRTTAdmin()});  
 
function NRTTAdmin(){  
var animate = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {  
window.setTimeout(callback, 1000 / 60)  
};  
var canvas = document.createElement("canvas");  
var width = 1920;  
var height = 1080;  
canvas.width = width;  
canvas.height = height;  
var ctx = canvas.getContext('2d');  
 
var div = document.getElementById("canvas");  
document.body.insertBefore(canvas, div);  
 
var clicks = [];  
var moves = [];  
 
var step = function () {  
render();  
animate(step);  
};  
 
function render(){  
ctx.clearRect(0, 0, width, height);  
for(key in clicks) {  
click = clicks[key];  
if (click.time < Date.now()) {  
clicks.splice(key, 1);  
}  
ctx.globalAlpha = 0.5;  
ctx.beginPath();  
ctx.fillStyle = click.color;  
ctx.arc(click.x, click.y, 4, 0, 2 * Math.PI, true);  
ctx.fill();  
ctx.lineWidth = 0.5;  
ctx.strokeStyle = '#003300';  
ctx.stroke();  
}  
for(key in moves) {  
move = moves[key];  
if (move.time < Date.now()) {  
moves.splice(key, 1);  
}  
ctx.beginPath();  
ctx.moveTo(move[0].x, move[0].y);  
ctx.lineTo(move[1].x, move[1].y);  
ctx.stroke();  
}  
}  
 
animate(step);  
 
var aSocket = io();  
aSocket.emit('t:connect', {w:window.width, h:window.height, admin:1234});  
aSocket.on('t:click', function(click){  
click.time = Date.now() + 15000;  
clicks.push(click);  
});  
aSocket.on('t:mousemove', function(move){  
move.time = Date.now() + 15000;  
moves.push(move);  
});  
aSocket.on('disconnect', function(){  
});  
}  
 
file:a/public/js/c.js (deleted)
var host = "/";  
 
function loadJs(i,s,o,g,c){  
a=s.createElement(o);m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m);  
a.onload=function(){  
c();  
}  
}  
loadJs(window,document,'script',host + 'socket.io-client/socket.io.js', function(){NRTT()});  
 
function NRTT() {  
var connected = false;  
 
var mouseAction = {enabled: false, interval:100};  
var clickAction = {enabled : true};  
 
var cursorX, cursorY;  
document.onmousemove = function(e){  
cursorX = e.pageX;  
cursorY = e.pageY;  
}  
document.onclick = function(e){  
if (connected && clickAction.enabled) {  
cSocket.emit('t:click', {x:e.pageX, y:e.pageY});  
}  
}  
var cSocket = io();  
var color = null;  
if(typeof(Storage) !== "undefined") {  
color = localStorage.getItem('tcolor');  
}  
cSocket.emit('t:connect', {w:window.width, h:window.height, color:color});  
cSocket.on('t:connected', function(msg){  
connected = true;  
if(typeof(Storage) !== "undefined") {  
if (msg.color) {  
localStorage.setItem("tcolor", msg.color);  
}  
}  
});  
cSocket.on('disconnect', function(){  
connected = false;  
});  
cSocket.on('t:changemm', function(msg){  
mouseAction = msg;  
});  
 
cSocket.on('t:changec', function(msg){  
clickAction = msg;  
});  
 
setInterval(function(){  
if (connected && mouseAction.enabled) {  
cSocket.emit('t:mousemove', {x:cursorX,y:cursorY});  
}  
}, mouseAction.interval);  
}  
 
file:b/src/admin.html (new)
  <!DOCTYPE html>
  <html>
  <head>
  <meta charset='utf-8'>
  <meta content='IE=edge' http-equiv='X-UA-Compatible'>
  <meta content='width=device-width,initial-scale=1' name='viewport'>
  <title>Tracking</title>
  </head>
  <body>
  <iframe src="" width="100%" height="2000" frameborder="0" scrolling="no" seamless="seamless"></iframe>
  <div id="div" style=""></div>
  <script type="text/javascript">
  (function(i,s,o,g){a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','/js/a.js');
  </script>
  </body>
  </html>
file:b/src/index.html (new)
  <!DOCTYPE html>
  <html>
  <head>
  <meta charset='utf-8'>
  <meta content='IE=edge' http-equiv='X-UA-Compatible'>
  <meta content='width=device-width,initial-scale=1' name='viewport'>
  <title>Tracking</title>
  </head>
  <body>
  <div id="div"></div>
  <script type="text/javascript">
  (function(i,s,o,g){a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','/js/a.js');
  (function(i,s,o,g){a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','/js/c.js');
  </script>
 
  </body>
  </html>
file:b/src/js/a.js (new)
  var host = "/";
 
  function loadJs(i,s,o,g,c){
  a=s.createElement(o);m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m);
  a.onload=function(){
  c();
  }
  }
  loadJs(window,document,'script','/socket.io-client/socket.io.js', function(){NRTTAdmin()});
 
  var viewportwidth;
  var viewportheight;
 
  function onResize() {
  // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
  if (typeof window.innerWidth != 'undefined')
  {
  viewportwidth = window.innerWidth,
  viewportheight = window.innerHeight
  }
  // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
  else if (typeof document.documentElement != 'undefined'
  && typeof document.documentElement.clientWidth !=
  'undefined' && document.documentElement.clientWidth != 0)
  {
  viewportwidth = document.documentElement.clientWidth,
  viewportheight = document.documentElement.clientHeight
  }
  // older versions of IE
  else
  {
  viewportwidth = document.getElementsByTagName('body')[0].clientWidth,
  viewportheight = document.getElementsByTagName('body')[0].clientHeight
  }
  canvas.width = viewportwidth;
  }
 
  function NRTTAdmin(){
  var animate = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {
  window.setTimeout(callback, 1000 / 60)
  };
  canvas = document.createElement("canvas");
  onResize();
  window.onresize = onResize;
  canvas.style = 'position:absolute;top:0;left:0';
  var width = viewportwidth;
  var height = 5000;
  canvas.width = width;
  canvas.height = height;
  var ctx = canvas.getContext('2d');
 
  var div = document.getElementById("canvas");
  document.body.insertBefore(canvas, div);
 
  var clicks = [];
  var moves = [];
  var cursorX, cursorY;
  document.onmousemove = function(e){
  cursorX = - viewportwidth/2 + e.pageX;
  cursorY = e.pageY;
  }
 
  document.onclick = function(e){
  var _cursorX = - viewportwidth/2 + e.pageX;
  var _cursorY = e.pageY;
  console.log (_cursorX + " " + _cursorY);
  }
 
  var step = function () {
  render();
  animate(step);
  };
 
  function render(){
  ctx.clearRect(0, 0, width, height);
  for(key in clicks) {
  click = clicks[key];
  var x = viewportwidth/2 + click.x;
  if (click.time < Date.now()) {
  clicks.splice(key, 1);
  }
  ctx.globalAlpha = 0.5;
  ctx.beginPath();
  if (cursorX >= click.x - 4 && cursorX <= click.x + 4 && cursorY >= click.y - 4 && cursorY <= click.y + 4) {
  ctx.strokeStyle = '#EBC167';
  ctx.fillStyle = '#EB1C8A';
  } else {
  ctx.strokeStyle = '#003300';
  ctx.fillStyle = click.color;
  }
  ctx.arc(x, click.y, 4, 0, 2 * Math.PI, true);
  ctx.fill();
  ctx.lineWidth = 0.5;
  ctx.stroke();
  }
  for(key in moves) {
  move = moves[key];
  if (move.time < Date.now()) {
  moves.splice(key, 1);
  }
  ctx.beginPath();
  ctx.strokeStyle = '#000000';
  x0 = viewportwidth/2 + move[0].x;
  x1 = viewportwidth/2 + move[1].x;
  ctx.moveTo(x0, move[0].y);
  ctx.lineTo(x1, move[1].y);
  ctx.stroke();
  }
  }
 
  animate(step);
 
  var aSocket = io();
  aSocket.emit('t:connect', {w:window.width, h:window.height, admin:1234});
  aSocket.on('t:click', function(click){
  click.time = Date.now() + 150000;
  clicks.push(click);
  });
  var xx = 1;
  aSocket.on('t:mousemove', function(move){
  move[0].time = Date.now() + 150000;
  move[1].time = Date.now() + 150000;
  moves.push(move);
  });
  aSocket.on('t:resolutions', function(resolutions){
  //console.log (resolutions);
  });
  aSocket.on('disconnect', function(){
  });
  }
 
file:b/src/js/c.js (new)
  var host = "http://node.dev.webstyler.ro/";
 
  /*function loadJs(i,s,o,g,c){
  a=s.createElement(o);m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m);
  a.onload=function(){
  c();
  }
  }
  loadJs(window,document,'script',host + 'socket.io-client/socket.io.js', function(){NRTT()});*/
 
  function NRTT() {
  var connected = false;
 
  var mouseAction = {enabled: true, interval:500};
  var clickAction = {enabled : true};
 
  var viewportwidth;
  var viewportheight;
 
  // the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
 
  if (typeof window.innerWidth != 'undefined')
  {
  viewportwidth = window.innerWidth,
  viewportheight = window.innerHeight
  }
 
  // IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)
 
  else if (typeof document.documentElement != 'undefined'
  && typeof document.documentElement.clientWidth !=
  'undefined' && document.documentElement.clientWidth != 0)
  {
  viewportwidth = document.documentElement.clientWidth,
  viewportheight = document.documentElement.clientHeight
  }
 
  // older versions of IE
 
  else
  {
  viewportwidth = document.getElementsByTagName('body')[0].clientWidth,
  viewportheight = document.getElementsByTagName('body')[0].clientHeight
  }
 
  var cursorX, cursorY;
  document.onmousemove = function(e){
  cursorX = e.pageX;
  cursorY = e.pageY;
  }
  document.onclick = function(e){
  if (connected && clickAction.enabled) {
  var x = - viewportwidth/2 + e.pageX;
  cSocket.emit('t:click', {x:x, y:e.pageY, url:window.location.href});
  }
  }
  var cSocket = io(host);
  var color = null;
  if(typeof(Storage) !== "undefined") {
  color = localStorage.getItem('tcolor');
  }
  cSocket.emit('t:connect', {w:viewportwidth, h:viewportheight, color:color});
  cSocket.on('t:connected', function(msg){
  connected = true;
  if(typeof(Storage) !== "undefined") {
  if (msg.color) {
  localStorage.setItem("tcolor", msg.color);
  }
  }
  });
  cSocket.on('disconnect', function(){
  connected = false;
  });
  cSocket.on('t:changemm', function(msg){
  mouseAction = msg;
  });
 
  cSocket.on('t:changec', function(msg){
  clickAction = msg;
  });
 
  setInterval(function(){
  if (connected && mouseAction.enabled) {
  var x = - viewportwidth/2 + cursorX;
  cSocket.emit('t:mousemove', {x:x, y:cursorY, url:window.location.href});
  }
  }, mouseAction.interval);
  }
  NRTT();
comments