Avoid
Avoid

Reputation: 402

Node.js Server - how to pass buttonclick function from client to client

What I'm trying to do is something like little chat taht I already made with some help. But what I want rly is taht when clicing on button1 (oppens new page) client1 passes buttonclick to client2 and same action happens on client2 (opens new page), something like remote control.

var nowjs = require('now');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
    res.sendFile(__dirname + '/startHTM.htm');
});

io.on('connection', function(socket){
    socket.on('chat message', function(msg){
        io.emit('chat message', msg);
    });
});

http.listen(8080, function(){
    console.log('listening on *:8080');
});

<!doctype html>
<html>
    <head>
        <title>Socket.IO chat</title>
        <style>
            * { margin: 0; padding: 0; box-sizing: border-box; }
            body { font: 13px Helvetica, Arial; }
            form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
            form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
            form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
            #messages { list-style-type: none; margin: 0; padding: 0; }
            #messages li { padding: 5px 10px; }
            #messages li:nth-child(odd) { background: #eee; }
        </style>
    </head>

    <body>
        <ul id="messages"></ul>
        <form action="">
            <input id="m" autocomplete="off" /><button>Send</button>
        </form>
        <script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
    var socket = io();
    $('form').submit(function(){
        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
    });
    socket.on('chat message', function(msg){
        $('#messages').append($('<li>').text(msg));
    });
</script>
    </body>
</html>

Thx for further help!

Upvotes: 0

Views: 1310

Answers (1)

rsp
rsp

Reputation: 111506

Here are few ideas to get you started:

You need to listen for every click event, either on the page itself and send coordinates of the click to the server, or listen for click events on elements and send e.g. an element id with every click event to the server.

The server needs to emit that event to every client except the originating one.

All clients that recieve such an event from the server need to simulate a click event.

I'll try to write a simple demo - I'll update the answer when I have a working example.

Update

Take a look at this example on GitHub:

It has a simple Socket.IO server in app.js:

var path = require('path');
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.use(express.static(path.join(__dirname, 'html')));

io.on('connection', s => {
  console.error('socket.io connection');
  s.on('click', d => {
    console.error('click on id '+d.id);
    s.broadcast.emit('click', d);
  });
});

http.listen(3002, () => console.error('Listening on http://localhost:3002/'));

See: https://github.com/rsp/node-socket.io-remote/blob/master/app.js

And client code in html/index.html using jQuery like in your question:

var ownClick = true;
var s = io();
s.on('connect_error', function (m) { log("error"); });
s.on('connect', function (m) { log("socket.io connection open"); });
s.on('message', function (m) { log(m); });
s.on('click', function (d) {
  log('received click message, id ' + d.id);
  ownClick = false;
  $('#'+d.id)[0].click();
  ownClick = true;
});

$('.remote').click(function (e) {
  if (ownClick) {
    log('emitting click message, id ' + e.target.id);
    s.emit('click', {id: e.target.id});
  }
});

(The log() function is defined in the source but I don't include it here for simplicity)

See: https://github.com/rsp/node-socket.io-remote/blob/master/html/index.html

Important issues

There are few important issues here:

There is a line with:

$('#'+d.id)[0].click();

and not:

$('#'+d.id).click();

because we want to run a native browser's click() method instead of the jQuery one, which would work differently.

Also I have a ownClick variable normally set to true except when running a handler for incoming remote click event. That is because we won't to send that event again to other windows. For this example it is not really needed because we are leaving the page with every click but if we stayed on the page then the events would cascade: for example if we had 3 windows and one of them sent a click to the other two, those two would start emulating their own clicks and send those clicks again to the server and again, and again with no end.

Here I am making only the elements with class "remote" remotely clickable, mostly because otherwise clicking the link to open new window with that page would click that link in all open windows opening more pages in the process, leading to browser warnings about too many popups, but instead of $('.remote') you could use $('a') to select all links if you want.

In this example only links with defined IDs will work, because those IDs are sent with the Socket.IO messages.

Upvotes: 1

Related Questions