Faisal Faisal - 3 months ago 24
Node.js Question

Sending mouse click events using socket.io

I'm trying to emit a mouse click event from the client side to the server using socket.io and node.js. The problem is that after emitting, the dictionary I am sending is not being sent as a whole. Here's my code:

client side:

document.addEventListener('click', function(event){
console.log("event sent", event.target,event);
var target = event.target;
var myClick = {id: target, event: event};
console.log(myClick);
socket.emit('myClick', myClick);
})

socket.on('myClick', function(data){
console.log("event received", data);
document.querySelectorAll(data.id).dispatchEvent(data.event);
});


The console logs this after a click event is registered on the body:

event sent <body>​…​</body>​
MouseEvent {isTrusted: true, screenX: 1145, screenY: 499, clientX: 1040, clientY: 398…}
Object {id: body, event: MouseEvent}


Other pages log this after they receive the event:

event received Object {id: Object, event: Object}


However, expanding Object gives us this:

event: Object
isTrusted: true
__proto__: Object
id: Object
__proto__: Object
__proto__: Object


So it is not receiving the whole event and id does not have the event target.

Server side:

io.sockets.on('connection', function (socket) {
console.log("socket connected");
console.log(socket);
socket.on('myClick', function (data) {

console.log("myClick in server.js");
console.log(socket);
console.log(data);
socket.broadcast.emit('myClick', data);
});
});


When the server recevies something on 'myClick' it print outs this:

myClick in server.js
{ id: {}, event: { isTrusted: true } }


As you can see, the target is empty, and what is supposed to be the full event object only has the isTrusted value. Has anyone faced this problem before? Any help would be appreciated. The way I was trying to do this is based on this stackoverflow answer, but they were using jQuery and I am just using javascript.

Answer

socket.io attempts to convert the arguments you pass it to JSON. Some things like DOM objects cannot be converted to JSON and either trigger errors or cause things to be ignored. So, you can't send event.target. It's a DOM object and you can't send a DOM object to your server. You must send something that can be converted to a string. For example you could send event.target.id.

What I would suggest you do is rather than trying to send the entire event object which contains many things which cannot be sent (such as DOM objects), create a new object and copy over just the properties you actually need to send. And, make sure things you are sending do not contain DOM objects and do not contain any circular references or other things that can't be converted to JSON.

I don't know exactly which properties from the event object you need, but here's' the general idea:

document.addEventListener('click', function(event){
  // create new object with just the things we need from the event object
  // this must contain only things that can be converted into JSON
  var clickData = {
     id: event.target.id, 
     timeStamp: event.timeStamp,
     type: event.type,
     clientX: event.clientX,
     clientY: event.clientY
  };
  socket.emit('myClick', clickData);
});
Comments