25 Feb 2016

Broadcast Mouse Over event with Socket.IO

Default blog image

Follow me @augustomaia

The post from last week, about Mouse Over, was a first step to create a sample with Socket.IO library for NodeJS. The main idea is: a 'master' user will have a 3D model with the location of each 'participant'. Once the 'master' move around, the mouse over event should notify each 'participant'. So we need a controlling server, a 'master' page with the 3D model and, finally, a 'participant' page that only received the notification.

First of all, call npm install socket.io and it should be ready to go.

The server side should have (server.js) 

var express = require('express');
var http = require('http');

// prepare the socket.io listener
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);

// and the port number: FORGE - 36743 :-)
server.listen(36743);

// now the messages
io.on('connection', function (socket) {

    // this handles the JOIN message
    socket.on('join', function (data) {
        // let's record each user by their email
        socket.join(data.email);
    });

    // this handle the MOUSE OVER message, from the V&D
    socket.on('mouseover', function (data) {
        var connectedUser = io.sockets.in(data.email);
        if (connectedUser != null)
            connectedUser.emit('newhighlight', {
                email : data.email
            });
    });
});

Now the master client-side script, starting from the previous highlight post: call emitMessage from onMouseOver passing the dbId.

Note you'll need a 3D model with a property that contains the emails you're expecting (or any other information that indicates where the mouse is):

var _lastEmail = '';

function emitMessage(dbId) {
    _viewer.model.getProperties(dbId, function (props) {
        props.properties.forEach(function (prop) {
            if (prop.displayName.indexOf('email') >= 0) {
                if (prop.displayValue != _lastEmail) { // avoid duplicated messages
                    _lastEmail = prop.displayValue;

                    // sent the message!
                    var socket = io.connect('http://localhost:36743');
                    socket.emit('mouseover', {
                        email: _lastEmail;
                    });
                }
            }
        });
    });
}

Finally the 'participant' that receives the message:

<!DOCTYPE html>
<html>

<head>
    <title>Socket.IO sample</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/css/bootstrap.min.css">
    <style>
        .vertical-center {
            min-height: 100%;
            /* Fallback for browsers do NOT support vh unit */
            min-height: 100vh;
            /* These two lines are counted as one :-)       */
            display: flex;
            align-items: center;
        }
    </style>
</head>
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
    $(document).ready(function () {
        var socket = io.connect('http://localhost:36743');

        // join the broadcast
        $('#join').click(function () {
            socket.emit('join', {
                seat: $('#email').val()
            });
            $('#inputForm').hide();
        });

        // message received!
        socket.on('newhighlight', function (data) {
            alert('you are on the spot ' + data.email);
        });
    });
</script>

<body>
    <div class="vertical-center">
        <div id="inputForm" class="large container-fluid">
            <input type="text" id="email" class="form-control" placeholder="Enter your email" />
            <button id="join" class="btn-lg btn-primary">Join</button>
        </div>
    </div>
</body>
</html>

Important: remember to replace 'localhost' with your server address! 

And yes, this sample is using jQuery and Bootstrap. If you haven't used them, check it out! It's a must! And here is how server them from NPM installed packages. 

This still a work in progress, but soon I'll have more to show! Stay tuned!

Related Article