Node JS Express Socket IO Chat Application Example

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 real time chat application using Node js, Express js and Socket.IO

Follow the following steps and build real time chat with node js socket.io and express js:

  • 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 -y
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

AuthorAdmin

My name is Devendra Dode. I am a full-stack developer, entrepreneur, and owner of Tutsmake.com. I like writing tutorials and tips that can help other developers. I share tutorials of PHP, Python, Javascript, JQuery, Laravel, Livewire, Codeigniter, Node JS, Express JS, Vue JS, Angular JS, React Js, MySQL, MongoDB, REST APIs, Windows, Xampp, Linux, Ubuntu, Amazon AWS, Composer, SEO, WordPress, SSL and Bootstrap from a starting stage. As well as demo example.

Leave a Reply

Your email address will not be published. Required fields are marked *