Node JS Express Socket IO Chat Application Example

Real time chat with nodejs socket.io and expressjs. In this tutorial, you will learn how to build real time chat with nodejs socket.io, jquery and expressjs.

This tutorial will help you step by step to on how to build chat application using Nodejs, Express and Socket.IO.

How to build chat application using Nodejs, Express and Socket.IO

Follow the following steps and create chat application using Nodejs, Express and Socket.IO:

  • Step 1 – Create Chat App Directory
  • Step 2 – Install Node Express JS, Socket.io and jQuery
  • Step 3 – Create Index.html and Style.css
  • Step 4 – Create Chat.js
  • Step 5 – Create index.js
  • Step 6 – Run Development Server

Step 1 – Create Chat App Directory

In this step, open your terminal and execute the following command to create chat app directory:

mkdir chat-app

Step 2 – Install Node Express JS, Socket.io and jQuery

In this step, you need to install node js express and jquery in your chat-app. So, execute the following command:

cd chat-app
npm init
npm install
npm install express
npm install jquery
npm install socket.io

Step 3 – Create Index.html and Style.css

In this step, you need to create index.html file and add the following code into it:

<!doctype html>
<html>
<head> <title>Nodejs Chat</title> <link rel="stylesheet" href="style.css">
</head>
<body> <ul class="pages"> <li class="chat page"> <div class="chat_area"> <ul class="messages"></ul> </div> <input class="input_message" placeholder="Type here..."/> </li> <li class="login page"> <div class="form"> <h3 class="title">What's your nickname?</h3> <input class="username_input" type="text" maxlength="14" /> </div> </li> </ul> <script src="//code.jquery.com/jquery-3.5.0.js"></script> <script src="/socket.io/socket.io.js"></script> <script src="/chat.js"></script>
</body>
</html>

After that, create style.css file and add the following code into it:

* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; } ul { list-style: none; word-wrap: break-word;
} .log { color: gray;
} .pages { height: 100%; /*margin: 0; padding: 0;*/ width: 100%;
} .page { height: 100%; position: absolute; width: 100%;
} .login.page { background-color: #000;
} .login.page .form { height: 100px; margin-top: -100px; position: absolute; text-align: center; top: 50%; width: 100%;
} .login.page .form .username_input { background-color: transparent; border: none; border-bottom: 2px solid #fff; outline: none; padding-bottom: 15px; text-align: center; width: 400px;
} .login.page .title { font-size: 200%;
} .login.page .username_input { font-size: 200%; letter-spacing: 3px;
} .login.page .title, .login.page .username_input { color: #fff; font-weight: 100;
} .chat.page { display: none;
} .input_message { font-size: 100%;
} .chat_area { height: 100%; padding-bottom: 60px;
} .messages { height: 100%; margin: 0; font-size: 150%; overflow-y: scroll; padding: 10px 20px 10px 20px;
} .message.typing .message_body { color: gray;
} .username { font-weight: 700; overflow: hidden; padding-right: 15px; text-align: right;
} .input_message { border: 10px solid #000; bottom: 0; height: 60px; left: 0; outline: none; padding-left: 10px; position: absolute; right: 0; width: 100%;
}

Step 4 – Create Chat.js

In this step, you need to create chat.js file and add the following code into it:

