I'm working on basic chat-application running on express.js and socket.io.
Server-side code:
var express = require("express");
var app = express();
var server = require('http').createServer(app);
var io = require("socket.io").listen(server);
var path = require("path");
app.use(express.static(path.join(__dirname, "public")));
app.set("view engine", "ejs");
server.listen(process.env.PORT || 3000, function() {
console.log("Server listening");
})
app.get("/", function(req, res) {
res.render("chat");
})
io.sockets.addListener("connection", function(socket) {
socket.addListener("chat-message", function(message, nickname) {
io.sockets.emit("chat-message", message, nickname)
})
})
Client-side code:
var socket = io();
var nickname = prompt("Whats your name?");
var input = document.getElementById("text-input");
var container = document.getElementById("chat-container");
input.addEventListener("keydown", function() {
if (event.keyCode == 13) {
event.preventDefault();
if (input.value !== "") {
socket.emit("chat-message", nickname + ": " + input.value);
input.value = "";
}
}
})
socket.addEventListener("chat-message", function(message) {
container.innerHTML += message + "</br>";
})
Is there any way to avoid deleting info from the webpage after refresh?
You can save all the messages and nicknames in a globar variable and send them on every new connection to the socket.
var messages = [];
io.sockets.addListener("connection", function(socket) {
//send messages to new connection
socket.addListener("chat-message", function(message, nickname) {
messages.push({message: message, nickname: nickname});
io.sockets.emit("chat-message", message, nickname)
})
})
[Edit]
Client Side
socket.addEventListener("chat-previous-messages", function(messages) {
for(let i = 0; i < messages.length; i++){
container.innerHTML += messages[i].message + "</br>";
}
})
Server side
var messages = [];
io.sockets.addListener("connection", function(socket) {
socket.emit('chat-previous-messages', messages); //new code
socket.addListener("chat-message", function(message, nickname) {
messages.push({message: message, nickname: nickname});
io.sockets.emit("chat-message", message, nickname)
})
})
Or you can serve the chat page with the messages already displayed
app.get("/", function(req, res) {
res.render("chat", messages);
})
//in the html part something like this
#chat-container
- each message in messages
message.message + '<br>'
Related
Hi I am making a chat site with the url http://localhost/Seminarska%20naloga%20NRSA/index.php?stran=chat
Once the message is submitted the server doesn't recive it and the client doesn't even connect to the server. The server is running on http://localhost:3000 when the code is in index.html file the chat works fina and with no problems connects to the server but when i put it in the php file called chat.html.php the connection fails.
HTML code:
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="/Seminarska naloga NRSA/template/node_modules/socket.io/client-dist/socket.io.js"></script>
<script>
const socket = io("http://192.168.88.152:3000");
var messages = document.getElementById('messages');
var form = document.getElementById('form');
var input = document.getElementById('input');
form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
socket.emit('chat message', input.value);
input.value = '';
}
});
socket.on('chat message', function(msg) {
var item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
Server code:
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
app.get('/', (req, res) => {
res.sendFile(__dirname+'/chat.html.php');
});
io.on('connection', (socket) => {
console.log('a user connected');
});
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
});
io.on('connection', (socket) => {
socket.on('chat message', (msg) => {
console.log('message: ' + msg);
});
});
io.on('connection', (socket) => {
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
In the console there are no errors or warnings if the code is in index.html and i go to http://logalhost:3000 the ctah works perfectly.
This should be your client
<script src="/Seminarska naloga NRSA/template/node_modules/socket.io/client-dist/socket.io.js"></script>
<script>
const socket = io("http://192.168.88.152:3000");
var messages = document.getElementById('messages');
var form = document.getElementById('form');
var input = document.getElementById('input');
form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
socket.emit('SendMsg', input.value);
input.value = '';
}
});
socket.on('RecieveMsg', msg => {
var item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
This should be your server
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require("socket.io")(server,
cors: {
origin: 'http://localhost',
methods: ["GET", "POST"]
}
);
app.get('/', (req, res) => {
res.sendFile(__dirname+'/chat.html.php');
});
io.on('connection', (socket) => {
console.log('a user connected');
io.on('SendMsg', msg => {
console.log('Message: ' + msg);
io.emit('RecieveMsg', msg);
});
io.on('disconnect', () => {
console.log('A user disconnected');
})
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
all of your io.on() functions should be inside of io.on('connection'), because you want your server to listen after the connection.
Hope this helps :D
So, recently I've been working on this school project. Nothing too much honestly, as I am not completely fluent in js. But I ran into this tutorial when trying to use the MongoDB database for my site.
After following the guide up to the point where the simple database is finished, there seem to be errors in my code. But for some reason, no errors are being printed, making it very difficult to work on. Here is an example of some of my files:
index.js
const express = require('express');
const app = express();
const server = 0000;
const socket = require('socket.io');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const Users = require('./public/UserModel.js');
let rooms = [];
app.use(express.static('./public'));
app.use(bodyParser.json());
const MongoClient = require('mongodb').MongoClient;
const mongo_username = process.env.MONGO_USERNAME
const mongo_password = process.env.MONGO_PASSWORD
const uri = "mongodb+srv://Killerswordsman9776:<password>#cluster0.r92qc.mongodb.net/Cluster0?retryWrites=true&w=majority";
console.log("grabbed link");
const client = new MongoClient(uri, { useNewUrlParser: true });
let http = require('http').Server(app);
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }));
app.set('port', process.env.PORT || server);
http.listen(app.get('port'), function() {
app.post('/index', function (req, res, next) {
client.connect(err => {
const users = client.db("crmdb").collection("users");
let user = { name: req.body.name, email: req.body.email, note: req.body.note };
users.insertOne(user, function(err, res) {
if (err) concole.log("{error}");
console.log("1 user inserted");
});
})
})
console.log('listening on port', app.get('port'));
});
script.js
input = document.createElement('textarea');
input.setAttribute('type', 'text');
input.setAttribute('placeholder', 'Message');
document.body.appendChild(input);
sendBtn = createButton('Send Message');
sendBtn.mousePressed(send);
del = createButton('Delete Messages');
del.mousePressed(deleteMess);
createP('');
info = '<strong><u>Messages:</u></strong><br/>';
output = document.createElement('iframe');
output.setAttribute('scrolling', 'auto');
output.setAttribute('srcdoc', info);
output.setAttribute('title', 'messages');
document.body.appendChild(output);
socket.on('message', (data, color) => {
info += `<strong>${data.handle}</strong>: ${data.value} || <i>${hr}:${min} ${time}</i><br>`;
output.setAttribute('srcdoc', info);
});
}
function send() {
data = {
value: input.value,
handle: username.value
}
socket.emit('message', data);
}
function deleteMess() {
info = '<strong><u>Messages:</u></strong><br/>';
}
function joining() {
if (room.value != '') {
socket.emit('join', room.value);
} else {
socket.emit('join', 'Default Room');
}
}
function draw() {
hr = hour();
min = minute();
if (hr / 12 > 1) {
hr -= 12;
time = 'PM';
} else {
time = 'AM';
}
}
If any other files need viewing, or I'm not including enough information, please let me know and I will fix that. But the main problem I have here is just to get my errors printing. Thx
I am currently doing socket.io project. When I connect to new socket it shows my input username on the "usersDiv" where all clients should be there. But the thing is when I open another tab and input my name, it only has the name of the new client but when I switch to the other tab 2 client names are there. the new client doesn't show recent connected client input.
Here is my Code:
app.js(server)
const app = express();
const socket = require('socket.io');
const server = app.listen(8001, function(){
console.log('listening to port 8001')
});
const io = socket(server);
app.use(express.static('./views'));
app.set('views','./views');
app.set('view engine','ejs');
app.get('/', function(req, res){
res.render('index');
});
io.on('connection', function(socket){
console.log('Made Connection');
socket.on('username', function(data){
let users = [];
users.push(data.userName);
io.emit('joined', users)
});
});
client.js(client)
let username = prompt('What is your username?');
let usersDiv = document.getElementById('users');
let container = document.getElementById('container');
let socket = io();
let clear = document.getElementById('clear');
let circle = document.createElement('div');
socket.emit('username', {
userName: username
})
socket.on('joined', function(data){
usersDiv.innerHTML += data + '<br>';
})
As Chris G pointed out you need to declare let users = []; outside of the event handler connection.
For an example in app.js using sockets with a express server:
const express = require('express');
const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
app.use(express.static("public"));
app.set('view engine','ejs');
app.get('/', function(req, res){
res.render('index');
});
let users = [];
io.on('connection', function(socket) {
console.log('Made Connection');
socket.on('username', function(data) {
io.emit('joined', users);
users.push(data.userName);
});
});
const listener = server.listen(process.env.PORT, () => {
console.log('app is running on port ' + listener.address().port);
});
Then for client side you can create path like: public/client.js
let username = prompt('What is your username?');
let usersDiv = document.getElementById('users');
let container = document.getElementById('container');
let clear = document.getElementById('clear');
let circle = document.createElement('div');
let socket = io.connect();
socket.emit('username', {
userName: username
});
socket.on('joined', function(data) {
usersDiv.innerHTML = data.join('<br>');
});
Also you need to be careful using html when you are appending the username or messages someone could do a xss attack.
I have 2 pages: play page, live page and server. I want to use socket.io to do this: i want to send data from play page to server and then to live and show a text that update automatically when I change it in play page.
play page emit this
var n = <%-JSON.stringify(v1)%>;
var socket = io.connect('http://localhost:3000');
socket.emit('event', { message: n });
server code
var server = app.listen(3000); //port 3000 is only for sockets. my app has web traffic on port 5000.
var io = require('socket.io')(server);
io.on('connection', function(socket) {
socket.on('event', function(data) {
console.log('A client sent us this dumb message:', data.message);
var n = data.message;
console.log("");
console.log("data received from play client..trying to send to live");
console.log("");
console.log("var n is");
console.log(n);
console.log("sending data...");
socket.emit('event', { message: n });
Whatever I do in live page it don't receive message.
I solved 50% of my problem creating another socket in server.js that listen to port 3002 and this worked. But now my content don't update automatically on live page. I have to refresh manually and I don't want this.
This is my new server.js code that worked(without realtime update on live.ejs page):
const express = require('express');
const store = require('./store');
const storeLyric = require('./storeLyric');
const searchF = require('./search');
// middleware to handle HTTP POST request
// extract the entire body portion of an incoming request and exposes it on req.body
const bodyParser = require('body-parser');
const app = express();
app.set('port', (process.env.PORT || 5000));
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
///new
var server = app.listen(3000);
var io = require('socket.io')(server);
var server2 = app.listen(3002);
var io2 = require('socket.io')(server2);
io.on('connection', function(socket) {
socket.on('event', function(data) {
console.log('A client sent us this dumb message:', data.message);
var n = data.message;
console.log("");
console.log("data received from play client..trying to send to live");
console.log("");
console.log("var n is");
console.log(n);
console.log("sending data...");
io2.on('connection', function(socket2) {
socket2.on('live', function(data2) {
console.log('status from live client:', data2);
socket2.emit('live', n);
});
});
////////////////////
});
});
//end new
////////////
// default page
app.get('/', (req,res) => {
let students = [];
var end = req.query.end;
if(end==1 || end==2){
io2.on('connection', function(socket2) {
socket2.on('live', function(data2) {
console.log('status from live client:', data2);
socket2.emit('live', '');
});
});
}
store.studentList().then((req,respond) => {
students = req;
res.render('pages/index', {
title: '',
students:students
})
})
})
//live page
app.get('/live', function (req, res) {
res.render('pages/live', {
n:'gsgs'
})
})
// search page
app.get('/search', (req,res) => {
let search = [];
var q = req.query.q; // $_GET["q"]
searchF.search(q).then((req,respond) => {
search = req;
res.render('pages/search', {
search:search,
q:q
})
})
})
// play page
app.get('/play', (req,res) => {
let lyrics = [];
var vers = req.query.vers; // $_GET["vers"]
var for_id = req.query.for_id; // $_GET["vers"]
storeLyric.lyrics(for_id, vers).then((req,respond) => {
lyrics = req;
res.render('pages/play', {
title: '',
lyrics:lyrics
})
});
////////
})
app.listen(app.get('port'), () => {
console.log("Listening to port: ", app.get("port"))
});
What I'm doing wrong and why socket.io doesn't work in realtime?
Thanks for help!
You need to emit the event from server side to the client side and then catch data there
var server = app.listen(3000);
var io = require('socket.io')(server);
io.on('connection', function(socket) {
socket.on('event', function(data) {
var n = data.message;
io.sockets.emit('event', message);
});
And then on frontend in live page you write this
var n = <%-JSON.stringify(v1)%>;
var socket = io.connect('http://localhost:3000');
socket.on('event', (data)=>{
console.log(data)
});
I'm trying to re-render my pug template through setInterval().
I'm trying to have a page display live data from a MySQL server. I can get the data to the page but I don't know how to update the data shown without refreshing the entire page.
I've attempted to implement AJAX and also tried to do this via socket.io but failed to send the data to the pug template on both attempts.
Server.js
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var pug = require('pug');
var io = require('socket.io').listen(server);
var clients = [];
var outsideData = require('./public/data.js');
app.set('views', __dirname + '/views');
app.set('view engine', 'pug');
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res) {
res.render('index.pug', {
data: outsideData.getData()
});
});
io.sockets.on('connect', function() {
clients.push(io.sockets);
console.log("connected");
});
//Recompile Pug Template
function recompile() {
var pug = require('pug');
var template = require('fs').readFileSync('./views/index.pug', 'utf8');
var pugFn = pug.compile(template, {
filename: './views/index.pug',
pretty: true
});
var renderedTemplate = pugFn({
data: outsideData.getData()
});
}
//Send data every second.
setInterval(function() {
for (i = 0; i < clients.length; i++) {
recompile();
clients[i].emit('data', outsideData.getData());
}
}, 30000);
//Handle diconnected clients.
io.sockets.on('disconnect', function() {
var index = clients.indexOf(io.socket);
if (index != -1) {
clients.splice(index, 1);
}
});
server.listen(3001);
index.pug
doctype html
html
head
title Socket Communication
script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js')
script(src="/socket.io/socket.io.js")
//script(src="client.js")
var socket = io.connect();
socket.on('data', function(data) {
var myData = $('myData');
console.log(data)
});
body
h1= "Help me..."
p= JSON.stringify(data)
Update:
Here are the changes that works. Thank you mk12ok.
Server.js
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var pug = require('pug');
var io = require('socket.io').listen(server);
var clients = [];
var outsideData = require('./public/data.js');
app.set('views', __dirname + '/views');
app.set('view engine', 'pug');
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res) {
res.render('index.pug');
});
io.sockets.on('connect', function() {
clients.push(io.sockets);
console.log("connected");
});
//Send data every second.
setInterval(function() {
for (i = 0; i < clients.length; i++) {
clients[i].emit('data', outsideData.getData());
}
}, 1000);
//Handle diconnected clients.
io.sockets.on('disconnect', function() {
var index = clients.indexOf(io.socket);
if (index != -1) {
clients.splice(index, 1);
}
});
server.listen(3001);
index.pug
doctype html
html
head
title Socket Communication
script(src="/socket.io/socket.io.js")
//script(src="client.js")
body
h1= "Help me..."
p(id="data")
script.
var socket = io.connect();
socket.on('data', function(data) {
//Replace JSON.stringify(data) with JSON.stringify(data.tag) to retrieve a specific value stored in your JSON data.
document.getElementById("data").innerHTML = "Received" + JSON.stringify(data);
console.log(data)
});
Instead of re-rendering the pug file you can try this:
your server (very much the same code):
const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const pug = require('pug');
app.set('views', __dirname + '/views');
app.set('view engine', 'pug');
app.get('/', function(req, res) {
res.render('index.pug');
});
setInterval(function() {
io.emit('data', 'random number: ' + Math.random().toString());
}, 1000);
io.on('connection', function (socket) {
console.log('client connected');
socket.on('disconnect', function() {
console.log('client disconnected');
});
});
http.listen(3001, function(){
console.log('listening on *:3001');
});
and an example of index.pug:
doctype html
html
head
title Testing socket.io
body
h1 Testing socket.io
br
h3(id="status") not connected
br
p(id="data")
script(src="/socket.io/socket.io.js")
script.
var socket = io();
socket.on('connect', function() {
document.getElementById("status").innerHTML = "connected";
});
socket.on('data', function(data) {
document.getElementById("data").innerHTML = "Received " + data;
});