Creating a Simple Live Chat in Express

The socket.IO enables real-time bidirectional event-based communication. It works on every platform, browser or device, focusing equally on reliability and speed. The socket.io middleware has two part.
  1. Node.js server in our case app.js where we include all our server code.
  2. Node.js client or A Javascript client library for the browser. 

To create a simple chat in our Express web app, we will follow the following steps. From step 1 to 3, we will create a page for the chat. In creating the chart, the first we have to create a view and route for the chat page. Once the chart page is created, we have to write Javascript code in app/public/js/chat. js file to monitor the chat form these tasks include

  1. Adding an event listener in the chat form for submit event.
  2. Taking chat submit messages and displaying into the message section of chat page.

Step 1: We will add a route for chat in our app.js is server code

app.use(require('./routes/chat'));

Step 2: Add the routing code for our chat page in app/routes/chat.js

var express = require('express');
var router = express.Router();

router.get('/chat', function(req, res) {
  res.render('chat', {
    pageTitle: 'Chat',
    pageID: 'chat'
  });
});

module.exports = router;

Step 3: Once we route to http://localhost:3000/chat, we will have to add a view for our route for chat in app/views/chat.ejs

<!DOCTYPE html>
<html>
  <head><% include partials/template/head.ejs %></head>
  <body id="<%= pageID %>">
    <% include partials/template/header.ejs %>
     <div class="container">
      <div class="row">
        <div class="col-sm-12">
          <article class="chat">
            <header class="chat-header">
              <div class="h3 chat-title">Roux Chat</div> <!-- chat-title -->
            </header> <!-- chat-header -->
            <form name="chatForm" class="form-horizontal chat-form">
              <div class="form-group">
                <label for="chat-username" class="col-sm-2 control-label">Name</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="chat-username" required placeholder="Enter your name">
                </div><!-- col-sm-10 -->
              </div><!-- form-group -->
              <div class="form-group">
                <label for="chat-message" class="col-sm-2 control-label">Message</label>
                <div class="col-sm-10">
                  <div class="input-group">
                    <input type="text" placeholder="Enter a message, then press enter" class="form-control" id="chat-message" rows="2" autocomplete="off"
                     required>
                    <span class="input-group-btn">
                      <button id="chat-submit" class="btn btn-info" type="submit">Chat</button>
                    </span>
                  </div> <!-- input-group -->
                </div> <!-- col-sm-10 -->
              </div> <!-- form-group -->
            </form>
            <div class="panel panel-default">
              <div class="panel-body chat-display">
                <p class="text-muted chat-text">Welcome...add your message using the form above</p>
              </div> <!-- panel-body -->
            </div> <!-- panel-default -->
          </article> <!-- article -->
        </div> <!-- col-sm-12 -->
      </div> <!-- row -->
    </div> <!-- container -->
    <% include partials/template/jsdefaults.ejs %>
  </body>
</html>

Step 4: Install socket.io middleware, we have to add client code for our socket.io middleware. We will add an event listener to our chat form. The socket.io allows us to communicate with client and server, also allow our client to know that there is the connection with other users.
>npm install –save socket.io

We need to add require module of the socket.io middleware in app.js.

var express = require('express');
var reload = require('reload')
var app = express();

var io = require('socket.io')();

app.set('port', process.env.PORT || 3000); 
app.set('view engine', 'ejs');
app.set('views', 'app/views');

app.locals.siteTitle = 'Tamo M';

app.use(express.static('app/public'));
app.use(require('./routes/index'));
app.use(require('./routes/feedback'));
app.use(require('./routes/api'));
app.use(require('./routes/chat'));

var server = app.listen(app.get('port'), function(){
    console.log('Listening on port' + app.get('port'));
});

io.attach(server);
io.on('connection', function(socket) {     
  socket.on('postMessage', function(data) {    
    io.emit('updateMessages', data);           
  });
});

reload(server, app);

We need to connect our server to socket.io and in the code, we have io.on(‘connection’, function(socket), Whenever a browser connects to the server we will detect event with this function and socket is parameter contain information about the connection.  

We have to add socket.io client side script in app/view/partials/template/jsdefaults.ejs, we can get this socket.io client code from http:socket.io

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>

<% if(typeof artwork !== "undefined") { %>
  <script src="/js/pixgrid.js"></script>
<% } %>

<% if(pageID == 'feedback') { %>
  <script src="/js/feedback.js"></script>
<% } %>

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<script src="/js/chat.js"></script>
<script src="/reload/reload.js"></script>

 

Step 5: We have to add or modify our app/public/js/chat.js file

var socket = io();
var chatUsername = document.querySelector('#chat-username');
var chatMessage = document.querySelector('#chat-message');

socket.on('connect', function() {
  var chatForm = document.forms.chatForm;

  if (chatForm) {
    chatForm.addEventListener('submit', function(e) {
      e.preventDefault();
      socket.emit('postMessage',{
        username: chatUsername.value,
        message: chatMessage.value,
      });
      chatMessage.value='';
      chatMessage.focus();
    }); //chatform event

    socket.on('updateMessages', function(data) {
      showMessage(data);
    }); //updateMessages
  } //chatform
}); //socket

function showMessage(data) {
  var chatDisplay = document.querySelector('.chat-display');
  var newMessage = document.createElement('p');

  if (chatUsername.value == data.username) {
    newMessage.className = 'bg-success chat-text';
  } else {
    newMessage.className = 'bg-info text-warning chat-text';
  }

  newMessage.innerHTML = '<strong>' + data.username + '</strong>: ' + data.message;
  chatDisplay.insertBefore(newMessage, chatDisplay.firstChild);
}

The socket.on(‘connect’, function() { …}) this function will only execute when there is connection. To communicate between different browser or client that are connected to our app, we will emit a custom event when a new browser connects and submit chat message to the server.  We will emit socket.emit(‘postMessage’,{ …}) event called postMessage to the server and passing client name and message with this event. 

Inside the server or app.js, we have to detect our postMessage event that has happened. In app.js we had already added our code to detect the postMessage event. We are collecting the first message from the client and sending it to the server so that it can send the chat message to all other connected clients to our apps.

io.on('connection', function(socket) {     
  socket.on('postMessage', function(data) {    
    io.emit('updateMessages', data);           
  })

Once the postMessage event is detected, we will emit another custom event called updateMessages in app.js or server with help of io.emit(‘updateMessages’, data),  and this event will issue a message to all the connected devices.

At last, we have to capture the updateMessage event in app/public/js/chat.js file.

socket.on('updateMessages', function(data) {
      showMessage(data);
    }); 

The updateMessage, in turn, call showMessage with data as parameter containing both name and chat message. We will use showMessage function to display all message in all the connected browser.