Chat messages repeated - javascript

I'm trying to create a very simple chat system with socket.io
Here's my html code :
<body>
<div id="messages"></div>
<form action="" id="form" autocomplete="off" onsubmit="event.preventDefault(); myScript();">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
<script src="client.js"></script>
</body>
And this code is called on the submit of the form :
var person = prompt("Please enter your name", "Name");
function myScript(){
var socket = io();
socket.emit('chat message', person+":"+document.getElementById("m").value);
document.getElementById("m").value = "";
socket.on('chat message', function(msg){
var messages = document.getElementById('messages');
messages.insertAdjacentHTML('beforeend', '<div>'+msg+'</div>');
});
}
The first time i type a message, this one is displayed once. The second time, the message is displayed twice, the third message is displayed three times, and so on.
For some reason, the socket.on('chat message', function(msg){ is executed multiple times, i just can't understand why
Here's the server code :
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static('public'));
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
Any help please ?
Thanks

Got it!
Frontend js :
var person = prompt("Please enter your name", "Name");
var socket = io();
function myScript(){
socket.emit('chat message', person+":"+document.getElementById("m").value);
document.getElementById("m").value = "";
}
socket.on('chat message', function(msg){
var messages = document.getElementById('messages');
messages.insertAdjacentHTML('beforeend', '<div>'+msg+'</div>');
});
The socket.on('chat message' shouldn't go in the submit function.
Thanks

Related

Socket.io some emmits doesn't trigger while others do

I've been trying to get familiarized with socket.io so use it in a real time app. I went through the basic example, a chat room, then I used ngrok to do a test with more than one client and it's all good. Now I'm looking to use TAFFY to save a log of the conversation on deploy it to a new user that connects to it so I added another emmit to send that log, and this particular emmit doesn't seem to ever trigger the on sentence in the client's side.
These are the server instructions
io.on('connection', function(socket){
console.log("someone connected");
var chatLog={log:[]};
log().each(function (iter){ //this is the taffy var
chatLog.log.push({"usr":iter.usr,"msg":iter.msg});
});
var stringLog=JSON.stringify(chatLog);
console.log(stringLog);
socket.emit('cargaLog', stringLog);// THIS is the naughty emmit
socket.on('chat message', function(msg){
var mensaje=JSON.parse(msg);
log.insert({"usr":mensaje.usr,
"msg":mensaje.msg
});
io.emit('chat message', mensaje.usr.toUpperCase()+" dice: "+mensaje.msg);
});
});
Client's side
$(function () {
var socket = io();
socket.on('cargaLog', function(log){
alert(log); //this never happens
console.log(log);
});
$('form').submit(function(){
var mensaje=$('#m').val();
var json='{"usr":"'+person+'","msg":"'+mensaje+'"}';
socket.emit('chat message', json);
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
var html='<li><img src="defaultUsrImg.png" alt="Usr_img" heigth="40" width="40">'+(msg)+'</li>';
$('#messages').append(html);
window.scrollTo(0, document.body.scrollHeight);
});
});
I've been staring at this code for a while and none of the solutions that worked with other people work for me (i.e. using io.connect() or io.connect('http://0.0.0.0:8080') on the client's side or having an emmit from the client that asks for the server emmit to be triggered).
Anyone has any idea why this happens?
Altenatively, anyone have any idea that could help me troubleshoot this better?
Other details are:
Running windows 10
Node version 8.2.1
socket.io version 2.0.3
This how I use the node requires:
var TAFFY = require('taffy');
var express=require('express');
var app = express();
var http = require('http');
var path=require('path');
var port = process.env.PORT || 3000;
var server= http.createServer(app).listen(port);
var io = require('socket.io').listen(server);
var log=TAFFY({"usr":"SERVER",
"msg":"WELCOME"
});
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
Client html code (only the boddy because mt html includes and it would bee way too long
<body>
<ul id="messages"></ul>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
<script type="text/javascript" src="./socket.io/socket.io.js"></script>
<script src="jquery-3.2.1.min.js"></script>
<!-- <script src="/mensajes.js"></script> THIS IS THE OLD CODE-->
<script >
var person = prompt("Introduce tu nombre o seudonimo", "anon"); //THIS IS THE WORKING CODE
if(person === null || person===""){
alert("Necesitas un nombre para participar");
}
else{
$(function () {
var socket = io();
socket.emit('ia iege',person);
socket.on('usrConectado',function(usr){
var html='<li><h6>'+(usr)+' se ha conectado</h6></li>';
$('#messages').append(html);
window.scrollTo(0, document.body.scrollHeight);
});
$('form').submit(function(){
var mensaje=$('#m').val();
var json='{"usr":"'+person+'","msg":"'+mensaje+'"}';
socket.emit('chat message', json);
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
var html='<li><img src="https://dujrsrsgsd3nh.cloudfront.net/img/emoticons/419693/pedreiro-1500067445.PNG" alt="Usr_img" heigth="40" width="40">'+(msg)+'</li>';
$('#messages').append(html);
window.scrollTo(0, document.body.scrollHeight);
});
socket.on('cargaLog', function(log){
console.log(log);
var oldLog=JSON.parse(log);
cargaLog(oldLog);
});
});
function cargaLog(newLog){
//newLog is an object
newLog.log.forEach(function(iter){
var msg=iter.usr.toUpperCase()+' dijo: '+iter.msg;
var html='<li><img src="https://dujrsrsgsd3nh.cloudfront.net/img/emoticons/419693/pedreiro-1500067445.PNG" alt="Usr_img" heigth="40" width="40">'+(msg)+'</li>';
$('#messages').append(html);
window.scrollTo(0, document.body.scrollHeight);
});
}
}
</script>
</body>
I reduced your code down to just the basics and I'm getting the message just fine that you were having trouble with. Here's the reduced code that works just fine:
Server code:
var express = require('express');
var app = express();
var http = require('http');
var path = require('path');
var port = process.env.PORT || 3000;
var server= http.createServer(app).listen(port);
var io = require('socket.io').listen(server);
app.get('/', function(req, res){
res.sendFile(__dirname + '/s1.html');
});
io.on('connection', function(socket) {
console.log("someone connected");
var chatLog = {log: [{usr: "someuser", msg: "somemsg"}]};
var stringLog = JSON.stringify(chatLog);
console.log(stringLog);
socket.emit('cargaLog', stringLog); // THIS is the naughty emmit
});
Client Code:
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
<script>
function dbg(x) {
let str = x;
if (typeof x === "object") {
str = JSON.stringify(x);
}
$("#log").append("<div>" + str + "</div>");
}
$(function() {
var socket = io();
socket.on('cargaLog', function(log) {
dbg(log);
});
});
</script>
</head>
<body>
Empty Content, waiting for message to arrive.
<div id="log"></div>
</body>
</html>
When I load the page, the browser immediately displays the cargaLog message that you were having trouble with. I would suggest that you backtrack to something super simple like this until you prove it works and then add things back one at a time until you find what is introducing the problem. If this code does not work for you, then you must have something goofed up in your environment and I'd probably do a reinstall of various components (socket.io, node.js, express, etc...).
Try
socket.emit('chat message' , { usr: person, msg: mensaje});
I think you can try to look at this repository https://github.com/egin10/socket-chat-example/blob/master/app.js for your server side.
and you can try this one for your client side https://github.com/egin10/socket-chat-example/blob/master/chat.html
Note: Just remember about socket.on(params, callback), it's for fetching data from emmiter, and io.emit(params, obj) on server side is for emmiting data.
so, you must make sure about what is your emmiting to server or client and what's your fetching (socket.on()) from serveror client must have same params.
and you must make sure about your object is var chatLog={log:[]};. if you want to get log, you must do like this chatLog.log.
It's work to me. i hope it can help you.

Socket.io simple node app is not working

I have this little socket room app, but for a reason is not working. I'm trying to make the user join the room on click and display an alert, can't figure out the issue, I'm kinda new to sockets and can't even get this simple app working.. This is my code
////app.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
socket.on('room', function(room) {
socket.join(room);
});
});
room = "abc123";
io.sockets.in(room).emit('message', 'what is going on, party people?');
http.listen(3000, function(){
console.log('listening on localhost:3000');
});
////index.html
<!DOCTYPE html>
<html>
<head>
<title>flip</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<button>Join the room!</button>
</body>
<script>
var socket = io.connect();
// let's assume that the client page, once rendered, knows what room it wants to join
var room = "abc123";
socket.on('connect', function() {
$('button').click(function() {
socket.emit('room', room);
})
});
socket.on('message', function(data) {
alert(data)
});
</script>
</html>
On the client side you have to:
var socket = io.connect('http://localhost:3000');
On the server side:
io.on('connection', function(socket) {
socket.on('room', function(room) {
socket.join(room);
room = "abc123";
io.to(room).emit('message', 'what is going on, party people?');
});
});
You can not emit until you receive the connection.
You should instantiate a new instance of io, like so:
const socket = io();

socket.io with Angular doesn't display message instantly

I am trying to create instanse message app (chat) using socket.io and Angular.
I have 2 files: index.html, and index.js showed below.
the chat works fine expect that when I press on the "Send" button I don't see the message stright away in the chat window.
I only see the message once I press the input text field with the mouse cursor...
What Am I doing wrong?
i addition, I also see the tag < li > as part of the text. I want this tag to be an html tag, not a text string...
Thanks
index.html
<html>
<head>
<title>My Chat</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
{{ message }}
<form >
<input autocomplete="off" ng-model="exampleText" type="text" />
<button type='button' ng-click="submit()">
Send
</button>
</form>
</div>
<script>
var app=angular.module("myApp", []);
var socket = io();
app.controller("myCtrl", function($scope) {
$scope.message='';
$scope.submit=function(){
socket.emit('chat message', angular.copy($scope.exampleText));
$scope.exampleText='';
return false;
}
socket.on('chat message', function(msg){
$scope.message=$scope.message+" <li> "+ msg;
});
});
</script>
</body>
</html>
index.js
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static(__dirname + '/'));
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log('a user connected');
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
First, the message delay. Look at the chat message handler:
socket.on('chat message', function(msg){
$scope.message=$scope.message+" <li> "+ msg;
});
- the problem here is that message update happens outside of the scope digest loop. Try the following:
socket.on('chat message', function(msg){
$scope.$apply(function() {
$scope.message=$scope.message+" <li> "+ msg + "</li>";
});
});
Next, if you want to get rid of "li" tags showing, you need to stop constructing HTML in your controller and display incoming messages directly. This can be achieved by making "message" an array of messages. In your HTML layout, replace:
{{ message }}
with
<ul>
<li ng-repeat="message in messages">{{message}}</li>
</ul>
then replace, in the controller
$scope.message='';
with
$scope.messages = [];
and finally change the chat message handler to:
socket.on('chat message', function(msg){
$scope.messages.push(msg);
});
This will do the trick.
Problem is that you are using socket.on from index.html that is outside of your angularjs app scope and it does not watch that method calls.
To avoid problems like that you can use $scope.$apply like this
socket.on('chat message', function(msg) {
$scope.$apply(function() {
...
}
});
Or better use angularjs component for socket.io that is completely attached to $scope and you don't to call additional methods
// in the top-level module of the app
angular.module('myApp', [
'btford.socket-io',
'myApp.MyCtrl'
]).
factory('mySocket', function (socketFactory) {
return socketFactory();
}).
controller('MyCtrl', function (mySocket) {
// ...
});

using jQuery with socket.io

I am trying to use jQuery in my socket.io js (index.js) file.
Whenever I try to do
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="index.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
socket.on('new user', function(data){
$('#newUserMessage').text(data);
});
</script>
I get this error in my console
GET http://localhost:3000/index.js
ReferenceError: $ is not defined
I'm not sure why this would happen?
But if I remove it I cant use jQuery's functions in index.js?
My index.js file
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var $usernameInput = $('.usernameInput');
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.broadcast.emit('new user', 'New User Joined, Say Hi :D');
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
function setUsername () {
username = cleanInput($usernameInput.val().trim());
if (username) {
socket.emit('add user', username);
}
}
You are a little confused, you have your front end and you have your back end.
Your index.js is your back end, you run that using NodeJS and you don't try to use jQuery on your back end, there's no DOM to manipulate. Also you don't include index.js on your front end, that's back end code.
This is wrong:
var $usernameInput = $('.usernameInput');
You can't access your DOM to get that value you have to send it to the back end, with some kind of event like this:
Front end
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chatMessage', $('#m').val());
$('#m').val('');
return false;
});
socket.on('connect', function(){
socket.emit('setUser', $('.usernameInput').val().trim());
});
socket.on('chatMessage', function(msg){
$('#messages').append($('<li>').text(msg));
});
socket.on('newUser', function(data){
$('#newUserMessage').text(data);
});
</script>
Back end
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.broadcast.emit('newUser', 'New User Joined, Say Hi :D');
socket.on('setUser', function(username){
console.log(username); //here you have your user name
});
socket.on('chatMessage', function(msg){
io.emit('chatMessage', msg);
});
});
Here is My code for socket IO
<script>
var socket = io.connect('<?php echo $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'] . ":8000" ?>');
console.log("tests" + socket);
socket.on('connect', function () {
});
socket.on('call_admin_notification', function (data) {
getAdminNotification();
});
</script>

