Socket is not defined + other errors - javascript

Server side code:
const http = require("http");
const host = 'localhost';
const port = 8000;
const { Server } = require("socket.io");
// creating the server and starting it on port 8000
const server = http.createServer();
server.listen(port, host, () => {
console.log(`Server is running on http://${host}:${port}`);
});
// making io object
const io = new Server(server);
// listening to connections to the server
io.on('connection', (socket) => {
console.log('a user connected');
});
// listening on port 8000
server.listen(8000, () => {
console.log('listening on *:8000');
});
// chat message coming to server
socket.on("details", (chatBundle) => {
console.log(chatBundle);
});
Client side code:
<!DOCTYPE html>
<html>
<body>
<h1>CHAT ROOM</h1>
<form onsubmit="return sendServer()">
<label for="name">Name:
<input id="name" name="name" type="text">
</label>
<label for="text">Message:
<input id="text" name="text" type="text">
</label>
<input type="submit" id="send" >
</form>
<script src="/Users/chanson/node_modules/socket.io/client-dist/socket.io.js">
</script>
<script>
function sendServer(){
var sender = document.getElementById("name");
var text = document.getElementById("text");
var tempArray = [sender, text]
socket.emit(chatmsg, tempArray)
};
</script>
</body>
</html>
Aim: to make a chat messenger that would work on same computer browsers + ports. e.g. Firefox port user can communicate to Chrome, Edge, Opera and Safari. (please don't ask why I have so many browsers).

Client side errors (3)
chatmsg has not been defined or given a value
socket has not been created or assigned to a variable
sendServer returns undefined, not false and hence will not prevent form submission when the submit button is pushed. (Calling event.preventDefault in the submit event is a more modern method of preventing submission).
A script element that addresses these considerations:
<script>
const chatmsg = "details"; // added
const socket = io(); // added
function sendServer(){
var sender = document.getElementById("name");
var text = document.getElementById("text");
var tempArray = [sender, text]
socket.emit(chatmsg, tempArray)
return false; // added
};
</script>
Server side errors (several)
No application.
The client page must be served from the server in order to communicate with it using sockets - CORS errors are generated if the client page is loaded using the file:// protocol and then tries to communicate with the local host server using socket.io.
A simple static express server can be set up to serve a request for http://localhost:8000/client.html.
The server must also be capable of serving the socket.io client script using a suitable url in the src attribute of the client side script tag. A client tag used in testing was
<script src="node_modules/socket.io-client/dist/socket.io.js"></script>
but will depend on server directory structure and possibly the version of socket.io.js in use.
The app is supplied as an argument when creating the http server.
In the version of socketIO used for testing, requiring socket.io returns a function that is called to generate a socket server. Check documentation to verify that later versions return an export object with a Socket property. (See notes at bottom of answer)
Socket message listening
This is in the wrong place - socket is an argument supplied to the io.on("connection", handler) handler function, and listening to socket events generated by the user who made the connection should be made in function scope of the connection handler.
Code used in testing
client.html
<!DOCTYPE html>
<html>
<body>
<h1>CHAT ROOM</h1>
<form onsubmit="return sendServer()">
<label for="name">Name:
<input id="name" name="name" type="text">
</label>
<label for="text">Message:
<input id="text" name="text" type="text">
</label>
<input type="submit" id="send" >
</form>
<!-- <script src="/Users/chanson/node_modules/socket.io/client-dist/socket.io.js"> -->
<!-- particular to server setup: -->
<script src="node_modules/socket.io-client/dist/socket.io.js"></script>
<script>
const chatmsg = "details";
var socket = io();
function sendServer(){
var sender = document.getElementById("name");
var text = document.getElementById("text");
var tempArray = [sender, text]
socket.emit(chatmsg, tempArray)
return false;
};
</script>
</body>
</html>
node script
const http = require("http");
const host = 'localhost';
const port = 8000;
//** const { Server } = require("socket.io");
//**
const express = require('express');
const app = express();
app.use(express.static('./'));
const socketIO = require("socket.io");
// creating the server and starting it on port 8000
//**const server = http.createServer();
const server = http.createServer(app);
server.listen(port, host, () => {
console.log(`Server is running on http://${host}:${port}`);
});
// making io object
//** const io = new Server(server);
const io = socketIO(server, {cookie: false}); /* prevent io cookie - see https://github.com/socketio/socket.io/issues/2276 */
// listening to connections to the server
io.on('connection', (socket) => {
console.log('a user connected');
//** move listening here, where socket is defined
// chat message coming to server
socket.on("details", (chatBundle) => {
console.log(chatBundle);
});
});
The version of socket.io used to prepare this answer was 2.2.0.
Version 4.x documentation confirms socket is still supplied to the connection handler.
Version 4.x doco shows Server as being imported from the socket.io package, which can't be done in CommonJS packages because the don't support the import statement.
AFAIK if in node you require an ECMA module package from within a CommonJS package, you are returned the default export of the ECMASScript module. You may need to investigate further if it is not the Server constructor function (or class object) exported in version 4.
You can import ECMAScript modules in CommonJS using the import function (not keyword), but the import operation is asynchronous. See How to use ES6 modules CommonJS for further details.

I don't like the way you import socket client please do something like
<script src="/socket.io/socket.io.js"></script>
or CDN
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js" integrity="sha384-/KNQL8Nu5gCHLqwqfQjA689Hhoqgi2S84SNUxC3roTe4EhJ9AfLkp8QiQcU8AMzI" crossorigin="anonymous"></script>
after that, you have to instantiate tour socket like:
const socket = io();
const text = document.getElementById("text")
socket.emit('chatMessage', text.value);
Make sure the event name is string ex here: chatMessage

Related

Nodejs is not fully functional when running on autostart

I am currently trying to change the volume of my Raspberry Pi with two html buttons (volume up and volume down), using nodeJS. The volume change is done by calling a bash script when clicking on one of the html-buttons in index.html.
When I start node manually from terminal with
node server.js
everything works fine and I can increase and decrease the volume using the two buttons.
As soon as I put the node script to autostart, only the "volume up" button is working, while the volume down does not seem to be working.
Killing the autostarted node process and starting it manually, it works just fine again.
How can the outcome be this different, depending on how node is started here?
What is my error in this?
My node script looks like this:
var express = require('express');
var path = require('path');
var open = require('open');
var fs = require('fs');
const { exec } = require('child_process');
var bodyParser = require('body-parser');
var port = 3000;
var app = express();
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'index.html'));
});
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/', function(request, respond) {
var inputValue = request.body.volume;
if (inputValue == "up") {
exec('sh volumeup.sh');
}
if(inputValue == "down") {
exec('sh volumedown.sh');
}
});
app.listen(port, function(err){
if(err){
console.log(err);
}else{
open('http://localhost:' + port);
}
});
with my index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<h2>Change Volume</h2>
<form action="" method="post">
<button name="volume" value="up">Volume Up</button>
<button name="volume" value="down">Volume Down</button>
</form>
</body>
</html>
To get the nodejs to run on autostart, I have set up a *.desktop-file:
[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=<Node>
Comment=
Exec=/usr/bin/node /home/pi/Desktop/server.js
StartupNotify=false
Terminal=true
Hidden=false
Thank you very much in advance, I really appreciate your help!
Figured it out by myself.
In case anyone is facing a similar issue:
What helped me, was to put both shell file names into their absolute path:
´´´
app.post('/', function(request, respond) {
var inputValue = request.body.volume;
if (inputValue == "up") {
exec('sh /home/pi/server/volumeup.sh');
}
if(inputValue == "down") {
exec('sh /home/pi/server/volumedown.sh');
}
});
´´´
Bothered me for longer than I want to admit :-)

