├── .gitignore
├── README.md
├── package.json
├── static
├── dateTime.js
├── client.js
└── style.css
├── server.js
└── client.html
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # chat-room
2 | * A simple real time chat app using socket.io
3 | * Link to [chat-room](https://chat-room.adarshkumar35.repl.co)
4 |
5 | ## how to use?
6 | * clone the project into your local pc
7 | * run the command ``` npm install ``` to install all required dependencies
8 | * now run ``` node server.js ```
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nodejs",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@types/node": "^18.0.6",
14 | "express": "^4.18.2",
15 | "node-fetch": "^3.2.6",
16 | "socket.io": "^4.6.1"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/static/dateTime.js:
--------------------------------------------------------------------------------
1 | let month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
2 |
3 | function getTime() {
4 | let d = new Date();
5 |
6 | let time = {
7 | date: d.getDate(),
8 | month: month[d.getMonth() - 1],
9 | year: d.getFullYear(),
10 | hours: d.getHours(),
11 | minutes: d.getMinutes(),
12 | seconds: d.getSeconds(),
13 | meridiem: (d.getHours() < 13) ? 'AM' : 'PM'
14 | }
15 |
16 | return time;
17 | }
18 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const app = express();
3 |
4 | const path = require('path');
5 |
6 | app.use('/static', express.static(path.join(__dirname, 'static')));
7 | app.use(express.urlencoded());
8 |
9 | const http = require('http');
10 | const server = http.createServer(app);
11 |
12 | let users = {}
13 |
14 | const io = require('socket.io')(server);
15 | console.log('server started');
16 | // socket server
17 | io.on('connection', (socket) => {
18 | socket.on('disconnect', () => {
19 | if (users[socket.id] != undefined) {
20 | console.log(`${users[socket.id]} leaved`);
21 | socket.broadcast.emit('user leaved', `${users[socket.id]} leaved`);
22 | }
23 | else {
24 | console.log(`${users[socket.id]} leaved`);
25 | }
26 | });
27 |
28 | socket.on('user message', (sender, msg) => {
29 | socket.broadcast.emit('um', sender, msg);
30 | });
31 |
32 | socket.on('user name', (name) => {
33 | users[socket.id] = name;
34 | console.log(name, ' connected');
35 | console.log(`${users[socket.id]}'s id :`, socket.id);
36 | socket.broadcast.emit('un', name);
37 | });
38 | });
39 |
40 | app.get('/', (req, res) => {
41 | res.sendFile(__dirname + '/client.html');
42 | });
43 |
44 | // app.get('./send icon.svg', (req, res) => {
45 | // res.sendFile(__dirname + '/sendIcon.svg');
46 | // })
47 |
48 | server.listen(8000, () => {
49 | console.log('server running on port 8000');
50 | });
--------------------------------------------------------------------------------
/client.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Chat Room
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
42 |
43 |
44 |
45 |
46 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/static/client.js:
--------------------------------------------------------------------------------
1 | // messageContainer.children[messageContainer.childElementCount - 1]
2 |
3 | messageContainer = document.querySelector('.messageContainer');
4 |
5 | function displayMsg(sender, senderName, msg) {
6 | let newMsg = document.createElement('div');
7 | newMsg.setAttribute('class', `msg ${sender}`);
8 | // if (senderName == lastMsgSender) {
9 | // if (sender == 'mm') {
10 | // newMsg.innerHTML = `
11 | // ${msg}
`;
12 | // }
13 | // else {
14 | // newMsg.innerHTML = `
15 | // ${msg}
`;
16 | // }
17 | // console.log('same');
18 | // }
19 | // else {
20 | // newMsg.setAttribute('style', 'margin : 8px 0px 0px 0px');
21 | // if (sender == 'mm') {
22 | newMsg.innerHTML = `
23 |
24 |
@${senderName}
25 |
${getTime().date} ${getTime().month} ${getTime().year} ${getTime().hours}:${getTime().minutes}:${getTime().seconds} ${getTime().meridiem}
26 |
27 |
28 | ${msg}
`;
29 | // }
30 | // else {
31 | // newMsg.innerHTML = `
32 | // @${senderName}
33 | // ${msg}
`;
34 | // }
35 | console.log(getTime());
36 | // console.log('not same');
37 | // }
38 | // newMsgLine.appendChild(newMsg);
39 | messageContainer.appendChild(newMsg);
40 | messageContainer.scroll(0, messageContainer.scrollHeight);
41 | lastMsgSender = senderName;
42 | }
43 |
44 | function notify(notification) {
45 | let notifier = document.createElement('div');
46 | notifier.innerText = notification;
47 | notifier.setAttribute('class', 'notifier');
48 | messageContainer.appendChild(notifier);
49 | messageContainer.scroll(0, messageContainer.scrollHeight);
50 | }
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | name = getName('enter your name :');
59 | function getName(str) {
60 | let userName = prompt(str);
61 | if (userName == '' || userName == null) {
62 | getName('please specify your name to join the chat room :');
63 | }
64 | if (userName.length > 26) {
65 | getName(
66 | `sorry! can't set username.\nusername should contain less than 26 characters.`);
67 | }
68 | else {
69 | socket.emit('user name', userName);
70 | notify(`you joined the chat as ${userName}`);
71 | return userName;
72 | }
73 | }
74 |
75 | socket.on('un', (name) => {
76 | notify(`${name} joined the chat`);
77 | });
78 | socket.on('user leaved', (wholeaved) => {
79 | notify(wholeaved);
80 | });
81 |
82 | let form = document.querySelector('form');
83 | let message = document.querySelector('input');
84 | form.addEventListener('submit', (e) => {
85 | e.preventDefault();
86 | if (message.value != 0) {
87 | socket.emit('user message', name, message.value);
88 | displayMsg('mm', name, message.value);
89 | message.value = '';
90 | }
91 | });
92 |
93 | socket.on('um', (sender, msg) => {
94 | displayMsg('om', sender, msg);
95 | });
--------------------------------------------------------------------------------
/static/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | /* --themebg: #1e2b2b;
3 | --themebgdark : #121a1a;
4 | --themeclr: #d7d28a; */
5 | /* --hoverclr: #374c4c; */
6 |
7 | --themebg: #303440;
8 | --themebgdark: #121a1a;
9 | --themeclr: #8b8ad7;
10 | --hoverclr: #9caad724;
11 | }
12 | * {
13 | margin: 0;
14 | padding: 0;
15 | }
16 | html{
17 | overflow: auto;
18 | }
19 | .container {
20 | height: calc(100vh - 2px);
21 | background: #4c4c4c;
22 | display: flex;
23 | flex-direction: column;
24 | align-items: center;
25 | padding-top: 2px;
26 | }
27 |
28 | .chatContainer {
29 | /* background: #1c2333; */
30 | background-color: var(--themebg);
31 | height: 100%;
32 | width: 100%;
33 | display: flex;
34 | flex-direction: column;
35 | align-items: center;
36 | padding: 0px 0px 2px 0px;
37 | }
38 |
39 | .messageContainer {
40 | width: 96%;
41 | height: -webkit-fill-available;
42 | border-radius: 10px 10px 0px 0px;
43 | overflow: auto;
44 | padding: 0px 7px;
45 | }
46 |
47 | .msg {
48 | color: lightgrey;
49 | min-height: 52px;
50 | height: 52px;
51 | /* border-bottom: 1px solid #3c3c3c; */
52 | display: flex;
53 | align-items: center;
54 | padding-left: 10px;
55 | }
56 | .msg:hover{
57 | background: var(--hoverclr);
58 | }
59 | .msg.mm{
60 | background-color: transparent;
61 | }
62 | .msg.om{
63 | background-color: transparent;
64 | }
65 | .at{
66 | color: gray;
67 | }
68 | .sender {
69 | color: var(--themeclr);
70 | border-right: 1px solid gray;
71 | padding-right: 10px;
72 | padding-left: 10px;
73 | height: 80%;
74 | width: 10%;
75 | display: flex;
76 | flex-direction: column;
77 | justify-content: center;
78 | align-items: end;
79 | gap: 2px;
80 | }
81 | .s{
82 | font-size: 17px;
83 | }
84 | .time {
85 | font-size: 12px;
86 | color: gray;
87 | }
88 | .mm, .om{
89 | min-width: 86%;
90 | }
91 | .mm {
92 | /* background: #47598b; */
93 | padding-left: 10px;
94 | }
95 | .om {
96 | /* background: #47598b; */
97 | padding-left: 10px;
98 | }
99 | .notifier {
100 | color: #808080a6;
101 | border: 1px solid #80808087;
102 | background: transparent;
103 | height: 30px;
104 | display: flex;
105 | justify-content: center;
106 | align-items: center;
107 | border: none;
108 | border-bottom: 1px solid #3c3c3c87;
109 | border-top: 1px solid #3c3c3c87;
110 | }
111 |
112 | .sendMsg {
113 | width: 100%;
114 | height: 66px;
115 | position: sticky;
116 | bottom: 0;
117 | }
118 |
119 |
120 |
121 |
122 | /* new form style */
123 | form{
124 | border-top: 1px solid #3c445c;
125 | position: sticky;
126 | bottom: 0;
127 | padding: 0px 0px 0px 0px;
128 | background: #1c2333;
129 | }
130 | button{
131 | font-size: 26px !important;
132 | height: 94% !important;
133 | width: 10% !important;
134 | background: transparent !important;
135 | display: flex !important;
136 | justify-content: center !important;
137 | align-items: center !important;
138 | }
139 | i{
140 | color: #374058;
141 | }
142 |
143 | /* */
144 |
145 |
146 |
147 |
148 | form {
149 | width: 100%;
150 | height: 100%;
151 | display: flex;
152 | justify-content: center;
153 | align-items: center;
154 | }
155 |
156 | input {
157 | color: white;
158 | width: 85%;
159 | height: 51%;
160 | background: transparent;
161 | border: none;
162 | outline: none;
163 | padding-left: 20px;
164 | font-size: 18px;
165 | background: #2b3245;
166 | border-radius: 7px;
167 | margin-right: 30px;
168 | height: 57%;
169 | }
170 |
171 | button {
172 | height: 100%;
173 | width: 5%;
174 | font-size: 20px;
175 | font-family: system-ui;
176 | background: #e0e3ff;
177 | color: white;
178 | border: none;
179 | cursor: pointer;
180 | }
181 |
182 | .messageContainer::-webkit-scrollbar {
183 | background: transparent;
184 | width: 5px;
185 | }
186 |
187 | .messageContainer::-webkit-scrollbar-thumb {
188 | background: #ffffff26;
189 | border-radius: 4px;
190 | }
191 |
192 | @media (max-width: 600px) {
193 | .container {
194 | height: 100vh;
195 | }
196 |
197 | .container>h1 {
198 | font-size: 20px;
199 | }
200 |
201 | .chatContainer{
202 | background-size: cover;
203 | }
204 |
205 | .messageContainer {
206 | height: calc(100% - 30px);
207 | width: 100%;
208 | }
209 |
210 | .msg.mm, .msg.om{
211 | margin: 8px 0px 8px 0px;
212 | box-shadow: black 0px 0px 8px -2px;
213 | min-height: 70px;
214 | display: block;
215 | height: auto;
216 | padding-bottom: 8px;
217 | }
218 | .msg.mm{
219 | border-left: 2px solid #8688c5;
220 | }
221 | .msg.om{
222 | border-left: 2px solid #7cb7b7;
223 | }
224 | .sender{
225 | width: 91%;
226 | border-right: none;
227 | flex-direction: row;
228 | align-items: center;
229 | height: 27px;
230 | gap: 52%;
231 | padding: 0;
232 | }
233 |
234 | .notifier {
235 | height: 14px;
236 | font-size: 12px;
237 | /* min-width: auto;
238 | width: fit-content; */
239 | }
240 |
241 |
242 | input{
243 | margin: 10px 5px 10px 5px;
244 | width: 70%;
245 | }
246 |
247 | button {
248 | font-size: 16px;
249 | width: 12%;
250 | height: 90%;
251 | margin-right: 1px;
252 | }
253 | }
--------------------------------------------------------------------------------