Pass data from HTTP to node.js to TCP?

I recently started using Socket.io, and node.js as a result, and I am kind of stuck. I do not even know if this is a practical solution for my application, but hopefully someone can help.
All I have here is a webpage with a checkbox, which reports it's status to the node console, and then when a TCP client connects, it receives the status as well.
I am wondering how I would go about making this event continuous, so that the TCP client constantly receives updates on the status of the checkbox.
If anyone has any idea, please let me know, and sorry for the long code...
Server Code:
var net = require('net');
var app = require('express')(); <!-- These are mandatory variables -->
var http = require('http').Server(app);
var io = require('socket.io')(http);
var HOST = 'localhost';
var PORT = 4040;
GLOBAL.MYVAR = "Hello world";
var server = net.createServer();
server.listen(PORT, HOST);
app.get('/', function(req, res){ <!-- This sends the html file -->
//send the index.html file for all requests
res.sendFile(__dirname + '/index.html');
});
http.listen(3001, function(){ <!-- Tells the HTTP server which port to use -->
console.log('listening for HTTP on *:3001'); <!-- Outputs text to the console -->
console.log('listening for TCP on port ' + PORT);
});
<!-- everything below this line are actual commands for the actual app -->
io.on('connection', function(socket) // Opens the socket
{
socket.on('checkbox1', function(msg){ // Creates an event
console.log(msg); // displays the message in the console
MYVAR = msg; // Sets the global variable to be the contents of the message recieved
});
});
server.on('connection', function(socket){ // Opens the socket for the TCP connection
socket.write(MYVAR);
}).listen(PORT, HOST);
Client code:
<!doctype html>
<html>
<head>
<title>Socket IO Test</title>
<form action="">
<input type='checkbox' onclick='checkbox1(this);'>Checkbox1</label>
</form>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
var number = 0;
function checkbox1(cb) {
socket.emit('checkbox1', 'checkbox 1 = ' + cb.checked);
return false;
}
</script>
</body>
</html>
Cheers
I believe the issue here is that you don't have a way to reference the TCP socket. Once you do have a reference it is as easy as receiving a message and sending it.
This will work for a single client.
var net = require('net');
var app = require('express')(); <!-- These are mandatory variables -->
var http = require('http').Server(app);
var io = require('socket.io')(3000);
var s;
var HOST = 'localhost';
var PORT = 4040;
GLOBAL.MYVAR = "Hello world";
var server = net.createServer();
server.listen(PORT, HOST);
app.get('/', function(req, res){ <!-- This sends the html file -->
//send the index.html file for all requests
res.sendFile(__dirname + '/index.html');
});
http.listen(3001, function(){ <!-- Tells the HTTP server which port to use -->
console.log('listening for HTTP on *:3001'); <!-- Outputs text to the console -->
console.log('listening for TCP on port ' + PORT);
});
<!-- everything below this line are actual commands for the actual app -->
io.on('connection', function(socket) // Opens the socket
{
socket.on('checkbox1', function(msg){ // Creates an event
console.log(msg); // displays the message in the console
MYVAR = msg; // Sets the global variable to be the contents of the message recieved
s.write(MYVAR, 'utf-8');
});
});
server.on('connection', function(socket){ // Opens the socket for the TCP connection
s = socket;
s.write(MYVAR, 'utf-8');
}).listen(PORT, HOST);
This will work for multiple clients.
var net = require('net');
var app = require('express')(); <!-- These are mandatory variables -->
var http = require('http').Server(app);
var io = require('socket.io')(3000);
var sockets = [];
var HOST = 'localhost';
var PORT = 4040;
GLOBAL.MYVAR = "Hello world";
var server = net.createServer();
server.listen(PORT, HOST);
app.get('/', function(req, res){ <!-- This sends the html file -->
//send the index.html file for all requests
res.sendFile(__dirname + '/index.html');
});
http.listen(3001, function(){ <!-- Tells the HTTP server which port to use -->
console.log('listening for HTTP on *:3001'); <!-- Outputs text to the console -->
console.log('listening for TCP on port ' + PORT);
});
<!-- everything below this line are actual commands for the actual app -->
io.on('connection', function(socket) // Opens the socket
{
socket.on('checkbox1', function(msg){ // Creates an event
console.log(msg); // displays the message in the console
MYVAR = msg; // Sets the global variable to be the contents of the message recieved
for (var i = 0; i < sockets.length; i++) {
if(sockets[i]) {
sockets[i].write(MYVAR, 'utf-8');
}
}
});
});
server.on('connection', function(socket){ // Opens the socket for the TCP connection
sockets.push(socket);
socket.write(MYVAR, 'utf-8');
}).listen(PORT, HOST);

Categories

Resources