socket id is not showing on html client side

i am trying to get the socket id on the client side but for some reason it's not showing. Here is my code
client side
<html>
<head>
<meta charset="utf-8" />
<title>Ringneck</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">
<script src="https://www.WebRTC-Experiment.com/RecordRTC.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io-stream/0.9.1/socket.io-stream.js"></script>
</head>
<body>
<div style="margin: 20px">
<h1 style="font-size: 18px;">Example 7: Media Translation Streaming</h1>
<div>
<button id="start-recording" disabled>Start Streaming</button>
<button id="stop-recording" disabled>Stop Streaming</button>
</div>
<h2 style="font-size: 16px; margin-bottom: 10px;">data.textTranslationResult.translation</h2>
<p>Record your voice in English, and see the German translation.</p>
<p>Keep recording for at least 4 seconds.</p>
<textarea id="results" style="width: 800px; height: 300px;"></textarea>
</div>
<script type="text/javascript">
const startRecording = document.getElementById('start-recording');
const stopRecording = document.getElementById('stop-recording');
let recordAudio;
const socketio = io();
console.log("JS file loaded"). // sanity check to make sure file is read
const socket = socketio.on('connect', function(msg) {
console.log("JS file loaded")
console.log("socket id: ",socket.id);
});
and my server side code
const express = require('express');
const cors = require('cors');
const path = require('path');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;
app.use(cors());
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/public/index.html'));
});
function onConnection(socket){
console.log(`Client connected [id=${socket.id}]`);
var returndata = {
"test":"yes"
}
socket.emit('server_setup', `Server connected [id=${socket.id}]`);
}
io.on('connection', onConnection);
http.listen(port, () => console.log('listening on port ' + port));
my server console log is
Client is connected [id=_RMXhb8Vz9XgSqhGAAGa]
but I could not get any response on the client side. what am i missing and how can i fix this and get the socket id ?
When I run your code, I found that there was a client-side Javascript parsing error on this line:
console.log("JS file loaded").
because of the period. When I replace that period with a semi-colon like this:
console.log("JS file loaded");
I get this output on the server:
Client connected [id=eoxspnNtoTg-2Kj3AAAB]
and this output in the debug console of the browser:
JS file loaded
socket id: eoxspnNtoTg-2Kj3AAAB
If you're not already doing so, you should be looking in the browser console for errors.

