Node JS Express Socket IO Chat Application Example

Node JS Express Socket IO Chat Application Example

Creating a chat application using express js framework of node js is very easy, for this, you just need to create a project of node js and then install express js, socket.io, and some necessary packages, and using these, you can build real time chat application built in Node JS with socket.io.

A step-by-step guide on how to build real-time chat application using nodejs with socket.io, jquery, and expressjs.

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
cd mkdir public

Important Note:- Go to your project root directory and create a directory name public.

Step 3 – Create Index.html and Style.css

In this step, you need to create index.html file inside public directory and add the following code in 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 inside public directory 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 inside public directory and add the following code in 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, '/public')));

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 the development server:

//run the below command

npm start

after run this command open your browser and hit 

http://127.0.0.1:4000/

The chat.js, sytle.css, and index.html files need to be placed in a public directory, which will be in the root directory of your node js chat project. Or if there is no public folder in the root directory of your node js project then create it. And keep chat.js, sytle.css, and index.html files in it.

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

Greetings, I'm Devendra Dode, a full-stack developer, entrepreneur, and the proud owner of Tutsmake.com. My passion lies in crafting informative tutorials and offering valuable tips to assist fellow developers on their coding journey. Within my content, I cover a spectrum of technologies, including 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. Whether you're starting out or looking for advanced examples, I provide step-by-step guides and practical demonstrations to make your learning experience seamless. Let's explore the diverse realms of coding together.

Leave a Reply

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