$(function() {
var win = $(window);
var usernameInput = $('.username_input'); // Input for username
var messages = $('.messages'); // Messages area
var inputMessage = $('.input_message'); // Input message input box
var loginPage = $('.login.page'); // The login page
var chatPage = $('.chat.page'); // The chatroom page
var username;
var connected = false;
var typing = false;
var currentInput = usernameInput.focus();
var socket = io();
const setParticipantsMessage = (data) => {
var message = '';
if (data.numberOfUsers === 1) {
message += "There is 1 participant";
} else {
message += "There are " + data.numberOfUsers + " participants";
}
log(message);
}
const log = (message, options) => {
var el = $('<li>').addClass('log').text(message);
addMessageElement(el, options);
}
const setUsername = () => {
username = cleanInput(usernameInput.val().trim());
if (username) {
loginPage.fadeOut();
chatPage.show();
loginPage.off('click');
currentInput = inputMessage.focus();
socket.emit('user_added', username);
}
}
const sendMessage = () => {
var message = cleanInput(inputMessage.val());
if (message && connected) {
inputMessage.val('');
addChatMessage({
username: username,
message: message
});
socket.emit('new_message', message);
}
}
const addChatMessage = (data, options) => {
var typingMessages = getTypingMessages(data);
options = options || {};
if (typingMessages.length !== 0) {
options.fade = false;
typingMessages.remove();
}
var usernameDiv = $('<span class="username"/>').text(data.username).css('font-weight', 'bold');
var messageBodyDiv = $('<span class="messageBody">').text(data.message);
var typingClass = data.typing ? 'typing' : '';
var messageDiv = $('<li class="message"/>').data('username', data.username).addClass(typingClass).append(usernameDiv, messageBodyDiv);
addMessageElement(messageDiv, options);
}
const addChatTyping = (data) => {
data.typing = true;
data.message = 'is typing';
addChatMessage(data);
}
const removeChatTyping = (data) => {
getTypingMessages(data).fadeOut(function () {
$(this).remove();
});
}
const addMessageElement = (el, options) => {
var el = $(el);
// Setup default options
if (!options) {
options = {};
}
if (typeof options.fade === 'undefined') {
options.fade = true;
}
if (typeof options.prepend === 'undefined') {
options.prepend = false;
}
// Apply options
if (options.fade) {
el.hide().fadeIn(150);
}
if (options.prepend) {
messages.prepend(el);
} else {
messages.append(el);
}
messages[0].scrollTop = messages[0].scrollHeight;
}
const cleanInput = (input) => {
return $('<div/>').text(input).html();
}
const updateTyping = () => {
if (connected) {
if (!typing) {
typing = true;
socket.emit('typing');
}
}
}
const getTypingMessages = (data) => {
return $('.typing.message').filter(function (i) {
return $(this).data('username') === data.username;
});
}
win.keydown(event => {
//console.log('event.which: ' + event.which);
// Auto-focus the current input when a key is typed
if (!(event.ctrlKey || event.metaKey || event.altKey)) {
currentInput.focus();
}
// When the client hits ENTER on their keyboard
if (event.which === 13) {
if (username) {
sendMessage();
socket.emit('typing_stop');
typing = false;
} else {
setUsername();
}
}
});
inputMessage.on('input', () => {
updateTyping();
});
loginPage.click(() => {
currentInput.focus();
});
inputMessage.click(() => {
inputMessage.focus();
});
socket.on('login', (data) => {
connected = true;
var message = "Welcome to Nodejs Chat Room";
log(message, {
prepend: true
});
setParticipantsMessage(data);
});
socket.on('new_message', (data) => {
addChatMessage(data);
});
socket.on('user_joined', (data) => {
log(data.username + ' joined');
setParticipantsMessage(data);
});
socket.on('user_left', (data) => {
log(data.username + ' left');
setParticipantsMessage(data);
removeChatTyping(data);
});
socket.on('typing', (data) => {
addChatTyping(data);
});
socket.on('typing_stop', (data) => {
removeChatTyping(data);
});
socket.on('disconnect', () => {
log('You have been disconnected');
});
socket.on('reconnect', () => {
log('You have been reconnected');
if (username) {
socket.emit('user_added', username);
}
});
socket.on('reconnect_error', () => {
log('Attempt to reconnect has failed');
});
});

Note that, The chat.js functions will works, as following:

  • The function setParticipantsMessage() displays the total number of participants currently in the chat room.
  • log() function logs the message in gray color text on chat window.
  • setUsername() function displays the user name on the chat window once he/she enter the name on initial screen where it asks for nick name.
  • sendMessage() sends the or broadcast the message to the active participants.
  • addChatMessage() adds the message to the chat window. While someone is typing it shows the person is typing otherwise once typing is done it sends the message to the window.
  • addChatTyping() shows while someone is typing.
  • removeChatTyping() removes typing once someone has just finished typing and hit the enter key.
  • win.keydown determines the events and accordingly it works with the events.

Step 5 – Create index.js

In this step, you need to open index.js file and add the following code into it:

var path = require('path');
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 4000;
server.listen(port, function(){
console.log('Listening on %d:' + port);
});
app.use(express.static(path.join(__dirname, 'static')));
var numberOfUsers = 0;
io.on('connection', (socket) => {
var userJoined = false;
socket.on('new_message', (msg) => {
socket.broadcast.emit('new_message', {
username: socket.username,
message: msg
});
});
socket.on('user_added', (username) => {
if (userJoined) return;
socket.username = username;
userJoined = true;
numberOfUsers++;
socket.emit('login', {
numberOfUsers: numberOfUsers
});
socket.broadcast.emit('user_joined', {
username: socket.username,
numberOfUsers: numberOfUsers
});
});
socket.on('typing', () => {
socket.broadcast.emit('typing', {
username: socket.username
});
});
socket.on('typing_stop', () => {
socket.broadcast.emit('typing_stop', {
username: socket.username
});
});
socket.on('disconnect', () => {
if (userJoined) {
--numberOfUsers;
socket.broadcast.emit('user_left', {
username: socket.username,
numberOfUsers: numberOfUsers
});
}
});
});

Step 6: Run Development Server

You can use the following command to run development server:

//run the below command
npm start
after run this command open your browser and hit http://127.0.0.1:3000/

Conclusion

Real-time chat with node js socket.io and express js. In this tutorial, you have learned how to build real-time chat with node js socket.io, jquery and express js.

Recommended Node Js Tutorials

Related Posts