How can I make an HTML page that edits variables in a .JSON file?

Basically I have a .json file, and I want to make a html page that someone can fill out a form, and the information in the form will change variables in the JSON file.
Example:
The json file (for example):
{“title”: “(variable)”}
then when the html form is submitted it will read (variable) as what was entered into the form.
It depends on what you have on the backend (Node, python, etc)
Welcome to Stackoverflow, seeing that you have NodeJS, you may want to establish some sort of communication from your back end to front end. Let's say you're using websockets. Here is how information would be passed:
userData.json:
{
name: "Mishra",
age: 89
}
server.js:
const app = express()
const server = app.listen(3000) // setup express server
const io = require('socket.io').listen(server); // using websockets
let userData = require('./userData.json');
// on socket connection event
io.on('connection', (socket) => {
socket.on('updateName', name => { // when updateName is called
userData.name = name // set JSON var to new name
})
}
// method to save JSON file goes here
myForm.html:
<head>
<script type="text/javascript" src="your/path/to/socket.io.js"></script>
<script>
var socket = io();
</script>
</head>
<body>
Set name:
<input type="text" id="nameField" name="fname"><br>
<input type="submit" value="Submit" id="submit">
<script>
document.getElementById("submit").onclick = () =>{
socket.emit("updateName", document.getElementById("nameField").value)
}
</script>
</body>

How to avoid socket id change with socket.io?

I'm currently trying to make a support application (like, to live chat with support) and I'm looking for a way to avoid the change of the socket id.
Here is my index.js code:
const app = require('express')();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server);
io.on('connection', function (socket) {
socket.on("hello",()=>{
socket.emit("hello",socket.id)
})
})
app.get("/",(req,res)=>{
res.sendFile(__dirname+"/client/index.html")
})
server.listen(1002)
And here is my client/index.html code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Socket.io</title>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<p id="socketid"></p>
<script>
const socket = io();
socket.emit("hello")
socket.on('hello',(message)=>{
document.getElementById("socketid").innerHTML=message;
})
</script>
</body>
</html>
Thanks in advance for your help!
I think you cannot make socketid constant. Every time you reconnect or connect a new socket id will be given to you. Actually why do you want to make socketid constant?

Why don't my Javascript prompts show up from my Express.IO .ejs file?

I am relatively new to JavaScript and subsequently Node + Express.IO. I am trying to build a page that will track in real time connections made by different 'users' to the server. Consequently, when I do include all the functions from the io module, my prompt() and alert do not work anymore. I am running nodemon app.js from my terminal and no compilation errors are showing up when I do so. The alert and prompt work again when I remove all the io functions.
These are the contents of my index.ejs <body> tag:
<body>
<h1>Chatroom</h1>
<script>
alert("Hello!");
var name = prompt("What is your name?");
io.connect();
io.emit.('got_a_new_user', {name: name});
io.on('new_user', function(data) {
//render this new info in the HTML
var users = data.users;
console.log(users);
if (users != undefined) {
console.log("\n\n\n" + users);
// if users is defined, append the new division containing the username
}
});
io.on('disconnect_user', function(data) {
var users = data.users;
if (users != undefined) {
// If users is defined remove the corresponding HTML element
}
});
</script>
<div id="container">
</div>
</body>
Any help would be much appreciated.
Adding example for the comment added by UKatz,
You will have to connect socket.io from the client as follows,
index.ejs
<script src="http://ip:port/socket.io/socket.io.js"></script>
<script type="text/javascript">
var socket = io.connect('http://ip:port');
socket.emit('got_a_new_user', {name: name});
</script>
Check socket.io documentation for how to connect socket.io with client.

Categories